Initial search model

This commit is contained in:
Refringe 2024-06-02 22:03:59 -04:00
parent b45b6cb1e5
commit 541eed2cab
Signed by: Refringe
GPG Key ID: 7715B85B4A6306ED
9 changed files with 727 additions and 6 deletions

View File

@ -0,0 +1,21 @@
<?php
namespace App\Livewire;
use App\Models\Mod;
use Illuminate\View\View;
use Livewire\Component;
class GlobalSearch extends Component
{
public string $query = '';
public function render(): View
{
$results = $this->query ? Mod::search($this->query)->get() : [];
return view('livewire.global-search', [
'results' => $results,
]);
}
}

View File

@ -10,13 +10,14 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Str;
use Laravel\Scout\Searchable;
/**
* @property string $slug
*/
class Mod extends Model
{
use HasFactory, SoftDeletes;
use HasFactory, SoftDeletes, Searchable;
protected $fillable = [
'user_id',
@ -107,4 +108,23 @@ class Mod extends Model
->havingNotNull('last_updated_spt_version_id')
->with(['lastUpdatedVersion', 'lastUpdatedVersion.sptVersion']);
}
public function toSearchableArray(): array
{
return [
'id' => (int) $this->id,
'name' => $this->name,
'slug' => $this->slug,
'description' => $this->description,
'thumbnail' => $this->thumbnail,
'featured' => $this->featured,
'created_at' => strtotime($this->created_at),
'updated_at' => strtotime($this->updated_at),
];
}
public function shouldBeSearchable(): bool
{
return ! $this->disabled;
}
}

View File

