feat(contacts): Anrede + Titel als getrennte Dropdowns

Anrede: Herr/Frau/Divers (fest), Titel: Dr./Prof./Dipl.-Ing./... (editierbar).
Beim Speichern werden beide zu vCard-PREFIX zusammengesetzt, beim Laden
wieder aufgesplittet.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Stefan Hacker 2026-04-13 09:37:41 +02:00
parent 50df055794
commit 655b789e06
1 changed files with 31 additions and 4 deletions

View File

@ -175,9 +175,14 @@
</div>
<div class="field-row">
<div class="field" style="max-width:140px">
<div class="field" style="max-width:130px">
<label>Anrede</label>
<Select v-model="contactForm.prefix" :options="prefixOptions"
<Select v-model="contactForm._salutation" :options="salutationOptions"
showClear placeholder="" />
</div>
<div class="field" style="max-width:160px">
<label>Titel</label>
<Select v-model="contactForm._title" :options="titleOptions"
editable showClear placeholder="" />
</div>
<div class="field">
@ -410,11 +415,27 @@ const urlTypes = [
{ label: 'Privat', value: 'home' }, { label: 'Geschäftlich', value: 'work' },
{ label: 'Sonstige', value: 'other' },
]
const prefixOptions = ['Herr', 'Frau', 'Divers', 'Dr.', 'Prof.']
const salutationOptions = ['Herr', 'Frau', 'Divers']
const titleOptions = ['Dr.', 'Dr. med.', 'Dr.-Ing.', 'Prof.', 'Prof. Dr.', 'Dipl.-Ing.', 'Dipl.-Kfm.', 'Mag.', 'M.Sc.', 'B.Sc.']
function splitPrefix(prefix) {
// "Herr Dr." -> { salutation: 'Herr', title: 'Dr.' }
const s = (prefix || '').trim()
if (!s) return { salutation: '', title: '' }
for (const sal of salutationOptions) {
if (s === sal) return { salutation: sal, title: '' }
if (s.startsWith(sal + ' ')) return { salutation: sal, title: s.slice(sal.length + 1).trim() }
}
return { salutation: '', title: s }
}
function joinPrefix(salutation, title) {
return [salutation, title].filter(x => x && x.trim()).join(' ').trim()
}
function emptyContact() {
return {
prefix: '', first_name: '', middle_name: '', last_name: '', suffix: '',
prefix: '', _salutation: '', _title: '',
first_name: '', middle_name: '', last_name: '', suffix: '',
display_name: '', nickname: '',
organization: '', department: '', job_title: '',
emails: [], phones: [], addresses: [], websites: [], impp: [], categories: [],
@ -596,8 +617,11 @@ async function openEditContact(row) {
editingContactId.value = row.id
const res = await apiClient.get(`/contacts/${row.id}`)
const c = res.data
const split = splitPrefix(c.prefix)
Object.assign(contactForm, emptyContact(), {
prefix: c.prefix || '',
_salutation: split.salutation,
_title: split.title,
first_name: c.first_name || '',
middle_name: c.middle_name || '',
last_name: c.last_name || '',
@ -638,6 +662,9 @@ function onPhotoSelected(ev) {
async function saveContact() {
const payload = { ...contactForm }
payload.prefix = joinPrefix(contactForm._salutation, contactForm._title)
delete payload._salutation
delete payload._title
payload.categories = categoriesString.value.split(',').map(s => s.trim()).filter(Boolean)
// Drop empty sub-rows
payload.emails = payload.emails.filter(e => e.value.trim())