diff --git a/api/app/Http/Controllers/Api/V1/InvitationController.php b/api/app/Http/Controllers/Api/V1/InvitationController.php index d9ebe6cf..2ad01531 100644 --- a/api/app/Http/Controllers/Api/V1/InvitationController.php +++ b/api/app/Http/Controllers/Api/V1/InvitationController.php @@ -64,7 +64,9 @@ final class InvitationController extends Controller return $this->success([ 'user' => [ 'id' => $user->id, - 'name' => $user->name, + 'first_name' => $user->first_name, + 'last_name' => $user->last_name, + 'full_name' => $user->full_name, 'email' => $user->email, ], 'token' => $sanctumToken, diff --git a/api/app/Http/Controllers/Api/V1/ShiftAssignmentController.php b/api/app/Http/Controllers/Api/V1/ShiftAssignmentController.php index 8655c564..f4791218 100644 --- a/api/app/Http/Controllers/Api/V1/ShiftAssignmentController.php +++ b/api/app/Http/Controllers/Api/V1/ShiftAssignmentController.php @@ -145,7 +145,8 @@ final class ShiftAssignmentController extends Controller $persons = Person::where('event_id', $festivalEventId) ->where('status', PersonStatus::APPROVED) ->with('crowdType') - ->orderBy('name') + ->orderBy('first_name') + ->orderBy('last_name') ->get(); // Batch: tags for all persons with user_id @@ -184,7 +185,9 @@ final class ShiftAssignmentController extends Controller return [ 'id' => $person->id, - 'name' => $person->name, + 'first_name' => $person->first_name, + 'last_name' => $person->last_name, + 'full_name' => $person->full_name, 'email' => $person->email, 'status' => $person->status, 'crowd_type' => $person->crowdType ? [ @@ -222,7 +225,7 @@ final class ShiftAssignmentController extends Controller ->sortBy([ ['already_assigned', 'asc'], ['is_available', 'desc'], - ['name', 'asc'], + ['first_name', 'asc'], ]) ->values(); diff --git a/api/app/Http/Requests/Api/V1/AcceptInvitationRequest.php b/api/app/Http/Requests/Api/V1/AcceptInvitationRequest.php index 98d98b15..c9045bf6 100644 --- a/api/app/Http/Requests/Api/V1/AcceptInvitationRequest.php +++ b/api/app/Http/Requests/Api/V1/AcceptInvitationRequest.php @@ -22,7 +22,8 @@ final class AcceptInvitationRequest extends FormRequest $userExists = $invitation && User::where('email', $invitation->email)->exists(); return [ - 'name' => [$userExists ? 'nullable' : 'required', 'string', 'max:255'], + 'first_name' => [$userExists ? 'nullable' : 'required', 'string', 'max:255'], + 'last_name' => [$userExists ? 'nullable' : 'required', 'string', 'max:255'], 'password' => [$userExists ? 'nullable' : 'required', 'string', 'min:8', 'confirmed'], ]; } diff --git a/api/app/Http/Requests/Api/V1/StoreCompanyRequest.php b/api/app/Http/Requests/Api/V1/StoreCompanyRequest.php index a1e56800..1ec8b27f 100644 --- a/api/app/Http/Requests/Api/V1/StoreCompanyRequest.php +++ b/api/app/Http/Requests/Api/V1/StoreCompanyRequest.php @@ -19,7 +19,8 @@ final class StoreCompanyRequest extends FormRequest return [ 'name' => ['required', 'string', 'max:100'], 'type' => ['required', 'in:supplier,partner,agency,venue,other'], - 'contact_name' => ['nullable', 'string', 'max:100'], + 'contact_first_name' => ['nullable', 'string', 'max:100'], + 'contact_last_name' => ['nullable', 'string', 'max:100'], 'contact_email' => ['nullable', 'email', 'max:100'], 'contact_phone' => ['nullable', 'string', 'max:30'], ]; diff --git a/api/app/Http/Requests/Api/V1/StorePersonRequest.php b/api/app/Http/Requests/Api/V1/StorePersonRequest.php index 23c117bb..04e5058c 100644 --- a/api/app/Http/Requests/Api/V1/StorePersonRequest.php +++ b/api/app/Http/Requests/Api/V1/StorePersonRequest.php @@ -18,7 +18,8 @@ final class StorePersonRequest extends FormRequest { return [ 'crowd_type_id' => ['required', 'ulid', 'exists:crowd_types,id'], - 'name' => ['required', 'string', 'max:255'], + 'first_name' => ['required', 'string', 'max:255'], + 'last_name' => ['required', 'string', 'max:255'], 'email' => ['required', 'email', 'max:255'], 'phone' => ['nullable', 'string', 'max:30'], 'company_id' => ['nullable', 'ulid', 'exists:companies,id'], diff --git a/api/app/Http/Requests/Api/V1/UpdateCompanyRequest.php b/api/app/Http/Requests/Api/V1/UpdateCompanyRequest.php index aee1a1ff..3ccb5de4 100644 --- a/api/app/Http/Requests/Api/V1/UpdateCompanyRequest.php +++ b/api/app/Http/Requests/Api/V1/UpdateCompanyRequest.php @@ -19,7 +19,8 @@ final class UpdateCompanyRequest extends FormRequest return [ 'name' => ['sometimes', 'string', 'max:100'], 'type' => ['sometimes', 'in:supplier,partner,agency,venue,other'], - 'contact_name' => ['nullable', 'string', 'max:100'], + 'contact_first_name' => ['nullable', 'string', 'max:100'], + 'contact_last_name' => ['nullable', 'string', 'max:100'], 'contact_email' => ['nullable', 'email', 'max:100'], 'contact_phone' => ['nullable', 'string', 'max:30'], ]; diff --git a/api/app/Http/Requests/Api/V1/UpdatePersonRequest.php b/api/app/Http/Requests/Api/V1/UpdatePersonRequest.php index eb0bf9b5..98eab264 100644 --- a/api/app/Http/Requests/Api/V1/UpdatePersonRequest.php +++ b/api/app/Http/Requests/Api/V1/UpdatePersonRequest.php @@ -18,7 +18,8 @@ final class UpdatePersonRequest extends FormRequest { return [ 'crowd_type_id' => ['sometimes', 'ulid', 'exists:crowd_types,id'], - 'name' => ['sometimes', 'string', 'max:255'], + 'first_name' => ['sometimes', 'string', 'max:255'], + 'last_name' => ['sometimes', 'string', 'max:255'], 'email' => ['sometimes', 'email', 'max:255'], 'phone' => ['nullable', 'string', 'max:30'], 'company_id' => ['nullable', 'ulid', 'exists:companies,id'], diff --git a/api/app/Http/Requests/Api/V1/VolunteerRegistrationRequest.php b/api/app/Http/Requests/Api/V1/VolunteerRegistrationRequest.php index 83d2afb5..7055df61 100644 --- a/api/app/Http/Requests/Api/V1/VolunteerRegistrationRequest.php +++ b/api/app/Http/Requests/Api/V1/VolunteerRegistrationRequest.php @@ -19,7 +19,8 @@ final class VolunteerRegistrationRequest extends FormRequest if ($user) { $this->merge([ - 'name' => $user->name, + 'first_name' => $user->first_name, + 'last_name' => $user->last_name, 'email' => $user->email, '_authenticated' => true, ]); @@ -30,7 +31,8 @@ final class VolunteerRegistrationRequest extends FormRequest public function rules(): array { return [ - 'name' => ['required_without:_authenticated', 'string', 'max:255'], + 'first_name' => ['required_without:_authenticated', 'string', 'max:255'], + 'last_name' => ['required_without:_authenticated', 'string', 'max:255'], 'email' => ['required_without:_authenticated', 'email', 'max:255'], 'phone' => ['nullable', 'string', 'max:50'], diff --git a/api/app/Http/Resources/Api/V1/CompanyResource.php b/api/app/Http/Resources/Api/V1/CompanyResource.php index 9a1fc214..c05088cc 100644 --- a/api/app/Http/Resources/Api/V1/CompanyResource.php +++ b/api/app/Http/Resources/Api/V1/CompanyResource.php @@ -16,7 +16,9 @@ final class CompanyResource extends JsonResource 'organisation_id' => $this->organisation_id, 'name' => $this->name, 'type' => $this->type, - 'contact_name' => $this->contact_name, + 'contact_first_name' => $this->contact_first_name, + 'contact_last_name' => $this->contact_last_name, + 'contact_full_name' => $this->contact_full_name, 'contact_email' => $this->contact_email, 'contact_phone' => $this->contact_phone, 'persons_count' => $this->whenCounted('persons'), diff --git a/api/app/Http/Resources/Api/V1/MeResource.php b/api/app/Http/Resources/Api/V1/MeResource.php index f665ca87..9ea92d86 100644 --- a/api/app/Http/Resources/Api/V1/MeResource.php +++ b/api/app/Http/Resources/Api/V1/MeResource.php @@ -13,7 +13,9 @@ final class MeResource extends JsonResource { return [ 'id' => $this->id, - 'name' => $this->name, + 'first_name' => $this->first_name, + 'last_name' => $this->last_name, + 'full_name' => $this->full_name, 'email' => $this->email, 'timezone' => $this->timezone, 'locale' => $this->locale, diff --git a/api/app/Http/Resources/Api/V1/MemberResource.php b/api/app/Http/Resources/Api/V1/MemberResource.php index 1130894e..c8f82f68 100644 --- a/api/app/Http/Resources/Api/V1/MemberResource.php +++ b/api/app/Http/Resources/Api/V1/MemberResource.php @@ -13,7 +13,9 @@ final class MemberResource extends JsonResource { return [ 'id' => $this->id, - 'name' => $this->name, + 'first_name' => $this->first_name, + 'last_name' => $this->last_name, + 'full_name' => $this->full_name, 'email' => $this->email, 'role' => $this->pivot?->role, 'avatar' => $this->avatar, diff --git a/api/app/Http/Resources/Api/V1/PersonResource.php b/api/app/Http/Resources/Api/V1/PersonResource.php index 848ed5cb..ed4de8cf 100644 --- a/api/app/Http/Resources/Api/V1/PersonResource.php +++ b/api/app/Http/Resources/Api/V1/PersonResource.php @@ -14,7 +14,9 @@ final class PersonResource extends JsonResource return [ 'id' => $this->id, 'event_id' => $this->event_id, - 'name' => $this->name, + 'first_name' => $this->first_name, + 'last_name' => $this->last_name, + 'full_name' => $this->full_name, 'email' => $this->email, 'phone' => $this->phone, 'status' => $this->status, @@ -33,7 +35,9 @@ final class PersonResource extends JsonResource 'match_id' => $match->id, 'matched_user' => [ 'id' => $match->matchedUser->id, - 'name' => $match->matchedUser->name, + 'first_name' => $match->matchedUser->first_name, + 'last_name' => $match->matchedUser->last_name, + 'full_name' => $match->matchedUser->full_name, 'email' => $match->matchedUser->email, ], 'matched_on' => $match->matched_on->value, diff --git a/api/app/Http/Resources/Api/V1/UserResource.php b/api/app/Http/Resources/Api/V1/UserResource.php index 240765eb..e2e8ff05 100644 --- a/api/app/Http/Resources/Api/V1/UserResource.php +++ b/api/app/Http/Resources/Api/V1/UserResource.php @@ -13,7 +13,9 @@ final class UserResource extends JsonResource { return [ 'id' => $this->id, - 'name' => $this->name, + 'first_name' => $this->first_name, + 'last_name' => $this->last_name, + 'full_name' => $this->full_name, 'email' => $this->email, 'roles' => $this->getRoleNames()->values()->all(), 'timezone' => $this->timezone, diff --git a/api/app/Models/Company.php b/api/app/Models/Company.php index 13fe8d88..60f479ad 100644 --- a/api/app/Models/Company.php +++ b/api/app/Models/Company.php @@ -22,11 +22,21 @@ final class Company extends Model 'organisation_id', 'name', 'type', - 'contact_name', + 'contact_first_name', + 'contact_last_name', 'contact_email', 'contact_phone', ]; + public function getContactFullNameAttribute(): ?string + { + if (! $this->contact_first_name) { + return null; + } + + return trim("{$this->contact_first_name} {$this->contact_last_name}"); + } + public function organisation(): BelongsTo { return $this->belongsTo(Organisation::class); diff --git a/api/app/Models/Person.php b/api/app/Models/Person.php index 905019b2..3371928f 100644 --- a/api/app/Models/Person.php +++ b/api/app/Models/Person.php @@ -28,7 +28,8 @@ final class Person extends Model 'event_id', 'crowd_type_id', 'company_id', - 'name', + 'first_name', + 'last_name', 'email', 'phone', 'status', @@ -37,6 +38,16 @@ final class Person extends Model 'custom_fields', ]; + public function getFullNameAttribute(): string + { + return trim("{$this->first_name} {$this->last_name}"); + } + + public function getNameAttribute(): string + { + return $this->full_name; + } + protected function casts(): array { return [ diff --git a/api/app/Models/User.php b/api/app/Models/User.php index 9252f4e0..1060da89 100644 --- a/api/app/Models/User.php +++ b/api/app/Models/User.php @@ -24,7 +24,8 @@ final class User extends Authenticatable use SoftDeletes; protected $fillable = [ - 'name', + 'first_name', + 'last_name', 'email', 'password', 'timezone', @@ -32,6 +33,16 @@ final class User extends Authenticatable 'avatar', ]; + public function getFullNameAttribute(): string + { + return trim("{$this->first_name} {$this->last_name}"); + } + + public function getNameAttribute(): string + { + return $this->full_name; + } + protected $hidden = [ 'password', 'remember_token', diff --git a/api/app/Services/InvitationService.php b/api/app/Services/InvitationService.php index a5c0c5c1..c0a1296c 100644 --- a/api/app/Services/InvitationService.php +++ b/api/app/Services/InvitationService.php @@ -76,7 +76,8 @@ final class InvitationService } $user = User::create([ - 'name' => Str::before($invitation->email, '@'), + 'first_name' => Str::before($invitation->email, '@'), + 'last_name' => '', 'email' => $invitation->email, 'password' => $password, 'email_verified_at' => now(), diff --git a/api/app/Services/ShiftAssignmentService.php b/api/app/Services/ShiftAssignmentService.php index da14789b..cfeb38e3 100644 --- a/api/app/Services/ShiftAssignmentService.php +++ b/api/app/Services/ShiftAssignmentService.php @@ -102,7 +102,7 @@ final class ShiftAssignmentService ->performedOn($existing) ->withProperties([ 'previous_status' => $previousStatus, - 'person_name' => $person->name, + 'person_name' => $person->full_name, ]) ->log('shift_assignment.reactivated'); @@ -124,7 +124,7 @@ final class ShiftAssignmentService 'filled_slots' => $filledSlots, 'slots_total' => $shift->slots_total, 'person_id' => $person->id, - 'person_name' => $person->name, + 'person_name' => $person->full_name, ]) ->log('shift.overbooked_assignment'); } diff --git a/api/app/Services/VolunteerRegistrationService.php b/api/app/Services/VolunteerRegistrationService.php index 72ca30ed..60caa09d 100644 --- a/api/app/Services/VolunteerRegistrationService.php +++ b/api/app/Services/VolunteerRegistrationService.php @@ -50,7 +50,8 @@ final class VolunteerRegistrationService [ 'user_id' => $user?->id, 'crowd_type_id' => $volunteerCrowdType->id, - 'name' => $user?->name ?? $validated['name'], + 'first_name' => $user?->first_name ?? $validated['first_name'], + 'last_name' => $user?->last_name ?? $validated['last_name'], 'phone' => $validated['phone'] ?? null, 'status' => PersonStatus::PENDING, 'custom_fields' => [ @@ -119,7 +120,7 @@ final class VolunteerRegistrationService return; } - if ($existing->status !== PersonStatus::REJECTED) { + if ($existing->status !== PersonStatus::REJECTED->value) { throw ValidationException::withMessages([ 'email' => ['Already registered for this event.'], ]); diff --git a/api/database/factories/CompanyFactory.php b/api/database/factories/CompanyFactory.php index e4cf7cb5..f4d9118e 100644 --- a/api/database/factories/CompanyFactory.php +++ b/api/database/factories/CompanyFactory.php @@ -18,7 +18,8 @@ final class CompanyFactory extends Factory 'organisation_id' => Organisation::factory(), 'name' => fake('nl_NL')->company(), 'type' => fake()->randomElement(['supplier', 'partner', 'agency', 'venue', 'other']), - 'contact_name' => fake('nl_NL')->name(), + 'contact_first_name' => fake('nl_NL')->firstName(), + 'contact_last_name' => fake('nl_NL')->lastName(), 'contact_email' => fake()->companyEmail(), 'contact_phone' => fake('nl_NL')->phoneNumber(), ]; diff --git a/api/database/factories/PersonFactory.php b/api/database/factories/PersonFactory.php index fc389e7a..65dbd918 100644 --- a/api/database/factories/PersonFactory.php +++ b/api/database/factories/PersonFactory.php @@ -18,7 +18,8 @@ final class PersonFactory extends Factory return [ 'event_id' => Event::factory(), 'crowd_type_id' => CrowdType::factory(), - 'name' => fake('nl_NL')->name(), + 'first_name' => fake('nl_NL')->firstName(), + 'last_name' => fake('nl_NL')->lastName(), 'email' => fake()->unique()->safeEmail(), 'phone' => fake('nl_NL')->phoneNumber(), 'status' => 'pending', @@ -31,4 +32,9 @@ final class PersonFactory extends Factory { return $this->state(fn () => ['status' => 'approved']); } + + public function rejected(): static + { + return $this->state(fn () => ['status' => 'rejected']); + } } diff --git a/api/database/factories/UserFactory.php b/api/database/factories/UserFactory.php index 3d14dfe6..838bcbd2 100644 --- a/api/database/factories/UserFactory.php +++ b/api/database/factories/UserFactory.php @@ -18,7 +18,8 @@ final class UserFactory extends Factory public function definition(): array { return [ - 'name' => fake()->name(), + 'first_name' => fake('nl_NL')->firstName(), + 'last_name' => fake('nl_NL')->lastName(), 'email' => fake()->unique()->safeEmail(), 'email_verified_at' => now(), 'password' => static::$password ??= Hash::make('password'), diff --git a/api/database/migrations/2026_04_10_400000_split_name_into_first_last_on_users_table.php b/api/database/migrations/2026_04_10_400000_split_name_into_first_last_on_users_table.php new file mode 100644 index 00000000..6a2295d6 --- /dev/null +++ b/api/database/migrations/2026_04_10_400000_split_name_into_first_last_on_users_table.php @@ -0,0 +1,48 @@ +string('first_name')->after('id'); + $table->string('last_name')->after('first_name'); + }); + + DB::table('users')->get()->each(function ($user) { + $parts = explode(' ', $user->name, 2); + DB::table('users')->where('id', $user->id)->update([ + 'first_name' => $parts[0], + 'last_name' => $parts[1] ?? '', + ]); + }); + + Schema::table('users', function (Blueprint $table) { + $table->dropColumn('name'); + }); + } + + public function down(): void + { + Schema::table('users', function (Blueprint $table) { + $table->string('name')->after('id'); + }); + + DB::table('users')->get()->each(function ($user) { + DB::table('users')->where('id', $user->id)->update([ + 'name' => trim("{$user->first_name} {$user->last_name}"), + ]); + }); + + Schema::table('users', function (Blueprint $table) { + $table->dropColumn(['first_name', 'last_name']); + }); + } +}; diff --git a/api/database/migrations/2026_04_10_400001_split_name_into_first_last_on_persons_table.php b/api/database/migrations/2026_04_10_400001_split_name_into_first_last_on_persons_table.php new file mode 100644 index 00000000..d06da3e6 --- /dev/null +++ b/api/database/migrations/2026_04_10_400001_split_name_into_first_last_on_persons_table.php @@ -0,0 +1,48 @@ +string('first_name')->after('company_id'); + $table->string('last_name')->after('first_name'); + }); + + DB::table('persons')->get()->each(function ($person) { + $parts = explode(' ', $person->name, 2); + DB::table('persons')->where('id', $person->id)->update([ + 'first_name' => $parts[0], + 'last_name' => $parts[1] ?? '', + ]); + }); + + Schema::table('persons', function (Blueprint $table) { + $table->dropColumn('name'); + }); + } + + public function down(): void + { + Schema::table('persons', function (Blueprint $table) { + $table->string('name')->after('company_id'); + }); + + DB::table('persons')->get()->each(function ($person) { + DB::table('persons')->where('id', $person->id)->update([ + 'name' => trim("{$person->first_name} {$person->last_name}"), + ]); + }); + + Schema::table('persons', function (Blueprint $table) { + $table->dropColumn(['first_name', 'last_name']); + }); + } +}; diff --git a/api/database/migrations/2026_04_10_400002_split_contact_name_on_companies_table.php b/api/database/migrations/2026_04_10_400002_split_contact_name_on_companies_table.php new file mode 100644 index 00000000..a06a01d9 --- /dev/null +++ b/api/database/migrations/2026_04_10_400002_split_contact_name_on_companies_table.php @@ -0,0 +1,48 @@ +string('contact_first_name')->nullable()->after('type'); + $table->string('contact_last_name')->nullable()->after('contact_first_name'); + }); + + DB::table('companies')->whereNotNull('contact_name')->get()->each(function ($company) { + $parts = explode(' ', $company->contact_name, 2); + DB::table('companies')->where('id', $company->id)->update([ + 'contact_first_name' => $parts[0], + 'contact_last_name' => $parts[1] ?? '', + ]); + }); + + Schema::table('companies', function (Blueprint $table) { + $table->dropColumn('contact_name'); + }); + } + + public function down(): void + { + Schema::table('companies', function (Blueprint $table) { + $table->string('contact_name')->nullable()->after('type'); + }); + + DB::table('companies')->whereNotNull('contact_first_name')->get()->each(function ($company) { + DB::table('companies')->where('id', $company->id)->update([ + 'contact_name' => trim("{$company->contact_first_name} {$company->contact_last_name}"), + ]); + }); + + Schema::table('companies', function (Blueprint $table) { + $table->dropColumn(['contact_first_name', 'contact_last_name']); + }); + } +}; diff --git a/api/database/seeders/DatabaseSeeder.php b/api/database/seeders/DatabaseSeeder.php index 03aa0d0d..b66d1455 100644 --- a/api/database/seeders/DatabaseSeeder.php +++ b/api/database/seeders/DatabaseSeeder.php @@ -16,7 +16,8 @@ class DatabaseSeeder extends Seeder $this->call(RoleSeeder::class); $admin = User::create([ - 'name' => 'Super Admin', + 'first_name' => 'Super', + 'last_name' => 'Admin', 'email' => 'admin@crewli.app', 'password' => Hash::make('password'), ]); diff --git a/api/database/seeders/DevSeeder.php b/api/database/seeders/DevSeeder.php index 9f000d47..821b61a7 100644 --- a/api/database/seeders/DevSeeder.php +++ b/api/database/seeders/DevSeeder.php @@ -71,19 +71,20 @@ class DevSeeder extends Seeder // ── Users (8) ── $usersData = [ - ['email' => 'admin@crewli.test', 'name' => 'Super Admin', 'app_role' => 'super_admin', 'org_role' => 'org_admin'], - ['email' => 'bert@feestfabriek.nl', 'name' => 'Bert Hausmans', 'org_role' => 'org_admin'], - ['email' => 'lisa@feestfabriek.nl', 'name' => 'Lisa van den Berg', 'org_role' => 'org_member'], - ['email' => 'ahmed@feestfabriek.nl', 'name' => 'Ahmed Yilmaz', 'org_role' => 'org_member'], - ['email' => 'sara@feestfabriek.nl', 'name' => 'Sara de Groot', 'org_role' => 'org_member'], - ['email' => 'tom@feestfabriek.nl', 'name' => 'Tom Visser', 'org_role' => 'org_member'], - ['email' => 'nina@feestfabriek.nl', 'name' => 'Nina Jansen', 'org_role' => 'org_member'], - ['email' => 'mark@feestfabriek.nl', 'name' => 'Mark de Boer', 'org_role' => 'org_member'], + ['email' => 'admin@crewli.test', 'first_name' => 'Super', 'last_name' => 'Admin', 'app_role' => 'super_admin', 'org_role' => 'org_admin'], + ['email' => 'bert@feestfabriek.nl', 'first_name' => 'Bert', 'last_name' => 'Hausmans', 'org_role' => 'org_admin'], + ['email' => 'lisa@feestfabriek.nl', 'first_name' => 'Lisa', 'last_name' => 'van den Berg', 'org_role' => 'org_member'], + ['email' => 'ahmed@feestfabriek.nl', 'first_name' => 'Ahmed', 'last_name' => 'Yilmaz', 'org_role' => 'org_member'], + ['email' => 'sara@feestfabriek.nl', 'first_name' => 'Sara', 'last_name' => 'de Groot', 'org_role' => 'org_member'], + ['email' => 'tom@feestfabriek.nl', 'first_name' => 'Tom', 'last_name' => 'Visser', 'org_role' => 'org_member'], + ['email' => 'nina@feestfabriek.nl', 'first_name' => 'Nina', 'last_name' => 'Jansen', 'org_role' => 'org_member'], + ['email' => 'mark@feestfabriek.nl', 'first_name' => 'Mark', 'last_name' => 'de Boer', 'org_role' => 'org_member'], ]; foreach ($usersData as $data) { $user = User::create([ - 'name' => $data['name'], + 'first_name' => $data['first_name'], + 'last_name' => $data['last_name'], 'email' => $data['email'], 'password' => Hash::make('password'), ]); @@ -99,12 +100,12 @@ class DevSeeder extends Seeder // ── Companies (6) ── $companiesData = [ - ['name' => 'Tap & Co Horeca', 'type' => 'supplier', 'contact_name' => 'Jan Tapper', 'contact_email' => 'jan@tapco.nl', 'contact_phone' => '+31612340001'], - ['name' => 'SecureEvent BV', 'type' => 'supplier', 'contact_name' => 'Klaas Veilig', 'contact_email' => 'klaas@secureevent.nl', 'contact_phone' => '+31612340002'], - ['name' => 'Podiumtechniek Rijnmond', 'type' => 'supplier', 'contact_name' => 'Pieter Geluid', 'contact_email' => 'pieter@podiumtechniek.nl', 'contact_phone' => '+31612340003'], - ['name' => 'Brouwerij De Schelde', 'type' => 'partner', 'contact_name' => 'Eva Brouwer', 'contact_email' => 'eva@brouwerijdeschelde.nl', 'contact_phone' => '+31612340004'], - ['name' => 'Van Dijk Catering', 'type' => 'supplier', 'contact_name' => 'Maria van Dijk', 'contact_email' => 'maria@vandijkcatering.nl', 'contact_phone' => '+31612340005'], - ['name' => 'Rotterdam Festivals', 'type' => 'agency', 'contact_name' => 'Femke de Wit', 'contact_email' => 'femke@rotterdamfestivals.nl', 'contact_phone' => '+31612340006'], + ['name' => 'Tap & Co Horeca', 'type' => 'supplier', 'contact_first_name' => 'Jan', 'contact_last_name' => 'Tapper', 'contact_email' => 'jan@tapco.nl', 'contact_phone' => '+31612340001'], + ['name' => 'SecureEvent BV', 'type' => 'supplier', 'contact_first_name' => 'Klaas', 'contact_last_name' => 'Veilig', 'contact_email' => 'klaas@secureevent.nl', 'contact_phone' => '+31612340002'], + ['name' => 'Podiumtechniek Rijnmond', 'type' => 'supplier', 'contact_first_name' => 'Pieter', 'contact_last_name' => 'Geluid', 'contact_email' => 'pieter@podiumtechniek.nl', 'contact_phone' => '+31612340003'], + ['name' => 'Brouwerij De Schelde', 'type' => 'partner', 'contact_first_name' => 'Eva', 'contact_last_name' => 'Brouwer', 'contact_email' => 'eva@brouwerijdeschelde.nl', 'contact_phone' => '+31612340004'], + ['name' => 'Van Dijk Catering', 'type' => 'supplier', 'contact_first_name' => 'Maria', 'contact_last_name' => 'van Dijk', 'contact_email' => 'maria@vandijkcatering.nl', 'contact_phone' => '+31612340005'], + ['name' => 'Rotterdam Festivals', 'type' => 'agency', 'contact_first_name' => 'Femke', 'contact_last_name' => 'de Wit', 'contact_email' => 'femke@rotterdamfestivals.nl', 'contact_phone' => '+31612340006'], ]; foreach ($companiesData as $data) { @@ -455,58 +456,59 @@ class DevSeeder extends Seeder // Create user accounts for volunteers who need user_id links $volunteerUsers = []; foreach ([ - ['name' => 'Jan de Vries', 'email' => 'jan@gmail.com'], - ['name' => 'Ahmed Hassan', 'email' => 'ahmed.h@gmail.com'], - ['name' => 'Tom Visser', 'email' => 'tom.visser@gmail.com'], - ['name' => 'Lotte de Jong', 'email' => 'lotte@gmail.com'], - ['name' => 'Pieter Geluid', 'email' => 'pieter@podiumtechniek.nl'], + ['first_name' => 'Jan', 'last_name' => 'de Vries', 'email' => 'jan@gmail.com'], + ['first_name' => 'Ahmed', 'last_name' => 'Hassan', 'email' => 'ahmed.h@gmail.com'], + ['first_name' => 'Tom', 'last_name' => 'Visser', 'email' => 'tom.visser@gmail.com'], + ['first_name' => 'Lotte', 'last_name' => 'de Jong', 'email' => 'lotte@gmail.com'], + ['first_name' => 'Pieter', 'last_name' => 'Geluid', 'email' => 'pieter@podiumtechniek.nl'], ] as $u) { $volunteerUsers[$u['email']] = User::create([ - 'name' => $u['name'], + 'first_name' => $u['first_name'], + 'last_name' => $u['last_name'], 'email' => $u['email'], 'password' => Hash::make('password'), ]); } // 15 named volunteers - $jan = Person::create(['event_id' => $festival->id, 'crowd_type_id' => $vol, 'user_id' => $volunteerUsers['jan@gmail.com']->id, 'name' => 'Jan de Vries', 'email' => 'jan@gmail.com', 'phone' => '+31612345001', 'status' => 'approved']); - $lisaB = Person::create(['event_id' => $festival->id, 'crowd_type_id' => $vol, 'name' => 'Lisa 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, 'name' => 'Ahmed Hassan', 'email' => 'ahmed.h@gmail.com', 'phone' => '+31612345003', 'status' => 'approved']); - $saraJ = Person::create(['event_id' => $festival->id, 'crowd_type_id' => $vol, 'name' => 'Sara 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, 'name' => 'Tom Visser', 'email' => 'tom.visser@gmail.com', 'phone' => '+31612345005', 'status' => 'approved']); - $fatima = Person::create(['event_id' => $festival->id, 'crowd_type_id' => $vol, 'name' => 'Fatima El Amrani', 'email' => 'fatima@gmail.com', 'phone' => '+31612345006', 'status' => 'approved']); - $daan = Person::create(['event_id' => $festival->id, 'crowd_type_id' => $vol, 'name' => 'Daan Smit', 'email' => 'daan.smit@gmail.com', 'phone' => '+31612345007', 'status' => 'pending']); - Person::create(['event_id' => $festival->id, 'crowd_type_id' => $vol, 'name' => 'Sophie Mulder', 'email' => 'sophie.m@hotmail.com', 'phone' => '+31612345008', 'status' => 'pending']); - Person::create(['event_id' => $festival->id, 'crowd_type_id' => $vol, 'name' => 'Jesse van Dijk', 'email' => 'jesse@gmail.com', 'phone' => '+31612345009', 'status' => 'applied']); - Person::create(['event_id' => $festival->id, 'crowd_type_id' => $vol, 'name' => 'Noa Hendriks', 'email' => 'noa.h@outlook.com', 'phone' => '+31612345010', 'status' => 'applied']); - Person::create(['event_id' => $festival->id, 'crowd_type_id' => $vol, 'name' => 'Kevin 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, 'name' => 'Priya 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, 'name' => 'Lotte de Jong', 'email' => 'lotte@gmail.com', 'phone' => '+31612345013', 'status' => 'approved']); - $robin = Person::create(['event_id' => $festival->id, 'crowd_type_id' => $vol, 'name' => 'Robin Peters', 'email' => 'robin.p@hotmail.com', 'phone' => '+31612345014', 'status' => 'approved']); - $emma = Person::create(['event_id' => $festival->id, 'crowd_type_id' => $vol, 'name' => 'Emma 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']); + $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]); // 6 named crew - $klaas = Person::create(['event_id' => $festival->id, 'crowd_type_id' => $crew, 'company_id' => $this->companies['SecureEvent BV']->id, 'name' => 'Klaas Veilig Jr.', 'email' => 'klaas.jr@secureevent.nl', 'phone' => '+31612345016', 'status' => 'approved']); - $dennis = Person::create(['event_id' => $festival->id, 'crowd_type_id' => $crew, 'company_id' => $this->companies['SecureEvent BV']->id, 'name' => 'Dennis Schild', 'email' => 'dennis@secureevent.nl', 'phone' => '+31612345017', 'status' => 'approved']); - $pieter = Person::create(['event_id' => $festival->id, 'crowd_type_id' => $crew, 'company_id' => $this->companies['Podiumtechniek Rijnmond']->id, 'user_id' => $volunteerUsers['pieter@podiumtechniek.nl']->id, 'name' => 'Pieter Geluid', 'email' => 'pieter@podiumtechniek.nl', 'phone' => '+31612345018', 'status' => 'approved']); - Person::create(['event_id' => $festival->id, 'crowd_type_id' => $crew, 'company_id' => $this->companies['Podiumtechniek Rijnmond']->id, 'name' => 'Marco Licht', 'email' => 'marco@podiumtechniek.nl', 'phone' => '+31612345019', 'status' => 'approved']); - $eva = Person::create(['event_id' => $festival->id, 'crowd_type_id' => $crew, 'company_id' => $this->companies['Brouwerij De Schelde']->id, 'name' => 'Eva Brouwer', 'email' => 'eva@brouwerijdeschelde.nl', 'phone' => '+31612345020', 'status' => 'approved']); - $maria = Person::create(['event_id' => $festival->id, 'crowd_type_id' => $crew, 'company_id' => $this->companies['Van Dijk Catering']->id, 'name' => 'Maria van Dijk', 'email' => 'maria@vandijkcatering.nl', 'phone' => '+31612345021', 'status' => 'approved']); + $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']); + $dennis = Person::create(['event_id' => $festival->id, 'crowd_type_id' => $crew, 'company_id' => $this->companies['SecureEvent BV']->id, 'first_name' => 'Dennis', 'last_name' => 'Schild', 'email' => 'dennis@secureevent.nl', 'phone' => '+31612345017', 'status' => 'approved']); + $pieter = Person::create(['event_id' => $festival->id, 'crowd_type_id' => $crew, 'company_id' => $this->companies['Podiumtechniek Rijnmond']->id, 'user_id' => $volunteerUsers['pieter@podiumtechniek.nl']->id, 'first_name' => 'Pieter', 'last_name' => 'Geluid', 'email' => 'pieter@podiumtechniek.nl', 'phone' => '+31612345018', 'status' => 'approved']); + Person::create(['event_id' => $festival->id, 'crowd_type_id' => $crew, 'company_id' => $this->companies['Podiumtechniek Rijnmond']->id, 'first_name' => 'Marco', 'last_name' => 'Licht', 'email' => 'marco@podiumtechniek.nl', 'phone' => '+31612345019', 'status' => 'approved']); + $eva = Person::create(['event_id' => $festival->id, 'crowd_type_id' => $crew, 'company_id' => $this->companies['Brouwerij De Schelde']->id, 'first_name' => 'Eva', 'last_name' => 'Brouwer', 'email' => 'eva@brouwerijdeschelde.nl', 'phone' => '+31612345020', 'status' => 'approved']); + $maria = Person::create(['event_id' => $festival->id, 'crowd_type_id' => $crew, 'company_id' => $this->companies['Van Dijk Catering']->id, 'first_name' => 'Maria', 'last_name' => 'van Dijk', 'email' => 'maria@vandijkcatering.nl', 'phone' => '+31612345021', 'status' => 'approved']); // 3 named press - Person::create(['event_id' => $festival->id, 'crowd_type_id' => $press, 'name' => 'Joris van Laar', 'email' => 'joris@pers.nl', 'phone' => '+31612345022', 'status' => 'approved']); - Person::create(['event_id' => $festival->id, 'crowd_type_id' => $press, 'name' => 'Tamara Smeets', 'email' => 'tamara@pers.nl', 'phone' => '+31612345023', 'status' => 'approved']); - Person::create(['event_id' => $festival->id, 'crowd_type_id' => $press, 'name' => 'Sven Pieterse', 'email' => 'sven@pers.nl', 'phone' => '+31612345024', 'status' => 'pending']); + Person::create(['event_id' => $festival->id, 'crowd_type_id' => $press, 'first_name' => 'Joris', 'last_name' => 'van Laar', 'email' => 'joris@pers.nl', 'phone' => '+31612345022', 'status' => 'approved']); + Person::create(['event_id' => $festival->id, 'crowd_type_id' => $press, 'first_name' => 'Tamara', 'last_name' => 'Smeets', 'email' => 'tamara@pers.nl', 'phone' => '+31612345023', 'status' => 'approved']); + Person::create(['event_id' => $festival->id, 'crowd_type_id' => $press, 'first_name' => 'Sven', 'last_name' => 'Pieterse', 'email' => 'sven@pers.nl', 'phone' => '+31612345024', 'status' => 'pending']); // 4 named guests - Person::create(['event_id' => $festival->id, 'crowd_type_id' => $guest, 'name' => 'Burgemeester Jan Slagter', 'email' => 'burgemeester@echt.nl', 'phone' => '+31612345025', 'status' => 'approved']); - Person::create(['event_id' => $festival->id, 'crowd_type_id' => $guest, 'name' => 'Wethouder Petra Kamps', 'email' => 'wethouder@echt.nl', 'phone' => '+31612345026', 'status' => 'approved']); - Person::create(['event_id' => $festival->id, 'crowd_type_id' => $guest, 'name' => 'Jan Sponsor', 'email' => 'sponsor@bedrijf.nl', 'phone' => '+31612345027', 'status' => 'approved']); - Person::create(['event_id' => $festival->id, 'crowd_type_id' => $guest, 'name' => 'Gast van Artiest', 'email' => 'artiestgast@gmail.com', 'phone' => '+31612345028', 'status' => 'invited']); + Person::create(['event_id' => $festival->id, 'crowd_type_id' => $guest, 'first_name' => 'Jan', 'last_name' => 'Slagter', 'email' => 'burgemeester@echt.nl', 'phone' => '+31612345025', 'status' => 'approved']); + Person::create(['event_id' => $festival->id, 'crowd_type_id' => $guest, 'first_name' => 'Petra', 'last_name' => 'Kamps', 'email' => 'wethouder@echt.nl', 'phone' => '+31612345026', 'status' => 'approved']); + Person::create(['event_id' => $festival->id, 'crowd_type_id' => $guest, 'first_name' => 'Jan', 'last_name' => 'Sponsor', 'email' => 'sponsor@bedrijf.nl', 'phone' => '+31612345027', 'status' => 'approved']); + Person::create(['event_id' => $festival->id, 'crowd_type_id' => $guest, 'first_name' => 'Gast', 'last_name' => 'van Artiest', 'email' => 'artiestgast@gmail.com', 'phone' => '+31612345028', 'status' => 'invited']); // 2 named suppliers - Person::create(['event_id' => $festival->id, 'crowd_type_id' => $supplier, 'company_id' => $this->companies['Tap & Co Horeca']->id, 'name' => 'Hans Tapper', 'email' => 'hans@tapco.nl', 'phone' => '+31612345029', 'status' => 'approved']); - Person::create(['event_id' => $festival->id, 'crowd_type_id' => $supplier, 'company_id' => $this->companies['Van Dijk Catering']->id, 'name' => 'Frank van Dijk', 'email' => 'frank@vandijkcatering.nl', 'phone' => '+31612345030', 'status' => 'pending']); + Person::create(['event_id' => $festival->id, 'crowd_type_id' => $supplier, 'company_id' => $this->companies['Tap & Co Horeca']->id, 'first_name' => 'Hans', 'last_name' => 'Tapper', 'email' => 'hans@tapco.nl', 'phone' => '+31612345029', 'status' => 'approved']); + Person::create(['event_id' => $festival->id, 'crowd_type_id' => $supplier, 'company_id' => $this->companies['Van Dijk Catering']->id, 'first_name' => 'Frank', 'last_name' => 'van Dijk', 'email' => 'frank@vandijkcatering.nl', 'phone' => '+31612345030', 'status' => 'pending']); // ── Factory persons (120) ── diff --git a/api/tests/Feature/Api/V1/AssignablePersonsTest.php b/api/tests/Feature/Api/V1/AssignablePersonsTest.php index cf16c815..de92ee7e 100644 --- a/api/tests/Feature/Api/V1/AssignablePersonsTest.php +++ b/api/tests/Feature/Api/V1/AssignablePersonsTest.php @@ -199,8 +199,8 @@ class AssignablePersonsTest extends TestCase $shift1 = $this->createOpenShift(); $shift2 = $this->createOpenShift(['festival_section_id' => $this->otherSection->id]); - $available = $this->createPerson(['name' => 'Anna Bakker']); - $conflicted = $this->createPerson(['name' => 'Bob Jansen']); + $available = $this->createPerson(['first_name' => 'Anna', 'last_name' => 'Bakker']); + $conflicted = $this->createPerson(['first_name' => 'Bob', 'last_name' => 'Jansen']); ShiftAssignment::factory()->create([ 'shift_id' => $shift1->id, diff --git a/api/tests/Feature/Api/V1/RegistrationSettingsTest.php b/api/tests/Feature/Api/V1/RegistrationSettingsTest.php index f74b904a..3f71c220 100644 --- a/api/tests/Feature/Api/V1/RegistrationSettingsTest.php +++ b/api/tests/Feature/Api/V1/RegistrationSettingsTest.php @@ -214,7 +214,8 @@ class RegistrationSettingsTest extends TestCase ]); $response = $this->postJson("/api/v1/events/{$event->id}/volunteer-register", [ - 'name' => 'Test Vrijwilliger', + 'first_name' => 'Test', + 'last_name' => 'Vrijwilliger', 'email' => 'test-section-pref@example.nl', 'section_preferences' => [ ['section_name' => 'Backstage', 'priority' => 1], diff --git a/api/tests/Feature/Api/V1/VolunteerRegistrationTest.php b/api/tests/Feature/Api/V1/VolunteerRegistrationTest.php index 944968bc..06ddcbf6 100644 --- a/api/tests/Feature/Api/V1/VolunteerRegistrationTest.php +++ b/api/tests/Feature/Api/V1/VolunteerRegistrationTest.php @@ -54,7 +54,8 @@ class VolunteerRegistrationTest extends TestCase public function test_volunteer_can_register_with_all_fields(): void { $response = $this->postJson("/api/v1/events/{$this->event->id}/volunteer-register", [ - 'name' => 'Jan de Vries', + 'first_name' => 'Jan', + 'last_name' => 'de Vries', 'email' => 'jan@voorbeeld.nl', 'phone' => '+31612345678', 'tshirt_size' => 'L', @@ -76,7 +77,8 @@ class VolunteerRegistrationTest extends TestCase public function test_volunteer_can_register_with_minimal_fields(): void { $response = $this->postJson("/api/v1/events/{$this->event->id}/volunteer-register", [ - 'name' => 'Sophie Bakker', + 'first_name' => 'Sophie', + 'last_name' => 'Bakker', 'email' => 'sophie@voorbeeld.nl', ]); @@ -84,7 +86,8 @@ class VolunteerRegistrationTest extends TestCase $this->assertDatabaseHas('persons', [ 'email' => 'sophie@voorbeeld.nl', - 'name' => 'Sophie Bakker', + 'first_name' => 'Sophie', + 'last_name' => 'Bakker', 'event_id' => $this->event->id, ]); } @@ -101,7 +104,8 @@ class VolunteerRegistrationTest extends TestCase TimeSlot::factory()->create(['event_id' => $festival->id]); $response = $this->postJson("/api/v1/events/{$subEvent->id}/volunteer-register", [ - 'name' => 'Pieter Jansen', + 'first_name' => 'Pieter', + 'last_name' => 'Jansen', 'email' => 'pieter@voorbeeld.nl', ]); @@ -118,7 +122,8 @@ class VolunteerRegistrationTest extends TestCase $timeSlot2 = TimeSlot::factory()->create(['event_id' => $this->event->id]); $response = $this->postJson("/api/v1/events/{$this->event->id}/volunteer-register", [ - 'name' => 'Fleur Vermeer', + 'first_name' => 'Fleur', + 'last_name' => 'Vermeer', 'email' => 'fleur@voorbeeld.nl', 'availabilities' => [ ['time_slot_id' => $this->timeSlot->id, 'preference_level' => 4], @@ -145,7 +150,8 @@ class VolunteerRegistrationTest extends TestCase public function test_registration_stores_custom_fields(): void { $response = $this->postJson("/api/v1/events/{$this->event->id}/volunteer-register", [ - 'name' => 'Daan Mulder', + 'first_name' => 'Daan', + 'last_name' => 'Mulder', 'email' => 'daan@voorbeeld.nl', 'tshirt_size' => 'XL', 'motivation' => 'Ik vind festivals geweldig.', @@ -167,12 +173,14 @@ class VolunteerRegistrationTest extends TestCase public function test_duplicate_email_rejected(): void { $this->postJson("/api/v1/events/{$this->event->id}/volunteer-register", [ - 'name' => 'Anna Smit', + 'first_name' => 'Anna', + 'last_name' => 'Smit', 'email' => 'anna@voorbeeld.nl', ]); $response = $this->postJson("/api/v1/events/{$this->event->id}/volunteer-register", [ - 'name' => 'Anna Smit', + 'first_name' => 'Anna', + 'last_name' => 'Smit', 'email' => 'anna@voorbeeld.nl', ]); @@ -189,7 +197,8 @@ class VolunteerRegistrationTest extends TestCase ]); $response = $this->postJson("/api/v1/events/{$this->event->id}/volunteer-register", [ - 'name' => 'Herkan Poging', + 'first_name' => 'Herkan', + 'last_name' => 'Poging', 'email' => 'herkan@voorbeeld.nl', ]); @@ -209,7 +218,8 @@ class VolunteerRegistrationTest extends TestCase ]); $response = $this->postJson("/api/v1/events/{$draftEvent->id}/volunteer-register", [ - 'name' => 'Test Persoon', + 'first_name' => 'Test', + 'last_name' => 'Persoon', 'email' => 'test@voorbeeld.nl', ]); @@ -219,7 +229,8 @@ class VolunteerRegistrationTest extends TestCase public function test_invalid_time_slot_rejected(): void { $response = $this->postJson("/api/v1/events/{$this->event->id}/volunteer-register", [ - 'name' => 'Bas van Dijk', + 'first_name' => 'Bas', + 'last_name' => 'van Dijk', 'email' => 'bas@voorbeeld.nl', 'availabilities' => [ ['time_slot_id' => '01JNONEXISTENT00000000000', 'preference_level' => 3], @@ -235,7 +246,8 @@ class VolunteerRegistrationTest extends TestCase public function test_authenticated_user_registration(): void { $user = User::factory()->create([ - 'name' => 'Lisa de Groot', + 'first_name' => 'Lisa', + 'last_name' => 'de Groot', 'email' => 'lisa@voorbeeld.nl', ]); $this->organisation->users()->attach($user, ['role' => 'org_member']); @@ -255,7 +267,8 @@ class VolunteerRegistrationTest extends TestCase public function test_authenticated_ignores_request_email(): void { $user = User::factory()->create([ - 'name' => 'Mark Visser', + 'first_name' => 'Mark', + 'last_name' => 'Visser', 'email' => 'mark@voorbeeld.nl', ]); $this->organisation->users()->attach($user, ['role' => 'org_member']); @@ -274,7 +287,8 @@ class VolunteerRegistrationTest extends TestCase public function test_authenticated_duplicate_rejected(): void { $user = User::factory()->create([ - 'name' => 'Eva Hendriks', + 'first_name' => 'Eva', + 'last_name' => 'Hendriks', 'email' => 'eva@voorbeeld.nl', ]); $this->organisation->users()->attach($user, ['role' => 'org_member']); @@ -326,7 +340,7 @@ class VolunteerRegistrationTest extends TestCase public function test_authenticated_user_gets_person(): void { - $user = User::factory()->create(['name' => 'Karin Bos']); + $user = User::factory()->create(['first_name' => 'Karin', 'last_name' => 'Bos']); $this->organisation->users()->attach($user, ['role' => 'org_member']); Person::factory()->create([ @@ -346,7 +360,7 @@ class VolunteerRegistrationTest extends TestCase public function test_authenticated_user_no_person_returns_404(): void { - $user = User::factory()->create(['name' => 'Tom Kuiper']); + $user = User::factory()->create(['first_name' => 'Tom', 'last_name' => 'Kuiper']); Sanctum::actingAs($user); $response = $this->getJson("/api/v1/portal/me?event_id={$this->event->id}"); @@ -357,7 +371,7 @@ class VolunteerRegistrationTest extends TestCase public function test_missing_event_id_returns_422(): void { - $user = User::factory()->create(['name' => 'Sanne Bruin']); + $user = User::factory()->create(['first_name' => 'Sanne', 'last_name' => 'Bruin']); Sanctum::actingAs($user); $response = $this->getJson('/api/v1/portal/me'); diff --git a/api/tests/Feature/Auth/LoginTest.php b/api/tests/Feature/Auth/LoginTest.php index 35b41154..114ddc8c 100644 --- a/api/tests/Feature/Auth/LoginTest.php +++ b/api/tests/Feature/Auth/LoginTest.php @@ -24,7 +24,7 @@ class LoginTest extends TestCase $response->assertOk() ->assertJsonStructure([ 'success', - 'data' => ['user' => ['id', 'name', 'email'], 'token'], + 'data' => ['user' => ['id', 'first_name', 'last_name', 'full_name', 'email'], 'token'], 'message', ]) ->assertJson(['success' => true]); diff --git a/api/tests/Feature/Auth/MeTest.php b/api/tests/Feature/Auth/MeTest.php index e2789efa..b3e4a93f 100644 --- a/api/tests/Feature/Auth/MeTest.php +++ b/api/tests/Feature/Auth/MeTest.php @@ -35,7 +35,7 @@ class MeTest extends TestCase ->assertJsonStructure([ 'success', 'data' => [ - 'id', 'name', 'email', 'timezone', 'locale', + 'id', 'first_name', 'last_name', 'full_name', 'email', 'timezone', 'locale', 'organisations', 'app_roles', 'permissions', ], ]); diff --git a/api/tests/Feature/Company/CompanyTest.php b/api/tests/Feature/Company/CompanyTest.php index 9a7a4eef..4b53bf12 100644 --- a/api/tests/Feature/Company/CompanyTest.php +++ b/api/tests/Feature/Company/CompanyTest.php @@ -100,7 +100,8 @@ class CompanyTest extends TestCase $response = $this->postJson("/api/v1/organisations/{$this->organisation->id}/companies", [ 'name' => 'Catering Janssen', 'type' => 'supplier', - 'contact_name' => 'Jan Janssen', + 'contact_first_name' => 'Jan', + 'contact_last_name' => 'Janssen', 'contact_email' => 'jan@janssen.nl', 'contact_phone' => '+31612345678', ]); diff --git a/api/tests/Feature/Event/FestivalEventTest.php b/api/tests/Feature/Event/FestivalEventTest.php index 08fd57d4..ad4da0c0 100644 --- a/api/tests/Feature/Event/FestivalEventTest.php +++ b/api/tests/Feature/Event/FestivalEventTest.php @@ -201,14 +201,16 @@ class FestivalEventTest extends TestCase Person::factory()->create([ 'event_id' => $this->festival->id, 'crowd_type_id' => $this->crowdType->id, - 'name' => 'Jan Festivalmedewerker', + 'first_name' => 'Jan', + 'last_name' => 'Festivalmedewerker', ]); // Create a person on the sub-event Person::factory()->create([ 'event_id' => $this->subEvent->id, 'crowd_type_id' => $this->crowdType->id, - 'name' => 'Piet Dagvrijwilliger', + 'first_name' => 'Piet', + 'last_name' => 'Dagvrijwilliger', ]); Sanctum::actingAs($this->orgAdmin); @@ -218,7 +220,7 @@ class FestivalEventTest extends TestCase $response->assertOk(); - $personNames = collect($response->json('data'))->pluck('name')->all(); + $personNames = collect($response->json('data'))->pluck('full_name')->all(); $this->assertContains('Jan Festivalmedewerker', $personNames); $this->assertNotContains('Piet Dagvrijwilliger', $personNames); } diff --git a/api/tests/Feature/Invitation/InvitationTest.php b/api/tests/Feature/Invitation/InvitationTest.php index b964435b..d33cbf84 100644 --- a/api/tests/Feature/Invitation/InvitationTest.php +++ b/api/tests/Feature/Invitation/InvitationTest.php @@ -152,13 +152,14 @@ class InvitationTest extends TestCase ]); $response = $this->postJson("/api/v1/invitations/{$invitation->token}/accept", [ - 'name' => 'New User', + 'first_name' => 'New', + 'last_name' => 'User', 'password' => 'password123', 'password_confirmation' => 'password123', ]); $response->assertOk(); - $response->assertJsonStructure(['data' => ['user' => ['id', 'name', 'email'], 'token']]); + $response->assertJsonStructure(['data' => ['user' => ['id', 'first_name', 'last_name', 'full_name', 'email'], 'token']]); $this->assertDatabaseHas('users', ['email' => 'newuser@test.nl']); $this->assertDatabaseHas('organisation_user', [ @@ -204,7 +205,8 @@ class InvitationTest extends TestCase ]); $response = $this->postJson("/api/v1/invitations/{$invitation->token}/accept", [ - 'name' => 'Test', + 'first_name' => 'Test', + 'last_name' => 'User', 'password' => 'password123', 'password_confirmation' => 'password123', ]); @@ -222,7 +224,8 @@ class InvitationTest extends TestCase ]); $response = $this->postJson("/api/v1/invitations/{$invitation->token}/accept", [ - 'name' => 'Test', + 'first_name' => 'Test', + 'last_name' => 'User', 'password' => 'password123', 'password_confirmation' => 'password123', ]); diff --git a/api/tests/Feature/Person/PersonTest.php b/api/tests/Feature/Person/PersonTest.php index 56da4b54..3b36d060 100644 --- a/api/tests/Feature/Person/PersonTest.php +++ b/api/tests/Feature/Person/PersonTest.php @@ -119,17 +119,19 @@ class PersonTest extends TestCase $response = $this->postJson("/api/v1/events/{$this->event->id}/persons", [ 'crowd_type_id' => $this->crowdType->id, - 'name' => 'Jan de Vries', + 'first_name' => 'Jan', + 'last_name' => 'de Vries', 'email' => 'jan@test.nl', 'phone' => '0612345678', ]); $response->assertCreated() - ->assertJson(['data' => ['name' => 'Jan de Vries', 'email' => 'jan@test.nl', 'status' => 'pending']]); + ->assertJson(['data' => ['first_name' => 'Jan', 'last_name' => 'de Vries', 'email' => 'jan@test.nl', 'status' => 'pending']]); $this->assertDatabaseHas('persons', [ 'event_id' => $this->event->id, - 'name' => 'Jan de Vries', + 'first_name' => 'Jan', + 'last_name' => 'de Vries', 'email' => 'jan@test.nl', ]); } diff --git a/api/tests/Feature/PersonIdentity/PersonIdentityMatchTest.php b/api/tests/Feature/PersonIdentity/PersonIdentityMatchTest.php index 3417603b..bad152be 100644 --- a/api/tests/Feature/PersonIdentity/PersonIdentityMatchTest.php +++ b/api/tests/Feature/PersonIdentity/PersonIdentityMatchTest.php @@ -66,7 +66,8 @@ class PersonIdentityMatchTest extends TestCase $response = $this->postJson("/api/v1/events/{$this->event->id}/persons", [ 'crowd_type_id' => $this->crowdType->id, - 'name' => 'Jan de Vries', + 'first_name' => 'Jan', + 'last_name' => 'de Vries', 'email' => 'jan@example.nl', ]); @@ -93,7 +94,8 @@ class PersonIdentityMatchTest extends TestCase $response = $this->postJson("/api/v1/events/{$this->event->id}/persons", [ 'crowd_type_id' => $this->crowdType->id, - 'name' => 'Piet Jansen', + 'first_name' => 'Piet', + 'last_name' => 'Jansen', 'email' => 'unknown@example.nl', ]); diff --git a/apps/app/src/components/crowd-lists/AddPersonToCrowdListDialog.vue b/apps/app/src/components/crowd-lists/AddPersonToCrowdListDialog.vue index 4372856b..d8b1316d 100644 --- a/apps/app/src/components/crowd-lists/AddPersonToCrowdListDialog.vue +++ b/apps/app/src/components/crowd-lists/AddPersonToCrowdListDialog.vue @@ -23,7 +23,7 @@ const errorMessage = ref('') const personItems = computed(() => (personsResponse.value?.data ?? []).map((p: Person) => ({ - title: p.name, + title: p.full_name, value: p.id, subtitle: p.email, })), diff --git a/apps/app/src/components/crowd-lists/CrowdListDetailPanel.vue b/apps/app/src/components/crowd-lists/CrowdListDetailPanel.vue index 1c69b564..c7f87661 100644 --- a/apps/app/src/components/crowd-lists/CrowdListDetailPanel.vue +++ b/apps/app/src/components/crowd-lists/CrowdListDetailPanel.vue @@ -68,7 +68,7 @@ const filteredPersons = computed(() => { if (searchQuery.value) { const q = searchQuery.value.toLowerCase() result = result.filter( - (p: Person) => p.name.toLowerCase().includes(q) || p.email.toLowerCase().includes(q), + (p: Person) => p.full_name.toLowerCase().includes(q) || p.email.toLowerCase().includes(q), ) } @@ -181,7 +181,7 @@ function getInitials(name: string) { function onApprove(person: Person) { approvePerson(person.id, { onSuccess: () => { - successMessage.value = `${person.name} goedgekeurd` + successMessage.value = `${person.full_name} goedgekeurd` showSuccess.value = true refetchPersons() }, @@ -195,7 +195,7 @@ function onRemoveConfirm(person: Person) { function onRemoveExecute() { if (!removingPerson.value || !props.crowdList) return - const name = removingPerson.value.name + const name = removingPerson.value.full_name removePerson( { listId: props.crowdList.id, personId: removingPerson.value.id }, @@ -613,11 +613,11 @@ function onApproveAllExecute() { color="primary" variant="tonal" > - {{ getInitials(person.name) }} + {{ getInitials(person.full_name) }}
- {{ person.name }} + {{ person.full_name }}
{{ person.email }}
@@ -715,7 +715,7 @@ function onApproveAllExecute() {
>
diff --git a/apps/app/src/components/events/EventTabsNav.vue b/apps/app/src/components/events/EventTabsNav.vue
index 705e0773..def3c731 100644
--- a/apps/app/src/components/events/EventTabsNav.vue
+++ b/apps/app/src/components/events/EventTabsNav.vue
@@ -4,6 +4,7 @@ import { dutchPlural } from '@/lib/dutch-plural'
import { useAuthStore } from '@/stores/useAuthStore'
import { useOrganisationStore } from '@/stores/useOrganisationStore'
import EditEventDialog from '@/components/events/EditEventDialog.vue'
+import RegistrationLinkCard from '@/components/events/RegistrationLinkCard.vue'
import type { EventStatus } from '@/types/event'
const route = useRoute()
@@ -177,6 +178,12 @@ const backRoute = computed(() => {
{{ registrationUrl }}
+
+
+
+ Zet de status op 'Registratie open' om het formulier te activeren.
+
+
+
{{ person.email }}
diff --git a/apps/app/src/components/sections/AssignShiftDialog.vue b/apps/app/src/components/sections/AssignShiftDialog.vue
index 386ecf1c..2253b9b7 100644
--- a/apps/app/src/components/sections/AssignShiftDialog.vue
+++ b/apps/app/src/components/sections/AssignShiftDialog.vue
@@ -25,6 +25,11 @@ const selectedPersonId = ref
{{ authStore.currentOrganisation?.name ?? 'Geen organisatie geselecteerd' }}
diff --git a/apps/app/src/pages/events/[id]/persons/index.vue b/apps/app/src/pages/events/[id]/persons/index.vue
index b7494d2b..7b73cebd 100644
--- a/apps/app/src/pages/events/[id]/persons/index.vue
+++ b/apps/app/src/pages/events/[id]/persons/index.vue
@@ -84,7 +84,7 @@ const statusColor: Record
- Welkom, {{ authStore.user?.name ?? 'gebruiker' }}! 👋
+ Welkom, {{ authStore.user?.full_name ?? 'gebruiker' }}! 👋