0bd4e5498e
- portal: new admin/ and partner/ surfaces with full component library (AppLauncher, Avatar, Badge, Card, Modal, Tabs, etc.), composables, layouts, partner-routing middleware, and supporting server APIs - pricing: Price schema/module with operator CRUD, pricing.vue catalog UI, Subscription extended with cycle/currency/perSeatAmount/seats snapshots for stable MRR aggregation - partner staff: User.partnerId, invite-partner-user DTO and flow, /partners/:slug/users endpoints, InvitePartnerUserModal, shared dezky-partner-staff Authentik group - /me: partner-aware endpoint returning user + partner context so portal can route between end-user and partner-admin surfaces - tenant: seats field for portfolio displays and future MRR calculations - operator: pricing page, signed-out page, useMe/useToast composables, ToastStack
87 lines
1.8 KiB
Vue
87 lines
1.8 KiB
Vue
<script setup lang="ts">
|
|
definePageMeta({ auth: false, layout: 'blank' })
|
|
|
|
const route = useRoute()
|
|
const accountEmail = computed(() => (route.query.email as string) || 'this account')
|
|
</script>
|
|
|
|
<template>
|
|
<AuthShell>
|
|
<div class="badge" data-tone="bad">
|
|
<UiIcon name="shield" :size="28" />
|
|
</div>
|
|
<AuthHeading
|
|
eyebrow="Access denied"
|
|
title="This account is suspended"
|
|
>
|
|
<template #body>
|
|
The account <b>{{ accountEmail }}</b> has been suspended by a workspace admin.
|
|
Contact them if you think this is wrong.
|
|
</template>
|
|
</AuthHeading>
|
|
|
|
<div class="admin-card">
|
|
<div class="admin-eyebrow">Workspace admin</div>
|
|
<div class="admin-name">Your administrator</div>
|
|
<div class="admin-email">contact via your organization</div>
|
|
</div>
|
|
|
|
<AuthButton variant="dark">
|
|
<template #leading>
|
|
<UiIcon name="mail" :size="14" />
|
|
</template>
|
|
Email your admin
|
|
</AuthButton>
|
|
|
|
<AuthFooterLink>
|
|
<NuxtLink to="/auth/login">← sign in with a different account</NuxtLink>
|
|
</AuthFooterLink>
|
|
</AuthShell>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.badge {
|
|
width: 56px;
|
|
height: 56px;
|
|
border-radius: 14px;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
margin: 0 0 18px 0;
|
|
}
|
|
|
|
.badge[data-tone='bad'] {
|
|
background: rgba(226, 48, 48, 0.1);
|
|
color: var(--bad);
|
|
}
|
|
|
|
.admin-card {
|
|
padding: 14px;
|
|
background: var(--bg);
|
|
border: 1px solid var(--border);
|
|
border-radius: 6px;
|
|
margin-bottom: 18px;
|
|
}
|
|
|
|
.admin-eyebrow {
|
|
font-family: var(--font-mono);
|
|
font-size: 10px;
|
|
color: var(--text-mute);
|
|
letter-spacing: 0.12em;
|
|
text-transform: uppercase;
|
|
margin-bottom: 6px;
|
|
}
|
|
|
|
.admin-name {
|
|
font-size: 13px;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.admin-email {
|
|
font-family: var(--font-mono);
|
|
font-size: 12px;
|
|
color: var(--text-dim);
|
|
margin-top: 2px;
|
|
}
|
|
</style>
|