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

100 lines
3.5 KiB
Vue
Raw Normal View History

<script setup lang="ts">
import type { Client } from '~/types'
definePageMeta({ middleware: 'auth' })
const route = useRoute()
const clientId = Number(route.params.id)
const { fetchClient, updateClient } = useClient()
const { entries, fetchEntries, addEntry, updateEntry, deleteEntry } = useHistory(clientId)
const client = ref<Client | null>(null)
client.value = await fetchClient(clientId)
await fetchEntries()
const editingName = ref(false)
const editName = ref(client.value?.name ?? '')
const editingFields = ref(false)
const saveName = async () => {
if (!client.value) return
client.value = await updateClient(clientId, { name: editName.value })
editingName.value = false
}
const saveFields = async (notes: Record<string, string>) => {
if (!client.value) return
client.value = await updateClient(clientId, { notes })
editingFields.value = false
}
const onAddEntry = async (payload: { type: string; body: string }) => {
await addEntry(payload)
}
const onUpdateEntry = async (id: number, body: string) => {
await updateEntry(id, body)
}
const onDeleteEntry = async (id: number) => {
if (!confirm('Eintrag wirklich löschen?')) return
await deleteEntry(id)
}
</script>
<template>
<div v-if="client" class="min-h-screen bg-gray-50">
<header class="bg-white border-b border-gray-200 px-6 py-3 flex items-center gap-4">
<NuxtLink to="/clients" class="text-sm text-blue-600 hover:underline"> Alle Mandanten</NuxtLink>
<h1 class="text-base font-semibold text-gray-800">
<span class="font-mono text-gray-500">{{ client.client_number }}</span>
<span class="mx-2 text-gray-400">·</span>
<span v-if="!editingName">{{ client.name }}</span>
<span v-else class="inline-flex gap-2 items-center">
<input v-model="editName" class="border border-gray-300 px-2 py-0.5 text-sm" />
<button @click="saveName" class="text-sm bg-blue-600 text-white px-2 py-0.5 hover:bg-blue-700">OK</button>
<button @click="editingName = false" class="text-sm text-gray-500">Abbrechen</button>
</span>
</h1>
<button v-if="!editingName" @click="editingName = true" class="text-xs text-gray-400 hover:text-gray-600">
Name ändern
</button>
<NuxtLink :to="`/clients/${clientId}/print`" class="ml-auto text-sm text-gray-500 hover:underline">
Drucken
</NuxtLink>
</header>
<div class="max-w-4xl mx-auto py-6 px-6 space-y-6">
<!-- Configurable fields -->
<section class="bg-white border border-gray-200 p-4">
<div class="flex items-center justify-between mb-3">
<h2 class="text-sm font-semibold text-gray-700">Stammdaten</h2>
<button @click="editingFields = !editingFields" class="text-xs text-blue-600 hover:underline">
{{ editingFields ? 'Abbrechen' : 'Bearbeiten' }}
</button>
</div>
<ClientFields :client="client" :editing="editingFields" @save="saveFields" />
</section>
<!-- History -->
<section>
<h2 class="text-sm font-semibold text-gray-700 mb-3">Verlauf</h2>
<HistoryForm @submit="onAddEntry" />
<div class="mt-3 space-y-2">
<HistoryEntry
v-for="entry in entries"
:key="entry.id"
:entry="entry"
@update="onUpdateEntry"
@delete="onDeleteEntry"
/>
<p v-if="entries.length === 0" class="text-sm text-gray-400 italic py-4 text-center">
Noch keine Einträge.
</p>
</div>
</section>
</div>
</div>
</template>