From 84162b577d3d96f5f50bd1af8739df6ab62a436a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Anna-Sara=20S=C3=A9lea?= Date: Sat, 15 Nov 2025 17:06:44 +0100 Subject: [PATCH] Participant resource --- .../Participants/Pages/CreateParticipant.php | 32 ++++ .../Participants/Pages/EditParticipant.php | 20 ++ .../Participants/Pages/ListParticipants.php | 20 ++ .../Participants/ParticipantResource.php | 51 +++++ .../Participants/Schemas/ParticipantForm.php | 102 ++++++++++ .../Participants/Tables/ParticipantsTable.php | 174 ++++++++++++++++++ .../Resources/Users/Pages/CreateUser.php | 11 ++ .../Resources/Users/Pages/EditUser.php | 19 ++ .../Resources/Users/Pages/ListUsers.php | 19 ++ .../Controllers/ParticipantController.php | 174 ++++++++++++++++++ app/Models/Participant.php | 79 ++++++++ ...09_26_165018_create_participants_table.php | 45 +++++ 12 files changed, 746 insertions(+) create mode 100644 app/Filament/Resources/Participants/Pages/CreateParticipant.php create mode 100644 app/Filament/Resources/Participants/Pages/EditParticipant.php create mode 100644 app/Filament/Resources/Participants/Pages/ListParticipants.php create mode 100644 app/Filament/Resources/Participants/ParticipantResource.php create mode 100644 app/Filament/Resources/Participants/Schemas/ParticipantForm.php create mode 100644 app/Filament/Resources/Participants/Tables/ParticipantsTable.php create mode 100644 app/Filament/Resources/Users/Pages/CreateUser.php create mode 100644 app/Filament/Resources/Users/Pages/EditUser.php create mode 100644 app/Filament/Resources/Users/Pages/ListUsers.php create mode 100644 app/Http/Controllers/ParticipantController.php create mode 100644 app/Models/Participant.php create mode 100644 database/migrations/2025_09_26_165018_create_participants_table.php diff --git a/app/Filament/Resources/Participants/Pages/CreateParticipant.php b/app/Filament/Resources/Participants/Pages/CreateParticipant.php new file mode 100644 index 0000000..7ad3ee4 --- /dev/null +++ b/app/Filament/Resources/Participants/Pages/CreateParticipant.php @@ -0,0 +1,32 @@ +count(); + if ($count < 1 && !$data['is_visiting']) { + $data['status'] = "lan"; + } + + else if ($data['is_visiting']) { + $data['status'] = "besök"; + } + + else { + $data['status'] = "reserv"; + } + + return $data; + } +} diff --git a/app/Filament/Resources/Participants/Pages/EditParticipant.php b/app/Filament/Resources/Participants/Pages/EditParticipant.php new file mode 100644 index 0000000..38fe119 --- /dev/null +++ b/app/Filament/Resources/Participants/Pages/EditParticipant.php @@ -0,0 +1,20 @@ + ListParticipants::route('/'), + 'create' => CreateParticipant::route('/create'), + //'edit' => EditParticipant::route('/{record}/edit'), + ]; + } +} diff --git a/app/Filament/Resources/Participants/Schemas/ParticipantForm.php b/app/Filament/Resources/Participants/Schemas/ParticipantForm.php new file mode 100644 index 0000000..12dbab8 --- /dev/null +++ b/app/Filament/Resources/Participants/Schemas/ParticipantForm.php @@ -0,0 +1,102 @@ +components([ + GazeBanner::make() + ->pollTimer(10) + ->hideOnCreate(), + Grid::make() + ->columnSpan('full') + ->columns(2) + ->schema([ + Grid::make() + ->columns(1) + ->schema([ + Radio::make('is_visiting') + ->label('Participating type') + ->boolean(falseLabel: 'LAN', trueLabel: 'Visit'), + ]), + Grid::make() + ->columns(2) + ->schema([ + Grid::make() + ->columns(1) + ->schema([ + Toggle::make('emailed') + ->required() + ->onColor('success') + ->offColor('danger'), + Toggle::make('member') + ->required() + ->onColor('success') + ->offColor('danger'), + ]), + Grid::make() + ->columns(1) + ->schema([ + Toggle::make('paid') + ->required() + ->onColor('success') + ->offColor('danger'), + Toggle::make('gdpr') + ->required() + ->onColor('success') + ->offColor('danger'), + ]) + ]), + ]), + TextInput::make('lan_id') + ->integer(), + Select::make('status') + ->options([ + 'lan' => 'Ordinarie', + 'reserv' => 'Reserv', + 'besök' => 'Besök', + ]), + TextInput::make('first_name') + ->required(), + TextInput::make('surname') + ->required(), + TextInput::make('grade') + ->integer() + ->columnSpan('full') + ->required(), + TextInput::make('phone') + ->tel() + ->default(null), + TextInput::make('email') + ->label('Email address') + ->email() + ->default(null), + TextInput::make('guardian_name') + ->required(), + TextInput::make('guardian_phone') + ->tel() + ->required(), + TextInput::make('guardian_email') + ->required(), + TextInput::make('special_diet') + ->default(null), + TextInput::make('friends') + ->default(null) + ->columnSpan('full'), + Textarea::make('comment') + ->columnSpan('full'), + ]); + } +} diff --git a/app/Filament/Resources/Participants/Tables/ParticipantsTable.php b/app/Filament/Resources/Participants/Tables/ParticipantsTable.php new file mode 100644 index 0000000..a46d438 --- /dev/null +++ b/app/Filament/Resources/Participants/Tables/ParticipantsTable.php @@ -0,0 +1,174 @@ +groups([ + Group::make('status') + ->label('Status') + ->collapsible(), + ]) + ->defaultGroup('status') + //->groupsOnly() + ->recordAction(null) + ->headerActions([ + ExportAction::make() + ->exporter(ParticipantExporter::class), + ]) + ->columns([ + TextColumn::make('lan_id') + ->label('ID') + ->searchable() + ->sortable(), + TextColumn::make('status') + ->label('Status') + ->badge() + ->summarize(Count::make()->label('')) + ->color(fn (string $state): string => match ($state) { + 'lan' => 'success', + 'reserv' => 'warning', + 'besök' => 'gray' + }) + ->formatStateUsing(fn (string $state): string => __(ucfirst($state))), + IconColumn::make('paid') + ->boolean() + ->sortable(), + IconColumn::make('emailed') + ->boolean() + ->sortable(), + TextColumn::make('first_name') + ->searchable() + ->sortable(), + TextColumn::make('surname') + ->searchable() + ->sortable(), + TextColumn::make('grade') + ->searchable() + ->sortable(), + TextColumn::make('phone') + ->searchable() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + TextColumn::make('email') + ->label('Email address') + ->searchable() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + TextColumn::make('guardian_name') + ->searchable() + ->sortable(), + TextColumn::make('guardian_phone') + ->searchable() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + TextColumn::make('guardian_email') + ->searchable() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + TextColumn::make('is_visiting') + ->label('Type') + ->formatStateUsing(fn (string $state): string => $state?'visit':'lan') + ->searchable() + ->sortable() + ->badge() + ->color('gray') + ->toggleable(isToggledHiddenByDefault: true), + + IconColumn::make('member') + ->boolean() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + TextColumn::make('comment') + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + IconColumn::make('gdpr') + ->boolean() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + TextColumn::make('friends') + ->searchable() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + TextColumn::make('special_diet') + ->searchable() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + TextColumn::make('created_at') + ->dateTime() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + TextColumn::make('updated_at') + ->dateTime() + ->sortable() + ->toggleable(isToggledHiddenByDefault: true), + ]) + ->filters([ + // + ]) + ->recordActions([ + EditAction::make() + ->modalWidth() + ->slideOver(), + Action::make('sendEmail') + ->label('Send email') + ->icon(Heroicon::Envelope) + ->schema([ + Select::make('mailtemplate') + ->label('Mailtemplate') + ->options(Mailtemplate::all()->pluck('title', 'id')) + ]) + ->action(function (array $data, Participant $record) { + $mailContent = Mailtemplate::where('id', $data['mailtemplate'])->get(); + Mail::to($record->guardian_email) + ->send(new LanMail($mailContent, $record)); + Participant::where('id', $record->id)->update(['emailed' => true]); + }) + ->hidden(fn($record) => $record->emailed), + Action::make('sendRemindEmail') + ->label('Send remind email') + ->icon(Heroicon::Envelope) + ->schema([ + Select::make('mailtemplate') + ->label('Mailtemplate') + ->options(Mailtemplate::all()->pluck('title', 'id')) + ]) + ->action(function (array $data, Participant $record) { + $mailContent = Mailtemplate::where('id', $data['mailtemplate'])->get(); + Mail::to($record->guardian_email) + ->send(new LanMail($mailContent, $record)); + Participant::where('id', $record->id)->update(['emailed' => true]); + }) + ->hidden(fn($record) => !$record->emailed) + + ]) + ->toolbarActions([ + BulkActionGroup::make([ + DeleteBulkAction::make(), + ]), + ]); + } +} diff --git a/app/Filament/Resources/Users/Pages/CreateUser.php b/app/Filament/Resources/Users/Pages/CreateUser.php new file mode 100644 index 0000000..125b3ff --- /dev/null +++ b/app/Filament/Resources/Users/Pages/CreateUser.php @@ -0,0 +1,11 @@ +ability; + + if ($ability === "key_1") { + + $participants = Participant::all()->makeHidden(['comment', 'emailed', 'paid', 'member', 'gdpr']); + $volunteers = Volunteer::all()->makeHidden(['gdpr']); + + $dataArr = [ + 'participant' => $participants, + 'volunteer' => $volunteers + ]; + + return $dataArr; + } + + if ($ability === "key_2") { + + $participants = Participant::all()->select('participant_id', 'first_name', 'surname'); + $volunteers = Volunteer::all()->select('first_name', 'surname'); + + $dataArr = [ + 'participant' => $participants, + 'volunteer' => $volunteers + ]; + + return $dataArr; + } + + if ($ability === "key_3") { + + $participants = Participant::all()->makeHidden(['comment', 'emailed', 'paid', 'member', 'gdpr']); + + return $participants; + } + + if ($ability === "key_4") { + + $participants = Participant::all()->select('participant_id', 'first_name', 'surname'); + + return $participants; + } + + return false; + } + + /** + * Show the form for creating a new resource. + */ + public function create() + { + // + } + + /** + * Store a newly created resource in storage. + */ + public function store(Request $request) + { + $ability = $request->ability; + + if ($ability === "key_1") { + + + $request->validate([ + 'member' => 'required', + 'first_name' => 'required', + 'surname' => 'required', + 'grade' => 'required', + 'phone' => 'nullable', + 'email' => 'nullable', + 'guardian_name' => 'required', + 'guardian_phone' => 'required', + 'guardian_email' => 'required', + 'visiting' => 'required', + 'gdpr' => 'required', + 'friends' => 'nullable', + 'special_diet' => 'nullable', + ]); + + $count = Participant::where('visiting', 0)->count(); + $status = ""; + + if ($count < 2 && $request->visiting === 0) { + $status = "lan"; + } + + else if ($request->visiting === 1) { + $status = "besök"; + } + + else { + $status = "reserv"; + } + + Participant::create([ + 'member' => $request->member, + 'first_name' => $request->first_name, + 'surname' => $request->surname, + 'grade' => $request->grade, + 'phone' => $request->phone, + 'email' => $request->email, + 'guardian_name' => $request->guardian_name, + 'guardian_phone' => $request->guardian_phone, + 'guardian_email' => $request->guardian_email, + 'visiting' => $request->visiting, + 'gdpr' => $request->gdpr, + 'friends' => $request->friends, + 'special_diet' => $request->special_diet, + 'status' => $status + ]); + + + return response()->json([ + 'success' => true, 'message' => 'Participant was created successfully' + ]); + + } + + return response()->json([ + 'success' => false, 'message' => 'Unauthorized' + ]); + + } + + /** + * Display the specified resource. + */ + public function show(Participant $participant) + { + // + } + + /** + * Show the form for editing the specified resource. + */ + public function edit(Participant $participant) + { + // + } + + /** + * Update the specified resource in storage. + */ + public function update(Request $request, Participant $participant) + { + // + } + + /** + * Remove the specified resource from storage. + */ + public function destroy(Participant $participant) + { + // + } +} + + diff --git a/app/Models/Participant.php b/app/Models/Participant.php new file mode 100644 index 0000000..f7f727c --- /dev/null +++ b/app/Models/Participant.php @@ -0,0 +1,79 @@ +latest()->first(); + + if($latest_version) { + Version::create([ + 'table' => 'participants', + 'version' => $latest_version->version + 1, + ]); + } else { + Version::create([ + 'table' => 'participants', + 'version' => 1, + ]); + } + }); + static::updated(function ($post) { + $latest_version = Version::where('table', 'participants')->latest()->first(); + + if($latest_version) { + Version::create([ + 'table' => 'participants', + 'version' => $latest_version->version + 1, + ]); + } else { + Version::create([ + 'table' => 'participants', + 'version' => 1, + ]); + } + }); + static::deleted(function ($post) { + $latest_version = Version::where('table', 'participants')->latest()->first(); + + if($latest_version) { + Version::create([ + 'table' => 'participants', + 'version' => $latest_version->version + 1, + ]); + } else { + Version::create([ + 'table' => 'participants', + 'version' => 1, + ]); + } + }); + } +} diff --git a/database/migrations/2025_09_26_165018_create_participants_table.php b/database/migrations/2025_09_26_165018_create_participants_table.php new file mode 100644 index 0000000..a3dd6ab --- /dev/null +++ b/database/migrations/2025_09_26_165018_create_participants_table.php @@ -0,0 +1,45 @@ +id(); + $table->integer('lan_id')->nullable(); + $table->boolean('member'); + $table->string('first_name'); + $table->string('surname'); + $table->string('grade'); + $table->string('phone')->nullable(); + $table->string('email')->nullable(); + $table->string('guardian_name'); + $table->string('guardian_phone'); + $table->string('guardian_email'); + $table->boolean('is_visiting')->default(false); + $table->boolean('gdpr')->default(false); + $table->string('friends')->nullable(); + $table->string('special_diet')->nullable(); + $table->string('status')->nullable(); + $table->boolean('paid')->default(false); + $table->boolean('emailed')->default(false); + $table->string('comment')->nullable(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('participants'); + } +};