diff --git a/app/Http/Controllers/SearchController.php b/app/Http/Controllers/SearchController.php new file mode 100644 index 0000000..4d8bd9d --- /dev/null +++ b/app/Http/Controllers/SearchController.php @@ -0,0 +1,55 @@ +query('q')); + $results = mb_strlen($q) >= 2 ? $this->results($q) : []; + + if ($request->expectsJson() || $request->ajax() || $request->wantsJson()) { + return response()->json(['results' => $results]); + } + + return view('search.index', [ + 'query' => $q, + 'results' => $results, + ]); + } + + /** @return list */ + private function results(string $q): array + { + $like = '%'.$q.'%'; + + return ladill_account()->qrCodes() + ->whereIn('type', QrTypeCatalog::eventsTypes()) + ->where(function ($query) use ($like): void { + $query->where('label', 'like', $like) + ->orWhere('short_code', 'like', $like) + ->orWhere('destination_url', 'like', $like); + }) + ->orderByDesc('updated_at') + ->limit(15) + ->get() + ->map(function (QrCode $code): array { + $content = $code->content(); + + return [ + 'type' => $code->type === QrCode::TYPE_EVENT ? 'event' : 'programme', + 'title' => $content['name'] ?? $code->label, + 'subtitle' => $code->typeLabel().' · '.$code->publicUrl(), + 'url' => route('events.show', $code), + ]; + }) + ->all(); + } +} diff --git a/resources/js/app.js b/resources/js/app.js index 3b5c12a..61cc8be 100644 --- a/resources/js/app.js +++ b/resources/js/app.js @@ -140,14 +140,20 @@ Alpine.data('afia', (config = {}) => ({ })); Alpine.data('topbarSearch', (config = {}) => ({ - query: '', - results: [], - open: false, + query: config.initialQuery || '', + results: Array.isArray(config.initialResults) ? config.initialResults : [], + open: !!config.openOnInit, loading: false, active: 0, _abort: null, searchUrl: config.searchUrl || '/search', + init() { + if (config.autoFocus) { + this.$nextTick(() => this.$refs.input?.focus()); + } + }, + onFocus() { if (this.results.length > 0 || this.query.trim().length >= 2) this.open = true; }, diff --git a/resources/views/components/mobile-page-header.blade.php b/resources/views/components/mobile-page-header.blade.php new file mode 100644 index 0000000..acd3927 --- /dev/null +++ b/resources/views/components/mobile-page-header.blade.php @@ -0,0 +1,28 @@ +@props([ + 'title', + 'subtitle' => null, + 'backUrl' => null, + 'badge' => null, +]) + +
+
+ @if ($backUrl) + + + + @endif +
+ @if ($subtitle) +

{{ $subtitle }}

+ @endif +

{{ $title }}

+
+ @if ($badge) + {{ $badge }} + @endif + {{ $actions ?? '' }} +
+ {{ $slot }} +
diff --git a/resources/views/layouts/user.blade.php b/resources/views/layouts/user.blade.php index 4f963f4..e560c02 100644 --- a/resources/views/layouts/user.blade.php +++ b/resources/views/layouts/user.blade.php @@ -1,7 +1,8 @@ @php $mobileFullScreenPage = request()->routeIs('account.settings') || request()->routeIs('events.create') - || request()->routeIs('events.show'); + || request()->routeIs('events.show') + || request()->routeIs('events.search'); $qrMobilePage = request()->routeIs('events.create') || request()->routeIs('events.show'); @endphp @@ -65,8 +66,8 @@ @include('partials.mobile-bottom-nav', [ 'homeUrl' => route('events.dashboard'), 'homeActive' => request()->routeIs('events.dashboard'), - 'searchUrl' => route('events.index'), - 'searchActive' => request()->routeIs('events.index') || request()->routeIs('events.show') || request()->routeIs('attendees.*') || request()->routeIs('events.attendees*') || request()->routeIs('badges.*') || request()->routeIs('events.badge-printing'), + 'searchUrl' => route('events.search'), + 'searchActive' => request()->routeIs('events.search'), 'notificationsUrl' => route('notifications.index'), 'notificationsActive' => request()->routeIs('notifications.*'), 'unreadUrl' => route('notifications.unread'), @@ -90,58 +91,6 @@