feat: add date_of_birth field to persons across all layers
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -20,6 +20,7 @@ final class StorePersonRequest extends FormRequest
|
||||
'crowd_type_id' => ['required', 'ulid', 'exists:crowd_types,id'],
|
||||
'first_name' => ['required', 'string', 'max:255'],
|
||||
'last_name' => ['required', 'string', 'max:255'],
|
||||
'date_of_birth' => ['nullable', 'date', 'before:today'],
|
||||
'email' => ['required', 'email', 'max:255'],
|
||||
'phone' => ['nullable', 'string', 'max:30'],
|
||||
'company_id' => ['nullable', 'ulid', 'exists:companies,id'],
|
||||
|
||||
@@ -20,6 +20,7 @@ final class UpdatePersonRequest extends FormRequest
|
||||
'crowd_type_id' => ['sometimes', 'ulid', 'exists:crowd_types,id'],
|
||||
'first_name' => ['sometimes', 'string', 'max:255'],
|
||||
'last_name' => ['sometimes', 'string', 'max:255'],
|
||||
'date_of_birth' => ['nullable', 'date', 'before:today'],
|
||||
'email' => ['sometimes', 'email', 'max:255'],
|
||||
'phone' => ['nullable', 'string', 'max:30'],
|
||||
'company_id' => ['nullable', 'ulid', 'exists:companies,id'],
|
||||
|
||||
@@ -35,6 +35,7 @@ final class VolunteerRegistrationRequest extends FormRequest
|
||||
'last_name' => ['required_without:_authenticated', 'string', 'max:255'],
|
||||
'email' => ['required_without:_authenticated', 'email', 'max:255'],
|
||||
'phone' => ['nullable', 'string', 'max:50'],
|
||||
'date_of_birth' => ['nullable', 'date', 'before:today'],
|
||||
|
||||
'tshirt_size' => ['nullable', 'string', 'in:XS,S,M,L,XL,XXL,XXXL'],
|
||||
'first_aid' => ['nullable', 'boolean'],
|
||||
|
||||
@@ -16,6 +16,7 @@ final class PersonResource extends JsonResource
|
||||
'event_id' => $this->event_id,
|
||||
'first_name' => $this->first_name,
|
||||
'last_name' => $this->last_name,
|
||||
'date_of_birth' => $this->date_of_birth?->toDateString(),
|
||||
'full_name' => $this->full_name,
|
||||
'email' => $this->email,
|
||||
'phone' => $this->phone,
|
||||
|
||||
@@ -30,6 +30,7 @@ final class Person extends Model
|
||||
'company_id',
|
||||
'first_name',
|
||||
'last_name',
|
||||
'date_of_birth',
|
||||
'email',
|
||||
'phone',
|
||||
'status',
|
||||
@@ -51,6 +52,7 @@ final class Person extends Model
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'date_of_birth' => 'date',
|
||||
'is_blacklisted' => 'boolean',
|
||||
'custom_fields' => 'array',
|
||||
];
|
||||
|
||||
@@ -53,6 +53,7 @@ final class VolunteerRegistrationService
|
||||
'first_name' => $user?->first_name ?? $validated['first_name'],
|
||||
'last_name' => $user?->last_name ?? $validated['last_name'],
|
||||
'phone' => $validated['phone'] ?? null,
|
||||
'date_of_birth' => $validated['date_of_birth'] ?? null,
|
||||
'status' => PersonStatus::PENDING,
|
||||
'custom_fields' => [
|
||||
'tshirt_size' => $validated['tshirt_size'] ?? null,
|
||||
|
||||
@@ -20,6 +20,7 @@ final class PersonFactory extends Factory
|
||||
'crowd_type_id' => CrowdType::factory(),
|
||||
'first_name' => fake('nl_NL')->firstName(),
|
||||
'last_name' => fake('nl_NL')->lastName(),
|
||||
'date_of_birth' => fake()->dateTimeBetween('-40 years', '-18 years')->format('Y-m-d'),
|
||||
'email' => fake()->unique()->safeEmail(),
|
||||
'phone' => fake('nl_NL')->phoneNumber(),
|
||||
'status' => 'pending',
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('persons', function (Blueprint $table) {
|
||||
$table->date('date_of_birth')->nullable()->after('last_name');
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('persons', function (Blueprint $table) {
|
||||
$table->dropColumn('date_of_birth');
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -471,21 +471,21 @@ class DevSeeder extends Seeder
|
||||
}
|
||||
|
||||
// 15 named volunteers
|
||||
$jan = Person::create(['event_id' => $festival->id, 'crowd_type_id' => $vol, 'user_id' => $volunteerUsers['jan@gmail.com']->id, 'first_name' => 'Jan', 'last_name' => 'de Vries', 'email' => 'jan@gmail.com', 'phone' => '+31612345001', 'status' => 'approved']);
|
||||
$lisaB = Person::create(['event_id' => $festival->id, 'crowd_type_id' => $vol, 'first_name' => 'Lisa', 'last_name' => 'Bakker', 'email' => 'lisa.bakker@hotmail.com', 'phone' => '+31612345002', 'status' => 'approved']);
|
||||
$ahmedP = Person::create(['event_id' => $festival->id, 'crowd_type_id' => $vol, 'user_id' => $volunteerUsers['ahmed.h@gmail.com']->id, 'first_name' => 'Ahmed', 'last_name' => 'Hassan', 'email' => 'ahmed.h@gmail.com', 'phone' => '+31612345003', 'status' => 'approved']);
|
||||
$saraJ = Person::create(['event_id' => $festival->id, 'crowd_type_id' => $vol, 'first_name' => 'Sara', 'last_name' => 'Jansen', 'email' => 'sara.j@outlook.com', 'phone' => '+31612345004', 'status' => 'approved']);
|
||||
$tomV = Person::create(['event_id' => $festival->id, 'crowd_type_id' => $vol, 'user_id' => $volunteerUsers['tom.visser@gmail.com']->id, 'first_name' => 'Tom', 'last_name' => 'Visser', 'email' => 'tom.visser@gmail.com', 'phone' => '+31612345005', 'status' => 'approved']);
|
||||
$fatima = Person::create(['event_id' => $festival->id, 'crowd_type_id' => $vol, 'first_name' => 'Fatima', 'last_name' => 'El Amrani', 'email' => 'fatima@gmail.com', 'phone' => '+31612345006', 'status' => 'approved']);
|
||||
$daan = Person::create(['event_id' => $festival->id, 'crowd_type_id' => $vol, 'first_name' => 'Daan', 'last_name' => 'Smit', 'email' => 'daan.smit@gmail.com', 'phone' => '+31612345007', 'status' => 'pending']);
|
||||
Person::create(['event_id' => $festival->id, 'crowd_type_id' => $vol, 'first_name' => 'Sophie', 'last_name' => 'Mulder', 'email' => 'sophie.m@hotmail.com', 'phone' => '+31612345008', 'status' => 'pending']);
|
||||
Person::create(['event_id' => $festival->id, 'crowd_type_id' => $vol, 'first_name' => 'Jesse', 'last_name' => 'van Dijk', 'email' => 'jesse@gmail.com', 'phone' => '+31612345009', 'status' => 'applied']);
|
||||
Person::create(['event_id' => $festival->id, 'crowd_type_id' => $vol, 'first_name' => 'Noa', 'last_name' => 'Hendriks', 'email' => 'noa.h@outlook.com', 'phone' => '+31612345010', 'status' => 'applied']);
|
||||
Person::create(['event_id' => $festival->id, 'crowd_type_id' => $vol, 'first_name' => 'Kevin', 'last_name' => 'Bos', 'email' => 'kevin.bos@gmail.com', 'phone' => '+31612345011', 'status' => 'rejected', 'admin_notes' => 'Vorig jaar no-show']);
|
||||
Person::create(['event_id' => $festival->id, 'crowd_type_id' => $vol, 'first_name' => 'Priya', 'last_name' => 'Sharma', 'email' => 'priya@gmail.com', 'phone' => '+31612345012', 'status' => 'invited']);
|
||||
$lotte = Person::create(['event_id' => $festival->id, 'crowd_type_id' => $vol, 'user_id' => $volunteerUsers['lotte@gmail.com']->id, 'first_name' => 'Lotte', 'last_name' => 'de Jong', 'email' => 'lotte@gmail.com', 'phone' => '+31612345013', 'status' => 'approved']);
|
||||
$robin = Person::create(['event_id' => $festival->id, 'crowd_type_id' => $vol, 'first_name' => 'Robin', 'last_name' => 'Peters', 'email' => 'robin.p@hotmail.com', 'phone' => '+31612345014', 'status' => 'approved']);
|
||||
$emma = Person::create(['event_id' => $festival->id, 'crowd_type_id' => $vol, 'first_name' => 'Emma', 'last_name' => 'Willems', 'email' => 'emma.w@gmail.com', 'phone' => '+31612345015', 'status' => 'no_show', 'is_blacklisted' => true]);
|
||||
$jan = Person::create(['event_id' => $festival->id, 'crowd_type_id' => $vol, 'user_id' => $volunteerUsers['jan@gmail.com']->id, 'first_name' => 'Jan', 'last_name' => 'de Vries', 'email' => 'jan@gmail.com', 'phone' => '+31612345001', 'status' => 'approved', 'date_of_birth' => '1995-03-15']);
|
||||
$lisaB = Person::create(['event_id' => $festival->id, 'crowd_type_id' => $vol, 'first_name' => 'Lisa', 'last_name' => 'Bakker', 'email' => 'lisa.bakker@hotmail.com', 'phone' => '+31612345002', 'status' => 'approved', 'date_of_birth' => '1998-07-22']);
|
||||
$ahmedP = Person::create(['event_id' => $festival->id, 'crowd_type_id' => $vol, 'user_id' => $volunteerUsers['ahmed.h@gmail.com']->id, 'first_name' => 'Ahmed', 'last_name' => 'Hassan', 'email' => 'ahmed.h@gmail.com', 'phone' => '+31612345003', 'status' => 'approved', 'date_of_birth' => '1992-11-08']);
|
||||
$saraJ = Person::create(['event_id' => $festival->id, 'crowd_type_id' => $vol, 'first_name' => 'Sara', 'last_name' => 'Jansen', 'email' => 'sara.j@outlook.com', 'phone' => '+31612345004', 'status' => 'approved', 'date_of_birth' => '2000-01-30']);
|
||||
$tomV = Person::create(['event_id' => $festival->id, 'crowd_type_id' => $vol, 'user_id' => $volunteerUsers['tom.visser@gmail.com']->id, 'first_name' => 'Tom', 'last_name' => 'Visser', 'email' => 'tom.visser@gmail.com', 'phone' => '+31612345005', 'status' => 'approved', 'date_of_birth' => '1997-06-14']);
|
||||
$fatima = Person::create(['event_id' => $festival->id, 'crowd_type_id' => $vol, 'first_name' => 'Fatima', 'last_name' => 'El Amrani', 'email' => 'fatima@gmail.com', 'phone' => '+31612345006', 'status' => 'approved', 'date_of_birth' => '1996-05-20']);
|
||||
$daan = Person::create(['event_id' => $festival->id, 'crowd_type_id' => $vol, 'first_name' => 'Daan', 'last_name' => 'Smit', 'email' => 'daan.smit@gmail.com', 'phone' => '+31612345007', 'status' => 'pending', 'date_of_birth' => '1993-08-11']);
|
||||
Person::create(['event_id' => $festival->id, 'crowd_type_id' => $vol, 'first_name' => 'Sophie', 'last_name' => 'Mulder', 'email' => 'sophie.m@hotmail.com', 'phone' => '+31612345008', 'status' => 'pending', 'date_of_birth' => '2001-02-28']);
|
||||
Person::create(['event_id' => $festival->id, 'crowd_type_id' => $vol, 'first_name' => 'Jesse', 'last_name' => 'van Dijk', 'email' => 'jesse@gmail.com', 'phone' => '+31612345009', 'status' => 'applied', 'date_of_birth' => '1999-10-05']);
|
||||
Person::create(['event_id' => $festival->id, 'crowd_type_id' => $vol, 'first_name' => 'Noa', 'last_name' => 'Hendriks', 'email' => 'noa.h@outlook.com', 'phone' => '+31612345010', 'status' => 'applied', 'date_of_birth' => '2000-07-19']);
|
||||
Person::create(['event_id' => $festival->id, 'crowd_type_id' => $vol, 'first_name' => 'Kevin', 'last_name' => 'Bos', 'email' => 'kevin.bos@gmail.com', 'phone' => '+31612345011', 'status' => 'rejected', 'admin_notes' => 'Vorig jaar no-show', 'date_of_birth' => '1994-12-01']);
|
||||
Person::create(['event_id' => $festival->id, 'crowd_type_id' => $vol, 'first_name' => 'Priya', 'last_name' => 'Sharma', 'email' => 'priya@gmail.com', 'phone' => '+31612345012', 'status' => 'invited', 'date_of_birth' => '1998-03-27']);
|
||||
$lotte = Person::create(['event_id' => $festival->id, 'crowd_type_id' => $vol, 'user_id' => $volunteerUsers['lotte@gmail.com']->id, 'first_name' => 'Lotte', 'last_name' => 'de Jong', 'email' => 'lotte@gmail.com', 'phone' => '+31612345013', 'status' => 'approved', 'date_of_birth' => '1994-09-25']);
|
||||
$robin = Person::create(['event_id' => $festival->id, 'crowd_type_id' => $vol, 'first_name' => 'Robin', 'last_name' => 'Peters', 'email' => 'robin.p@hotmail.com', 'phone' => '+31612345014', 'status' => 'approved', 'date_of_birth' => '1991-12-03']);
|
||||
$emma = Person::create(['event_id' => $festival->id, 'crowd_type_id' => $vol, 'first_name' => 'Emma', 'last_name' => 'Willems', 'email' => 'emma.w@gmail.com', 'phone' => '+31612345015', 'status' => 'no_show', 'is_blacklisted' => true, 'date_of_birth' => '1999-04-17']);
|
||||
|
||||
// 6 named crew
|
||||
$klaas = Person::create(['event_id' => $festival->id, 'crowd_type_id' => $crew, 'company_id' => $this->companies['SecureEvent BV']->id, 'first_name' => 'Klaas', 'last_name' => 'Veilig Jr.', 'email' => 'klaas.jr@secureevent.nl', 'phone' => '+31612345016', 'status' => 'approved']);
|
||||
|
||||
@@ -170,6 +170,48 @@ class VolunteerRegistrationTest extends TestCase
|
||||
$this->assertNotEmpty($customFields['section_preferences']);
|
||||
}
|
||||
|
||||
public function test_volunteer_can_register_with_date_of_birth(): void
|
||||
{
|
||||
$response = $this->postJson("/api/v1/events/{$this->event->id}/volunteer-register", [
|
||||
'first_name' => 'Mila',
|
||||
'last_name' => 'de Boer',
|
||||
'email' => 'mila@voorbeeld.nl',
|
||||
'date_of_birth' => '1998-05-12',
|
||||
]);
|
||||
|
||||
$response->assertStatus(201);
|
||||
|
||||
$person = Person::where('email', 'mila@voorbeeld.nl')->first();
|
||||
$this->assertEquals('1998-05-12', $person->date_of_birth->format('Y-m-d'));
|
||||
}
|
||||
|
||||
public function test_volunteer_can_register_without_date_of_birth(): void
|
||||
{
|
||||
$response = $this->postJson("/api/v1/events/{$this->event->id}/volunteer-register", [
|
||||
'first_name' => 'Sem',
|
||||
'last_name' => 'van Beek',
|
||||
'email' => 'sem@voorbeeld.nl',
|
||||
]);
|
||||
|
||||
$response->assertStatus(201);
|
||||
|
||||
$person = Person::where('email', 'sem@voorbeeld.nl')->first();
|
||||
$this->assertNull($person->date_of_birth);
|
||||
}
|
||||
|
||||
public function test_date_of_birth_must_be_before_today(): void
|
||||
{
|
||||
$response = $this->postJson("/api/v1/events/{$this->event->id}/volunteer-register", [
|
||||
'first_name' => 'Tijn',
|
||||
'last_name' => 'Kuiper',
|
||||
'email' => 'tijn@voorbeeld.nl',
|
||||
'date_of_birth' => now()->addDay()->format('Y-m-d'),
|
||||
]);
|
||||
|
||||
$response->assertStatus(422);
|
||||
$response->assertJsonValidationErrors('date_of_birth');
|
||||
}
|
||||
|
||||
public function test_duplicate_email_rejected(): void
|
||||
{
|
||||
$this->postJson("/api/v1/events/{$this->event->id}/volunteer-register", [
|
||||
|
||||
@@ -23,6 +23,7 @@ const form = ref({
|
||||
crowd_type_id: '',
|
||||
first_name: '',
|
||||
last_name: '',
|
||||
date_of_birth: '',
|
||||
email: '',
|
||||
phone: '',
|
||||
company_id: '',
|
||||
@@ -72,6 +73,7 @@ function resetForm() {
|
||||
crowd_type_id: '',
|
||||
first_name: '',
|
||||
last_name: '',
|
||||
date_of_birth: '',
|
||||
email: '',
|
||||
phone: '',
|
||||
company_id: '',
|
||||
@@ -91,6 +93,7 @@ function onSubmit() {
|
||||
crowd_type_id: form.value.crowd_type_id,
|
||||
first_name: form.value.first_name,
|
||||
last_name: form.value.last_name,
|
||||
...(form.value.date_of_birth ? { date_of_birth: form.value.date_of_birth } : {}),
|
||||
email: form.value.email,
|
||||
...(form.value.phone ? { phone: form.value.phone } : {}),
|
||||
...(form.value.company_id ? { company_id: form.value.company_id } : {}),
|
||||
@@ -164,6 +167,17 @@ function onSubmit() {
|
||||
:error-messages="errors.last_name"
|
||||
/>
|
||||
</VCol>
|
||||
<VCol
|
||||
cols="12"
|
||||
md="6"
|
||||
>
|
||||
<AppTextField
|
||||
v-model="form.date_of_birth"
|
||||
label="Geboortedatum"
|
||||
type="date"
|
||||
:error-messages="errors.date_of_birth"
|
||||
/>
|
||||
</VCol>
|
||||
<VCol cols="12">
|
||||
<AppTextField
|
||||
v-model="form.email"
|
||||
|
||||
@@ -25,6 +25,7 @@ const form = ref({
|
||||
crowd_type_id: '',
|
||||
first_name: '',
|
||||
last_name: '',
|
||||
date_of_birth: '',
|
||||
email: '',
|
||||
phone: '',
|
||||
company_id: '',
|
||||
@@ -42,6 +43,7 @@ watch(() => props.person, (p) => {
|
||||
crowd_type_id: p.crowd_type?.id ?? '',
|
||||
first_name: p.first_name,
|
||||
last_name: p.last_name,
|
||||
date_of_birth: p.date_of_birth ?? '',
|
||||
email: p.email,
|
||||
phone: p.phone ?? '',
|
||||
company_id: p.company?.id ?? '',
|
||||
@@ -96,6 +98,7 @@ function onSubmit() {
|
||||
crowd_type_id: form.value.crowd_type_id,
|
||||
first_name: form.value.first_name,
|
||||
last_name: form.value.last_name,
|
||||
date_of_birth: form.value.date_of_birth || undefined,
|
||||
email: form.value.email,
|
||||
phone: form.value.phone || undefined,
|
||||
company_id: form.value.company_id || undefined,
|
||||
@@ -167,6 +170,17 @@ function onSubmit() {
|
||||
:error-messages="errors.last_name"
|
||||
/>
|
||||
</VCol>
|
||||
<VCol
|
||||
cols="12"
|
||||
md="6"
|
||||
>
|
||||
<AppTextField
|
||||
v-model="form.date_of_birth"
|
||||
label="Geboortedatum"
|
||||
type="date"
|
||||
:error-messages="errors.date_of_birth"
|
||||
/>
|
||||
</VCol>
|
||||
<VCol cols="12">
|
||||
<AppTextField
|
||||
v-model="form.email"
|
||||
|
||||
@@ -37,10 +37,20 @@ const dateFormatter = new Intl.DateTimeFormat('nl-NL', {
|
||||
year: 'numeric',
|
||||
})
|
||||
|
||||
const dobFormatter = new Intl.DateTimeFormat('nl-NL', {
|
||||
day: 'numeric',
|
||||
month: 'long',
|
||||
year: 'numeric',
|
||||
})
|
||||
|
||||
function formatDate(iso: string) {
|
||||
return dateFormatter.format(new Date(iso))
|
||||
}
|
||||
|
||||
function formatDateOfBirth(dateStr: string) {
|
||||
return dobFormatter.format(new Date(`${dateStr}T00:00:00`))
|
||||
}
|
||||
|
||||
function getInitials(name: string) {
|
||||
return name
|
||||
.split(' ')
|
||||
@@ -175,6 +185,17 @@ function onBlacklistToggle(val: boolean | null) {
|
||||
<!-- Tab: Informatie -->
|
||||
<VTabsWindowItem value="info">
|
||||
<VList class="pa-0">
|
||||
<VListItem>
|
||||
<template #prepend>
|
||||
<VIcon
|
||||
icon="tabler-cake"
|
||||
class="me-3"
|
||||
/>
|
||||
</template>
|
||||
<VListItemTitle>Geboortedatum</VListItemTitle>
|
||||
<VListItemSubtitle>{{ person.date_of_birth ? formatDateOfBirth(person.date_of_birth) : 'Niet opgegeven' }}</VListItemSubtitle>
|
||||
</VListItem>
|
||||
|
||||
<VListItem>
|
||||
<template #prepend>
|
||||
<VIcon
|
||||
|
||||
@@ -47,6 +47,7 @@ export interface Person {
|
||||
id: string
|
||||
first_name: string
|
||||
last_name: string
|
||||
date_of_birth: string | null
|
||||
full_name: string
|
||||
email: string
|
||||
phone: string | null
|
||||
@@ -67,6 +68,7 @@ export interface CreatePersonPayload {
|
||||
crowd_type_id: string
|
||||
first_name: string
|
||||
last_name: string
|
||||
date_of_birth?: string
|
||||
email: string
|
||||
phone?: string
|
||||
company_id?: string
|
||||
|
||||
@@ -40,6 +40,7 @@ const { errors, defineField, validateField, setFieldValue } = useForm({
|
||||
first_name: '',
|
||||
last_name: '',
|
||||
email: '',
|
||||
date_of_birth: '',
|
||||
phone: '',
|
||||
tshirt_size: '',
|
||||
first_aid: false,
|
||||
@@ -53,6 +54,7 @@ const { errors, defineField, validateField, setFieldValue } = useForm({
|
||||
|
||||
const [firstName] = defineField('first_name')
|
||||
const [lastName] = defineField('last_name')
|
||||
const [dateOfBirth] = defineField('date_of_birth')
|
||||
const [email] = defineField('email')
|
||||
const [phone] = defineField('phone')
|
||||
const [tshirtSize] = defineField('tshirt_size')
|
||||
@@ -157,10 +159,10 @@ const formattedDates = computed(() => {
|
||||
})
|
||||
|
||||
// Step field mapping for validation (0-based)
|
||||
type FormField = 'first_name' | 'last_name' | 'email' | 'phone' | 'tshirt_size' | 'first_aid' | 'allergies' | 'access_requirements' | 'driving_licence' | 'motivation' | 'motivation_other'
|
||||
type FormField = 'first_name' | 'last_name' | 'date_of_birth' | 'email' | 'phone' | 'tshirt_size' | 'first_aid' | 'allergies' | 'access_requirements' | 'driving_licence' | 'motivation' | 'motivation_other'
|
||||
|
||||
const stepFields: Record<number, FormField[]> = {
|
||||
0: ['first_name', 'last_name', 'email', 'phone'],
|
||||
0: ['first_name', 'last_name', 'date_of_birth', 'email', 'phone'],
|
||||
1: ['tshirt_size', 'first_aid', 'allergies', 'access_requirements', 'driving_licence'],
|
||||
2: ['motivation', 'motivation_other'],
|
||||
}
|
||||
@@ -270,6 +272,7 @@ async function onSubmit() {
|
||||
const payload: VolunteerRegistrationForm = {
|
||||
first_name: firstName.value ?? '',
|
||||
last_name: lastName.value ?? '',
|
||||
date_of_birth: dateOfBirth.value ?? '',
|
||||
email: email.value ?? '',
|
||||
phone: phone.value ?? '',
|
||||
tshirt_size: tshirtSize.value ?? '',
|
||||
@@ -678,6 +681,19 @@ async function onSubmit() {
|
||||
density="comfortable"
|
||||
/>
|
||||
</VCol>
|
||||
|
||||
<VCol
|
||||
cols="12"
|
||||
md="6"
|
||||
>
|
||||
<VTextField
|
||||
v-model="dateOfBirth"
|
||||
label="Geboortedatum"
|
||||
type="date"
|
||||
:error-messages="errors.date_of_birth"
|
||||
density="comfortable"
|
||||
/>
|
||||
</VCol>
|
||||
</VRow>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ export const step1Schema = z.object({
|
||||
first_name: z.string().min(1, 'Voornaam is verplicht').max(255),
|
||||
last_name: z.string().min(1, 'Achternaam is verplicht').max(255),
|
||||
email: z.string().min(1, 'E-mailadres is verplicht').email('Ongeldig e-mailadres').max(255),
|
||||
date_of_birth: z.string().optional().or(z.literal('')),
|
||||
phone: z.string().max(50).optional().or(z.literal('')),
|
||||
})
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ export interface VolunteerRegistrationForm {
|
||||
// Step 1
|
||||
first_name: string
|
||||
last_name: string
|
||||
date_of_birth: string
|
||||
email: string
|
||||
phone: string
|
||||
// Step 2
|
||||
|
||||
@@ -664,6 +664,7 @@ $effectiveDate = $shift->end_date ?? $shift->timeSlot->date;
|
||||
| `company_id` | ULID FK nullable | → companies |
|
||||
| `first_name` | string | |
|
||||
| `last_name` | string | |
|
||||
| `date_of_birth` | date nullable | |
|
||||
| `email` | string | Indexed deduplication key |
|
||||
| `phone` | string nullable | |
|
||||
| `status` | enum | `invited\|applied\|pending\|approved\|rejected\|no_show` |
|
||||
|
||||
Reference in New Issue
Block a user