Deploy Ladill Frontdesk / deploy (push) Successful in 28s
Only show the sidebar link when a host record is linked to the signed-in user, and redirect direct visits to the dashboard with a clear message instead of a 403 page. Co-authored-by: Cursor <cursoragent@cursor.com>
132 lines
4.8 KiB
PHP
132 lines
4.8 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Frontdesk;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Http\Controllers\Frontdesk\Concerns\ScopesToAccount;
|
|
use App\Models\Host;
|
|
use App\Models\Visit;
|
|
use App\Services\Frontdesk\OrganizationResolver;
|
|
use App\Services\Frontdesk\VisitLifecycleService;
|
|
use App\Services\Frontdesk\VisitScheduleService;
|
|
use Illuminate\Http\Exceptions\HttpResponseException;
|
|
use Illuminate\Http\RedirectResponse;
|
|
use Illuminate\Http\Request;
|
|
use Illuminate\View\View;
|
|
|
|
class HostPortalController extends Controller
|
|
{
|
|
use ScopesToAccount;
|
|
|
|
public function index(Request $request): View
|
|
{
|
|
$host = $this->resolveLinkedHost($request);
|
|
$organization = $this->organization($request);
|
|
|
|
$pending = Visit::owned($host->owner_ref)
|
|
->where('organization_id', $organization->id)
|
|
->where('host_id', $host->id)
|
|
->where('status', Visit::STATUS_WAITING)
|
|
->with('visitor')
|
|
->orderByDesc('updated_at')
|
|
->get()
|
|
->filter(fn (Visit $v) => $v->awaitingApproval());
|
|
|
|
$upcoming = Visit::owned($host->owner_ref)
|
|
->where('organization_id', $organization->id)
|
|
->where('host_id', $host->id)
|
|
->whereIn('status', [Visit::STATUS_SCHEDULED, Visit::STATUS_EXPECTED, Visit::STATUS_OVERDUE])
|
|
->with('visitor')
|
|
->orderBy('scheduled_at')
|
|
->limit(10)
|
|
->get();
|
|
|
|
$recent = Visit::owned($host->owner_ref)
|
|
->where('organization_id', $organization->id)
|
|
->where('host_id', $host->id)
|
|
->whereIn('status', [Visit::STATUS_CHECKED_IN, Visit::STATUS_CHECKED_OUT, Visit::STATUS_CANCELLED])
|
|
->with('visitor')
|
|
->orderByDesc('updated_at')
|
|
->limit(15)
|
|
->get();
|
|
|
|
return view('frontdesk.host-portal.index', compact('host', 'organization', 'pending', 'upcoming', 'recent'));
|
|
}
|
|
|
|
public function scheduleForm(Request $request): View
|
|
{
|
|
$host = $this->resolveLinkedHost($request);
|
|
$organization = $this->organization($request);
|
|
|
|
return view('frontdesk.host-portal.schedule', compact('host', 'organization'));
|
|
}
|
|
|
|
public function scheduleStore(Request $request, VisitScheduleService $scheduler): RedirectResponse
|
|
{
|
|
$host = $this->resolveLinkedHost($request);
|
|
$organization = $this->organization($request);
|
|
|
|
$validated = $request->validate([
|
|
'full_name' => ['required', 'string', 'max:255'],
|
|
'company' => ['nullable', 'string', 'max:255'],
|
|
'phone' => ['nullable', 'string', 'max:50'],
|
|
'email' => ['nullable', 'email', 'max:255'],
|
|
'visitor_type' => ['required', 'string', 'in:'.implode(',', array_keys(config('frontdesk.visitor_types')))],
|
|
'purpose' => ['nullable', 'string', 'max:500'],
|
|
'expected_duration_minutes' => ['nullable', 'integer', 'min:5', 'max:480'],
|
|
'scheduled_at' => ['required', 'date'],
|
|
'notes' => ['nullable', 'string', 'max:2000'],
|
|
]);
|
|
|
|
$scheduler->schedule(
|
|
$host->owner_ref,
|
|
$organization,
|
|
[
|
|
...$validated,
|
|
'host_id' => $host->id,
|
|
'branch_id' => $host->branch_id,
|
|
],
|
|
$this->ownerRef($request),
|
|
);
|
|
|
|
return redirect()->route('frontdesk.host.index')->with('success', 'Visit scheduled.');
|
|
}
|
|
|
|
public function approve(Request $request, Visit $visit, VisitLifecycleService $lifecycle): RedirectResponse
|
|
{
|
|
$host = $this->resolveLinkedHost($request);
|
|
$this->authorizeOwner($request, $visit);
|
|
abort_unless($visit->host_id === $host->id, 403);
|
|
abort_unless($visit->awaitingApproval(), 422);
|
|
|
|
$lifecycle->approve($visit, $this->ownerRef($request));
|
|
|
|
return redirect()->route('frontdesk.host.index')->with('success', 'Visit approved.');
|
|
}
|
|
|
|
public function toggleAvailability(Request $request): RedirectResponse
|
|
{
|
|
$host = $this->resolveLinkedHost($request);
|
|
$host->update(['is_available' => ! $host->is_available]);
|
|
|
|
return back()->with('success', $host->is_available ? 'You are now available.' : 'You are marked unavailable.');
|
|
}
|
|
|
|
protected function resolveLinkedHost(Request $request): Host
|
|
{
|
|
$host = app(OrganizationResolver::class)->hostFor($request->user());
|
|
|
|
if (! $host) {
|
|
throw new HttpResponseException(
|
|
redirect()
|
|
->route('frontdesk.dashboard')
|
|
->with('error', 'No host profile is linked to your account. Ask an administrator to link your Ladill user on the Hosts screen.'),
|
|
);
|
|
}
|
|
|
|
$this->authorizeOwner($request, $host);
|
|
|
|
return $host;
|
|
}
|
|
}
|