Files
ladill-frontdesk/app/Http/Controllers/Frontdesk/HostPortalController.php
T
isaaccladandCursor 1163b50b39
Deploy Ladill Frontdesk / deploy (push) Successful in 28s
Fix Host portal showing for users without a linked host profile.
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>
2026-06-27 21:13:50 +00:00

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;
}
}