mandant-crm/frontend/pages/clients/[id]/print.vue
Tim Stollberg e5e0be57da 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 17:33:39 +07:00

73 lines
2.3 KiB
Vue

<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 labelMap: Record<string, string> = {
phone_call: 'Telefonat',
consultation: 'Beratungsgespräch',
recommendation: 'Empfehlung',
instruction: 'Anweisung',
remark: 'Bemerkung',
other: 'Sonstiges',
}
const formatDate = (iso: string) =>
new Date(iso).toLocaleString('de-DE', { dateStyle: 'short', timeStyle: 'short' })
onMounted(() => {
window.print()
})
</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>
<template v-for="(val, key) in client.notes" :key="key">
<tr class="border-b border-gray-200">
<td class="py-1 text-gray-500">{{ key }}</td>
<td class="py-1">{{ val }}</td>
</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">
<span class="font-medium text-gray-700">{{ labelMap[entry.type] ?? entry.type }}</span>
<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>