Initial Ladill Queue release — enterprise QMS standalone app.
Deploy Ladill Queue / deploy (push) Successful in 56s

Phases 1–6: tickets, counters, displays, appointments, workflows, rules, analytics, reports, feedback, admin, device API, and Gitea deploy workflow for queue.ladill.com.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
isaacclad
2026-06-29 20:19:52 +00:00
co-authored by Cursor
commit cca98eefd2
297 changed files with 27263 additions and 0 deletions
@@ -0,0 +1,42 @@
<x-app-layout title="New appointment">
<div class="mx-auto max-w-lg">
<h1 class="text-2xl font-semibold">Schedule appointment</h1>
<form method="POST" action="{{ route('qms.appointments.store') }}" class="mt-6 space-y-4 rounded-2xl border bg-white p-6 dark:border-slate-700 dark:bg-slate-900">
@csrf
<div>
<label class="block text-sm font-medium">Branch</label>
<select name="branch_id" required class="mt-1 w-full rounded-lg border-slate-300 text-sm">
@foreach ($branches as $branch)
<option value="{{ $branch->id }}">{{ $branch->name }}</option>
@endforeach
</select>
</div>
<div>
<label class="block text-sm font-medium">Queue (optional)</label>
<select name="service_queue_id" class="mt-1 w-full rounded-lg border-slate-300 text-sm">
<option value="">Auto-select at check-in</option>
@foreach ($queues as $queue)
<option value="{{ $queue->id }}">{{ $queue->name }}</option>
@endforeach
</select>
</div>
<div>
<label class="block text-sm font-medium">Customer name</label>
<input name="customer_name" required class="mt-1 w-full rounded-lg border-slate-300 text-sm">
</div>
<div>
<label class="block text-sm font-medium">Phone</label>
<input name="customer_phone" type="tel" class="mt-1 w-full rounded-lg border-slate-300 text-sm">
</div>
<div>
<label class="block text-sm font-medium">Email</label>
<input name="customer_email" type="email" class="mt-1 w-full rounded-lg border-slate-300 text-sm">
</div>
<div>
<label class="block text-sm font-medium">Scheduled at</label>
<input name="scheduled_at" type="datetime-local" required class="mt-1 w-full rounded-lg border-slate-300 text-sm">
</div>
<button type="submit" class="btn-primary w-full">Save appointment</button>
</form>
</div>
</x-app-layout>
@@ -0,0 +1,18 @@
<x-app-layout title="Edit appointment">
<div class="mx-auto max-w-lg">
<h1 class="text-2xl font-semibold">Edit appointment</h1>
<form method="POST" action="{{ route('qms.appointments.update', $appointment) }}" class="mt-6 space-y-4 rounded-2xl border bg-white p-6">
@csrf @method('PUT')
<div><label class="block text-sm font-medium">Branch</label>
<select name="branch_id" required class="mt-1 w-full rounded-lg border-slate-300 text-sm">@foreach($branches as $b)<option value="{{ $b->id }}" @selected($appointment->branch_id==$b->id)>{{ $b->name }}</option>@endforeach</select>
</div>
<div><label class="block text-sm font-medium">Queue</label>
<select name="service_queue_id" class="mt-1 w-full rounded-lg border-slate-300 text-sm"><option value="">Auto</option>@foreach($queues as $q)<option value="{{ $q->id }}" @selected($appointment->service_queue_id==$q->id)>{{ $q->name }}</option>@endforeach</select>
</div>
<div><label class="block text-sm font-medium">Customer</label><input name="customer_name" value="{{ $appointment->customer_name }}" required class="mt-1 w-full rounded-lg border-slate-300 text-sm"></div>
<div><label class="block text-sm font-medium">Phone</label><input name="customer_phone" value="{{ $appointment->customer_phone }}" class="mt-1 w-full rounded-lg border-slate-300 text-sm"></div>
<div><label class="block text-sm font-medium">Scheduled at</label><input type="datetime-local" name="scheduled_at" value="{{ $appointment->scheduled_at->format('Y-m-d\TH:i') }}" required class="mt-1 w-full rounded-lg border-slate-300 text-sm"></div>
<button type="submit" class="btn-primary w-full">Save</button>
</form>
</div>
</x-app-layout>
@@ -0,0 +1,47 @@
<x-app-layout title="Appointments">
<div class="mb-6 flex items-center justify-between">
<div>
<h1 class="text-2xl font-semibold text-slate-900 dark:text-white">Appointments</h1>
<p class="mt-1 text-sm text-slate-600 dark:text-slate-400">Schedule and check in pre-booked customers.</p>
</div>
@if(app(\App\Services\Qms\QmsPermissions::class)->can(app(\App\Services\Qms\OrganizationResolver::class)->memberFor(auth()->user()), 'appointments.manage'))
<a href="{{ route('qms.appointments.create') }}" class="btn-primary">New appointment</a>
@endif
</div>
@include('partials.flash')
<div class="overflow-hidden rounded-2xl border border-slate-200 bg-white dark:border-slate-700 dark:bg-slate-900">
<table class="min-w-full divide-y divide-slate-200 dark:divide-slate-700">
<thead class="bg-slate-50 dark:bg-slate-800">
<tr>
<th class="px-4 py-3 text-left text-xs font-semibold uppercase text-slate-500">Customer</th>
<th class="px-4 py-3 text-left text-xs font-semibold uppercase text-slate-500">Scheduled</th>
<th class="px-4 py-3 text-left text-xs font-semibold uppercase text-slate-500">Queue</th>
<th class="px-4 py-3 text-left text-xs font-semibold uppercase text-slate-500">Status</th>
<th class="px-4 py-3"></th>
</tr>
</thead>
<tbody class="divide-y divide-slate-200 dark:divide-slate-700">
@forelse ($appointments as $appointment)
<tr>
<td class="px-4 py-3 text-sm">{{ $appointment->customer_name }}</td>
<td class="px-4 py-3 text-sm">{{ $appointment->scheduled_at->format('M j, H:i') }}</td>
<td class="px-4 py-3 text-sm">{{ $appointment->serviceQueue?->name ?? '—' }}</td>
<td class="px-4 py-3 text-sm capitalize">{{ str_replace('_', ' ', $appointment->status) }}</td>
<td class="px-4 py-3 text-right text-sm">
@if ($appointment->status === 'scheduled')
<a href="{{ route('qms.appointments.edit', $appointment) }}" class="text-indigo-600">Edit</a>
<form method="POST" action="{{ route('qms.appointments.check-in', $appointment) }}" class="inline ml-2">@csrf<button class="text-indigo-600">Check in</button></form>
<form method="POST" action="{{ route('qms.appointments.cancel', $appointment) }}" class="inline ml-2">@csrf<button class="text-amber-600">Cancel</button></form>
@elseif ($appointment->ticket)
<a href="{{ route('qms.tickets.show', $appointment->ticket) }}" class="text-indigo-600">View ticket</a>
@endif
</td>
</tr>
@empty
<tr><td colspan="5" class="px-6 py-12 text-center text-sm text-slate-500">No appointments yet.</td></tr>
@endforelse
</tbody>
</table>
</div>
<div class="mt-4">{{ $appointments->links() }}</div>
</x-app-layout>