diff --git a/app/Enums/ApplicationStatus.php b/app/Enums/ApplicationStatus.php index 2a3fc7f..25ff8bd 100644 --- a/app/Enums/ApplicationStatus.php +++ b/app/Enums/ApplicationStatus.php @@ -11,11 +11,14 @@ enum ApplicationStatus: string case TableOffered = 'table_offered'; case TableAccepted = 'table_accepted'; case CheckedIn = 'checked_in'; + case CheckedOut = 'checked_out'; static function for(\App\Models\Application $application): ApplicationStatus { if (!is_null($application->canceled_at)) { return ApplicationStatus::Canceled; + } elseif (!is_null($application->checked_out_at)) { + return ApplicationStatus::CheckedOut; } elseif (!is_null($application->checked_in_at)) { return ApplicationStatus::CheckedIn; } elseif (!is_null($application->waiting_at)) { @@ -38,20 +41,28 @@ function orWhere(\Illuminate\Database\Eloquent\Builder $query) fn (\Illuminate\Database\Eloquent\Builder $query) => $query->where('canceled_at', '!=', null) ), + ApplicationStatus::CheckedOut => $query->orWhere( + fn (\Illuminate\Database\Eloquent\Builder $query) => + $query->where('canceled_at', '=', null) + ->where('checked_out_at', '!=', null) + ), ApplicationStatus::CheckedIn => $query->orWhere( fn (\Illuminate\Database\Eloquent\Builder $query) => $query->where('canceled_at', '=', null) + ->where('checked_out_at', '=', null) ->where('checked_in_at', '!=', null) ), ApplicationStatus::Waiting => $query->orWhere( fn (\Illuminate\Database\Eloquent\Builder $query) => $query->where('canceled_at', '=', null) + ->where('checked_out_at', '=', null) ->where('checked_in_at', '=', null) ->where('waiting_at', '!=', null) ), ApplicationStatus::TableAccepted => $query->orWhere( fn (\Illuminate\Database\Eloquent\Builder $query) => $query->where('canceled_at', '=', null) + ->where('checked_out_at', '=', null) ->where('checked_in_at', '=', null) ->where('waiting_at', '=', null) ->where('offer_accepted_at', '!=', null) @@ -59,6 +70,7 @@ function orWhere(\Illuminate\Database\Eloquent\Builder $query) ApplicationStatus::TableOffered => $query->orWhere( fn (\Illuminate\Database\Eloquent\Builder $query) => $query->where('canceled_at', '=', null) + ->where('checked_out_at', '=', null) ->where('checked_in_at', '=', null) ->where('waiting_at', '=', null) ->where('offer_accepted_at', '=', null) @@ -67,6 +79,7 @@ function orWhere(\Illuminate\Database\Eloquent\Builder $query) ApplicationStatus::TableAssigned => $query->orWhere( fn (\Illuminate\Database\Eloquent\Builder $query) => $query->where('canceled_at', '=', null) + ->where('checked_out_at', '=', null) ->where('checked_in_at', '=', null) ->where('waiting_at', '=', null) ->where('offer_accepted_at', '=', null) @@ -81,6 +94,7 @@ function orWhere(\Illuminate\Database\Eloquent\Builder $query) ApplicationStatus::Open => $query->orWhere( fn (\Illuminate\Database\Eloquent\Builder $query) => $query->where('canceled_at', '=', null) + ->where('checked_out_at', '=', null) ->where('checked_in_at', '=', null) ->where('waiting_at', '=', null) ->where('offer_accepted_at', '=', null) diff --git a/app/Filament/Resources/ApplicationResource.php b/app/Filament/Resources/ApplicationResource.php index 23e6c51..98eefb4 100755 --- a/app/Filament/Resources/ApplicationResource.php +++ b/app/Filament/Resources/ApplicationResource.php @@ -68,7 +68,8 @@ public static function form(Form $form): Form "table_assigned" => "Table assigned (Open)", "table_offered" => "Table offered", "table_accepted" => "Table accepted", - "checked_in" => "Checked in (on-site)" + "checked_in" => "Checked in (on-site)", + "checked_out" => "Checked out (on-site)", ])->disablePlaceholderSelection()->required()->reactive(), Forms\Components\TextInput::make('table_number') ->maxLength(255), @@ -96,6 +97,7 @@ public static function form(Form $form): Form Forms\Components\Placeholder::make('offer_accepted_at')->content(fn (?Application $record): string => $record?->offer_accepted_at?->diffForHumans() ?? '-'), Forms\Components\Placeholder::make('waiting_at')->content(fn (?Application $record): string => $record?->waiting_at?->diffForHumans() ?? '-'), Forms\Components\Placeholder::make('checked_in_at')->content(fn (?Application $record): string => $record?->checked_in_at?->diffForHumans() ?? '-'), + Forms\Components\Placeholder::make('checked_out_at')->content(fn (?Application $record): string => $record?->checked_out_at?->diffForHumans() ?? '-'), Forms\Components\Placeholder::make('canceled_at')->content(fn (?Application $record): string => $record?->canceled_at?->diffForHumans() ?? '-'), Forms\Components\Placeholder::make('updated_at')->content(fn (?Application $record): string => $record?->updated_at?->diffForHumans() ?? '-'), Forms\Components\Placeholder::make('created_at')->content(fn (?Application $record): string => $record?->created_at?->diffForHumans() ?? '-'), @@ -348,8 +350,6 @@ public static function table(Table $table): Table ]); } - - public static function getRelations(): array { return [ @@ -357,6 +357,7 @@ public static function getRelations(): array RelationManagers\ParentRelationManager::class, RelationManagers\UserRelationManager::class, RelationManagers\ProfileRelationManager::class, + RelationManagers\CommentRelationManager::class, ]; } diff --git a/app/Filament/Resources/ApplicationResource/RelationManagers/CommentRelationManager.php b/app/Filament/Resources/ApplicationResource/RelationManagers/CommentRelationManager.php new file mode 100644 index 0000000..063a0d2 --- /dev/null +++ b/app/Filament/Resources/ApplicationResource/RelationManagers/CommentRelationManager.php @@ -0,0 +1,83 @@ +schema([ + // + ]); + } + + public static function table(Table $table): Table + { + return $table + ->columns([ + Tables\Columns\TextColumn::make('author.name'), + Tables\Columns\IconColumn::make('admin_only') + ->boolean(), + Tables\Columns\TextColumn::make('text'), + Tables\Columns\TextColumn::make('created_at') + ->sortable(), + Tables\Columns\TextColumn::make('updated_at') + ->sortable(), + ]) + ->filters([ + // + ]) + ->headerActions([ + Tables\Actions\Action::make('New comment') + ->form([ + Forms\Components\TextInput::make('application_id') + ->default(function (RelationManager $livewire) { + return $livewire->ownerRecord->id; + }) + ->required(), + Forms\Components\TextInput::make('user_id') + ->label("User ID (Author)") + ->default(\Auth::user()->id) + ->required(), + Forms\Components\Toggle::make('admin_only'), + Forms\Components\Textarea::make('text') + ->required() + ->maxLength(4096), + + ]) + ->action(function (array $data): void { + Comment::create([ + 'text' => $data['text'], + 'admin_only' => $data['admin_only'], + 'application_id' => $data['application_id'], + 'user_id' => $data['user_id'], + ]); + }) + ->icon('heroicon-o-pencil'), + + ]) + ->actions([ + Tables\Actions\Action::make('Show') + ->url(fn(Comment $record): string => CommentResource::getUrl('edit', ['record' => $record])), + + ]) + ->bulkActions([ + ]); + } +} diff --git a/app/Filament/Resources/CommentResource.php b/app/Filament/Resources/CommentResource.php new file mode 100644 index 0000000..031ab2e --- /dev/null +++ b/app/Filament/Resources/CommentResource.php @@ -0,0 +1,92 @@ +columns(3) + ->schema([ + Forms\Components\Group::make()->columnSpan(2)->columns()->schema([ + Forms\Components\Group::make()->columns(1)->schema([ + Forms\Components\Select::make('user_id')->searchable()->relationship('author', 'name') + ->required(), + Forms\Components\Select::make('application_id')->searchable()->relationship('application', 'id') + ->required(), + Forms\Components\Toggle::make('admin_only'), + ]), + Forms\Components\Textarea::make('text') + ->required() + ->maxLength(4096), + ]), + Forms\Components\Fieldset::make('Dates')->columnSpan(1)->columns()->schema([ + Forms\Components\Placeholder::make('created_at')->content(fn (?Comment $record): string => $record?->created_at?->diffForHumans() ?? '-'), + Forms\Components\Placeholder::make('updated_at')->content(fn (?Comment $record): string => $record?->updated_at?->diffForHumans() ?? '-'), + ]), + + ]); + } + + public static function table(Table $table): Table + { + return $table + ->columns([ + Tables\Columns\TextColumn::make('uuid')->hidden()->url(fn($record) => CommentResource::getUrl('edit', ['record' => $record->uuid])), + Tables\Columns\TextColumn::make('application_id') + ->searchable() + ->sortable(), + Tables\Columns\TextColumn::make('author.name') + ->searchable(), + Tables\Columns\IconColumn::make('admin_only') + ->boolean(), + Tables\Columns\TextColumn::make('text'), + Tables\Columns\TextColumn::make('created_at') + ->sortable(), + Tables\Columns\TextColumn::make('updated_at') + ->sortable(), + ]) + ->filters([ + Tables\Filters\Filter::make('admin_only') + ->query(fn(Builder $query): Builder => $query->where('admin_only', '=', '1')) + ->label('Is Admin only'), + ]) + ->actions([ + Tables\Actions\EditAction::make(), + ]) + ->bulkActions([ + Tables\Actions\DeleteBulkAction::make(), + ]); + } + + public static function getRelations(): array + { + return [ + RelationManagers\ApplicationRelationManager::class, + ]; + } + + public static function getPages(): array + { + return [ + 'index' => Pages\ListComments::route('/'), + 'create' => Pages\CreateComment::route('/create'), + 'edit' => Pages\EditComment::route('/{record}/edit'), + ]; + } +} diff --git a/app/Filament/Resources/CommentResource/Pages/CreateComment.php b/app/Filament/Resources/CommentResource/Pages/CreateComment.php new file mode 100644 index 0000000..b1815a4 --- /dev/null +++ b/app/Filament/Resources/CommentResource/Pages/CreateComment.php @@ -0,0 +1,12 @@ +columns([ + Tables\Columns\TextColumn::make('user.name'), + Tables\Columns\TextColumn::make('type'), + Tables\Columns\BadgeColumn::make('status')->enum(ApplicationStatus::cases())->formatStateUsing(function (Application $record) { + return $record->status->name; + })->colors([ + 'secondary', + 'success' => ApplicationStatus::TableAccepted->value, + 'danger' => ApplicationStatus::Canceled->value + ]), + Tables\Columns\TextColumn::make('assignedTable.name'), + Tables\Columns\TextColumn::make('table_number'), + + ]) + ->filters([ + // + ]) + ->headerActions([ + ]) + ->actions([ + Tables\Actions\Action::make('Show') + ->url(fn(Application $record): string => ApplicationResource::getUrl('edit', ['record' => $record])), + + ]) + ->bulkActions([ + ]); + } +} diff --git a/app/Http/Controllers/FrontdeskController.php b/app/Http/Controllers/FrontdeskController.php new file mode 100644 index 0000000..9cc698e --- /dev/null +++ b/app/Http/Controllers/FrontdeskController.php @@ -0,0 +1,143 @@ +authorize('view-any', Application::class); + + $search = $request->get('search'); + + if (empty($search)) { + return view('frontdesk', [ + 'user' => \Auth::user(), + 'search' => null, + 'application' => null, + 'applicant' => null + ]); + } + + // 1. search by user user_id + // 2. search by user name + $user = User::where('reg_id', $search)->orWhere('name', 'like', $search)->first(); + $application = $user ? Application::where('user_id', $user->id)->first() : null; + + // 2. search by application table_number + // 4. search by dealership display_name + if ($application === null) { + $application = Application::where('table_number', strtoupper($search))->orWhere('display_name', 'like', $search)->first(); + $user = $application ? $application->user : null; + } + + $table = $application ? $application->assignedTable : null; + + $parent = $application && $application->type !== ApplicationType::Dealer ? $application->parent()->first() : null; + $parentApplicant = $parent ? $parent->user : null; + + $children = $application && $application->type === ApplicationType::Dealer ? $application->children : []; + $shares = []; + $assistants = []; + foreach ($children as $child) { + if ($child->type === ApplicationType::Share) { + array_push($shares, $child); + } elseif ($child->type === ApplicationType::Assistant) { + array_push($assistants, $child); + } else { + Log::warning('Encountered child of unexpected type.', ['parent' => $parent, 'child' => $child]); + } + } + + $profile = $application ? $application->profile : null; + + return view('frontdesk', [ + 'user' => \Auth::user(), + 'search' => $search, + 'application' => $application, + 'applicant' => $user, + 'table' => $table, + 'parent' => $parent, + 'parentApplicant' => $parentApplicant, + 'shares' => $shares, + 'assistants' => $assistants, + 'profile' => $profile, + 'showAdditional' => $request->has('show_additional'), + ]); + } + + public function comment(CommentRequest $request) + { + $this->authorize('create', Comment::class); + + $text = strip_tags($request->get('comment')); + $application = Application::findOrFail($request->get('application')); + + $author = \Auth::user(); + Comment::create([ + 'text' => trim($text), + 'admin_only' => $request->has('admin_only'), + 'user_id' => $author->id, + 'application_id' => $application->id, + ]); + return Redirect::route('frontdesk', [ + "search" => $application->user->reg_id, + ]); + } + + public function checkIn(CheckInRequest $request) + { + $this->authorize('check-in', Application::class); + $application = Application::findOrFail($request->get('application')); + + abort_if(!$application->checkIn(), 403, 'Application status does not allow check-in.'); + + $comment = strip_tags($request->get('ci_comment')); + $author = \Auth::user(); + Comment::create([ + 'text' => trim(join("\n", ['Check-In Performed', $comment])), + 'admin_only' => false, + 'user_id' => $author->id, + 'application_id' => $application->id, + ]); + + return Redirect::route('frontdesk', [ + "search" => $application->user->reg_id, + ]); + } + + public function checkOut(CheckOutRequest $request) + { + $this->authorize('check-out', Application::class); + $application = Application::findOrFail($request->get('application')); + + abort_if(!$application->checkOut(), 403, 'Application status does not allow check-out.'); + + $comment = strip_tags($request->get('co_comment')); + $author = \Auth::user(); + Comment::create([ + 'text' => trim(join("\n", ['Check-Out Performed', $comment])), + 'admin_only' => false, + 'user_id' => $author->id, + 'application_id' => $application->id, + ]); + + return Redirect::route('frontdesk', [ + "search" => $application->user->reg_id, + ]); + } +} diff --git a/app/Http/Requests/CheckInRequest.php b/app/Http/Requests/CheckInRequest.php new file mode 100644 index 0000000..4b0293c --- /dev/null +++ b/app/Http/Requests/CheckInRequest.php @@ -0,0 +1,29 @@ + [ + "integer", + ], + "waiver_signed" => [ + "accepted", + ], + "badge_received" => [ + "accepted", + ], + "ci_comment" => [ + "max:". Comment::MAX_LENGTH, + ], + ]; + } +} diff --git a/app/Http/Requests/CheckOutRequest.php b/app/Http/Requests/CheckOutRequest.php new file mode 100644 index 0000000..0b6ed27 --- /dev/null +++ b/app/Http/Requests/CheckOutRequest.php @@ -0,0 +1,38 @@ + [ + "integer", + ], + "table_clean" => [ + "accepted", + ], + "waste_disposed" => [ + "accepted", + ], + "floor_undamaged" => [ + "accepted", + ], + "materials_removed" => [ + "accepted", + ], + "power_strip" => [ + "accepted", + ], + "ci_comment" => [ + "max:". Comment::MAX_LENGTH, + ], + ]; + } +} diff --git a/app/Http/Requests/CommentRequest.php b/app/Http/Requests/CommentRequest.php new file mode 100644 index 0000000..ede913d --- /dev/null +++ b/app/Http/Requests/CommentRequest.php @@ -0,0 +1,24 @@ + [ + "filled", + "max:". Comment::MAX_LENGTH, + ], + "application" => [ + "integer", + ], + ]; + } +} diff --git a/app/Models/Application.php b/app/Models/Application.php index 467af42..ad97a2d 100644 --- a/app/Models/Application.php +++ b/app/Models/Application.php @@ -32,6 +32,7 @@ class Application extends Model "canceled_at" => "datetime", "waiting_at" => "datetime", "checked_in_at" => "datetime", + "checked_out_at" => "datetime", "offer_sent_at" => "datetime", "offer_accepted_at" => "datetime", ]; @@ -120,10 +121,16 @@ public function children() return $this->hasMany(__CLASS__, 'parent'); } - public function profile() { + public function profile() + { return $this->belongsTo(Profile::class, 'id', 'application_id', 'profiles'); } + public function comments() + { + return $this->hasMany(Comment::class, 'application_id'); + } + public function getStatus() { return ApplicationStatus::for($this); @@ -134,6 +141,24 @@ public function isActive() return $this->getStatus() !== ApplicationStatus::Canceled; } + public function checkIn() { + if ($this->status === ApplicationStatus::TableAccepted) { + $this->status = ApplicationStatus::CheckedIn; + $this->save(); + return true; + } + return false; + } + + public function checkOut() { + if ($this->status === ApplicationStatus::CheckedIn) { + $this->status = ApplicationStatus::CheckedOut; + $this->save(); + return true; + } + return false; + } + public function cancel() { $this->canceled_at = now(); @@ -272,6 +297,14 @@ public function setStatusAttribute(ApplicationStatus|string $status) if ($status === ApplicationStatus::CheckedIn) { $this->update([ 'checked_in_at' => now(), + 'checked_out_at' => null, + 'canceled_at' => null, + ]); + } + + if ($status === ApplicationStatus::CheckedOut) { + $this->update([ + 'checked_out_at' => now(), 'canceled_at' => null, ]); } @@ -334,6 +367,7 @@ public static function getAllApplicationsForExport() 'offer_sent_at', 'offer_accepted_at', 'checked_in_at', + 'checked_out_at', 'canceled_at', 'profiles.*', ) diff --git a/app/Models/Comment.php b/app/Models/Comment.php new file mode 100644 index 0000000..a0d4e33 --- /dev/null +++ b/app/Models/Comment.php @@ -0,0 +1,37 @@ + 'boolean', + 'text' => 'string', + ]; + protected $attributes = [ + 'admin_only' => false, + ]; + + public function application() + { + return $this->belongsTo(Application::class); + } + + public function author() + { + return $this->belongsTo(User::class, 'user_id'); + } +} diff --git a/app/Policies/ApplicationPolicy.php b/app/Policies/ApplicationPolicy.php new file mode 100644 index 0000000..38cabc9 --- /dev/null +++ b/app/Policies/ApplicationPolicy.php @@ -0,0 +1,24 @@ +isFrontdesk(); + } + + public function checkIn(User $user): bool + { + return $user->isFrontdesk(); + } + + public function checkOut(User $user): bool + { + return $user->isFrontdesk(); + } +} diff --git a/app/Policies/CommentPolicy.php b/app/Policies/CommentPolicy.php new file mode 100644 index 0000000..8d38056 --- /dev/null +++ b/app/Policies/CommentPolicy.php @@ -0,0 +1,69 @@ +isAdmin(); + } + + /** + * Determine whether the user can view the model. + */ + public function view(User $user, Comment $comment): bool + { + if ($comment->admin_only) { + return $user->isAdmin(); + } else { + return $user->isFrontdesk(); + } + } + + /** + * Determine whether the user can create models. + */ + public function create(User $user): bool + { + return $user->isFrontdesk(); + } + + /** + * Determine whether the user can update the model. + */ + public function update(User $user, Comment $comment): bool + { + return $user->isAdmin(); + } + + /** + * Determine whether the user can delete the model. + */ + public function delete(User $user, Comment $comment): bool + { + return $user->isAdmin(); + } + + /** + * Determine whether the user can restore the model. + */ + public function restore(User $user, Comment $comment): bool + { + return $user->isAdmin(); + } + + /** + * Determine whether the user can permanently delete the model. + */ + public function forceDelete(User $user, Comment $comment): bool + { + return false; + } +} diff --git a/database/factories/UserFactory.php b/database/factories/UserFactory.php index 882dac8..125f14d 100644 --- a/database/factories/UserFactory.php +++ b/database/factories/UserFactory.php @@ -21,7 +21,7 @@ public function definition(): array 'name' => fake()->name(), 'email' => fake()->unique()->safeEmail(), 'identity_id' => fake()->uuid(), - 'groups' => [], + 'groups' => '[]', ]; } diff --git a/database/migrations/2023_08_08_000000_alter_users_groups_to_longtext.php b/database/migrations/2023_08_08_000000_alter_users_groups_to_longtext.php new file mode 100644 index 0000000..19f40b5 --- /dev/null +++ b/database/migrations/2023_08_08_000000_alter_users_groups_to_longtext.php @@ -0,0 +1,29 @@ +longText('groups')->change(); + $table->longText('groups')->nullable()->change(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('users', function (Blueprint $table) { + $table->json('groups')->change(); + }); + } +}; diff --git a/database/migrations/2023_08_08_215547_create_comments_table.php b/database/migrations/2023_08_08_215547_create_comments_table.php new file mode 100644 index 0000000..cb2bdb9 --- /dev/null +++ b/database/migrations/2023_08_08_215547_create_comments_table.php @@ -0,0 +1,31 @@ +uuid(); + $table->foreignIdFor(\App\Models\User::class)->constrained()->cascadeOnUpdate(); + $table->foreignIdFor(\App\Models\Application::class)->constrained()->cascadeOnUpdate()->cascadeOnDelete(); + $table->string('text'); + $table->boolean('admin_only'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('comments'); + } +}; diff --git a/database/migrations/2023_08_09_222220_add_checked_out_status.php b/database/migrations/2023_08_09_222220_add_checked_out_status.php new file mode 100644 index 0000000..4dd651a --- /dev/null +++ b/database/migrations/2023_08_09_222220_add_checked_out_status.php @@ -0,0 +1,28 @@ +timestamp('checked_out_at')->nullable()->default(null); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('applications', function (Blueprint $table) { + $table->dropColumn('checked_out_at'); + }); + } +}; diff --git a/database/migrations/2023_08_13_135050_increase_comment_text_length.php b/database/migrations/2023_08_13_135050_increase_comment_text_length.php new file mode 100644 index 0000000..a099af3 --- /dev/null +++ b/database/migrations/2023_08_13_135050_increase_comment_text_length.php @@ -0,0 +1,28 @@ +text('text')->change(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('comments', function (Blueprint $table) { + $table->string('text')->change(); + }); + } +}; diff --git a/resources/views/components/frontdesk/applicationbutton.blade.php b/resources/views/components/frontdesk/applicationbutton.blade.php new file mode 100644 index 0000000..d186149 --- /dev/null +++ b/resources/views/components/frontdesk/applicationbutton.blade.php @@ -0,0 +1,16 @@ +@props(['applicant', 'application']) + + $application->status === \App\Enums\ApplicationStatus::CheckedIn, + 'btn-warning' => $application->status === \App\Enums\ApplicationStatus::TableAccepted || + $application->status === \App\Enums\ApplicationStatus::CheckedOut, + 'btn-danger' => $application->status !== \App\Enums\ApplicationStatus::CheckedIn && $application->status !== \App\Enums\ApplicationStatus::TableAccepted && + $application->status !== \App\Enums\ApplicationStatus::CheckedOut, + ])> + {{ $applicant->name }} ({{$applicant->reg_id}}) – {{ $application->status->name }} diff --git a/resources/views/frontdesk.blade.php b/resources/views/frontdesk.blade.php new file mode 100644 index 0000000..60d9534 --- /dev/null +++ b/resources/views/frontdesk.blade.php @@ -0,0 +1,600 @@ + + + + + + + + + Frontdesk - Dealer's Registration - Eurofurence + + + @vite(['resources/css/app.scss', 'resources/js/app.js']) + + + + + + + +
+ + + + +
+
+ + +
+
+ +
+
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+
+ + +
+ @if (empty($search)) +
+
+ Welcome to the Dealers' Den Frontdesk! +
+
+ You can search Dealers, Shares or Assistants by: +
    +
  • registration ID (exact match; no checksum!),
  • +
  • attendee nickname (supports % as wildcard; not + case-sensitive),
  • +
  • table number (exact match) or
  • +
  • display name (supports % as wildcard; not + case-sensitive).
  • +
+
+ +
+ @elseif ($applicant === null) +
+
+ No dealer, share or assistant found for search query "{{ $search }}". +
+
+ @else + @if ($application->status === \App\Enums\ApplicationStatus::TableAccepted) +
+
+ {{ $application->status->name }} – Ready for Check-In +
+
+ @elseif ($application->status === \App\Enums\ApplicationStatus::CheckedIn) +
+
+ {{ $application->status->name }} – + Ready for Check-Out +
+
+ @else +
+
+ {{ $application->status->name }} +
+
+ @endif + + +
+ + +
+ + + +
+ !$errors->hasBag('check-in') && + !$errors->hasBag('check-out') && + !$showAdditional, + ]) + data-bs-parent="#applicationData"> +
+
+ + +
+
+ + +
+ + + + @if ($parent) +
+ Dealership + +
+ @endif + + + @if (!empty($shares)) +
+ Shares + @foreach ($shares as $share) + @php($shareApplicant = $share->user) + + @endforeach +
+ @endif + + + @if (!empty($assistants)) +
+ Assistants + @foreach ($assistants as $assistant) + @php($assistantApplicant = $assistant->user) + + @endforeach +
+ @endif +
+
+
+ + +
+

