feat: enhance contact management UI with improved layout and validation messages

This commit is contained in:
olli 2025-11-09 11:50:30 +01:00
parent 6f971be904
commit 45232be689

View File

@ -192,59 +192,44 @@
<!-- Basisdaten --> <!-- Basisdaten -->
<Card class="mb-3"> <Card class="mb-3">
<template #title> <template #title>
<div class="flex align-items-center gap-2"> <div class="flex items-center gap-2">
<i class="pi pi-building text-primary"></i> <i class="pi pi-building text-primary"></i>
<span>Basisdaten</span> <span>Basisdaten</span>
</div> </div>
</template> </template>
<template #content> <template #content>
<div class="formgrid grid"> <div class="flex flex-col gap-4">
<div class="field col-12 md:col-8"> <div class="flex flex-col md:flex-row gap-4">
<label for="companyName" class="block mb-2 font-medium"> <div class="flex flex-col gap-2 w-full md:w-2/3">
Firmenname <span class="text-red-500">*</span> <label for="companyName">Firmenname <span class="text-red-500">*</span></label>
</label> <InputText
<InputText id="companyName"
id="companyName" v-model="editingContact.companyName"
v-model="editingContact.companyName" :invalid="submitted && !editingContact.companyName"
class="w-full" />
:class="{ 'p-invalid': submitted && !editingContact.companyName }" <small v-if="submitted && !editingContact.companyName" class="text-red-500">
/> Firmenname ist erforderlich
<small v-if="submitted && !editingContact.companyName" class="p-error"> </small>
Firmenname ist erforderlich </div>
</small>
<div class="flex flex-col gap-2 w-full md:w-1/3">
<label for="companyNumber">Kundennummer</label>
<InputText id="companyNumber" v-model="editingContact.companyNumber" />
</div>
</div> </div>
<div class="field col-12 md:col-4"> <div class="flex gap-4">
<label for="companyNumber" class="block mb-2 font-medium">Kundennummer</label> <div class="flex items-center gap-2">
<InputText id="companyNumber" v-model="editingContact.companyNumber" class="w-full" /> <Checkbox inputId="isDebtor" v-model="editingContact.isDebtor" :binary="true" />
</div> <label for="isDebtor">Debitor</label>
</div>
<div class="field col-12"> <div class="flex items-center gap-2">
<div class="flex gap-4"> <Checkbox inputId="isCreditor" v-model="editingContact.isCreditor" :binary="true" />
<div class="field-checkbox mb-0"> <label for="isCreditor">Kreditor</label>
<Checkbox </div>
inputId="isDebtor" <div class="flex items-center gap-2">
v-model="editingContact.isDebtor" <Checkbox inputId="isActive" v-model="editingContact.isActive" :binary="true" />
:binary="true" <label for="isActive">Aktiv</label>
/>
<label for="isDebtor" class="ml-2">Debitor</label>
</div>
<div class="field-checkbox mb-0">
<Checkbox
inputId="isCreditor"
v-model="editingContact.isCreditor"
:binary="true"
/>
<label for="isCreditor" class="ml-2">Kreditor</label>
</div>
<div class="field-checkbox mb-0">
<Checkbox
inputId="isActive"
v-model="editingContact.isActive"
:binary="true"
/>
<label for="isActive" class="ml-2">Aktiv</label>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -254,31 +239,33 @@
<!-- Adresse --> <!-- Adresse -->
<Card class="mb-3"> <Card class="mb-3">
<template #title> <template #title>
<div class="flex align-items-center gap-2"> <div class="flex items-center gap-2">
<i class="pi pi-map-marker text-primary"></i> <i class="pi pi-map-marker text-primary"></i>
<span>Adresse</span> <span>Adresse</span>
</div> </div>
</template> </template>
<template #content> <template #content>
<div class="formgrid grid"> <div class="flex flex-col gap-4">
<div class="field col-12"> <div class="flex flex-col gap-2">
<label for="street" class="block mb-2 font-medium">Straße</label> <label for="street">Straße</label>
<InputText id="street" v-model="editingContact.street" class="w-full" /> <InputText id="street" v-model="editingContact.street" />
</div> </div>
<div class="field col-12 md:col-3"> <div class="flex flex-col md:flex-row gap-4">
<label for="zipCode" class="block mb-2 font-medium">PLZ</label> <div class="flex flex-col gap-2 w-full md:w-1/4">
<InputText id="zipCode" v-model="editingContact.zipCode" class="w-full" /> <label for="zipCode">PLZ</label>
</div> <InputText id="zipCode" v-model="editingContact.zipCode" />
</div>
<div class="field col-12 md:col-5"> <div class="flex flex-col gap-2 w-full md:w-1/2">
<label for="city" class="block mb-2 font-medium">Ort</label> <label for="city">Ort</label>
<InputText id="city" v-model="editingContact.city" class="w-full" /> <InputText id="city" v-model="editingContact.city" />
</div> </div>
<div class="field col-12 md:col-4"> <div class="flex flex-col gap-2 w-full md:w-1/4">
<label for="country" class="block mb-2 font-medium">Land</label> <label for="country">Land</label>
<InputText id="country" v-model="editingContact.country" class="w-full" /> <InputText id="country" v-model="editingContact.country" />
</div>
</div> </div>
</div> </div>
</template> </template>
@ -287,31 +274,35 @@
<!-- Kontaktdaten --> <!-- Kontaktdaten -->
<Card class="mb-3"> <Card class="mb-3">
<template #title> <template #title>
<div class="flex align-items-center gap-2"> <div class="flex items-center gap-2">
<i class="pi pi-phone text-primary"></i> <i class="pi pi-phone text-primary"></i>
<span>Kontaktdaten</span> <span>Kontaktdaten</span>
</div> </div>
</template> </template>
<template #content> <template #content>
<div class="formgrid grid"> <div class="flex flex-col gap-4">
<div class="field col-12 md:col-6"> <div class="flex flex-col md:flex-row gap-4">
<label for="phone" class="block mb-2 font-medium">Telefon</label> <div class="flex flex-col gap-2 w-full">
<InputText id="phone" v-model="editingContact.phone" class="w-full" /> <label for="phone">Telefon</label>
<InputText id="phone" v-model="editingContact.phone" />
</div>
<div class="flex flex-col gap-2 w-full">
<label for="fax">Fax</label>
<InputText id="fax" v-model="editingContact.fax" />
</div>
</div> </div>
<div class="field col-12 md:col-6"> <div class="flex flex-col md:flex-row gap-4">
<label for="fax" class="block mb-2 font-medium">Fax</label> <div class="flex flex-col gap-2 w-full">
<InputText id="fax" v-model="editingContact.fax" class="w-full" /> <label for="email">E-Mail</label>
</div> <InputText id="email" v-model="editingContact.email" type="email" />
</div>
<div class="field col-12 md:col-6"> <div class="flex flex-col gap-2 w-full">
<label for="email" class="block mb-2 font-medium">E-Mail</label> <label for="website">Website</label>
<InputText id="email" v-model="editingContact.email" type="email" class="w-full" /> <InputText id="website" v-model="editingContact.website" />
</div> </div>
<div class="field col-12 md:col-6">
<label for="website" class="block mb-2 font-medium">Website</label>
<InputText id="website" v-model="editingContact.website" class="w-full" />
</div> </div>
</div> </div>
</template> </template>
@ -320,21 +311,21 @@
<!-- Steuerdaten --> <!-- Steuerdaten -->
<Card class="mb-3"> <Card class="mb-3">
<template #title> <template #title>
<div class="flex align-items-center gap-2"> <div class="flex items-center gap-2">
<i class="pi pi-calculator text-primary"></i> <i class="pi pi-calculator text-primary"></i>
<span>Steuerdaten</span> <span>Steuerdaten</span>
</div> </div>
</template> </template>
<template #content> <template #content>
<div class="formgrid grid"> <div class="flex flex-col md:flex-row gap-4">
<div class="field col-12 md:col-6"> <div class="flex flex-col gap-2 w-full">
<label for="taxNumber" class="block mb-2 font-medium">Steuernummer</label> <label for="taxNumber">Steuernummer</label>
<InputText id="taxNumber" v-model="editingContact.taxNumber" class="w-full" /> <InputText id="taxNumber" v-model="editingContact.taxNumber" />
</div> </div>
<div class="field col-12 md:col-6"> <div class="flex flex-col gap-2 w-full">
<label for="vatNumber" class="block mb-2 font-medium">USt-IdNr.</label> <label for="vatNumber">USt-IdNr.</label>
<InputText id="vatNumber" v-model="editingContact.vatNumber" class="w-full" /> <InputText id="vatNumber" v-model="editingContact.vatNumber" />
</div> </div>
</div> </div>
</template> </template>
@ -343,8 +334,8 @@
<!-- Ansprechpartner --> <!-- Ansprechpartner -->
<Card class="mb-3"> <Card class="mb-3">
<template #title> <template #title>
<div class="flex align-items-center justify-content-between"> <div class="flex items-center justify-between">
<div class="flex align-items-center gap-2"> <div class="flex items-center gap-2">
<i class="pi pi-users text-primary"></i> <i class="pi pi-users text-primary"></i>
<span>Ansprechpartner</span> <span>Ansprechpartner</span>
</div> </div>
@ -370,8 +361,8 @@
class="mb-4" class="mb-4"
> >
<Divider v-if="index > 0" /> <Divider v-if="index > 0" />
<div class="formgrid grid"> <div class="flex flex-col gap-4">
<div class="field col-12 flex justify-content-between align-items-center mb-3"> <div class="flex justify-between items-center mb-3">
<h4 class="m-0 font-semibold"> <h4 class="m-0 font-semibold">
<i class="pi pi-user mr-2"></i> <i class="pi pi-user mr-2"></i>
Ansprechpartner {{ index + 1 }} Ansprechpartner {{ index + 1 }}
@ -387,105 +378,85 @@
/> />
</div> </div>
<div class="field col-12 md:col-3"> <div class="flex flex-col md:flex-row gap-4">
<label :for="'salutation-' + index" class="block mb-2 font-medium"> <div class="flex flex-col gap-2 w-full md:w-1/4">
Anrede <label :for="'salutation-' + index">Anrede</label>
</label> <Dropdown
<Dropdown :id="'salutation-' + index"
:id="'salutation-' + index" v-model="person.salutation"
v-model="person.salutation" :options="salutations"
:options="salutations" placeholder="Wählen..."
placeholder="Wählen..."
class="w-full"
/>
</div>
<div class="field col-12 md:col-3">
<label :for="'title-' + index" class="block mb-2 font-medium">Titel</label>
<InputText :id="'title-' + index" v-model="person.title" class="w-full" />
</div>
<div class="field col-12 md:col-3">
<label :for="'firstName-' + index" class="block mb-2 font-medium">
Vorname <span class="text-red-500">*</span>
</label>
<InputText
:id="'firstName-' + index"
v-model="person.firstName"
class="w-full"
:class="{ 'p-invalid': submitted && !person.firstName }"
/>
</div>
<div class="field col-12 md:col-3">
<label :for="'lastName-' + index" class="block mb-2 font-medium">
Nachname <span class="text-red-500">*</span>
</label>
<InputText
:id="'lastName-' + index"
v-model="person.lastName"
class="w-full"
:class="{ 'p-invalid': submitted && !person.lastName }"
/>
</div>
<div class="field col-12 md:col-6">
<label :for="'position-' + index" class="block mb-2 font-medium">
Position
</label>
<InputText :id="'position-' + index" v-model="person.position" class="w-full" />
</div>
<div class="field col-12 md:col-6">
<label :for="'department-' + index" class="block mb-2 font-medium">
Abteilung
</label>
<InputText
:id="'department-' + index"
v-model="person.department"
class="w-full"
/>
</div>
<div class="field col-12 md:col-4">
<label :for="'personPhone-' + index" class="block mb-2 font-medium">
Telefon
</label>
<InputText
:id="'personPhone-' + index"
v-model="person.phone"
class="w-full"
/>
</div>
<div class="field col-12 md:col-4">
<label :for="'mobile-' + index" class="block mb-2 font-medium">Mobil</label>
<InputText :id="'mobile-' + index" v-model="person.mobile" class="w-full" />
</div>
<div class="field col-12 md:col-4">
<label :for="'personEmail-' + index" class="block mb-2 font-medium">
E-Mail
</label>
<InputText
:id="'personEmail-' + index"
v-model="person.email"
type="email"
class="w-full"
/>
</div>
<div class="field col-12">
<div class="field-checkbox mb-0">
<Checkbox
:inputId="'isPrimary-' + index"
v-model="person.isPrimary"
:binary="true"
/> />
<label :for="'isPrimary-' + index" class="ml-2">
Hauptansprechpartner
</label>
</div> </div>
<div class="flex flex-col gap-2 w-full md:w-1/4">
<label :for="'title-' + index">Titel</label>
<InputText :id="'title-' + index" v-model="person.title" />
</div>
<div class="flex flex-col gap-2 w-full md:w-1/4">
<label :for="'firstName-' + index">
Vorname <span class="text-red-500">*</span>
</label>
<InputText
:id="'firstName-' + index"
v-model="person.firstName"
:invalid="submitted && !person.firstName"
/>
</div>
<div class="flex flex-col gap-2 w-full md:w-1/4">
<label :for="'lastName-' + index">
Nachname <span class="text-red-500">*</span>
</label>
<InputText
:id="'lastName-' + index"
v-model="person.lastName"
:invalid="submitted && !person.lastName"
/>
</div>
</div>
<div class="flex flex-col md:flex-row gap-4">
<div class="flex flex-col gap-2 w-full">
<label :for="'position-' + index">Position</label>
<InputText :id="'position-' + index" v-model="person.position" />
</div>
<div class="flex flex-col gap-2 w-full">
<label :for="'department-' + index">Abteilung</label>
<InputText :id="'department-' + index" v-model="person.department" />
</div>
</div>
<div class="flex flex-col md:flex-row gap-4">
<div class="flex flex-col gap-2 w-full">
<label :for="'personPhone-' + index">Telefon</label>
<InputText :id="'personPhone-' + index" v-model="person.phone" />
</div>
<div class="flex flex-col gap-2 w-full">
<label :for="'mobile-' + index">Mobil</label>
<InputText :id="'mobile-' + index" v-model="person.mobile" />
</div>
<div class="flex flex-col gap-2 w-full">
<label :for="'personEmail-' + index">E-Mail</label>
<InputText
:id="'personEmail-' + index"
v-model="person.email"
type="email"
/>
</div>
</div>
<div class="flex items-center gap-2">
<Checkbox
:inputId="'isPrimary-' + index"
v-model="person.isPrimary"
:binary="true"
/>
<label :for="'isPrimary-' + index">Hauptansprechpartner</label>
</div> </div>
</div> </div>
</div> </div>
@ -495,19 +466,21 @@
<!-- Notizen --> <!-- Notizen -->
<Card> <Card>
<template #title> <template #title>
<div class="flex align-items-center gap-2"> <div class="flex items-center gap-2">
<i class="pi pi-comment text-primary"></i> <i class="pi pi-comment text-primary"></i>
<span>Notizen</span> <span>Notizen</span>
</div> </div>
</template> </template>
<template #content> <template #content>
<Textarea <div class="flex flex-col gap-2">
id="notes" <label for="notes">Interne Notizen zu diesem Kontakt</label>
v-model="editingContact.notes" <Textarea
class="w-full" id="notes"
:rows="4" v-model="editingContact.notes"
placeholder="Interne Notizen zu diesem Kontakt..." :rows="4"
/> placeholder="Interne Notizen..."
/>
</div>
</template> </template>
</Card> </Card>
</div> </div>