Volunteer resource

This commit is contained in:
Anna-Sara Sélea 2025-11-15 17:07:19 +01:00
parent 84162b577d
commit 6791ac5407
10 changed files with 462 additions and 0 deletions

View file

@ -0,0 +1,13 @@
<?php
namespace App\Filament\Resources\Volunteers\Pages;
use App\Filament\Resources\Volunteers\VolunteerResource;
use Filament\Resources\Pages\CreateRecord;
class CreateVolunteer extends CreateRecord
{
protected static string $resource = VolunteerResource::class;
}

View file

@ -0,0 +1,21 @@
<?php
namespace App\Filament\Resources\Volunteers\Pages;
use App\Filament\Resources\Volunteers\VolunteerResource;
use Filament\Actions\DeleteAction;
use Filament\Resources\Pages\EditRecord;
use App\Models\Version;
class EditVolunteer extends EditRecord
{
protected static string $resource = VolunteerResource::class;
protected function getHeaderActions(): array
{
return [
DeleteAction::make(),
];
}
}

View file

@ -0,0 +1,19 @@
<?php
namespace App\Filament\Resources\Volunteers\Pages;
use App\Filament\Resources\Volunteers\VolunteerResource;
use Filament\Actions\CreateAction;
use Filament\Resources\Pages\ListRecords;
class ListVolunteers extends ListRecords
{
protected static string $resource = VolunteerResource::class;
protected function getHeaderActions(): array
{
return [
CreateAction::make(),
];
}
}

View file

@ -0,0 +1,50 @@
<?php
namespace App\Filament\Resources\Volunteers\Schemas;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\Textarea;
use Filament\Forms\Components\Toggle;
use Filament\Schemas\Schema;
use Filament\Forms\Components\CheckboxList;
use DiscoveryDesign\FilamentGaze\Forms\Components\GazeBanner;
class VolunteerForm
{
public static function configure(Schema $schema): Schema
{
return $schema
->components([
GazeBanner::make()
->pollTimer(10)
->hideOnCreate(),
TextInput::make('lan_id')
->integer(),
Toggle::make('gdpr')
->columnSpan('full')
->required(),
TextInput::make('first_name')
->required(),
TextInput::make('surname')
->required(),
TextInput::make('phone')
->tel()
->required(),
TextInput::make('email')
->label('Email address')
->email()
->required(),
CheckboxList::make('areas')
->required()
->columnSpan('full')
->options([
'Städ' => 'Städ',
'Säkerhet' => 'Säkerhet',
'Kiosk' => 'Kiosk',
]),
Textarea::make('comment')
->columnSpan('full'),
]);
}
}

View file

@ -0,0 +1,109 @@
<?php
namespace App\Filament\Resources\Volunteers\Tables;
use Filament\Actions\BulkActionGroup;
use Filament\Actions\DeleteBulkAction;
use Filament\Actions\EditAction;
use Filament\Tables\Columns\IconColumn;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
use Filament\Actions\Action;
use Filament\Forms\Components\Select;
use Illuminate\Support\Facades\Mail;
use App\Mail\LanMail;
use Filament\Support\Icons\Heroicon;
use App\Models\Volunteer;
use App\Models\Mailtemplate;
class VolunteersTable
{
public static function configure(Table $table): Table
{
return $table
->recordAction(null)
->columns([
TextColumn::make('lan_id')
->label('ID')
->searchable()
->sortable(),
IconColumn::make('emailed')
->boolean()
->sortable(),
TextColumn::make('first_name')
->searchable()
->sortable(),
TextColumn::make('surname')
->searchable()
->sortable(),
TextColumn::make('phone')
->searchable()
->sortable(),
TextColumn::make('email')
->label('Email address')
->searchable()
->sortable(),
TextColumn::make('areas')
->label('Areas')
->searchable()
->sortable(),
IconColumn::make('gdpr')
->boolean()
->sortable(),
TextColumn::make('comment')
->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, Volunteer $record) {
$mailContent = Mailtemplate::where('id', $data['mailtemplate'])->get();
Mail::to($record->email)
->send(new LanMail($mailContent, $record));
Volunteer::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, Volunteer $record) {
$mailContent = Mailtemplate::where('id', $data['mailtemplate'])->get();
Mail::to($record->email)
->send(new LanMail($mailContent, $record));
Volunteer::where('id', $record->id)->update(['emailed' => true]);
})
->hidden(fn($record) => !$record->emailed)
])
->toolbarActions([
BulkActionGroup::make([
DeleteBulkAction::make(),
]),
]);
}
}

