feat(mail): center-align action button in email template
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -47,3 +47,26 @@
|
||||
.bg-custom-background {
|
||||
background-color: rgb(var(--v-table-header-color));
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Vuexy (Bootstrap 5) parity — spacing + horizontal rules in cards
|
||||
// (e.g. form-layouts-horizontal “Form separator”)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
.my-6 {
|
||||
margin-block-end: 1.5rem !important;
|
||||
margin-block-start: 1.5rem !important;
|
||||
}
|
||||
|
||||
.mx-n6 {
|
||||
margin-inline-end: -1.5rem !important;
|
||||
margin-inline-start: -1.5rem !important;
|
||||
}
|
||||
|
||||
// BS: `.card hr { color: var(--bs-card-border-color); }` — Vuetify card border token
|
||||
.v-card .v-card-text hr {
|
||||
border: 0;
|
||||
border-top: 1px solid rgba(var(--v-border-color), var(--v-border-opacity));
|
||||
color: rgba(var(--v-border-color), var(--v-border-opacity));
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,58 @@
|
||||
.v-card-subtitle {
|
||||
color: rgba(var(--v-theme-on-background), 0.55);
|
||||
}
|
||||
|
||||
/* Card border shadow — colored bottom border with hover effect */
|
||||
.v-card[class*="card-border-shadow-"] {
|
||||
position: relative;
|
||||
overflow: visible;
|
||||
border-block-end: none;
|
||||
transition: box-shadow 0.3s ease;
|
||||
|
||||
&::after {
|
||||
position: absolute;
|
||||
border-radius: inherit;
|
||||
block-size: 100%;
|
||||
border-block-end: 0.125rem solid var(--card-border-bottom-color, rgba(var(--v-theme-on-surface), 0.12));
|
||||
content: "";
|
||||
inline-size: 100%;
|
||||
inset-block-end: 0;
|
||||
inset-inline-start: 0;
|
||||
pointer-events: none;
|
||||
transition: border-color 0.3s ease, border-width 0.3s ease;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 0.25rem 1.125rem rgba(var(--v-theme-on-surface), 0.16) !important;
|
||||
|
||||
&::after {
|
||||
border-color: var(--card-hover-border-bottom-color, rgba(var(--v-theme-on-surface), 0.3));
|
||||
border-block-end-width: 0.1875rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.v-card.card-border-shadow-primary {
|
||||
--card-border-bottom-color: rgba(var(--v-theme-primary), 0.38);
|
||||
--card-hover-border-bottom-color: rgb(var(--v-theme-primary));
|
||||
}
|
||||
|
||||
.v-card.card-border-shadow-warning {
|
||||
--card-border-bottom-color: rgba(var(--v-theme-warning), 0.38);
|
||||
--card-hover-border-bottom-color: rgb(var(--v-theme-warning));
|
||||
}
|
||||
|
||||
.v-card.card-border-shadow-info {
|
||||
--card-border-bottom-color: rgba(var(--v-theme-info), 0.38);
|
||||
--card-hover-border-bottom-color: rgb(var(--v-theme-info));
|
||||
}
|
||||
|
||||
.v-card.card-border-shadow-success {
|
||||
--card-border-bottom-color: rgba(var(--v-theme-success), 0.38);
|
||||
--card-hover-border-bottom-color: rgb(var(--v-theme-success));
|
||||
}
|
||||
|
||||
.v-card.card-border-shadow-error {
|
||||
--card-border-bottom-color: rgba(var(--v-theme-error), 0.38);
|
||||
--card-hover-border-bottom-color: rgb(var(--v-theme-error));
|
||||
}
|
||||
|
||||
@@ -80,33 +80,37 @@ const shiftFillPercent = computed(() => {
|
||||
md="3"
|
||||
>
|
||||
<VCard
|
||||
class="cursor-pointer"
|
||||
hover
|
||||
:class="[
|
||||
'cursor-pointer h-100',
|
||||
stats.persons_approved_without_shift > 0 ? 'card-border-shadow-warning' : 'card-border-shadow-success',
|
||||
]"
|
||||
@click="navigateTo('events-id-persons')"
|
||||
>
|
||||
<VCardText class="d-flex align-center gap-x-3">
|
||||
<VAvatar
|
||||
:color="stats.persons_approved_without_shift > 0 ? 'warning' : 'success'"
|
||||
variant="tonal"
|
||||
size="44"
|
||||
rounded
|
||||
>
|
||||
<VIcon
|
||||
icon="tabler-user-exclamation"
|
||||
size="28"
|
||||
/>
|
||||
</VAvatar>
|
||||
<div>
|
||||
<h4 class="text-h4">
|
||||
<VCardText>
|
||||
<div class="d-flex align-center mb-1">
|
||||
<VAvatar
|
||||
:color="stats.persons_approved_without_shift > 0 ? 'warning' : 'success'"
|
||||
variant="tonal"
|
||||
size="44"
|
||||
rounded
|
||||
class="me-4"
|
||||
>
|
||||
<VIcon
|
||||
icon="tabler-user-exclamation"
|
||||
size="28"
|
||||
/>
|
||||
</VAvatar>
|
||||
<h4 class="text-h4 mb-0">
|
||||
{{ stats.persons_approved_without_shift }}
|
||||
</h4>
|
||||
<p class="text-body-2 text-medium-emphasis mb-0">
|
||||
goedgekeurd zonder shift
|
||||
</p>
|
||||
<p class="text-caption text-disabled mb-0">
|
||||
van {{ stats.persons_approved }} goedgekeurde personen
|
||||
</p>
|
||||
</div>
|
||||
<p class="mb-1">
|
||||
Goedgekeurd zonder shift
|
||||
</p>
|
||||
<p class="mb-0">
|
||||
<span class="text-heading fw-medium me-2">{{ stats.persons_approved }}</span>
|
||||
<span class="text-body-secondary text-sm">goedgekeurde personen</span>
|
||||
</p>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</VCol>
|
||||
@@ -118,30 +122,36 @@ const shiftFillPercent = computed(() => {
|
||||
md="3"
|
||||
>
|
||||
<VCard
|
||||
class="cursor-pointer"
|
||||
hover
|
||||
:class="[
|
||||
'cursor-pointer h-100',
|
||||
stats.persons_pending > 0 ? 'card-border-shadow-warning' : 'card-border-shadow-success',
|
||||
]"
|
||||
@click="navigateTo('events-id-persons')"
|
||||
>
|
||||
<VCardText class="d-flex align-center gap-x-3">
|
||||
<VAvatar
|
||||
:color="stats.persons_pending > 0 ? 'warning' : 'success'"
|
||||
variant="tonal"
|
||||
size="44"
|
||||
rounded
|
||||
>
|
||||
<VIcon
|
||||
icon="tabler-clock"
|
||||
size="28"
|
||||
/>
|
||||
</VAvatar>
|
||||
<div>
|
||||
<h4 class="text-h4">
|
||||
<VCardText>
|
||||
<div class="d-flex align-center mb-1">
|
||||
<VAvatar
|
||||
:color="stats.persons_pending > 0 ? 'warning' : 'success'"
|
||||
variant="tonal"
|
||||
size="44"
|
||||
rounded
|
||||
class="me-4"
|
||||
>
|
||||
<VIcon
|
||||
icon="tabler-clock"
|
||||
size="28"
|
||||
/>
|
||||
</VAvatar>
|
||||
<h4 class="text-h4 mb-0">
|
||||
{{ stats.persons_pending }}
|
||||
</h4>
|
||||
<p class="text-body-2 text-medium-emphasis mb-0">
|
||||
wachtende goedkeuringen
|
||||
</p>
|
||||
</div>
|
||||
<p class="mb-1">
|
||||
Wachtende goedkeuringen
|
||||
</p>
|
||||
<p class="mb-0">
|
||||
<span class="text-body-secondary text-sm">te beoordelen aanmeldingen</span>
|
||||
</p>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</VCol>
|
||||
@@ -153,30 +163,36 @@ const shiftFillPercent = computed(() => {
|
||||
md="3"
|
||||
>
|
||||
<VCard
|
||||
class="cursor-pointer"
|
||||
hover
|
||||
:class="[
|
||||
'cursor-pointer h-100',
|
||||
stats.pending_identity_matches > 0 ? 'card-border-shadow-info' : 'card-border-shadow-success',
|
||||
]"
|
||||
@click="navigateTo('events-id-persons')"
|
||||
>
|
||||
<VCardText class="d-flex align-center gap-x-3">
|
||||
<VAvatar
|
||||
:color="stats.pending_identity_matches > 0 ? 'info' : 'success'"
|
||||
variant="tonal"
|
||||
size="44"
|
||||
rounded
|
||||
>
|
||||
<VIcon
|
||||
icon="tabler-user-search"
|
||||
size="28"
|
||||
/>
|
||||
</VAvatar>
|
||||
<div>
|
||||
<h4 class="text-h4">
|
||||
<VCardText>
|
||||
<div class="d-flex align-center mb-1">
|
||||
<VAvatar
|
||||
:color="stats.pending_identity_matches > 0 ? 'info' : 'success'"
|
||||
variant="tonal"
|
||||
size="44"
|
||||
rounded
|
||||
class="me-4"
|
||||
>
|
||||
<VIcon
|
||||
icon="tabler-user-search"
|
||||
size="28"
|
||||
/>
|
||||
</VAvatar>
|
||||
<h4 class="text-h4 mb-0">
|
||||
{{ stats.pending_identity_matches }}
|
||||
</h4>
|
||||
<p class="text-body-2 text-medium-emphasis mb-0">
|
||||
onopgeloste matches
|
||||
</p>
|
||||
</div>
|
||||
<p class="mb-1">
|
||||
Onopgeloste matches
|
||||
</p>
|
||||
<p class="mb-0">
|
||||
<span class="text-body-secondary text-sm">identiteitscontrole nodig</span>
|
||||
</p>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</VCol>
|
||||
@@ -188,36 +204,37 @@ const shiftFillPercent = computed(() => {
|
||||
md="3"
|
||||
>
|
||||
<VCard
|
||||
class="cursor-pointer"
|
||||
hover
|
||||
:class="[
|
||||
'cursor-pointer h-100',
|
||||
`card-border-shadow-${shiftFillColor}`,
|
||||
]"
|
||||
@click="navigateTo('events-id-sections')"
|
||||
>
|
||||
<VCardText class="d-flex align-center gap-x-3">
|
||||
<VAvatar
|
||||
:color="shiftFillColor"
|
||||
variant="tonal"
|
||||
size="44"
|
||||
rounded
|
||||
>
|
||||
<VIcon
|
||||
icon="tabler-calendar-check"
|
||||
size="28"
|
||||
/>
|
||||
</VAvatar>
|
||||
<div class="flex-grow-1">
|
||||
<h4 class="text-h4">
|
||||
<VCardText>
|
||||
<div class="d-flex align-center mb-1">
|
||||
<VAvatar
|
||||
:color="shiftFillColor"
|
||||
variant="tonal"
|
||||
size="44"
|
||||
rounded
|
||||
class="me-4"
|
||||
>
|
||||
<VIcon
|
||||
icon="tabler-calendar-check"
|
||||
size="28"
|
||||
/>
|
||||
</VAvatar>
|
||||
<h4 class="text-h4 mb-0">
|
||||
{{ stats.shifts_filled }}/{{ stats.shifts_total }}
|
||||
</h4>
|
||||
<p class="text-body-2 text-medium-emphasis mb-1">
|
||||
shifts gevuld
|
||||
</p>
|
||||
<VProgressLinear
|
||||
:model-value="shiftFillPercent"
|
||||
:color="shiftFillColor"
|
||||
height="6"
|
||||
rounded
|
||||
/>
|
||||
</div>
|
||||
<p class="mb-1">
|
||||
Shifts gevuld
|
||||
</p>
|
||||
<p class="mb-0">
|
||||
<span class="text-heading fw-medium me-2">{{ shiftFillPercent }}%</span>
|
||||
<span class="text-body-secondary text-sm">bezetting</span>
|
||||
</p>
|
||||
</VCardText>
|
||||
</VCard>
|
||||
</VCol>
|
||||
|
||||
@@ -3,6 +3,7 @@ import { useOrganisationStore } from '@/stores/useOrganisationStore'
|
||||
import PersonTagsTab from '@/components/organisation/PersonTagsTab.vue'
|
||||
import RegistrationFieldTemplatesTab from '@/components/organisation/RegistrationFieldTemplatesTab.vue'
|
||||
import CrowdTypesManager from '@/components/organisations/CrowdTypesManager.vue'
|
||||
import EmailBrandingTab from '@/components/organisation/EmailBrandingTab.vue'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
@@ -14,6 +15,7 @@ const tabs = [
|
||||
{ value: 'tags', label: 'Tags & Vaardigheden', icon: 'tabler-tag' },
|
||||
{ value: 'templates', label: 'Registratieveld-templates', icon: 'tabler-forms' },
|
||||
{ value: 'crowd-types', label: 'Crowd types', icon: 'tabler-users-group' },
|
||||
{ value: 'email-branding', label: 'E-mail opmaak', icon: 'tabler-mail' },
|
||||
]
|
||||
|
||||
const activeTab = computed({
|
||||
@@ -67,6 +69,9 @@ const activeTab = computed({
|
||||
<VWindowItem value="crowd-types">
|
||||
<CrowdTypesManager :org-id="orgId" />
|
||||
</VWindowItem>
|
||||
<VWindowItem value="email-branding">
|
||||
<EmailBrandingTab :org-id="orgId" />
|
||||
</VWindowItem>
|
||||
</VWindow>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -4,6 +4,11 @@ export interface Organisation {
|
||||
slug: string
|
||||
billing_status: 'trial' | 'active' | 'suspended' | 'cancelled'
|
||||
settings: Record<string, unknown> | null
|
||||
email_logo_url: string | null
|
||||
email_primary_color: string | null
|
||||
email_reply_to: string | null
|
||||
email_sender_name: string | null
|
||||
email_footer_text: string | null
|
||||
created_at: string
|
||||
}
|
||||
|
||||
@@ -19,6 +24,11 @@ export interface UpdateOrganisationPayload {
|
||||
slug?: string
|
||||
billing_status?: Organisation['billing_status']
|
||||
settings?: Record<string, unknown>
|
||||
email_logo_url?: string | null
|
||||
email_primary_color?: string | null
|
||||
email_reply_to?: string | null
|
||||
email_sender_name?: string | null
|
||||
email_footer_text?: string | null
|
||||
}
|
||||
|
||||
export interface CrowdType {
|
||||
|
||||
Reference in New Issue
Block a user