feat(frontend): scaffold Nuxt 3 CSR SPA with full auth + client/history UI
- Nuxt 3 CSR (ssr:false), @nuxtjs/tailwindcss, dev proxy to backend
- useAuth composable: CSRF cookie, XSRF token, login/logout/fetchUser
- auth middleware: redirects to /login if no session
- Login page, client list with search + create modal
- Client detail with editable name, dynamic notes (JSON), history feed
- History form with type select, inline edit/delete per entry
- Print layout at /clients/:id/print (calls window.print on mount)
- TypeScript interfaces: User, Client, HistoryEntry, PaginatedResponse
- German UI labels throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 10:33:39 +00:00
|
|
|
|
<script setup lang="ts">
|
|
|
|
|
|
import type { Client, HistoryEntry } from '~/types'
|
|
|
|
|
|
|
|
|
|
|
|
definePageMeta({ middleware: 'auth' })
|
|
|
|
|
|
|
|
|
|
|
|
const route = useRoute()
|
|
|
|
|
|
const clientId = Number(route.params.id)
|
|
|
|
|
|
|
|
|
|
|
|
const { fetchClient } = useClient()
|
|
|
|
|
|
const { entries, fetchEntries } = useHistory(clientId)
|
|
|
|
|
|
|
|
|
|
|
|
const client = ref<Client | null>(null)
|
|
|
|
|
|
client.value = await fetchClient(clientId)
|
|
|
|
|
|
await fetchEntries()
|
|
|
|
|
|
|
|
|
|
|
|
const formatDate = (iso: string) =>
|
|
|
|
|
|
new Date(iso).toLocaleString('de-DE', { dateStyle: 'short', timeStyle: 'short' })
|
|
|
|
|
|
|
feat(frontend): commit uncommitted settings, custom fields, and import work
This local working tree had accumulated a substantial amount of
finished-but-never-committed frontend work: custom client fields
(replacing the old static ClientFields with a dynamic
ClientCustomFieldCard + useCustomFields), CSV import
(useImport + settings/import page), history type management
(useHistoryTypes + settings/history-types page), an admin-only route
middleware, several new icon components, a shared useApiFetch
composable, and a client detail page restructure ([id].vue ->
[id]/index.vue). None of it had ever been pushed, so production was
running a stale build that was already linking to routes/components
that didn't exist server-side (missing IconSettings, 404s on
/settings/import, etc). This commit brings the repo in line with
local state.
2026-07-18 09:27:19 +00:00
|
|
|
|
const formatValue = (field: { type: string; value: string | null }) => {
|
|
|
|
|
|
if (field.value === null || field.value === '') return '—'
|
|
|
|
|
|
if (field.type === 'date') {
|
|
|
|
|
|
const d = new Date(field.value)
|
|
|
|
|
|
return Number.isNaN(d.getTime()) ? field.value : d.toLocaleDateString('de-DE', { dateStyle: 'medium' })
|
|
|
|
|
|
}
|
|
|
|
|
|
return field.value
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
onMounted(async () => {
|
|
|
|
|
|
// Wait for the freshly navigated DOM to render and paint before opening the
|
|
|
|
|
|
// print dialog, otherwise the preview can capture a blank page.
|
|
|
|
|
|
await nextTick()
|
|
|
|
|
|
requestAnimationFrame(() => requestAnimationFrame(() => window.print()))
|
feat(frontend): scaffold Nuxt 3 CSR SPA with full auth + client/history UI
- Nuxt 3 CSR (ssr:false), @nuxtjs/tailwindcss, dev proxy to backend
- useAuth composable: CSRF cookie, XSRF token, login/logout/fetchUser
- auth middleware: redirects to /login if no session
- Login page, client list with search + create modal
- Client detail with editable name, dynamic notes (JSON), history feed
- History form with type select, inline edit/delete per entry
- Print layout at /clients/:id/print (calls window.print on mount)
- TypeScript interfaces: User, Client, HistoryEntry, PaginatedResponse
- German UI labels throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 10:33:39 +00:00
|
|
|
|
})
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<template>
|
|
|
|
|
|
<div v-if="client" class="print-page p-8 max-w-3xl mx-auto font-sans text-sm text-gray-900">
|
|
|
|
|
|
<h1 class="text-lg font-bold mb-1">Mandantenakte</h1>
|
|
|
|
|
|
<p class="text-gray-500 mb-6 text-xs">Gedruckt: {{ new Date().toLocaleString('de-DE') }}</p>
|
|
|
|
|
|
|
|
|
|
|
|
<table class="w-full mb-6 border-collapse text-sm">
|
|
|
|
|
|
<tr class="border-b border-gray-200">
|
|
|
|
|
|
<td class="py-1 text-gray-500 w-40">Mandantennummer</td>
|
|
|
|
|
|
<td class="py-1 font-mono">{{ client.client_number }}</td>
|
|
|
|
|
|
</tr>
|
|
|
|
|
|
<tr class="border-b border-gray-200">
|
|
|
|
|
|
<td class="py-1 text-gray-500">Name</td>
|
|
|
|
|
|
<td class="py-1">{{ client.name }}</td>
|
|
|
|
|
|
</tr>
|
feat(frontend): commit uncommitted settings, custom fields, and import work
This local working tree had accumulated a substantial amount of
finished-but-never-committed frontend work: custom client fields
(replacing the old static ClientFields with a dynamic
ClientCustomFieldCard + useCustomFields), CSV import
(useImport + settings/import page), history type management
(useHistoryTypes + settings/history-types page), an admin-only route
middleware, several new icon components, a shared useApiFetch
composable, and a client detail page restructure ([id].vue ->
[id]/index.vue). None of it had ever been pushed, so production was
running a stale build that was already linking to routes/components
that didn't exist server-side (missing IconSettings, 404s on
/settings/import, etc). This commit brings the repo in line with
local state.
2026-07-18 09:27:19 +00:00
|
|
|
|
<template v-for="field in client.custom_fields ?? []" :key="field.definition_id">
|
feat(frontend): scaffold Nuxt 3 CSR SPA with full auth + client/history UI
- Nuxt 3 CSR (ssr:false), @nuxtjs/tailwindcss, dev proxy to backend
- useAuth composable: CSRF cookie, XSRF token, login/logout/fetchUser
- auth middleware: redirects to /login if no session
- Login page, client list with search + create modal
- Client detail with editable name, dynamic notes (JSON), history feed
- History form with type select, inline edit/delete per entry
- Print layout at /clients/:id/print (calls window.print on mount)
- TypeScript interfaces: User, Client, HistoryEntry, PaginatedResponse
- German UI labels throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 10:33:39 +00:00
|
|
|
|
<tr class="border-b border-gray-200">
|
feat(frontend): commit uncommitted settings, custom fields, and import work
This local working tree had accumulated a substantial amount of
finished-but-never-committed frontend work: custom client fields
(replacing the old static ClientFields with a dynamic
ClientCustomFieldCard + useCustomFields), CSV import
(useImport + settings/import page), history type management
(useHistoryTypes + settings/history-types page), an admin-only route
middleware, several new icon components, a shared useApiFetch
composable, and a client detail page restructure ([id].vue ->
[id]/index.vue). None of it had ever been pushed, so production was
running a stale build that was already linking to routes/components
that didn't exist server-side (missing IconSettings, 404s on
/settings/import, etc). This commit brings the repo in line with
local state.
2026-07-18 09:27:19 +00:00
|
|
|
|
<td class="py-1 text-gray-500">{{ field.label }}</td>
|
|
|
|
|
|
<td class="py-1">{{ formatValue(field) }}</td>
|
feat(frontend): scaffold Nuxt 3 CSR SPA with full auth + client/history UI
- Nuxt 3 CSR (ssr:false), @nuxtjs/tailwindcss, dev proxy to backend
- useAuth composable: CSRF cookie, XSRF token, login/logout/fetchUser
- auth middleware: redirects to /login if no session
- Login page, client list with search + create modal
- Client detail with editable name, dynamic notes (JSON), history feed
- History form with type select, inline edit/delete per entry
- Print layout at /clients/:id/print (calls window.print on mount)
- TypeScript interfaces: User, Client, HistoryEntry, PaginatedResponse
- German UI labels throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 10:33:39 +00:00
|
|
|
|
</tr>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
</table>
|
|
|
|
|
|
|
|
|
|
|
|
<h2 class="font-semibold mb-3">Verlauf</h2>
|
|
|
|
|
|
<div v-for="entry in entries" :key="entry.id" class="mb-4 border-t border-gray-200 pt-3">
|
|
|
|
|
|
<div class="flex gap-3 text-xs text-gray-500 mb-1">
|
feat(frontend): commit uncommitted settings, custom fields, and import work
This local working tree had accumulated a substantial amount of
finished-but-never-committed frontend work: custom client fields
(replacing the old static ClientFields with a dynamic
ClientCustomFieldCard + useCustomFields), CSV import
(useImport + settings/import page), history type management
(useHistoryTypes + settings/history-types page), an admin-only route
middleware, several new icon components, a shared useApiFetch
composable, and a client detail page restructure ([id].vue ->
[id]/index.vue). None of it had ever been pushed, so production was
running a stale build that was already linking to routes/components
that didn't exist server-side (missing IconSettings, 404s on
/settings/import, etc). This commit brings the repo in line with
local state.
2026-07-18 09:27:19 +00:00
|
|
|
|
<span class="font-medium text-gray-700">
|
|
|
|
|
|
{{ entry.type_name ?? '—' }}<template v-if="entry.occurred_at"> – {{ formatEventDateTime(entry.occurred_at) }}</template>
|
|
|
|
|
|
</span>
|
feat(frontend): scaffold Nuxt 3 CSR SPA with full auth + client/history UI
- Nuxt 3 CSR (ssr:false), @nuxtjs/tailwindcss, dev proxy to backend
- useAuth composable: CSRF cookie, XSRF token, login/logout/fetchUser
- auth middleware: redirects to /login if no session
- Login page, client list with search + create modal
- Client detail with editable name, dynamic notes (JSON), history feed
- History form with type select, inline edit/delete per entry
- Print layout at /clients/:id/print (calls window.print on mount)
- TypeScript interfaces: User, Client, HistoryEntry, PaginatedResponse
- German UI labels throughout
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 10:33:39 +00:00
|
|
|
|
<span>{{ formatDate(entry.created_at) }}</span>
|
|
|
|
|
|
<span>{{ entry.author_name }}</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<p class="whitespace-pre-wrap text-gray-800">{{ entry.body }}</p>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<p v-if="entries.length === 0" class="text-gray-400 italic">Keine Einträge.</p>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
|
|
<style>
|
|
|
|
|
|
@media print {
|
|
|
|
|
|
.print-page { padding: 0; }
|
|
|
|
|
|
@page { margin: 2cm; }
|
|
|
|
|
|
}
|
|
|
|
|
|
</style>
|