feat: split name into first_name + last_name across users, persons, and companies
Cross-cutting migration affecting the entire stack: - Database: 3 migrations splitting name columns with data migration - Models: first_name/last_name on User, Person; contact_first_name/contact_last_name on Company; backward-compatible name accessors - API: all resources return first_name, last_name, full_name; assignablePersons endpoint updated - Requests: validation rules updated for all person/user/company forms - Services: VolunteerRegistrationService, ShiftAssignmentService, InvitationService updated - Frontend: TypeScript types, Zod schemas, all forms split into Voornaam/Achternaam fields - Display: all person/user name references use full_name; initials use first_name[0]+last_name[0] - Tests: all 371 tests passing - Docs: SCHEMA.md and API.md updated Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -21,7 +21,8 @@ const { data: companies } = useCompanies(orgIdRef)
|
||||
|
||||
const form = ref({
|
||||
crowd_type_id: '',
|
||||
name: '',
|
||||
first_name: '',
|
||||
last_name: '',
|
||||
email: '',
|
||||
phone: '',
|
||||
company_id: '',
|
||||
@@ -69,7 +70,8 @@ const statusOptions: { title: string; value: PersonStatus }[] = [
|
||||
function resetForm() {
|
||||
form.value = {
|
||||
crowd_type_id: '',
|
||||
name: '',
|
||||
first_name: '',
|
||||
last_name: '',
|
||||
email: '',
|
||||
phone: '',
|
||||
company_id: '',
|
||||
@@ -87,7 +89,8 @@ function onSubmit() {
|
||||
|
||||
const payload = {
|
||||
crowd_type_id: form.value.crowd_type_id,
|
||||
name: form.value.name,
|
||||
first_name: form.value.first_name,
|
||||
last_name: form.value.last_name,
|
||||
email: form.value.email,
|
||||
...(form.value.phone ? { phone: form.value.phone } : {}),
|
||||
...(form.value.company_id ? { company_id: form.value.company_id } : {}),
|
||||
@@ -96,7 +99,7 @@ function onSubmit() {
|
||||
|
||||
createPerson(payload, {
|
||||
onSuccess: () => {
|
||||
successName.value = form.value.name
|
||||
successName.value = `${form.value.first_name} ${form.value.last_name}`.trim()
|
||||
modelValue.value = false
|
||||
showSuccess.value = true
|
||||
},
|
||||
@@ -108,7 +111,7 @@ function onSubmit() {
|
||||
)
|
||||
}
|
||||
else if (data?.message) {
|
||||
errors.value = { name: data.message }
|
||||
errors.value = { first_name: data.message }
|
||||
}
|
||||
},
|
||||
})
|
||||
@@ -138,15 +141,29 @@ function onSubmit() {
|
||||
:error-messages="errors.crowd_type_id"
|
||||
/>
|
||||
</VCol>
|
||||
<VCol cols="12">
|
||||
<VCol
|
||||
cols="12"
|
||||
md="6"
|
||||
>
|
||||
<AppTextField
|
||||
v-model="form.name"
|
||||
label="Naam"
|
||||
v-model="form.first_name"
|
||||
label="Voornaam"
|
||||
:rules="[requiredValidator]"
|
||||
:error-messages="errors.name"
|
||||
:error-messages="errors.first_name"
|
||||
autofocus
|
||||
/>
|
||||
</VCol>
|
||||
<VCol
|
||||
cols="12"
|
||||
md="6"
|
||||
>
|
||||
<AppTextField
|
||||
v-model="form.last_name"
|
||||
label="Achternaam"
|
||||
:rules="[requiredValidator]"
|
||||
:error-messages="errors.last_name"
|
||||
/>
|
||||
</VCol>
|
||||
<VCol cols="12">
|
||||
<AppTextField
|
||||
v-model="form.email"
|
||||
|
||||
@@ -23,7 +23,8 @@ const { mutate: updatePerson, isPending } = useUpdatePerson(eventIdRef)
|
||||
|
||||
const form = ref({
|
||||
crowd_type_id: '',
|
||||
name: '',
|
||||
first_name: '',
|
||||
last_name: '',
|
||||
email: '',
|
||||
phone: '',
|
||||
company_id: '',
|
||||
@@ -39,7 +40,8 @@ const showSuccess = ref(false)
|
||||
watch(() => props.person, (p) => {
|
||||
form.value = {
|
||||
crowd_type_id: p.crowd_type?.id ?? '',
|
||||
name: p.name,
|
||||
first_name: p.first_name,
|
||||
last_name: p.last_name,
|
||||
email: p.email,
|
||||
phone: p.phone ?? '',
|
||||
company_id: p.company?.id ?? '',
|
||||
@@ -92,7 +94,8 @@ function onSubmit() {
|
||||
updatePerson({
|
||||
id: props.person.id,
|
||||
crowd_type_id: form.value.crowd_type_id,
|
||||
name: form.value.name,
|
||||
first_name: form.value.first_name,
|
||||
last_name: form.value.last_name,
|
||||
email: form.value.email,
|
||||
phone: form.value.phone || undefined,
|
||||
company_id: form.value.company_id || undefined,
|
||||
@@ -112,7 +115,7 @@ function onSubmit() {
|
||||
)
|
||||
}
|
||||
else if (data?.message) {
|
||||
errors.value = { name: data.message }
|
||||
errors.value = { first_name: data.message }
|
||||
}
|
||||
},
|
||||
})
|
||||
@@ -141,15 +144,29 @@ function onSubmit() {
|
||||
:error-messages="errors.crowd_type_id"
|
||||
/>
|
||||
</VCol>
|
||||
<VCol cols="12">
|
||||
<VCol
|
||||
cols="12"
|
||||
md="6"
|
||||
>
|
||||
<AppTextField
|
||||
v-model="form.name"
|
||||
label="Naam"
|
||||
v-model="form.first_name"
|
||||
label="Voornaam"
|
||||
:rules="[requiredValidator]"
|
||||
:error-messages="errors.name"
|
||||
:error-messages="errors.first_name"
|
||||
autofocus
|
||||
/>
|
||||
</VCol>
|
||||
<VCol
|
||||
cols="12"
|
||||
md="6"
|
||||
>
|
||||
<AppTextField
|
||||
v-model="form.last_name"
|
||||
label="Achternaam"
|
||||
:rules="[requiredValidator]"
|
||||
:error-messages="errors.last_name"
|
||||
/>
|
||||
</VCol>
|
||||
<VCol cols="12">
|
||||
<AppTextField
|
||||
v-model="form.email"
|
||||
|
||||
@@ -103,11 +103,11 @@ function onBlacklistToggle(val: boolean | null) {
|
||||
color="primary"
|
||||
variant="tonal"
|
||||
>
|
||||
<span class="text-h6">{{ getInitials(person.name) }}</span>
|
||||
<span class="text-h6">{{ getInitials(person.full_name) }}</span>
|
||||
</VAvatar>
|
||||
<div>
|
||||
<h5 class="text-h5 mb-1">
|
||||
{{ person.name }}
|
||||
{{ person.full_name }}
|
||||
</h5>
|
||||
<p class="text-body-2 text-disabled mb-2">
|
||||
{{ person.email }}
|
||||
|
||||
Reference in New Issue
Block a user