Drop heroes from analytics pages and remove bordered show cards.
Deploy Ladill Queue / deploy (push) Successful in 43s
Deploy Ladill Queue / deploy (push) Successful in 43s
Analytics, Reports, Feedback, and Branches use simple headers again; report and related show views use shadow panels instead of card borders. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -26,13 +26,7 @@ class BranchController extends Controller
|
|||||||
->orderBy('name')
|
->orderBy('name')
|
||||||
->get();
|
->get();
|
||||||
|
|
||||||
$heroStats = [
|
return view('qms.admin.branches.index', compact('branches', 'organization'));
|
||||||
'total' => $branches->count(),
|
|
||||||
'active' => $branches->where('is_active', true)->count(),
|
|
||||||
'departments' => $branches->sum('departments_count'),
|
|
||||||
];
|
|
||||||
|
|
||||||
return view('qms.admin.branches.index', compact('branches', 'organization', 'heroStats'));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function create(Request $request): View
|
public function create(Request $request): View
|
||||||
|
|||||||
@@ -32,21 +32,10 @@ class FeedbackAdminController extends Controller
|
|||||||
->when($branchScope, fn ($q) => $q->whereHas('ticket', fn ($t) => $t->where('branch_id', $branchScope)))
|
->when($branchScope, fn ($q) => $q->whereHas('ticket', fn ($t) => $t->where('branch_id', $branchScope)))
|
||||||
->avg('rating');
|
->avg('rating');
|
||||||
|
|
||||||
$feedbackQuery = CustomerFeedback::owned($owner)
|
|
||||||
->where('organization_id', $organization->id)
|
|
||||||
->when($branchScope, fn ($q) => $q->whereHas('ticket', fn ($t) => $t->where('branch_id', $branchScope)));
|
|
||||||
|
|
||||||
$heroStats = [
|
|
||||||
'total' => (clone $feedbackQuery)->count(),
|
|
||||||
'avg_rating' => round((float) $avgRating, 1),
|
|
||||||
'this_month' => (clone $feedbackQuery)->where('created_at', '>=', now()->startOfMonth())->count(),
|
|
||||||
];
|
|
||||||
|
|
||||||
return view('qms.feedback.index', [
|
return view('qms.feedback.index', [
|
||||||
'feedback' => $feedback,
|
'feedback' => $feedback,
|
||||||
'organization' => $organization,
|
'organization' => $organization,
|
||||||
'avgRating' => round((float) $avgRating, 1),
|
'avgRating' => round((float) $avgRating, 1),
|
||||||
'heroStats' => $heroStats,
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,10 +36,6 @@ class ReportController extends Controller
|
|||||||
'organization' => $organization,
|
'organization' => $organization,
|
||||||
'branches' => $branches,
|
'branches' => $branches,
|
||||||
'reports' => config('qms.report_types'),
|
'reports' => config('qms.report_types'),
|
||||||
'heroStats' => [
|
|
||||||
'reports' => count(config('qms.report_types')),
|
|
||||||
'branches' => $branches->count(),
|
|
||||||
],
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<x-app-layout title="New branch">
|
<x-app-layout title="New branch">
|
||||||
<div class="mx-auto max-w-lg">
|
<div class="mx-auto max-w-lg">
|
||||||
<h1 class="text-2xl font-semibold">New branch</h1>
|
<h1 class="text-2xl font-semibold">New branch</h1>
|
||||||
<form method="POST" action="{{ route('qms.branches.store') }}" class="mt-6 space-y-4 rounded-2xl border bg-white p-6 dark:border-slate-700 dark:bg-slate-900">
|
<form method="POST" action="{{ route('qms.branches.store') }}" class="mt-6 space-y-4 rounded-2xl bg-white p-6 shadow-sm">
|
||||||
@csrf
|
@csrf
|
||||||
<div><label class="block text-sm font-medium">Name</label><input name="name" required class="mt-1 w-full rounded-lg border-slate-300 text-sm"></div>
|
<div><label class="block text-sm font-medium">Name</label><input name="name" required class="mt-1 w-full rounded-lg border-slate-300 text-sm"></div>
|
||||||
<div><label class="block text-sm font-medium">Code</label><input name="code" class="mt-1 w-full rounded-lg border-slate-300 text-sm"></div>
|
<div><label class="block text-sm font-medium">Code</label><input name="code" class="mt-1 w-full rounded-lg border-slate-300 text-sm"></div>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<x-app-layout title="Edit branch">
|
<x-app-layout title="Edit branch">
|
||||||
<div class="mx-auto max-w-lg">
|
<div class="mx-auto max-w-lg">
|
||||||
<h1 class="text-2xl font-semibold">Edit branch</h1>
|
<h1 class="text-2xl font-semibold">Edit branch</h1>
|
||||||
<form method="POST" action="{{ route('qms.branches.update', $branch) }}" class="mt-6 space-y-4 rounded-2xl border bg-white p-6 dark:border-slate-700 dark:bg-slate-900">
|
<form method="POST" action="{{ route('qms.branches.update', $branch) }}" class="mt-6 space-y-4 rounded-2xl bg-white p-6 shadow-sm">
|
||||||
@csrf @method('PUT')
|
@csrf @method('PUT')
|
||||||
<div><label class="block text-sm font-medium">Name</label><input name="name" value="{{ $branch->name }}" required class="mt-1 w-full rounded-lg border-slate-300 text-sm"></div>
|
<div><label class="block text-sm font-medium">Name</label><input name="name" value="{{ $branch->name }}" required class="mt-1 w-full rounded-lg border-slate-300 text-sm"></div>
|
||||||
<div><label class="block text-sm font-medium">Code</label><input name="code" value="{{ $branch->code }}" class="mt-1 w-full rounded-lg border-slate-300 text-sm"></div>
|
<div><label class="block text-sm font-medium">Code</label><input name="code" value="{{ $branch->code }}" class="mt-1 w-full rounded-lg border-slate-300 text-sm"></div>
|
||||||
|
|||||||
@@ -6,26 +6,16 @@
|
|||||||
@endphp
|
@endphp
|
||||||
|
|
||||||
<x-app-layout title="Branches">
|
<x-app-layout title="Branches">
|
||||||
<div class="space-y-6">
|
<div class="mb-6 flex items-center justify-between">
|
||||||
<x-qms.page-hero
|
<h1 class="text-2xl font-semibold text-slate-900">Branches</h1>
|
||||||
badge="Locations · Sites · Coverage"
|
|
||||||
title="Branches"
|
|
||||||
description="Organize queue operations by location — branches scope queues, counters, displays, and team access."
|
|
||||||
:stats="[
|
|
||||||
['value' => number_format($heroStats['total']), 'label' => 'Branches'],
|
|
||||||
['value' => number_format($heroStats['active']), 'label' => 'Active'],
|
|
||||||
['value' => number_format($heroStats['departments']), 'label' => 'Departments'],
|
|
||||||
]">
|
|
||||||
@if ($canManageBranches)
|
@if ($canManageBranches)
|
||||||
<x-slot name="actions">
|
|
||||||
<a href="{{ route('qms.branches.create') }}" class="btn-primary">New branch</a>
|
<a href="{{ route('qms.branches.create') }}" class="btn-primary">New branch</a>
|
||||||
</x-slot>
|
|
||||||
@endif
|
@endif
|
||||||
</x-qms.page-hero>
|
</div>
|
||||||
|
|
||||||
@include('partials.flash')
|
@include('partials.flash')
|
||||||
|
|
||||||
<div class="overflow-hidden rounded-2xl bg-white">
|
<div class="overflow-hidden rounded-2xl bg-white shadow-sm">
|
||||||
<table class="min-w-full divide-y divide-slate-200">
|
<table class="min-w-full divide-y divide-slate-200">
|
||||||
<thead class="bg-slate-50"><tr>
|
<thead class="bg-slate-50"><tr>
|
||||||
<th class="px-4 py-3 text-left text-xs font-semibold uppercase text-slate-500">Name</th>
|
<th class="px-4 py-3 text-left text-xs font-semibold uppercase text-slate-500">Name</th>
|
||||||
@@ -47,5 +37,4 @@
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</x-app-layout>
|
</x-app-layout>
|
||||||
|
|||||||
@@ -1,16 +1,24 @@
|
|||||||
<x-app-layout title="Analytics">
|
<x-app-layout title="Analytics">
|
||||||
<div class="space-y-6">
|
<h1 class="mb-6 text-2xl font-semibold text-slate-900">Analytics</h1>
|
||||||
<x-qms.page-hero
|
|
||||||
badge="Live ops · Trends · Performance"
|
|
||||||
title="Analytics"
|
|
||||||
description="Real-time queue performance, wait times, and customer satisfaction across your organization."
|
|
||||||
:stats="[
|
|
||||||
['value' => number_format($overview['waiting'] ?? 0), 'label' => 'Waiting now'],
|
|
||||||
['value' => number_format($overview['served_today'] ?? 0), 'label' => 'Served today'],
|
|
||||||
['value' => $overview['feedback_avg_30d'] ?? '—', 'label' => 'Avg rating (30d)'],
|
|
||||||
]" />
|
|
||||||
|
|
||||||
<div class="grid gap-6 lg:grid-cols-2">
|
<div class="grid gap-4 sm:grid-cols-2 lg:grid-cols-4">
|
||||||
|
@foreach ([
|
||||||
|
'waiting' => 'Waiting now',
|
||||||
|
'serving' => 'Being served',
|
||||||
|
'served_today' => 'Served today',
|
||||||
|
'no_shows_today' => 'No-shows today',
|
||||||
|
'avg_wait_seconds' => 'Avg wait (sec)',
|
||||||
|
'appointments_today' => 'Appointments today',
|
||||||
|
'feedback_avg_30d' => 'Avg rating (30d)',
|
||||||
|
] as $key => $label)
|
||||||
|
<div class="rounded-2xl bg-white p-4 shadow-sm">
|
||||||
|
<div class="text-xs font-semibold uppercase text-slate-500">{{ $label }}</div>
|
||||||
|
<div class="mt-2 text-2xl font-semibold text-slate-900">{{ $overview[$key] ?? 0 }}</div>
|
||||||
|
</div>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mt-8 grid gap-6 lg:grid-cols-2">
|
||||||
<div class="rounded-2xl bg-white p-6 shadow-sm">
|
<div class="rounded-2xl bg-white p-6 shadow-sm">
|
||||||
<h2 class="text-sm font-semibold uppercase text-slate-500">14-day trend</h2>
|
<h2 class="text-sm font-semibold uppercase text-slate-500">14-day trend</h2>
|
||||||
<table class="mt-4 w-full text-sm">
|
<table class="mt-4 w-full text-sm">
|
||||||
@@ -33,19 +41,4 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="grid gap-4 sm:grid-cols-2 lg:grid-cols-4">
|
|
||||||
@foreach ([
|
|
||||||
'serving' => 'Being served',
|
|
||||||
'no_shows_today' => 'No-shows today',
|
|
||||||
'avg_wait_seconds' => 'Avg wait (sec)',
|
|
||||||
'appointments_today' => 'Appointments today',
|
|
||||||
] as $key => $label)
|
|
||||||
<div class="rounded-2xl bg-white p-4 shadow-sm">
|
|
||||||
<div class="text-xs font-semibold uppercase text-slate-500">{{ $label }}</div>
|
|
||||||
<div class="mt-2 text-2xl font-semibold text-slate-900">{{ $overview[$key] ?? 0 }}</div>
|
|
||||||
</div>
|
|
||||||
@endforeach
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</x-app-layout>
|
</x-app-layout>
|
||||||
|
|||||||
@@ -17,14 +17,14 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mt-6 grid gap-4 lg:grid-cols-3">
|
<div class="mt-6 grid gap-4 lg:grid-cols-3">
|
||||||
<section class="rounded-2xl border border-slate-200 bg-white p-5 lg:col-span-2">
|
<section class="rounded-2xl bg-white p-5 shadow-sm lg:col-span-2">
|
||||||
<h2 class="text-sm font-semibold text-slate-900">Assigned queues</h2>
|
<h2 class="text-sm font-semibold text-slate-900">Assigned queues</h2>
|
||||||
@if ($counter->serviceQueues->isEmpty())
|
@if ($counter->serviceQueues->isEmpty())
|
||||||
<p class="mt-3 text-sm text-slate-500">No queues linked yet. Edit this counter to assign service queues.</p>
|
<p class="mt-3 text-sm text-slate-500">No queues linked yet. Edit this counter to assign service queues.</p>
|
||||||
@else
|
@else
|
||||||
<ul class="mt-4 space-y-3">
|
<ul class="mt-4 space-y-3">
|
||||||
@foreach ($counter->serviceQueues as $queue)
|
@foreach ($counter->serviceQueues as $queue)
|
||||||
<li class="flex items-center justify-between rounded-xl border border-slate-100 bg-slate-50 px-4 py-3">
|
<li class="flex items-center justify-between rounded-xl bg-slate-50 px-4 py-3">
|
||||||
<div>
|
<div>
|
||||||
<p class="font-medium text-slate-900">{{ $queue->name }}</p>
|
<p class="font-medium text-slate-900">{{ $queue->name }}</p>
|
||||||
<p class="text-xs text-slate-500">Prefix {{ $queue->prefix }}</p>
|
<p class="text-xs text-slate-500">Prefix {{ $queue->prefix }}</p>
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
@endif
|
@endif
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="rounded-2xl border border-slate-200 bg-white p-5">
|
<section class="rounded-2xl bg-white p-5 shadow-sm">
|
||||||
<h2 class="text-sm font-semibold text-slate-900">Now at this counter</h2>
|
<h2 class="text-sm font-semibold text-slate-900">Now at this counter</h2>
|
||||||
@if ($currentTicket)
|
@if ($currentTicket)
|
||||||
<div class="mt-4 rounded-xl bg-indigo-50 p-4 ring-1 ring-indigo-100">
|
<div class="mt-4 rounded-xl bg-indigo-50 p-4 ring-1 ring-indigo-100">
|
||||||
|
|||||||
@@ -41,7 +41,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mt-6 grid gap-4 lg:grid-cols-3">
|
<div class="mt-6 grid gap-4 lg:grid-cols-3">
|
||||||
<section class="rounded-2xl border border-slate-200 bg-white p-5 lg:col-span-2">
|
<section class="rounded-2xl bg-white p-5 shadow-sm lg:col-span-2">
|
||||||
<h2 class="text-sm font-semibold text-slate-900">Assigned queues</h2>
|
<h2 class="text-sm font-semibold text-slate-900">Assigned queues</h2>
|
||||||
<p class="mt-1 text-sm text-slate-500">Tickets from these queues appear on this screen and trigger voice calls.</p>
|
<p class="mt-1 text-sm text-slate-500">Tickets from these queues appear on this screen and trigger voice calls.</p>
|
||||||
|
|
||||||
@@ -56,7 +56,7 @@
|
|||||||
@else
|
@else
|
||||||
<ul class="mt-4 grid gap-3 sm:grid-cols-2">
|
<ul class="mt-4 grid gap-3 sm:grid-cols-2">
|
||||||
@foreach ($queues as $queue)
|
@foreach ($queues as $queue)
|
||||||
<li class="flex items-start gap-3 rounded-xl border border-slate-100 bg-slate-50 px-4 py-3">
|
<li class="flex items-start gap-3 rounded-xl bg-slate-50 px-4 py-3">
|
||||||
<span class="mt-0.5 flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-white text-xs font-bold text-indigo-700 ring-1 ring-indigo-100">
|
<span class="mt-0.5 flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-white text-xs font-bold text-indigo-700 ring-1 ring-indigo-100">
|
||||||
{{ $queue->prefix }}
|
{{ $queue->prefix }}
|
||||||
</span>
|
</span>
|
||||||
@@ -73,7 +73,7 @@
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="space-y-4">
|
<section class="space-y-4">
|
||||||
<div class="rounded-2xl border border-slate-200 bg-white p-5">
|
<div class="rounded-2xl bg-white p-5 shadow-sm">
|
||||||
<h2 class="text-sm font-semibold text-slate-900">Display details</h2>
|
<h2 class="text-sm font-semibold text-slate-900">Display details</h2>
|
||||||
<dl class="mt-4 space-y-3 text-sm">
|
<dl class="mt-4 space-y-3 text-sm">
|
||||||
<div class="flex justify-between gap-4">
|
<div class="flex justify-between gap-4">
|
||||||
@@ -96,7 +96,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="rounded-2xl border border-slate-200 bg-white p-5"
|
class="rounded-2xl bg-white p-5 shadow-sm"
|
||||||
x-data="{
|
x-data="{
|
||||||
url: @js($publicUrl),
|
url: @js($publicUrl),
|
||||||
copied: false,
|
copied: false,
|
||||||
@@ -113,7 +113,7 @@
|
|||||||
>
|
>
|
||||||
<h2 class="text-sm font-semibold text-slate-900">Public display URL</h2>
|
<h2 class="text-sm font-semibold text-slate-900">Public display URL</h2>
|
||||||
<p class="mt-1 text-sm text-slate-500">Open this link on a TV, tablet, or kiosk in your waiting area.</p>
|
<p class="mt-1 text-sm text-slate-500">Open this link on a TV, tablet, or kiosk in your waiting area.</p>
|
||||||
<div class="mt-4 rounded-xl border border-slate-200 bg-slate-50 p-3">
|
<div class="mt-4 rounded-xl bg-slate-50 p-3">
|
||||||
<p class="break-all font-mono text-xs text-slate-700" x-text="url"></p>
|
<p class="break-all font-mono text-xs text-slate-700" x-text="url"></p>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-3 flex flex-wrap gap-2">
|
<div class="mt-3 flex flex-wrap gap-2">
|
||||||
@@ -124,7 +124,7 @@
|
|||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<section class="mt-4 overflow-hidden rounded-2xl border border-slate-200 bg-slate-900">
|
<section class="mt-4 overflow-hidden rounded-2xl bg-slate-900 shadow-sm">
|
||||||
<div class="flex items-center justify-between border-b border-white/10 px-5 py-3">
|
<div class="flex items-center justify-between border-b border-white/10 px-5 py-3">
|
||||||
<p class="text-xs font-semibold uppercase tracking-widest text-slate-400">Live preview</p>
|
<p class="text-xs font-semibold uppercase tracking-widest text-slate-400">Live preview</p>
|
||||||
<span class="inline-flex items-center gap-1.5 text-xs text-slate-400">
|
<span class="inline-flex items-center gap-1.5 text-xs text-slate-400">
|
||||||
|
|||||||
@@ -1,16 +1,10 @@
|
|||||||
<x-app-layout title="Customer feedback">
|
<x-app-layout title="Customer feedback">
|
||||||
<div class="space-y-6">
|
<div class="mb-6">
|
||||||
<x-qms.page-hero
|
<h1 class="text-2xl font-semibold text-slate-900">Customer feedback</h1>
|
||||||
badge="Ratings · Comments · Service quality"
|
<p class="mt-1 text-sm text-slate-600">Average rating: {{ $avgRating ?: '—' }} / 5</p>
|
||||||
title="Customer feedback"
|
</div>
|
||||||
description="Reviews collected after service — track average ratings and read customer comments by ticket."
|
|
||||||
:stats="[
|
|
||||||
['value' => number_format($heroStats['total']), 'label' => 'Responses'],
|
|
||||||
['value' => $heroStats['avg_rating'] ?: '—', 'label' => 'Avg rating'],
|
|
||||||
['value' => number_format($heroStats['this_month']), 'label' => 'This month'],
|
|
||||||
]" />
|
|
||||||
|
|
||||||
<div class="overflow-hidden rounded-2xl bg-white">
|
<div class="overflow-hidden rounded-2xl bg-white shadow-sm">
|
||||||
<table class="min-w-full divide-y divide-slate-200">
|
<table class="min-w-full divide-y divide-slate-200">
|
||||||
<thead class="bg-slate-50"><tr>
|
<thead class="bg-slate-50"><tr>
|
||||||
<th class="px-4 py-3 text-left text-xs font-semibold uppercase text-slate-500">Ticket</th>
|
<th class="px-4 py-3 text-left text-xs font-semibold uppercase text-slate-500">Ticket</th>
|
||||||
@@ -32,6 +26,5 @@
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
<div>{{ $feedback->links() }}</div>
|
<div class="mt-4">{{ $feedback->links() }}</div>
|
||||||
</div>
|
|
||||||
</x-app-layout>
|
</x-app-layout>
|
||||||
|
|||||||
@@ -9,9 +9,9 @@
|
|||||||
</div>
|
</div>
|
||||||
@include('partials.flash')
|
@include('partials.flash')
|
||||||
<div class="grid gap-4 sm:grid-cols-3">
|
<div class="grid gap-4 sm:grid-cols-3">
|
||||||
<div class="rounded-2xl border bg-white p-4"><div class="text-xs uppercase text-slate-500">Waiting</div><div class="mt-1 text-2xl font-semibold">{{ $waiting }}</div></div>
|
<div class="rounded-2xl bg-white p-4 shadow-sm"><div class="text-xs uppercase text-slate-500">Waiting</div><div class="mt-1 text-2xl font-semibold text-slate-900">{{ $waiting }}</div></div>
|
||||||
<div class="rounded-2xl border bg-white p-4"><div class="text-xs uppercase text-slate-500">Prefix</div><div class="mt-1 text-2xl font-mono">{{ $queue->prefix }}</div></div>
|
<div class="rounded-2xl bg-white p-4 shadow-sm"><div class="text-xs uppercase text-slate-500">Prefix</div><div class="mt-1 text-2xl font-mono text-slate-900">{{ $queue->prefix }}</div></div>
|
||||||
<div class="rounded-2xl border bg-white p-4"><div class="text-xs uppercase text-slate-500">Status</div><div class="mt-1 text-lg">{{ $queue->is_paused ? 'Paused' : ($queue->is_active ? 'Active' : 'Inactive') }}</div></div>
|
<div class="rounded-2xl bg-white p-4 shadow-sm"><div class="text-xs uppercase text-slate-500">Status</div><div class="mt-1 text-lg text-slate-900">{{ $queue->is_paused ? 'Paused' : ($queue->is_active ? 'Active' : 'Inactive') }}</div></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-4 flex gap-2">
|
<div class="mt-4 flex gap-2">
|
||||||
<a href="{{ route('qms.rules.index', $queue) }}" class="text-sm text-indigo-600">Queue rules</a>
|
<a href="{{ route('qms.rules.index', $queue) }}" class="text-sm text-indigo-600">Queue rules</a>
|
||||||
|
|||||||
@@ -1,14 +1,5 @@
|
|||||||
<x-app-layout title="Reports">
|
<x-app-layout title="Reports">
|
||||||
<div class="space-y-6">
|
<h1 class="mb-6 text-2xl font-semibold text-slate-900">Reports</h1>
|
||||||
<x-qms.page-hero
|
|
||||||
badge="Export · Metrics · CSV"
|
|
||||||
title="Reports"
|
|
||||||
description="Drill into tickets, wait times, counters, appointments, and feedback — view metrics and export CSV for any date range."
|
|
||||||
:stats="[
|
|
||||||
['value' => number_format($heroStats['reports']), 'label' => 'Report types'],
|
|
||||||
['value' => number_format($heroStats['branches']), 'label' => 'Branches'],
|
|
||||||
['value' => 'CSV', 'label' => 'Export format'],
|
|
||||||
]" />
|
|
||||||
|
|
||||||
<div class="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
<div class="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
|
||||||
@foreach ($reports as $type => $label)
|
@foreach ($reports as $type => $label)
|
||||||
@@ -18,5 +9,4 @@
|
|||||||
</a>
|
</a>
|
||||||
@endforeach
|
@endforeach
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</x-app-layout>
|
</x-app-layout>
|
||||||
|
|||||||
@@ -2,13 +2,14 @@
|
|||||||
<div class="mb-6 flex flex-wrap items-end justify-between gap-4">
|
<div class="mb-6 flex flex-wrap items-end justify-between gap-4">
|
||||||
<div>
|
<div>
|
||||||
<a href="{{ route('qms.reports.index') }}" class="text-sm text-indigo-600">← Reports</a>
|
<a href="{{ route('qms.reports.index') }}" class="text-sm text-indigo-600">← Reports</a>
|
||||||
<h1 class="mt-2 text-2xl font-semibold">{{ $label }}</h1>
|
<h1 class="mt-2 text-2xl font-semibold text-slate-900">{{ $label }}</h1>
|
||||||
</div>
|
</div>
|
||||||
@if ($canExport)
|
@if ($canExport)
|
||||||
<a href="{{ route('qms.reports.export', array_merge(['type' => $type], request()->only(['from', 'to', 'branch_id']))) }}" class="btn-primary">Export CSV</a>
|
<a href="{{ route('qms.reports.export', array_merge(['type' => $type], request()->only(['from', 'to', 'branch_id']))) }}" class="btn-primary">Export CSV</a>
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
<form method="GET" class="mb-6 flex flex-wrap gap-3 rounded-2xl border bg-white p-4 dark:border-slate-700 dark:bg-slate-900">
|
|
||||||
|
<form method="GET" class="mb-6 flex flex-wrap gap-3 rounded-2xl bg-white p-4 shadow-sm">
|
||||||
<input type="date" name="from" value="{{ $from }}" class="rounded-lg border-slate-300 text-sm">
|
<input type="date" name="from" value="{{ $from }}" class="rounded-lg border-slate-300 text-sm">
|
||||||
<input type="date" name="to" value="{{ $to }}" class="rounded-lg border-slate-300 text-sm">
|
<input type="date" name="to" value="{{ $to }}" class="rounded-lg border-slate-300 text-sm">
|
||||||
<select name="branch_id" class="rounded-lg border-slate-300 text-sm">
|
<select name="branch_id" class="rounded-lg border-slate-300 text-sm">
|
||||||
@@ -19,20 +20,21 @@
|
|||||||
</select>
|
</select>
|
||||||
<button type="submit" class="rounded-lg bg-slate-100 px-4 py-2 text-sm">Apply</button>
|
<button type="submit" class="rounded-lg bg-slate-100 px-4 py-2 text-sm">Apply</button>
|
||||||
</form>
|
</form>
|
||||||
<div class="rounded-2xl border bg-white p-6 dark:border-slate-700 dark:bg-slate-900">
|
|
||||||
|
<div class="rounded-2xl bg-white p-6 shadow-sm">
|
||||||
@if ($type === 'wait_times' && isset($data['hourly']))
|
@if ($type === 'wait_times' && isset($data['hourly']))
|
||||||
<table class="w-full text-sm"><thead><tr><th class="text-left py-2">Hour</th><th class="text-right">Avg wait (sec)</th></tr></thead>
|
<table class="w-full text-sm"><thead><tr><th class="text-left py-2">Hour</th><th class="text-right">Avg wait (sec)</th></tr></thead>
|
||||||
<tbody>@foreach ($data['hourly'] as $row)<tr class="border-t"><td class="py-2">{{ $row['hour'] }}:00</td><td class="text-right">{{ $row['avg_wait_seconds'] }}</td></tr>@endforeach</tbody>
|
<tbody>@foreach ($data['hourly'] as $row)<tr class="border-t border-slate-100"><td class="py-2">{{ $row['hour'] }}:00</td><td class="text-right">{{ $row['avg_wait_seconds'] }}</td></tr>@endforeach</tbody>
|
||||||
</table>
|
</table>
|
||||||
@elseif ($type === 'counters' && isset($data['counters']))
|
@elseif ($type === 'counters' && isset($data['counters']))
|
||||||
<table class="w-full text-sm"><thead><tr><th class="text-left py-2">Counter</th><th class="text-right">Served</th></tr></thead>
|
<table class="w-full text-sm"><thead><tr><th class="text-left py-2">Counter</th><th class="text-right">Served</th></tr></thead>
|
||||||
<tbody>@foreach ($data['counters'] as $row)<tr class="border-t"><td class="py-2">{{ $row['name'] }}</td><td class="text-right">{{ $row['served'] }}</td></tr>@endforeach</tbody>
|
<tbody>@foreach ($data['counters'] as $row)<tr class="border-t border-slate-100"><td class="py-2">{{ $row['name'] }}</td><td class="text-right">{{ $row['served'] }}</td></tr>@endforeach</tbody>
|
||||||
</table>
|
</table>
|
||||||
@else
|
@else
|
||||||
<dl class="space-y-3">
|
<dl class="space-y-3">
|
||||||
@foreach ($data as $key => $value)
|
@foreach ($data as $key => $value)
|
||||||
@if (!is_array($value))
|
@if (!is_array($value))
|
||||||
<div class="flex justify-between border-b pb-2 text-sm"><dt class="text-slate-600">{{ str_replace('_', ' ', $key) }}</dt><dd class="font-medium">{{ $value }}</dd></div>
|
<div class="flex justify-between border-b border-slate-100 pb-2 text-sm"><dt class="text-slate-600">{{ str_replace('_', ' ', $key) }}</dt><dd class="font-medium text-slate-900">{{ $value }}</dd></div>
|
||||||
@endif
|
@endif
|
||||||
@endforeach
|
@endforeach
|
||||||
</dl>
|
</dl>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
@if (session('success'))
|
@if (session('success'))
|
||||||
<p class="mb-4 rounded-lg bg-emerald-50 px-3 py-2 text-sm text-emerald-800">{{ session('success') }}</p>
|
<p class="mb-4 rounded-lg bg-emerald-50 px-3 py-2 text-sm text-emerald-800">{{ session('success') }}</p>
|
||||||
@endif
|
@endif
|
||||||
<div class="rounded-2xl border bg-white p-8 text-center dark:border-slate-700 dark:bg-slate-900">
|
<div class="rounded-2xl bg-white p-8 text-center shadow-sm">
|
||||||
<p class="text-sm uppercase text-slate-500">Ticket</p>
|
<p class="text-sm uppercase text-slate-500">Ticket</p>
|
||||||
<p class="text-5xl font-bold text-indigo-600">{{ $ticket->ticket_number }}</p>
|
<p class="text-5xl font-bold text-indigo-600">{{ $ticket->ticket_number }}</p>
|
||||||
<p class="mt-2 text-lg">{{ $ticket->serviceQueue?->name }}</p>
|
<p class="mt-2 text-lg">{{ $ticket->serviceQueue?->name }}</p>
|
||||||
|
|||||||
@@ -4,11 +4,11 @@
|
|||||||
<h1 class="mt-2 text-2xl font-semibold">{{ $workflow->name }}</h1>
|
<h1 class="mt-2 text-2xl font-semibold">{{ $workflow->name }}</h1>
|
||||||
@if ($workflow->description)<p class="mt-1 text-sm text-slate-600">{{ $workflow->description }}</p>@endif
|
@if ($workflow->description)<p class="mt-1 text-sm text-slate-600">{{ $workflow->description }}</p>@endif
|
||||||
</div>
|
</div>
|
||||||
<div class="rounded-2xl border bg-white p-6 dark:border-slate-700 dark:bg-slate-900">
|
<div class="rounded-2xl bg-white p-6 shadow-sm">
|
||||||
<h2 class="text-sm font-semibold uppercase text-slate-500">Steps</h2>
|
<h2 class="text-sm font-semibold uppercase text-slate-500">Steps</h2>
|
||||||
<ol class="mt-4 space-y-3">
|
<ol class="mt-4 space-y-3">
|
||||||
@foreach ($workflow->steps as $step)
|
@foreach ($workflow->steps as $step)
|
||||||
<li class="flex items-center gap-3 rounded-lg border px-4 py-3">
|
<li class="flex items-center gap-3 rounded-lg bg-slate-50 px-4 py-3">
|
||||||
<span class="flex h-8 w-8 items-center justify-center rounded-full bg-indigo-50 text-sm font-semibold text-indigo-700">{{ $step->sort_order }}</span>
|
<span class="flex h-8 w-8 items-center justify-center rounded-full bg-indigo-50 text-sm font-semibold text-indigo-700">{{ $step->sort_order }}</span>
|
||||||
<div>
|
<div>
|
||||||
<div class="font-medium">{{ $step->name }}</div>
|
<div class="font-medium">{{ $step->name }}</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user