mandant-crm/frontend/components/client/ClientFields.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

52 lines
2 KiB
Vue

<script setup lang="ts">
import type { Client } from '~/types'
const props = defineProps<{ client: Client; editing: boolean }>()
const emit = defineEmits<{ save: [notes: Record<string, string>] }>()
const localNotes = ref<Record<string, string>>({ ...props.client.notes })
const newKey = ref('')
const newVal = ref('')
const addField = () => {
if (!newKey.value.trim()) return
localNotes.value[newKey.value.trim()] = newVal.value
newKey.value = ''
newVal.value = ''
}
const removeField = (key: string) => {
const copy = { ...localNotes.value }
delete copy[key]
localNotes.value = copy
}
</script>
<template>
<div>
<div v-if="!editing" class="space-y-1">
<div v-for="(val, key) in client.notes" :key="key" class="flex gap-4 text-sm">
<span class="text-gray-500 w-40 shrink-0">{{ key }}</span>
<span class="text-gray-800">{{ val }}</span>
</div>
<p v-if="!Object.keys(client.notes ?? {}).length" class="text-sm text-gray-400 italic">
Keine Felder konfiguriert.
</p>
</div>
<div v-else class="space-y-2">
<div v-for="(val, key) in localNotes" :key="key" class="flex gap-2 items-center text-sm">
<span class="text-gray-600 w-40 shrink-0">{{ key }}</span>
<input v-model="localNotes[key]" class="flex-1 border border-gray-300 px-2 py-1 text-sm" />
<button @click="removeField(key)" class="text-red-500 text-xs hover:underline">Entfernen</button>
</div>
<div class="flex gap-2 items-center">
<input v-model="newKey" placeholder="Feldname" class="w-40 border border-gray-300 px-2 py-1 text-sm" />
<input v-model="newVal" placeholder="Wert" class="flex-1 border border-gray-300 px-2 py-1 text-sm" />
<button type="button" @click="addField" class="text-sm text-blue-600 hover:underline">Hinzufügen</button>
</div>
<button @click="emit('save', localNotes)" class="bg-blue-600 text-white px-3 py-1.5 text-sm hover:bg-blue-700">
Felder speichern
</button>
</div>
</div>
</template>