mandant-crm/frontend/pages/clients/[id]/print.vue

79 lines
2.8 KiB
Vue
Raw Permalink Normal View History

<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' })
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()))
})
</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="field in client.custom_fields ?? []" :key="field.definition_id">
<tr class="border-b border-gray-200">
<td class="py-1 text-gray-500">{{ field.label }}</td>
<td class="py-1">{{ formatValue(field) }}</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">
{{ entry.type_name ?? '—' }}<template v-if="entry.occurred_at"> {{ formatEventDateTime(entry.occurred_at) }}</template>
</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>