Files
Atomcms-edit/app/Filament/Resources/Hotel/StaffApplications/StaffApplicationResource.php
T

233 lines
9.5 KiB
PHP
Executable File

<?php
namespace App\Filament\Resources\Hotel\StaffApplications;
use App\Filament\Resources\Hotel\StaffApplications\Pages\ListStaffApplications;
use App\Models\Community\Staff\WebsiteStaffApplications;
use Filament\Actions\Action;
use Filament\Actions\DeleteAction;
use Filament\Actions\DeleteBulkAction;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\Textarea;
use Filament\Notifications\Notification;
use Filament\Resources\Resource;
use Filament\Schemas\Schema;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
class StaffApplicationResource extends Resource
{
#[\Override]
protected static ?string $model = WebsiteStaffApplications::class;
#[\Override]
protected static string|\BackedEnum|null $navigationIcon = 'heroicon-o-user-group';
#[\Override]
protected static string|\UnitEnum|null $navigationGroup = 'Hotel';
#[\Override]
public static function canCreate(): bool
{
return false;
}
#[\Override]
public static function form(Schema $schema): Schema
{
return $schema->components([
Select::make('user_id')
->relationship('user', 'username')
->required()
->searchable(),
Select::make('rank_id')
->label(__('Rank'))
->relationship('rank', 'rank_name')
->searchable()
->nullable(),
Select::make('team_id')
->label(__('Team'))
->relationship('team', 'rank_name')
->searchable()
->nullable(),
Textarea::make('content')
->required()
->columnSpanFull(),
]);
}
#[\Override]
public static function table(Table $table): Table
{
return $table
->columns([
TextColumn::make('user.username')
->label(__('User'))
->sortable()
->searchable(),
TextColumn::make('applied_for')
->label(__('Applied For'))
->state(fn (WebsiteStaffApplications $record) => $record->team_id
? ($record->team->rank_name ?? '-')
: ($record->rank->rank_name ?? '-'))
->searchable(query: function ($query, string $search) {
$query
->orWhereHas('rank', fn ($q) => $q->where('rank_name', 'like', "%{$search}%"))
->orWhereHas('team', fn ($q) => $q->where('rank_name', 'like', "%{$search}%"));
})
->sortable(),
TextColumn::make('status')
->label(__('Status'))
->badge()
->formatStateUsing(fn (?string $state) => ucfirst($state ?? 'pending'))
->color(fn (?string $state) => [
'pending' => 'warning',
'approved' => 'success',
'rejected' => 'danger',
][$state ?? 'pending'] ?? 'gray')
->sortable(),
TextColumn::make('content')->limit(50)->wrap()->sortable(),
TextColumn::make('created_at')->dateTime()->sortable(),
TextColumn::make('updated_at')->dateTime()->sortable(),
])
->recordActions([
Action::make('approveTeam')
->label(__('Approve to Team'))
->icon('heroicon-o-check-circle')
->color('success')
->visible(fn (WebsiteStaffApplications $r) => filled($r->team_id) && ($r->status === 'pending' || is_null($r->status)))
->requiresConfirmation()
->modalHeading(__('Approve to Team'))
->modalDescription(function (WebsiteStaffApplications $r): string {
$user = $r->user;
$targetTeam = optional($r->team)->rank_name ?? '—';
$currentTeam = optional($user?->team)->rank_name;
if ($currentTeam && $user?->team_id !== $r->team_id) {
return __('This user is currently in :team. Approving will move them to :target. Continue?', ['team' => $currentTeam, 'target' => $targetTeam]);
}
return __('Approve this application and assign the user to :team?', ['team' => $targetTeam]);
})
->action(function (WebsiteStaffApplications $r) {
$user = $r->user;
$team = $r->team;
if (! $user || ! $team) {
Notification::make()
->danger()->title(__('Unable to approve'))
->body(__('Missing user or team on this application.'))
->send();
return;
}
if ((int) $user->team_id !== (int) $team->id) {
$user->forceFill(['team_id' => $team->id])->save();
}
$r->update([
'status' => 'approved',
'approved_by' => auth()->id(),
'approved_at' => now(),
'rejected_by' => null,
'rejected_at' => null,
]);
Notification::make()
->success()->title(__('Approved'))
->body(__(':username has been added to :team.', ['username' => $user->username, 'team' => $team->rank_name]))
->send();
}),
Action::make('rejectTeam')
->label(__('Reject'))
->icon('heroicon-o-x-circle')
->color('danger')
->visible(fn (WebsiteStaffApplications $r) => filled($r->team_id) && in_array($r->status, ['pending', 'approved', null], true))
->requiresConfirmation()
->modalHeading(__('Reject Application'))
->modalDescription(function (WebsiteStaffApplications $r): string {
$user = $r->user;
$teamName = optional($r->team)->rank_name ?? '—';
if ($r->status === 'approved') {
return __('This will mark the application as rejected and remove :username from :team. Continue?', ['username' => $user->username, 'team' => $teamName]);
}
return __('This will mark the application as rejected. Continue?');
})
->action(function (WebsiteStaffApplications $r) {
$user = $r->user;
$team = $r->team;
if (! $user || ! $team) {
Notification::make()
->danger()->title(__('Unable to reject'))
->body(__('Missing user or team on this application.'))
->send();
return;
}
if ($r->status === 'approved' && (int) $user->team_id === (int) $team->id) {
$user->forceFill(['team_id' => null])->save();
}
$r->update([
'status' => 'rejected',
'rejected_by' => auth()->id(),
'rejected_at' => now(),
]);
Notification::make()
->success()->title(__('Rejected'))
->body($r->status === 'approved'
? __(':username has been removed from :team and the application marked as rejected.', ['username' => $user->username, 'team' => $team->rank_name])
: __('Application has been marked as rejected.'))
->send();
}),
Action::make('reopen')
->label(__('Re-open'))
->icon('heroicon-o-arrow-path')
->color('warning')
->visible(fn (WebsiteStaffApplications $r) => $r->status === 'rejected')
->requiresConfirmation()
->modalHeading(__('Re-open Application'))
->modalDescription(__('This will set the application status back to pending.'))
->action(function (WebsiteStaffApplications $r) {
$r->update([
'status' => 'pending',
'rejected_by' => null,
'rejected_at' => null,
]);
Notification::make()
->success()->title(__('Re-opened'))
->body(__('Application status set to pending.'))
->send();
}),
DeleteAction::make(),
])
->toolbarActions([
DeleteBulkAction::make(),
]);
}
#[\Override]
public static function getPages(): array
{
return [
'index' => ListStaffApplications::route('/'),
];
}
}