+ +

+
$showAdditional, + ]) + data-bs-parent="#applicationData"> +
+ @if ($profile) +
+
+ + + +
+
+
+ + + +
+
+ Categories: + @if($profile->is_print) + + @endif + @if($profile->is_artwork) + + @endif + @if($profile->is_fursuit) + + @endif + @if($profile->is_commissions) + + @endif + @if($profile->is_misc) + + @endif + @if(!$profile->is_print && !$profile->is_artwork && !$profile->is_fursuit && !$profile->is_commissions && !$profile->is_misc) + + @endif +
+ + @else + n/a + @endif +
+
+
+ + + @if ($application->status === \App\Enums\ApplicationStatus::TableAccepted) +
+

+ +

+
$errors->hasBag('check-in'), + ]) + data-bs-parent="#applicationData"> +
+
+
+ + +
+
+ + +
+ + + + @csrf +
+
+
+
+ + + @elseif ($application->status === \App\Enums\ApplicationStatus::CheckedIn) +
+

+ +

+
$errors->hasBag('check-out'), + ]) + data-bs-parent="#applicationData"> +
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ + + + @csrf +
+
+
+
+ @endif +
+ @endif +
+ + +
+
+
+
+ Comments +
+
+ + @error('comment') +
{{ $message }}
+ @enderror +
+ +
+ @csrf + +
+ @if ($application) + @foreach ($application->comments()->orderBy('created_at', 'desc')->get() as $comment) + @can('view', $comment) +
+
{{ $comment->text }}
+ +
+ @endcan + @endforeach + @else +
+
+ No application selected. +
+
+ @endif +
+
+
+
+ + + diff --git a/routes/web.php b/routes/web.php index 2bb98ed..8db8b3b 100755 --- a/routes/web.php +++ b/routes/web.php @@ -2,6 +2,8 @@ use App\Http\Controllers\ProfileController; use App\Http\Controllers\Applications\ApplicationController; +use App\Models\Application; +use App\Models\Comment; use Illuminate\Support\Facades\Route; /* @@ -59,9 +61,16 @@ Route::get('admin/export/appdata', [ApplicationController::class, 'exportAppDataAdmin']); Route::get('admin/export/csv', [ApplicationController::class, 'exportCsvAdmin']); +}); +Route::middleware(['auth:web',\App\Http\Middleware\AccessTokenValidationMiddleware::class])->group(function () { + Route::get('frontdesk',\App\Http\Controllers\FrontdeskController::class)->name('frontdesk')->can('viewAny', Application::class); + Route::post('frontdesk/check-in',[\App\Http\Controllers\FrontdeskController::class,'checkIn'])->name('frontdesk.check-in')->can('checkIn', Application::class); + Route::post('frontdesk/check-out',[\App\Http\Controllers\FrontdeskController::class,'checkOut'])->name('frontdesk.check-out')->can('checkOut', Application::class); + Route::post('frontdesk/comment',[\App\Http\Controllers\FrontdeskController::class,'comment'])->name('frontdesk.comment')->can('create', Comment::class); }); + // Basic auth using credentials from env Route::middleware('auth.api.basic')->group(function () { Route::get('export/appdata', [ApplicationController::class, 'exportAppData']);