chore(portal,operator): upgrade to Nuxt 4

Upgrade both Nuxt apps to Nuxt 4.4.6 (vue-tsc 3, TypeScript 5.6, undici 7) and add a root tsconfig.json to each app. Fix the strict-null / noUncheckedIndexedAccess errors surfaced by Nuxt 4's stricter generated tsconfig and vue-tsc 3. Drop the nuxt-oidc-auth pnpm patch (Nuxt 4 fixes the prepare:types crash natively).
This commit is contained in:
Ronni Baslund
2026-05-30 08:02:43 +02:00
parent 0bd4e5498e
commit 17ffd95a70
25 changed files with 888 additions and 706 deletions
+2 -2
View File
@@ -302,9 +302,9 @@ function confirmPause() {
<div class="lead">Pick a new tier. We'll prorate the difference and apply it on your next invoice.</div>
<div class="plan-options">
<button v-for="p in [
{ id: 'basic', name: 'Basic', price: '49 DKK / seat / mo', d: 'Mail · Drev · 50 GB' },
{ id: 'basic', name: 'Basic', price: '49 DKK / seat / mo', d: 'Mail · Drev · 50 GB', current: false },
{ id: 'business', name: 'Business · current', price: '78 DKK / seat / mo', d: 'Everything in Basic + Møder + Chat · 200 GB', current: true },
{ id: 'enterprise', name: 'Enterprise', price: 'from 140 DKK / seat / mo', d: 'SSO contracts · audit log retention · 1 TB' },
{ id: 'enterprise', name: 'Enterprise', price: 'from 140 DKK / seat / mo', d: 'SSO contracts · audit log retention · 1 TB', current: false },
]" :key="p.id" :class="['plan-card', { active: p.current }]">
<div class="plan-name">{{ p.name }}</div>
<Mono dim>{{ p.price }}</Mono>
+5 -1
View File
@@ -18,6 +18,10 @@ const editTemplate = ref<typeof TEMPLATES[number] | null>(null)
const subject = ref('')
const body = ref('')
const testSent = ref(false)
function sendTest() {
testSent.value = true
setTimeout(() => (testSent.value = false), 2500)
}
const publishOpen = ref(false)
const publishState = ref<'confirm' | 'publishing' | 'done'>('confirm')
@@ -384,7 +388,7 @@ const renderedBody = computed(() =>
Reset to default
</UiButton>
<div style="flex: 1" />
<UiButton variant="secondary" @click="testSent = true; setTimeout(() => testSent = false, 2500)">
<UiButton variant="secondary" @click="sendTest">
<template #leading><UiIcon name="mail" :size="13" /></template>
{{ testSent ? 'Sent to anne@dezky.com ✓' : 'Send test to me' }}
</UiButton>
+12 -6
View File
@@ -17,12 +17,18 @@ const inviteStep = ref(1)
const seatsOpen = ref(false)
const seatsExtra = ref(5)
const stats = [
{ label: 'Seats used', value: '11 / 25', delta: '+2 this week', deltaTone: 'up' as const, hint: '' },
{ label: 'Storage', value: '1.4 TB', delta: '64% of 2.2 TB', hint: '' },
{ label: 'Mail flow', value: 'Healthy', hint: '99.98% · last 7d' },
{ label: 'Monthly spend', value: '1.940 DKK', hint: 'next invoice 01 Jun' },
] as const
const stats: Array<{
label: string
value: string
delta?: string
deltaTone?: 'up' | 'down'
hint: string
}> = [
{ label: 'Seats used', value: '11 / 25', delta: '+2 this week', deltaTone: 'up', hint: '' },
{ label: 'Storage', value: '1.4 TB', delta: '64% of 2.2 TB', hint: '' },
{ label: 'Mail flow', value: 'Healthy', hint: '99.98% · last 7d' },
{ label: 'Monthly spend', value: '1.940 DKK', hint: 'next invoice 01 Jun' },
]
const recent = sampleAudit.slice(0, 6)
+1 -1
View File
@@ -605,7 +605,7 @@ Mikkel Sørensen,mikkel@baslund.dk,admin,Engineering,business</pre>
<label v-for="r in ['member', 'admin', 'owner'] as const" :key="r" class="role-row" :class="{ active: roleChoice === r }">
<input type="radio" :value="r" v-model="roleChoice" />
<div>
<div class="role-name">{{ r[0].toUpperCase() + r.slice(1) }}</div>
<div class="role-name">{{ r.charAt(0).toUpperCase() + r.slice(1) }}</div>
<Mono dim>
{{ r === 'member' ? 'Standard access to apps' :
r === 'admin' ? 'Manage users, billing, and settings' :