Switch team invites to email-only flow via identity API.
Deploy Ladill Frontdesk / deploy (push) Successful in 44s

Replace local member UUID invites with platform email invites, SSO post-auth
redirect, and provisioner-backed pending access until accept.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
isaacclad
2026-07-01 00:25:09 +00:00
co-authored by Cursor
parent 6bc52d9ef3
commit b68331cdaf
6 changed files with 216 additions and 23 deletions
@@ -1,28 +1,38 @@
<x-app-layout title="Add team member">
<x-app-layout title="Add member">
<div class="mx-auto max-w-lg">
<h1 class="text-xl font-semibold text-slate-900">Add team member</h1>
<p class="mt-1 text-sm text-slate-500">Enter the Ladill user public ID (OIDC sub) of the person to invite.</p>
<h1 class="text-xl font-semibold text-slate-900">Invite team member</h1>
<form method="POST" action="{{ route('frontdesk.members.store') }}" class="mt-6 space-y-4 rounded-2xl border border-slate-200 bg-white p-6">
@csrf
<div><label class="block text-sm font-medium">User public ID</label><input type="text" name="user_ref" required class="mt-1 w-full rounded-lg border-slate-300 text-sm font-mono"></div>
<div>
<label class="block text-sm font-medium">Role</label>
<label class="block text-sm font-medium text-slate-700">Email address</label>
<input type="email" name="email" value="{{ old('email') }}" required
class="mt-1 w-full rounded-lg border-slate-300 text-sm"
placeholder="colleague@company.com">
<p class="mt-1 text-xs text-slate-500">They will receive an email to accept and join your Frontdesk organization.</p>
</div>
<div>
<label class="block text-sm font-medium text-slate-700">Role</label>
<select name="role" class="mt-1 w-full rounded-lg border-slate-300 text-sm">
@foreach ($roles as $key => $label)
<option value="{{ $key }}">{{ $label }}</option>
<option value="{{ $key }}" @selected(old('role') === $key)>{{ $label }}</option>
@endforeach
</select>
</div>
<div>
<label class="block text-sm font-medium">Branch (optional)</label>
<label class="block text-sm font-medium text-slate-700">Branch (optional)</label>
<select name="branch_id" class="mt-1 w-full rounded-lg border-slate-300 text-sm">
<option value="">All branches</option>
@foreach ($branches as $branch)
<option value="{{ $branch->id }}">{{ $branch->name }}</option>
<option value="{{ $branch->id }}" @selected(old('branch_id') == $branch->id)>{{ $branch->name }}</option>
@endforeach
</select>
</div>
<button type="submit" class="btn-primary w-full">Save member</button>
<button type="submit" class="btn-primary">Send invitation</button>
</form>
</div>
</x-app-layout>
@@ -7,12 +7,17 @@
<div class="mt-4 overflow-hidden rounded-2xl border border-slate-200 bg-white">
<table class="min-w-full text-sm">
<thead class="bg-slate-50 text-left text-xs uppercase text-slate-500">
<tr><th class="px-4 py-3">User ID</th><th class="px-4 py-3">Role</th><th class="px-4 py-3">Branch</th><th class="px-4 py-3"></th></tr>
<tr><th class="px-4 py-3">Member</th><th class="px-4 py-3">Role</th><th class="px-4 py-3">Branch</th><th class="px-4 py-3"></th></tr>
</thead>
<tbody class="divide-y divide-slate-50">
@foreach ($members as $member)
@php
$display = str_contains($member->user_ref, '@')
? $member->user_ref
: (\App\Models\User::where('public_id', $member->user_ref)->value('email') ?? $member->user_ref);
@endphp
<tr>
<td class="px-4 py-3 font-mono text-xs">{{ $member->user_ref }}</td>
<td class="px-4 py-3 text-sm">{{ $display }}</td>
<td class="px-4 py-3">{{ $roles[$member->role] ?? $member->role }}</td>
<td class="px-4 py-3">{{ $member->branch?->name ?? 'All branches' }}</td>
<td class="px-4 py-3 text-right">