View file

@ -0,0 +1,48 @@
<?php
namespace App\Filament\Resources\Volunteers;
use App\Filament\Resources\Volunteers\Pages\CreateVolunteer;
use App\Filament\Resources\Volunteers\Pages\EditVolunteer;
use App\Filament\Resources\Volunteers\Pages\ListVolunteers;
use App\Filament\Resources\Volunteers\Schemas\VolunteerForm;
use App\Filament\Resources\Volunteers\Tables\VolunteersTable;
use App\Models\Volunteer;
use BackedEnum;
use Filament\Resources\Resource;
use Filament\Schemas\Schema;
use Filament\Support\Icons\Heroicon;
use Filament\Tables\Table;
class VolunteerResource extends Resource
{
protected static ?string $model = Volunteer::class;
protected static string|BackedEnum|null $navigationIcon = Heroicon::OutlinedRectangleStack;
public static function form(Schema $schema): Schema
{
return VolunteerForm::configure($schema);
}
public static function table(Table $table): Table
{
return VolunteersTable::configure($table);
}
public static function getRelations(): array
{
return [
//
];
}
public static function getPages(): array
{
return [
'index' => ListVolunteers::route('/'),
'create' => CreateVolunteer::route('/create'),
//'edit' => EditVolunteer::route('/{record}/edit'),
];
}
}

View file

@ -0,0 +1,51 @@
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Models\Volunteer;
class VolunteerController extends Controller
{
/**
* Store a newly created resource in storage.
*/
public function store(Request $request)
{
$ability = $request->ability;
if ($ability === "key_1") {
$request->validate([
'first_name' => 'required',
'surname' => 'required',
'phone' => 'required',
'email' => 'required',
'gdpr' => 'required',
'areas' => 'required',
]);
Volunteer::create([
'first_name' => $request->first_name,
'surname' => $request->surname,
'phone' => $request->phone,
'email' => $request->email,
'gdpr' => $request->gdpr,
'areas' => $request->areas,
]);
return response()->json([
'success' => true, 'message' => 'Volunteer was created successfully'
]);
}
return response()->json([
'success' => false, 'message' => 'Unauthorized'
]);
}
}

82
app/Models/Volunteer.php Normal file
View file

@ -0,0 +1,82 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
use App\Models\Version;
class Volunteer extends Model
{
protected $fillable = [
'lan_id',
'first_name',
'surname',
'phone',
'email',
'gdpr',
'areas',
'emailed',
'comment'
];
/**
* @return array<string, string>
*/
protected function casts(): array
{
return [
'areas' => 'array',
];
}
protected static function booted()
{
static::created(function ($post) {
$latest_version = Version::where('table', 'volunteers')->latest()->first();
if($latest_version) {
Version::create([
'table' => 'volunteers',
'version' => $latest_version->version + 1,
]);
} else {
Version::create([
'table' => 'volunteers',
'version' => 1,
]);
}
});
static::updated(function ($post) {
$latest_version = Version::where('table', 'volunteers')->latest()->first();
if($latest_version) {
Version::create([
'table' => 'volunteers',
'version' => $latest_version->version + 1,
]);
} else {
Version::create([
'table' => 'volunteers',
'version' => 1,
]);
}
});
static::deleted(function ($post) {
$latest_version = Version::where('table', 'volunteers')->latest()->first();
if($latest_version) {
Version::create([
'table' => 'volunteers',
'version' => $latest_version->version + 1,
]);
} else {
Version::create([
'table' => 'volunteers',
'version' => 1,
]);
}
});
}
}

View file

@ -0,0 +1,33 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('personal_access_tokens', function (Blueprint $table) {
$table->id();
$table->morphs('tokenable');
$table->text('name');
$table->string('token', 64)->unique();
$table->text('abilities')->nullable();
$table->timestamp('last_used_at')->nullable();
$table->timestamp('expires_at')->nullable()->index();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('personal_access_tokens');
}
};

View file

@ -0,0 +1,36 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('volunteers', function (Blueprint $table) {
$table->id();
$table->integer('lan_id')->nullable();
$table->string('first_name');
$table->string('surname');
$table->string('phone');
$table->string('email');
$table->boolean('gdpr')->default(false);
$table->json('areas');
$table->boolean('emailed')->default(false);
$table->string('comment')->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('volunteers');
}
};