@ -10,6 +10,7 @@ use Illuminate\Notifications\Notifiable;
use Laravel\Fortify\TwoFactorAuthenticatable;
use Laravel\Jetstream\HasProfilePhoto;
use Laravel\Sanctum\HasApiTokens;
use Laravel\Scout\Searchable;
class User extends Authenticatable implements MustVerifyEmail
{
@ -18,6 +19,7 @@ class User extends Authenticatable implements MustVerifyEmail
use HasProfilePhoto;
use Notifiable;
use TwoFactorAuthenticatable;
use Searchable;
protected $fillable = [
'name',
@ -48,4 +50,17 @@ class User extends Authenticatable implements MustVerifyEmail
{
return $this->hasMany(Mod::class);
}
public function toSearchableArray(): array
{
return [
'id' => (int) $this->id,
'name' => $this->name,
];
}
public function shouldBeSearchable(): bool
{
return ! is_null($this->email_verified_at);
}
}

View File

@ -10,6 +10,7 @@
"require": {
"php": "^8.3",
"ext-curl": "*",
"http-interop/http-factory-guzzle": "^1.2",
"laravel/framework": "^11.0",
"laravel/jetstream": "^5.1",
"laravel/nova": "^4.0",
@ -19,6 +20,7 @@
"laravel/tinker": "^2.9",
"league/html-to-markdown": "^5.1",
"livewire/livewire": "^3.0",
"meilisearch/meilisearch-php": "^1.8",
"stevebauman/purify": "^6.2"
},
"require-dev": {

587
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "b42a2bd2686065b7db27628579fde13c",
"content-hash": "cf943e5dca69a9321599e06cd8e5a114",
"packages": [
{
"name": "bacon/bacon-qr-code",
@ -247,6 +247,72 @@
],
"time": "2024-02-09T16:56:22+00:00"
},
{
"name": "clue/stream-filter",
"version": "v1.7.0",
"source": {
"type": "git",
"url": "https://github.com/clue/stream-filter.git",
"reference": "049509fef80032cb3f051595029ab75b49a3c2f7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/clue/stream-filter/zipball/049509fef80032cb3f051595029ab75b49a3c2f7",
"reference": "049509fef80032cb3f051595029ab75b49a3c2f7",
"shasum": ""
},
"require": {
"php": ">=5.3"
},
"require-dev": {
"phpunit/phpunit": "^9.6 || ^5.7 || ^4.8.36"
},
"type": "library",
"autoload": {
"files": [
"src/functions_include.php"
],
"psr-4": {
"Clue\\StreamFilter\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Christian Lück",
"email": "christian@clue.engineering"
}
],
"description": "A simple and modern approach to stream filtering in PHP",
"homepage": "https://github.com/clue/stream-filter",
"keywords": [
"bucket brigade",
"callback",
"filter",
"php_user_filter",
"stream",
"stream_filter_append",
"stream_filter_register"
],
"support": {
"issues": "https://github.com/clue/stream-filter/issues",
"source": "https://github.com/clue/stream-filter/tree/v1.7.0"
},
"funding": [
{
"url": "https://clue.engineering/support",
"type": "custom"
},
{
"url": "https://github.com/clue",
"type": "github"
}
],
"time": "2023-12-20T15:40:13+00:00"
},
{
"name": "dasprid/enum",
"version": "1.0.5",
@ -1483,6 +1549,64 @@
],
"time": "2023-12-03T19:50:20+00:00"
},
{
"name": "http-interop/http-factory-guzzle",
"version": "1.2.0",
"source": {
"type": "git",
"url": "https://github.com/http-interop/http-factory-guzzle.git",
"reference": "8f06e92b95405216b237521cc64c804dd44c4a81"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/http-interop/http-factory-guzzle/zipball/8f06e92b95405216b237521cc64c804dd44c4a81",
"reference": "8f06e92b95405216b237521cc64c804dd44c4a81",
"shasum": ""
},
"require": {
"guzzlehttp/psr7": "^1.7||^2.0",
"php": ">=7.3",
"psr/http-factory": "^1.0"
},
"provide": {
"psr/http-factory-implementation": "^1.0"
},
"require-dev": {
"http-interop/http-factory-tests": "^0.9",
"phpunit/phpunit": "^9.5"
},
"suggest": {
"guzzlehttp/psr7": "Includes an HTTP factory starting in version 2.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Http\\Factory\\Guzzle\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "An HTTP Factory using Guzzle PSR7",
"keywords": [
"factory",
"http",
"psr-17",
"psr-7"
],
"support": {
"issues": "https://github.com/http-interop/http-factory-guzzle/issues",
"source": "https://github.com/http-interop/http-factory-guzzle/tree/1.2.0"
},
"time": "2021-07-21T13:50:14+00:00"
},
{
"name": "inertiajs/inertia-laravel",
"version": "v1.2.0",
@ -3039,6 +3163,74 @@
],
"time": "2024-05-21T13:39:04+00:00"
},
{
"name": "meilisearch/meilisearch-php",
"version": "v1.8.0",
"source": {
"type": "git",
"url": "https://github.com/meilisearch/meilisearch-php.git",
"reference": "77058e5cd0c9ee1236eaf8dfabdde2b339370b21"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/meilisearch/meilisearch-php/zipball/77058e5cd0c9ee1236eaf8dfabdde2b339370b21",
"reference": "77058e5cd0c9ee1236eaf8dfabdde2b339370b21",
"shasum": ""
},
"require": {
"ext-json": "*",
"php": "^7.4 || ^8.0",
"php-http/client-common": "^2.0",
"php-http/discovery": "^1.7",
"php-http/httplug": "^2.1"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.0",
"guzzlehttp/guzzle": "^7.1",
"http-interop/http-factory-guzzle": "^1.0",
"phpstan/extension-installer": "^1.1",
"phpstan/phpstan": "1.10.67",
"phpstan/phpstan-deprecation-rules": "^1.0",
"phpstan/phpstan-phpunit": "^1.0",
"phpstan/phpstan-strict-rules": "^1.1",
"phpunit/phpunit": "^9.5 || ^10.1"
},
"suggest": {
"guzzlehttp/guzzle": "Use Guzzle ^7 as HTTP client",
"http-interop/http-factory-guzzle": "Factory for guzzlehttp/guzzle"
},
"type": "library",
"autoload": {
"psr-4": {
"MeiliSearch\\": "src/",
"Meilisearch\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Clementine",
"email": "clementine@meilisearch.com"
}
],
"description": "PHP wrapper for the Meilisearch API",
"keywords": [
"api",
"client",
"instant",
"meilisearch",
"php",
"search"
],
"support": {
"issues": "https://github.com/meilisearch/meilisearch-php/issues",
"source": "https://github.com/meilisearch/meilisearch-php/tree/v1.8.0"
},
"time": "2024-05-06T13:58:08+00:00"
},
{
"name": "mobiledetect/mobiledetectlib",
"version": "4.8.06",
@ -3764,6 +3956,332 @@
},
"time": "2024-05-08T12:18:48+00:00"
},
{
"name": "php-http/client-common",
"version": "2.7.1",
"source": {
"type": "git",
"url": "https://github.com/php-http/client-common.git",
"reference": "1e19c059b0e4d5f717bf5d524d616165aeab0612"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-http/client-common/zipball/1e19c059b0e4d5f717bf5d524d616165aeab0612",
"reference": "1e19c059b0e4d5f717bf5d524d616165aeab0612",
"shasum": ""
},
"require": {
"php": "^7.1 || ^8.0",
"php-http/httplug": "^2.0",
"php-http/message": "^1.6",
"psr/http-client": "^1.0",
"psr/http-factory": "^1.0",
"psr/http-message": "^1.0 || ^2.0",
"symfony/options-resolver": "~4.0.15 || ~4.1.9 || ^4.2.1 || ^5.0 || ^6.0 || ^7.0",
"symfony/polyfill-php80": "^1.17"
},
"require-dev": {
"doctrine/instantiator": "^1.1",
"guzzlehttp/psr7": "^1.4",
"nyholm/psr7": "^1.2",
"phpspec/phpspec": "^5.1 || ^6.3 || ^7.1",
"phpspec/prophecy": "^1.10.2",
"phpunit/phpunit": "^7.5.20 || ^8.5.33 || ^9.6.7"
},
"suggest": {
"ext-json": "To detect JSON responses with the ContentTypePlugin",
"ext-libxml": "To detect XML responses with the ContentTypePlugin",
"php-http/cache-plugin": "PSR-6 Cache plugin",
"php-http/logger-plugin": "PSR-3 Logger plugin",
"php-http/stopwatch-plugin": "Symfony Stopwatch plugin"
},
"type": "library",
"autoload": {
"psr-4": {
"Http\\Client\\Common\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Márk Sági-Kazár",
"email": "mark.sagikazar@gmail.com"
}
],
"description": "Common HTTP Client implementations and tools for HTTPlug",
"homepage": "http://httplug.io",
"keywords": [
"client",
"common",
"http",
"httplug"
],
"support": {
"issues": "https://github.com/php-http/client-common/issues",
"source": "https://github.com/php-http/client-common/tree/2.7.1"
},
"time": "2023-11-30T10:31:25+00:00"
},
{
"name": "php-http/discovery",
"version": "1.19.4",
"source": {
"type": "git",
"url": "https://github.com/php-http/discovery.git",
"reference": "0700efda8d7526335132360167315fdab3aeb599"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-http/discovery/zipball/0700efda8d7526335132360167315fdab3aeb599",
"reference": "0700efda8d7526335132360167315fdab3aeb599",
"shasum": ""
},
"require": {
"composer-plugin-api": "^1.0|^2.0",
"php": "^7.1 || ^8.0"
},
"conflict": {
"nyholm/psr7": "<1.0",
"zendframework/zend-diactoros": "*"
},
"provide": {
"php-http/async-client-implementation": "*",
"php-http/client-implementation": "*",
"psr/http-client-implementation": "*",
"psr/http-factory-implementation": "*",
"psr/http-message-implementation": "*"
},
"require-dev": {
"composer/composer": "^1.0.2|^2.0",
"graham-campbell/phpspec-skip-example-extension": "^5.0",
"php-http/httplug": "^1.0 || ^2.0",
"php-http/message-factory": "^1.0",
"phpspec/phpspec": "^5.1 || ^6.1 || ^7.3",
"sebastian/comparator": "^3.0.5 || ^4.0.8",
"symfony/phpunit-bridge": "^6.4.4 || ^7.0.1"
},
"type": "composer-plugin",
"extra": {
"class": "Http\\Discovery\\Composer\\Plugin",
"plugin-optional": true
},
"autoload": {
"psr-4": {
"Http\\Discovery\\": "src/"
},
"exclude-from-classmap": [
"src/Composer/Plugin.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Márk Sági-Kazár",
"email": "mark.sagikazar@gmail.com"
}
],
"description": "Finds and installs PSR-7, PSR-17, PSR-18 and HTTPlug implementations",
"homepage": "http://php-http.org",
"keywords": [
"adapter",
"client",
"discovery",
"factory",
"http",
"message",
"psr17",
"psr7"
],
"support": {
"issues": "https://github.com/php-http/discovery/issues",
"source": "https://github.com/php-http/discovery/tree/1.19.4"
},
"time": "2024-03-29T13:00:05+00:00"
},
{
"name": "php-http/httplug",
"version": "2.4.0",
"source": {
"type": "git",
"url": "https://github.com/php-http/httplug.git",
"reference": "625ad742c360c8ac580fcc647a1541d29e257f67"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-http/httplug/zipball/625ad742c360c8ac580fcc647a1541d29e257f67",
"reference": "625ad742c360c8ac580fcc647a1541d29e257f67",
"shasum": ""
},
"require": {
"php": "^7.1 || ^8.0",
"php-http/promise": "^1.1",
"psr/http-client": "^1.0",
"psr/http-message": "^1.0 || ^2.0"
},
"require-dev": {
"friends-of-phpspec/phpspec-code-coverage": "^4.1 || ^5.0 || ^6.0",
"phpspec/phpspec": "^5.1 || ^6.0 || ^7.0"
},
"type": "library",
"autoload": {
"psr-4": {
"Http\\Client\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Eric GELOEN",
"email": "geloen.eric@gmail.com"
},
{
"name": "Márk Sági-Kazár",
"email": "mark.sagikazar@gmail.com",
"homepage": "https://sagikazarmark.hu"
}
],
"description": "HTTPlug, the HTTP client abstraction for PHP",
"homepage": "http://httplug.io",
"keywords": [
"client",
"http"
],
"support": {
"issues": "https://github.com/php-http/httplug/issues",
"source": "https://github.com/php-http/httplug/tree/2.4.0"
},
"time": "2023-04-14T15:10:03+00:00"
},
{
"name": "php-http/message",
"version": "1.16.1",
"source": {
"type": "git",
"url": "https://github.com/php-http/message.git",
"reference": "5997f3289332c699fa2545c427826272498a2088"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-http/message/zipball/5997f3289332c699fa2545c427826272498a2088",
"reference": "5997f3289332c699fa2545c427826272498a2088",
"shasum": ""
},
"require": {
"clue/stream-filter": "^1.5",
"php": "^7.2 || ^8.0",
"psr/http-message": "^1.1 || ^2.0"
},
"provide": {
"php-http/message-factory-implementation": "1.0"
},
"require-dev": {
"ergebnis/composer-normalize": "^2.6",
"ext-zlib": "*",
"guzzlehttp/psr7": "^1.0 || ^2.0",
"laminas/laminas-diactoros": "^2.0 || ^3.0",
"php-http/message-factory": "^1.0.2",
"phpspec/phpspec": "^5.1 || ^6.3 || ^7.1",
"slim/slim": "^3.0"
},
"suggest": {
"ext-zlib": "Used with compressor/decompressor streams",
"guzzlehttp/psr7": "Used with Guzzle PSR-7 Factories",
"laminas/laminas-diactoros": "Used with Diactoros Factories",
"slim/slim": "Used with Slim Framework PSR-7 implementation"
},
"type": "library",
"autoload": {
"files": [
"src/filters.php"
],
"psr-4": {
"Http\\Message\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Márk Sági-Kazár",
"email": "mark.sagikazar@gmail.com"
}
],
"description": "HTTP Message related tools",
"homepage": "http://php-http.org",
"keywords": [
"http",
"message",
"psr-7"
],
"support": {
"issues": "https://github.com/php-http/message/issues",
"source": "https://github.com/php-http/message/tree/1.16.1"
},
"time": "2024-03-07T13:22:09+00:00"
},
{
"name": "php-http/promise",
"version": "1.3.1",
"source": {
"type": "git",
"url": "https://github.com/php-http/promise.git",
"reference": "fc85b1fba37c169a69a07ef0d5a8075770cc1f83"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-http/promise/zipball/fc85b1fba37c169a69a07ef0d5a8075770cc1f83",
"reference": "fc85b1fba37c169a69a07ef0d5a8075770cc1f83",
"shasum": ""
},
"require": {
"php": "^7.1 || ^8.0"
},
"require-dev": {
"friends-of-phpspec/phpspec-code-coverage": "^4.3.2 || ^6.3",
"phpspec/phpspec": "^5.1.2 || ^6.2 || ^7.4"
},
"type": "library",
"autoload": {
"psr-4": {
"Http\\Promise\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Joel Wurtz",
"email": "joel.wurtz@gmail.com"
},
{
"name": "Márk Sági-Kazár",
"email": "mark.sagikazar@gmail.com"
}
],
"description": "Promise used for asynchronous HTTP requests",
"homepage": "http://httplug.io",
"keywords": [
"promise"
],
"support": {
"issues": "https://github.com/php-http/promise/issues",
"source": "https://github.com/php-http/promise/tree/1.3.1"
},
"time": "2024-03-15T13:55:21+00:00"
},
{
"name": "phpoption/phpoption",
"version": "1.9.2",
@ -5741,6 +6259,73 @@
],
"time": "2024-05-29T15:16:11+00:00"
},
{
"name": "symfony/options-resolver",
"version": "v7.1.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/options-resolver.git",
"reference": "9564f64c16f99e29f252eafc642965e8fcb755ce"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/options-resolver/zipball/9564f64c16f99e29f252eafc642965e8fcb755ce",
"reference": "9564f64c16f99e29f252eafc642965e8fcb755ce",
"shasum": ""
},
"require": {
"php": ">=8.2",
"symfony/deprecation-contracts": "^2.5|^3"
},
"type": "library",
"autoload": {
"psr-4": {
"Symfony\\Component\\OptionsResolver\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fabien Potencier",
"email": "fabien@symfony.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Provides an improved replacement for the array_replace PHP function",
"homepage": "https://symfony.com",
"keywords": [
"config",
"configuration",
"options"
],
"support": {
"source": "https://github.com/symfony/options-resolver/tree/v7.1.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2024-04-18T09:32:20+00:00"
},
{
"name": "symfony/polyfill-ctype",
"version": "v1.29.0",

View File

@ -1,5 +1,8 @@
<?php
use App\Models\Mod;
use App\Models\User;
return [
/*
@ -134,9 +137,10 @@ return [
'host' => env('MEILISEARCH_HOST', 'http://localhost:7700'),
'key' => env('MEILISEARCH_KEY'),
'index-settings' => [
// 'users' => [
// 'filterableAttributes'=> ['id', 'name', 'email'],
// ],
Mod::class => [
'filterableAttributes'=> ['featured'],
'sortableAttributes' => ['created_at', 'updated_at'],
]
],
],

View File

@ -27,7 +27,7 @@
@vite(['resources/css/app.css', 'resources/js/app.js'])
@livewireStyles
</head>
<body class="font-sans antialiased">
<body class="font-sans antialiased" x-data="{ searchOpen: false }">
<x-warning/>
@ -51,6 +51,7 @@
<x-footer/>
@livewire('global-search')
@stack('modals')
@livewireScripts

View File

@ -0,0 +1,67 @@
<div class="relative z-10" role="dialog" aria-modal="true">
<div
x-cloak
x-show="searchOpen"
x-transition:enter="transition ease-out duration-300 transform"
x-transition:enter-start="opacity-0"
x-transition:enter-end="opacity-100"
x-transition:leave="transition ease-in duration-200 transform"
x-transition:leave-start="opacity-100"
x-transition:leave-end="opacity-0"
class="fixed inset-0 bg-gray-500 bg-opacity-50 transition-opacity"
></div>
<div
x-cloak
x-show="searchOpen"
x-transition:enter="transition ease-out duration-300 transform"
x-transition:enter-start="opacity-0"
x-transition:enter-end="opacity-100"
x-transition:leave="transition ease-in duration-200 transform"
x-transition:leave-start="opacity-100"
x-transition:leave-end="opacity-0"
@keyup.escape.window="searchOpen = false"
class="fixed inset-0 z-10 w-screen overflow-y-auto p-4 sm:p-6 md:p-20"
>
<div
@click.outside="searchOpen = false"
class="mx-auto max-w-2xl transform divide-y divide-gray-100 overflow-hidden rounded-xl bg-white shadow-2xl ring-1 ring-black ring-opacity-5 transition-all"
>
<div class="relative">
<svg class="pointer-events-none absolute left-4 top-3.5 h-5 w-5 text-gray-400" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
<path fill-rule="evenodd" d="M9 3.5a5.5 5.5 0 100 11 5.5 5.5 0 000-11zM2 9a7 7 0 1112.452 4.391l3.328 3.329a.75.75 0 11-1.06 1.06l-3.329-3.328A7 7 0 012 9z" clip-rule="evenodd" />
</svg>
<input wire:model.live="query" id="global-search" type="text" class="h-12 w-full border-0 bg-transparent pl-11 pr-4 text-gray-900 placeholder:text-gray-400 focus:ring-0 sm:text-sm" placeholder="{{ __('Search for a mod...') }}">
</div>
<!-- Default state, show/hide based on command palette state. -->
@if($results)
<ul class="max-h-80 scroll-py-2 divide-y divide-gray-100 overflow-y-auto">
@foreach($results as $result)
<li class="p-2">
<h2 class="sr-only">{{ __('Search Results') }}</h2>
<ul class="text-sm text-gray-700">
<!-- Active: "bg-indigo-600 text-white" -->
<li class="group flex cursor-default select-none items-center rounded-md px-3 py-2">
<!-- Active: "text-white", Not Active: "text-gray-400" -->
<img src="{{ $result->thumbnail }}" alt="{{ $result->name }}" class="h-6 w-6 flex-none">
<span class="ml-3 flex-auto truncate"><a href="/mod/{{ $result->id }}/{{ $result->slug }}">{{ $result->name }}</a></span>
<!-- Active: "text-indigo-100", Not Active: "text-gray-400" -->
<span class="ml-3 flex-none text-xs font-semibold text-gray-400">Mod</span>
</li>
</ul>
</li>
@endforeach
</ul>
@else
<!-- Empty state, show/hide based on command palette state. -->
<div class="px-6 py-14 text-center sm:px-14">
<svg class="mx-auto h-6 w-6 text-gray-400" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" d="M2.25 12.75V12A2.25 2.25 0 014.5 9.75h15A2.25 2.25 0 0121.75 12v.75m-8.69-6.44l-2.12-2.12a1.5 1.5 0 00-1.061-.44H4.5A2.25 2.25 0 002.25 6v12a2.25 2.25 0 002.25 2.25h15A2.25 2.25 0 0021.75 18V9a2.25 2.25 0 00-2.25-2.25h-5.379a1.5 1.5 0 01-1.06-.44z" />
</svg>
<p class="mt-4 text-sm text-gray-900">{{ __('We couldn\'t find any projects with that term. Please try again.') }}</p>
</div>
@endif
</div>
</div>
</div>

View File

@ -19,6 +19,12 @@
</div>
<div class="hidden sm:flex sm:items-center sm:ms-6">
<button type="button" @click="searchOpen = !searchOpen; $nextTick(() => { document.querySelector('#global-search').focus(); });" class="text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-none focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 rounded-lg text-sm p-2.5">
<svg id="theme-toggle-dark-icon" class="hidden w-5 h-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z"></path>
</svg>
</button>
{{-- Theme Toggle Button --}}
<button id="theme-toggle" type="button" class="text-gray-500 dark:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-700 focus:outline-none focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 rounded-lg text-sm p-2.5">
<svg id="theme-toggle-dark-icon" class="hidden w-5 h-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">