Compare commits

...

3 Commits

Author SHA1 Message Date
fc2b66528b WIP 2024-05-23 16:51:55 +02:00
6d4dd5f653 chore: add macos specific files to gitignore 2024-05-21 09:29:43 +02:00
71c35c989d chore: remove DS_Store Files 2024-05-21 09:28:08 +02:00
21 changed files with 280 additions and 114 deletions

BIN
.DS_Store vendored

Binary file not shown.

3
.gitignore vendored
View File

@@ -17,3 +17,6 @@ yarn-error.log
/.fleet /.fleet
/.idea /.idea
/.vscode /.vscode
.DS_Store
.AppleDouble
.LSOverride

View File

@@ -5,12 +5,26 @@ namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Support\Collection;
class Album extends Model class Album extends Model
{ {
use HasFactory; use HasFactory;
public function category() : BelongsTo { public function category() : BelongsTo {
$this->belongsTo(Category::class); return $this->belongsTo(Category::class);
}
public function images() : HasMany {
return $this->hasMany(Image::class);
}
public function media() : Collection {
return $this->images;
}
public function getThumbnailAttribute() : ?string {
return $this->images()->where('isCover', 1)->first()?->getThumbnail();
} }
} }

View File

@@ -3,4 +3,5 @@
return [ return [
App\Providers\AppServiceProvider::class, App\Providers\AppServiceProvider::class,
App\Providers\LivewireAssetProvider::class, App\Providers\LivewireAssetProvider::class,
App\Providers\TelescopeServiceProvider::class,
]; ];

View File

@@ -7,6 +7,7 @@
"require": { "require": {
"php": "^8.2", "php": "^8.2",
"laravel/framework": "^11.0", "laravel/framework": "^11.0",
"laravel/telescope": "^5.0",
"laravel/tinker": "^2.9", "laravel/tinker": "^2.9",
"livewire/livewire": "^3.4" "livewire/livewire": "^3.4"
}, },

73
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "3e788d36623f5aa3b9b254a19bb9a8a9", "content-hash": "26523f4293916dbcb8f8c1260b93b569",
"packages": [ "packages": [
{ {
"name": "brick/math", "name": "brick/math",
@@ -1367,6 +1367,75 @@
}, },
"time": "2023-11-08T14:08:06+00:00" "time": "2023-11-08T14:08:06+00:00"
}, },
{
"name": "laravel/telescope",
"version": "v5.0.5",
"source": {
"type": "git",
"url": "https://github.com/laravel/telescope.git",
"reference": "ae5c28ca1e40a7a66bfc9b2557e7e1d84d95363c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/telescope/zipball/ae5c28ca1e40a7a66bfc9b2557e7e1d84d95363c",
"reference": "ae5c28ca1e40a7a66bfc9b2557e7e1d84d95363c",
"shasum": ""
},
"require": {
"ext-json": "*",
"laravel/framework": "^8.37|^9.0|^10.0|^11.0",
"php": "^8.0",
"symfony/console": "^5.3|^6.0|^7.0",
"symfony/var-dumper": "^5.0|^6.0|^7.0"
},
"require-dev": {
"ext-gd": "*",
"guzzlehttp/guzzle": "^6.0|^7.0",
"laravel/octane": "^1.4|^2.0|dev-develop",
"orchestra/testbench": "^6.40|^7.37|^8.17|^9.0",
"phpstan/phpstan": "^1.10",
"phpunit/phpunit": "^9.0|^10.5"
},
"type": "library",
"extra": {
"laravel": {
"providers": [
"Laravel\\Telescope\\TelescopeServiceProvider"
]
}
},
"autoload": {
"psr-4": {
"Laravel\\Telescope\\": "src/",
"Laravel\\Telescope\\Database\\Factories\\": "database/factories/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Taylor Otwell",
"email": "taylor@laravel.com"
},
{
"name": "Mohamed Said",
"email": "mohamed@laravel.com"
}
],
"description": "An elegant debug assistant for the Laravel framework.",
"keywords": [
"debugging",
"laravel",
"monitoring"
],
"support": {
"issues": "https://github.com/laravel/telescope/issues",
"source": "https://github.com/laravel/telescope/tree/v5.0.5"
},
"time": "2024-05-09T17:09:01+00:00"
},
{ {
"name": "laravel/tinker", "name": "laravel/tinker",
"version": "v2.9.0", "version": "v2.9.0",
@@ -8216,5 +8285,5 @@
"php": "^8.2" "php": "^8.2"
}, },
"platform-dev": [], "platform-dev": [],
"plugin-api-version": "2.6.0" "plugin-api-version": "2.3.0"
} }

View File

@@ -36,6 +36,12 @@ return [
'throw' => false, 'throw' => false,
], ],
'images' => [
'driver' => 'local',
'root' => storage_path('app/images'),
'throw' => false,
],
'public' => [ 'public' => [
'driver' => 'local', 'driver' => 'local',
'root' => storage_path('app/public'), 'root' => storage_path('app/public'),

View File

@@ -20,7 +20,6 @@ class AlbumFactory extends Factory
{ {
return [ return [
'name' => fake()->sentence(2), 'name' => fake()->sentence(2),
'cover' => './covers/image-'.rand(1,12).'-big.jpg',
'category_id' => Category::all()->random(1)->first()->id, 'category_id' => Category::all()->random(1)->first()->id,
]; ];
} }

View File

@@ -34,6 +34,4 @@ class CategoryFactory extends Factory
'cover' => './covers/image-'.rand(1,12).'-big.jpg', 'cover' => './covers/image-'.rand(1,12).'-big.jpg',
]; ];
} }
} }

View File

@@ -15,7 +15,6 @@ return new class extends Migration
Schema::create('albums', function (Blueprint $table) { Schema::create('albums', function (Blueprint $table) {
$table->id(); $table->id();
$table->string('name'); $table->string('name');
$table->string('cover');
$table->foreignIdFor(Category::class); $table->foreignIdFor(Category::class);
$table->timestamps(); $table->timestamps();
}); });

View File

@@ -17,6 +17,7 @@ class DatabaseSeeder extends Seeder
TagSeeder::class, TagSeeder::class,
CategorySeeder::class, CategorySeeder::class,
AlbumSeeder::class, AlbumSeeder::class,
ImageSeeder::class,
]); ]);
} }
} }

62
package-lock.json generated
View File

@@ -4,6 +4,15 @@
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"dependencies": {
"filepond": "^4.31.1",
"filepond-plugin-file-validate-size": "^2.2.8",
"filepond-plugin-file-validate-type": "^1.2.9",
"filepond-plugin-image-edit": "^1.6.3",
"filepond-plugin-image-exif-orientation": "^1.0.11",
"filepond-plugin-image-preview": "^4.6.12",
"filepond-plugin-image-transform": "^3.8.7"
},
"devDependencies": { "devDependencies": {
"@tailwindcss/forms": "^0.5.7", "@tailwindcss/forms": "^0.5.7",
"autoprefixer": "^10.4.19", "autoprefixer": "^10.4.19",
@@ -1157,6 +1166,59 @@
"reusify": "^1.0.4" "reusify": "^1.0.4"
} }
}, },
"node_modules/filepond": {
"version": "4.31.1",
"resolved": "https://registry.npmjs.org/filepond/-/filepond-4.31.1.tgz",
"integrity": "sha512-yWYK91Ky72L2AG7BlI8Cb0UjvJz+DjuYdLN1JbkJg8qmoiZ9AU5b5MuOkHmExk/9jQ5R7tRT+H+b8wDiFEJlxQ=="
},
"node_modules/filepond-plugin-file-validate-size": {
"version": "2.2.8",
"resolved": "https://registry.npmjs.org/filepond-plugin-file-validate-size/-/filepond-plugin-file-validate-size-2.2.8.tgz",
"integrity": "sha512-yzb8scATmkWqPTP7oKQz6L8WwJm6Xmgc/fuq6DFGRaLz0I7372BUvBsxagBk/hypMIjvieNzhggm33Y60x3rcw==",
"peerDependencies": {
"filepond": ">=3.1.2 <5.x"
}
},
"node_modules/filepond-plugin-file-validate-type": {
"version": "1.2.9",
"resolved": "https://registry.npmjs.org/filepond-plugin-file-validate-type/-/filepond-plugin-file-validate-type-1.2.9.tgz",
"integrity": "sha512-Tzv07aNdZvjUXDRA3XL16QMEvh6llDrXlcZ6W0eTHQ+taHaVg/JKJTFs/AViO+6ZcpPCcQStbhYEL2HoS+vldw==",
"peerDependencies": {
"filepond": ">=1.x <5.x"
}
},
"node_modules/filepond-plugin-image-edit": {
"version": "1.6.3",
"resolved": "https://registry.npmjs.org/filepond-plugin-image-edit/-/filepond-plugin-image-edit-1.6.3.tgz",
"integrity": "sha512-5q3RDaVlfvyI346ckF1DfKw4uN5rfAmUCv7HCG30jBZcGmepg8hFyjVM71uZXYeb4AgLhpCkSPP8Immwig8bzw==",
"peerDependencies": {
"filepond": ">=3.7.2 <5.x"
}
},
"node_modules/filepond-plugin-image-exif-orientation": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/filepond-plugin-image-exif-orientation/-/filepond-plugin-image-exif-orientation-1.0.11.tgz",
"integrity": "sha512-hLBc12Fk6Zkj3L8mSAn+elugHOqT5rLUbgVXQQIQjMe0FsGjtpoxqeVR6jt4IWHGat2L9sFAgU2TGmd1mqosCg==",
"peerDependencies": {
"filepond": ">=3.x <5.x"
}
},
"node_modules/filepond-plugin-image-preview": {
"version": "4.6.12",
"resolved": "https://registry.npmjs.org/filepond-plugin-image-preview/-/filepond-plugin-image-preview-4.6.12.tgz",
"integrity": "sha512-Y8ETX5QVV0mbPB0586UH8AUmG9tZg8PuN5bdEAIlZVJFTct5ebViJ7+Am94/VhTPjLqZjBf1zmDq5JU6XRsZKw==",
"peerDependencies": {
"filepond": ">=4.x <5.x"
}
},
"node_modules/filepond-plugin-image-transform": {
"version": "3.8.7",
"resolved": "https://registry.npmjs.org/filepond-plugin-image-transform/-/filepond-plugin-image-transform-3.8.7.tgz",
"integrity": "sha512-vgKwyIDG2y5twanf7YpqZvxkaLudTjwd9vRcoq5sQDB8egUlX5/NA0bQ0823pocrm0fjbFeetICu44mkqeDkIA==",
"peerDependencies": {
"filepond": ">=3.6.0 <5.x"
}
},
"node_modules/fill-range": { "node_modules/fill-range": {
"version": "7.0.1", "version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",

View File

@@ -13,5 +13,13 @@
"postcss": "^8.4.38", "postcss": "^8.4.38",
"tailwindcss": "^3.4.3", "tailwindcss": "^3.4.3",
"vite": "^5.0" "vite": "^5.0"
},
"dependencies": {
"filepond": "^4.31.1",
"filepond-plugin-file-validate-size": "^2.2.8",
"filepond-plugin-file-validate-type": "^1.2.9",
"filepond-plugin-image-exif-orientation": "^1.0.11",
"filepond-plugin-image-preview": "^4.6.12",
"filepond-plugin-image-transform": "^3.8.7"
} }
} }

View File

@@ -1,3 +1,6 @@
@import 'filepond/dist/filepond.min.css';
@import 'filepond-plugin-image-preview/dist/filepond-plugin-image-preview.css';
@tailwind base; @tailwind base;
@tailwind components; @tailwind components;
@tailwind utilities; @tailwind utilities;
@@ -7,3 +10,23 @@
animation-play-state: paused; animation-play-state: paused;
} }
} }
@media screen(sm) {
.filepond--item {
width: calc(50% - 0.5em);
}
}
@media screen(md) {
.filepond--item {
width: calc(25% - 1em);
}
}
.filepond--panel-root {
@apply bg-gray-50 dark:bg-gray-700 !important;
}
.filepond--drop-label {
@apply text-gray-900 dark:text-white;
}

View File

@@ -1 +1,25 @@
import './bootstrap'; import './bootstrap';
import * as FilePond from 'filepond';
import FilePondPluginImageExifOrientation from 'filepond-plugin-image-exif-orientation';
import FilePondPluginImagePreview from 'filepond-plugin-image-preview';
import FilePondPluginFileValidateSize from 'filepond-plugin-file-validate-size';
import FilePondPluginFileValidateType from 'filepond-plugin-file-validate-type';
import FilePondPluginImageTransform from 'filepond-plugin-image-transform';
FilePond.registerPlugin(FilePondPluginImageExifOrientation);
FilePond.registerPlugin(FilePondPluginImagePreview);
FilePond.registerPlugin(FilePondPluginFileValidateSize);
FilePond.registerPlugin(FilePondPluginFileValidateType);
FilePond.registerPlugin(FilePondPluginImageTransform);
window.FilePond = FilePond;
document.addEventListener('alpine:init', () => {
Alpine.store('uploader', {
states: {},
setState(state, value) {
console.log(state, value);
this.states[state] = value;
},
})
});

View File

@@ -5,17 +5,19 @@
</svg> </svg>
</x-menu-action> </x-menu-action>
<div class="flex items-center justify-center"> <div class="flex items-center justify-center">
<x-drawer-trigger target="album-add" action="open">
<button data-tooltip-target="tooltip-new" type="button" class="inline-flex items-center justify-center w-10 h-10 font-medium bg-blue-600 rounded-full hover:bg-blue-700 group focus:ring-4 focus:ring-blue-300 focus:outline-none dark:focus:ring-blue-800"> <button data-tooltip-target="tooltip-new" type="button" class="inline-flex items-center justify-center w-10 h-10 font-medium bg-blue-600 rounded-full hover:bg-blue-700 group focus:ring-4 focus:ring-blue-300 focus:outline-none dark:focus:ring-blue-800">
<svg class="w-4 h-4 text-white" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 18 18"> <svg class="w-4 h-4 text-white" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 18 18">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 1v16M1 9h16"/> <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 1v16M1 9h16"/>
</svg> </svg>
<span class="sr-only">New item</span> <span class="sr-only">New item</span>
</button> </button>
</div> </x-drawer-trigger>
<div id="tooltip-new" role="tooltip" class="absolute z-10 invisible inline-block px-3 py-2 text-sm font-medium text-white transition-opacity duration-300 bg-gray-900 rounded-lg shadow-sm opacity-0 tooltip dark:bg-gray-700"> </div>
Create new item <div id="tooltip-new" role="tooltip" class="absolute z-10 invisible inline-block px-3 py-2 text-sm font-medium text-white transition-opacity duration-300 bg-gray-900 rounded-lg shadow-sm opacity-0 tooltip dark:bg-gray-700">
<div class="tooltip-arrow" data-popper-arrow></div> Create new item
</div> <div class="tooltip-arrow" data-popper-arrow></div>
</div>
@endpush @endpush
<x-layout> <x-layout>
@@ -25,96 +27,27 @@
</h1> </h1>
<div class="m-8 flex flex-wrap flex-row gap-4"> <div class="m-8 flex flex-wrap flex-row gap-4">
@foreach ($albums as $album) @foreach ($albums as $album)
<figure class="relative rounded-lg cursor-pointer h-80 flex-grow overflow-hidden"> <figure class="relative rounded-lg cursor-pointer h-80 flex-grow overflow-hidden group">
<a href="{{ route('album.show', $album) }}"> <a href="{{ route('album.show', $album) }}" wire:navigate>
<img class="max-h-full min-w-full align-bottom object-cover" <img class="max-h-full min-w-full align-bottom object-cover"
src="{{ url($album->cover) }}" alt="{{ $album->name }} Cover"> src="{{ $album->thumbnail }}" alt="{{ $album->name }} Cover">
<figcaption class="absolute p-4 text-lg text-white top-1/2 bottom-0 bg-opacity-20 min-w-full bg-gradient-to-b from-transparent to-slate-900 flex flex-col-reverse"> <figcaption class="absolute p-4 text-lg text-white top-1/2 bottom-0 bg-opacity-20 min-w-full bg-gradient-to-b from-transparent to-slate-900 flex flex-col-reverse">
<span>{{ $album->name }}</span> <span class="z-10">{{ $album->name }}</span>
</figcaption> </figcaption>
<div class="opacity-0 z-0 group-hover:opacity-40 absolute inset-0 w-full h-full bg-black flex items-center justify-center transition-opacity">
<svg class="w-1/2 h-1/2 dark:text-white" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
<path stroke="currentColor" stroke-width="2" d="M21 12c0 1.2-4.03 6-9 6s-9-4.8-9-6c0-1.2 4.03-6 9-6s9 4.8 9 6Z"/>
<path stroke="currentColor" stroke-width="2" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z"/>
</svg>
</div>
</a> </a>
</figure> </figure>
@endforeach @endforeach
</div> </div>
<x-drawer-trigger target="user-edit" action="open"> <x-drawer name="album-add" >
<button>Open</button> <x-slot:title>Neues Album in {{ $category->name }} erstellen</x-slot:title>
</x-drawer-trigger>
<x-drawer name="user-edit" >
<x-slot:title>Tester</x-slot:title>
<x-slot:content> <x-slot:content>
<div class="p-4 cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-700" data-drawer-toggle="drawer-swipe"> <livewire:drawer.album.create></livewire:drawer.album.create>
<span class="absolute w-8 h-1 -translate-x-1/2 bg-gray-300 rounded-lg top-3 left-1/2 dark:bg-gray-600"></span>
<h5 id="drawer-swipe-label" class="inline-flex items-center text-base text-gray-500 dark:text-gray-400 font-medium"><svg class="w-4 h-4 me-2" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 18 18">
<path d="M6.143 0H1.857A1.857 1.857 0 0 0 0 1.857v4.286C0 7.169.831 8 1.857 8h4.286A1.857 1.857 0 0 0 8 6.143V1.857A1.857 1.857 0 0 0 6.143 0Zm10 0h-4.286A1.857 1.857 0 0 0 10 1.857v4.286C10 7.169 10.831 8 11.857 8h4.286A1.857 1.857 0 0 0 18 6.143V1.857A1.857 1.857 0 0 0 16.143 0Zm-10 10H1.857A1.857 1.857 0 0 0 0 11.857v4.286C0 17.169.831 18 1.857 18h4.286A1.857 1.857 0 0 0 8 16.143v-4.286A1.857 1.857 0 0 0 6.143 10ZM17 13h-2v-2a1 1 0 0 0-2 0v2h-2a1 1 0 0 0 0 2h2v2a1 1 0 0 0 2 0v-2h2a1 1 0 0 0 0-2Z"/>
</svg>Add widget</h5>
</div>
<div class="grid grid-cols-3 gap-4 p-4 lg:grid-cols-4">
<div class="p-4 rounded-lg cursor-pointer bg-gray-50 hover:bg-gray-100 dark:hover:bg-gray-600 dark:bg-gray-700">
<div class="flex justify-center items-center p-2 mx-auto mb-2 bg-gray-200 dark:bg-gray-600 rounded-full w-[48px] h-[48px] max-w-[48px] max-h-[48px]">
<svg class="inline w-5 h-5 text-gray-500 dark:text-gray-400" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 22 21">
<path d="M16.975 11H10V4.025a1 1 0 0 0-1.066-.998 8.5 8.5 0 1 0 9.039 9.039.999.999 0 0 0-1-1.066h.002Z"/>
<path d="M12.5 0c-.157 0-.311.01-.565.027A1 1 0 0 0 11 1.02V10h8.975a1 1 0 0 0 1-.935c.013-.188.028-.374.028-.565A8.51 8.51 0 0 0 12.5 0Z"/>
</svg>
</div>
<div class="font-medium text-center text-gray-500 dark:text-gray-400">Chart</div>
</div>
<div class="p-4 rounded-lg cursor-pointer bg-gray-50 hover:bg-gray-100 dark:hover:bg-gray-600 dark:bg-gray-700">
<div class="flex justify-center items-center p-2 mx-auto mb-2 bg-gray-200 dark:bg-gray-600 rounded-full w-[48px] h-[48px] max-w-[48px] max-h-[48px]">
<svg class="inline w-5 h-5 text-gray-500 dark:text-gray-400" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 14">
<path d="M18 0H2a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2ZM9 6v2H2V6h7Zm2 0h7v2h-7V6Zm-9 4h7v2H2v-2Zm9 2v-2h7v2h-7Z"/>
</svg>
</div>
<div class="font-medium text-center text-gray-500 dark:text-gray-400">Table</div>
</div>
<div class="hidden p-4 rounded-lg cursor-pointer bg-gray-50 hover:bg-gray-100 dark:hover:bg-gray-600 dark:bg-gray-700 lg:block">
<div class="flex justify-center items-center p-2 mx-auto mb-2 bg-gray-200 dark:bg-gray-600 rounded-full w-[48px] h-[48px] max-w-[48px] max-h-[48px]">
<svg class="inline w-5 h-5 text-gray-500 dark:text-gray-400" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 14 20">
<path d="M13.383.076a1 1 0 0 0-1.09.217L11 1.586 9.707.293a1 1 0 0 0-1.414 0L7 1.586 5.707.293a1 1 0 0 0-1.414 0L3 1.586 1.707.293A1 1 0 0 0 0 1v18a1 1 0 0 0 1.707.707L3 18.414l1.293 1.293a1 1 0 0 0 1.414 0L7 18.414l1.293 1.293a1 1 0 0 0 1.414 0L11 18.414l1.293 1.293A1 1 0 0 0 14 19V1a1 1 0 0 0-.617-.924ZM10 15H4a1 1 0 1 1 0-2h6a1 1 0 0 1 0 2Zm0-4H4a1 1 0 1 1 0-2h6a1 1 0 1 1 0 2Zm0-4H4a1 1 0 0 1 0-2h6a1 1 0 1 1 0 2Z"/>
</svg>
</div>
<div class="hidden font-medium text-center text-gray-500 dark:text-gray-400">Ticket</div>
</div>
<div class="p-4 rounded-lg cursor-pointer bg-gray-50 hover:bg-gray-100 dark:hover:bg-gray-600 dark:bg-gray-700">
<div class="flex justify-center items-center p-2 mx-auto mb-2 bg-gray-200 dark:bg-gray-600 rounded-full w-[48px] h-[48px] max-w-[48px] max-h-[48px]">
<svg class="inline w-5 h-5 text-gray-500 dark:text-gray-400" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 18 20">
<path d="M16 1h-3.278A1.992 1.992 0 0 0 11 0H7a1.993 1.993 0 0 0-1.722 1H2a2 2 0 0 0-2 2v15a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2V3a2 2 0 0 0-2-2Zm-3 14H5a1 1 0 0 1 0-2h8a1 1 0 0 1 0 2Zm0-4H5a1 1 0 0 1 0-2h8a1 1 0 1 1 0 2Zm0-5H5a1 1 0 0 1 0-2h2V2h4v2h2a1 1 0 1 1 0 2Z"/>
</svg>
</div>
<div class="font-medium text-center text-gray-500 dark:text-gray-400">List</div>
</div>
<div class="p-4 rounded-lg cursor-pointer bg-gray-50 hover:bg-gray-100 dark:hover:bg-gray-600 dark:bg-gray-700">
<div class="flex justify-center items-center p-2 mx-auto mb-2 bg-gray-200 dark:bg-gray-600 rounded-full w-[48px] h-[48px] max-w-[48px] max-h-[48px]">
<svg class="inline w-5 h-5 text-gray-500 dark:text-gray-400" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 20 16">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 2a1 1 0 0 1 1-1h12a1 1 0 0 1 1 1v8a1 1 0 0 1-1 1M2 5h12a1 1 0 0 1 1 1v8a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1V6a1 1 0 0 1 1-1Zm8 5a2 2 0 1 1-4 0 2 2 0 0 1 4 0Z"/>
</svg>
</div>
<div class="font-medium text-center text-gray-500 dark:text-gray-400">Price</div>
</div>
<div class="p-4 rounded-lg cursor-pointer bg-gray-50 hover:bg-gray-100 dark:hover:bg-gray-600 dark:bg-gray-700">
<div class="flex justify-center items-center p-2 mx-auto mb-2 bg-gray-200 dark:bg-gray-600 rounded-full w-[48px] h-[48px] max-w-[48px] max-h-[48px]">
<svg class="inline w-5 h-5 text-gray-500 dark:text-gray-400" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 18">
<path d="M14 2a3.963 3.963 0 0 0-1.4.267 6.439 6.439 0 0 1-1.331 6.638A4 4 0 1 0 14 2Zm1 9h-1.264A6.957 6.957 0 0 1 15 15v2a2.97 2.97 0 0 1-.184 1H19a1 1 0 0 0 1-1v-1a5.006 5.006 0 0 0-5-5ZM6.5 9a4.5 4.5 0 1 0 0-9 4.5 4.5 0 0 0 0 9ZM8 10H5a5.006 5.006 0 0 0-5 5v2a1 1 0 0 0 1 1h11a1 1 0 0 0 1-1v-2a5.006 5.006 0 0 0-5-5Z"/>
</svg>
</div>
<div class="font-medium text-center text-gray-500 dark:text-gray-400">Users</div>
</div>
<div class="hidden p-4 rounded-lg cursor-pointer bg-gray-50 hover:bg-gray-100 dark:hover:bg-gray-600 dark:bg-gray-700 lg:block">
<div class="flex justify-center items-center p-2 mx-auto mb-2 bg-gray-200 dark:bg-gray-600 rounded-full w-[48px] h-[48px] max-w-[48px] max-h-[48px]">
<svg class="inline w-5 h-5 text-gray-500 dark:text-gray-400" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 18">
<path d="M6.5 9a4.5 4.5 0 1 0 0-9 4.5 4.5 0 0 0 0 9Zm-1.391 7.361.707-3.535a3 3 0 0 1 .82-1.533L7.929 10H5a5.006 5.006 0 0 0-5 5v2a1 1 0 0 0 1 1h4.259a2.975 2.975 0 0 1-.15-1.639ZM8.05 17.95a1 1 0 0 1-.981-1.2l.708-3.536a1 1 0 0 1 .274-.511l6.363-6.364a3.007 3.007 0 0 1 4.243 0 3.007 3.007 0 0 1 0 4.243l-6.365 6.363a1 1 0 0 1-.511.274l-3.536.708a1.07 1.07 0 0 1-.195.023Z"/>
</svg>
</div>
<div class="font-medium text-center text-gray-500 dark:text-gray-400">Task</div>
</div>
<div class="p-4 rounded-lg cursor-pointer bg-gray-50 hover:bg-gray-100 dark:hover:bg-gray-600 dark:bg-gray-700">
<div class="flex justify-center items-center p-2 mx-auto mb-2 bg-gray-200 dark:bg-gray-600 rounded-full w-[48px] h-[48px] max-w-[48px] max-h-[48px]">
<svg class="inline w-5 h-5 text-gray-500 dark:text-gray-400" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 20 20">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 12.25V1m0 11.25a2.25 2.25 0 0 0 0 4.5m0-4.5a2.25 2.25 0 0 1 0 4.5M4 19v-2.25m6-13.5V1m0 2.25a2.25 2.25 0 0 0 0 4.5m0-4.5a2.25 2.25 0 0 1 0 4.5M10 19V7.75m6 4.5V1m0 11.25a2.25 2.25 0 1 0 0 4.5 2.25 2.25 0 0 0 0-4.5ZM16 19v-2"/>
</svg>
</div>
<div class="font-medium text-center text-gray-500 dark:text-gray-400">Custom</div>
</div>
</div>
</x-slot:content> </x-slot:content>
</x-drawer> </x-drawer>
</x-layout> </x-layout>

View File

@@ -1,3 +1,3 @@
<div @click="$dispatch('drawer-{{ $action }}-{{ $target }}')"> <div @click="$dispatch('drawer-{{ $action }}-{{ $target }}')" x-on:touchstart="$dispatch('drawer-{{ $action }}-{{ $target }}')">
{{ $slot }} {{ $slot }}
</div> </div>

View File

@@ -1,22 +1,37 @@
<template x-teleport="body"> <template x-teleport="body">
<div <div x-cloak
id="drawer-{{ $name }}"
tabindex="-1"
class="fixed z-40 w-full overflow-y-auto bg-white border-t border-gray-200 rounded-t-lg dark:border-gray-700 dark:bg-gray-800 transition-transform left-0 right-0 bottom-0"
aria-labelledby="drawer-{{ $name }}"
x-data="{ show: false }" x-data="{ show: false }"
@drawer-open-{{ $name }}.window="show = true" class="overflow-y-auto overflow-x-hidden fixed top-0 right-0 left-0 justify-center items-center w-full md:inset-0 h-screen max-h-full flex backdrop-blur-md bg-white/30 dark:bg-gray-800/30"
@drawer-close-{{ $name }}.window="show = false"
:class="{ 'translate-y-full': !show }" :class="{ 'translate-y-full': !show }"
x-cloak @click="$dispatch('drawer-close-{{ $name }}')"
x-on:touchstart="$dispatch('drawer-close-{{ $name }}')"
> >
<div class="p-4 cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-700" @click="show = false"> <div
<span class="absolute w-8 h-1 -translate-x-1/2 bg-gray-300 rounded-lg top-3 left-1/2 dark:bg-gray-600"> id="drawer-{{ $name }}"
</span> tabindex="-1"
<h5 class="inline-flex items-center text-base text-gray-500 dark:text-gray-400 font-medium"> class="fixed z-40 w-full overflow-y-auto bg-white border-t border-gray-200 rounded-t-lg dark:border-gray-700 dark:bg-gray-800 transition-all max-xl:left-0 max-xl:right-0 max-xl:bottom-0 max-h-full xl:m-auto xl:relative xl:p-4 xl:w-max xl:max-w-7xl xl:rounded-lg xl:border"
{{ $title }} aria-labelledby="drawer-{{ $name }}"
</h5> @drawer-open-{{ $name }}.window="$dispatch('menu-hide'); show = true"
@drawer-close-{{ $name }}.window="show = false; $dispatch('menu-show')"
:class="{ 'translate-y-full': !show, 'xl:-bottom-full': !show }"
>
<div
class="p-4 cursor-pointer max-xl:hover:bg-gray-50 max-xl:dark:hover:bg-gray-700 xl:border-b dark:border-gray-600 xl:flex xl:items-center xl:justify-between xl:p-4"
@click="$dispatch('drawer-close-{{ $name }}')"
x-on:touchstart="$dispatch('drawer-close-{{ $name }}')"
>
<span class="xl:hidden absolute w-8 h-1 -translate-x-1/2 bg-gray-300 rounded-lg top-3 left-1/2 dark:bg-gray-600">
</span>
<h5 class="inline-flex items-center text-base text-gray-500 dark:text-gray-400 font-medium">
{{ $title }}
</h5>
<button class="end-2.5 text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm w-8 h-8 ms-auto inline-flex justify-center items-center dark:hover:bg-gray-600 dark:hover:text-white">
<svg class="max-xl:hidden w-3 h-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6"/>
</svg>
</button>
</div>
{{ $content }}
</div> </div>
{{ $content }}
</div> </div>
</template> </template>

View File

@@ -18,7 +18,9 @@
<title>{{ $title ?? config('app.name') }}</title> <title>{{ $title ?? config('app.name') }}</title>
</head> </head>
<body class="bg-white dark:bg-gray-800"> <body class="bg-white dark:bg-gray-800">
<x-theme-switcher /> @persist('theme-switcher')
<x-theme-switcher />
@endpersist
{{ $slot }} {{ $slot }}
<x-menu /> <x-menu />

View File

@@ -1,6 +1,12 @@
<div class="fixed z-50 w-full h-16 max-w-lg -translate-x-1/2 bg-white border border-gray-200 rounded-full bottom-4 left-1/2 dark:bg-gray-700 dark:border-gray-600"> <div
class="fixed z-50 w-11/12 h-16 max-w-lg -translate-x-1/2 bg-white border border-gray-200 rounded-full left-1/2 dark:bg-gray-700 dark:border-gray-600 transition-all"
x-data="{ visible: true }"
@menu-hide.window="visible = false"
@menu-show.window="visible = true"
:class="{ '-bottom-16': !visible, 'bottom-4': visible }"
x-cloak
>
<div class="grid grid-flow-col h-full max-w-lg mx-auto"> <div class="grid grid-flow-col h-full max-w-lg mx-auto">
<x-menu-action tooltip="Startseite"> <x-menu-action tooltip="Startseite">
<svg class="w-5 h-5 mb-1 text-gray-500 dark:text-gray-400 group-hover:text-blue-600 dark:group-hover:text-blue-500" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 20"> <svg class="w-5 h-5 mb-1 text-gray-500 dark:text-gray-400 group-hover:text-blue-600 dark:group-hover:text-blue-500" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 20 20">
<path d="m19.707 9.293-2-2-7-7a1 1 0 0 0-1.414 0l-7 7-2 2a1 1 0 0 0 1.414 1.414L2 10.414V18a2 2 0 0 0 2 2h3a1 1 0 0 0 1-1v-4a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v4a1 1 0 0 0 1 1h3a2 2 0 0 0 2-2v-7.586l.293.293a1 1 0 0 0 1.414-1.414Z"/> <path d="m19.707 9.293-2-2-7-7a1 1 0 0 0-1.414 0l-7 7-2 2a1 1 0 0 0 1.414 1.414L2 10.414V18a2 2 0 0 0 2 2h3a1 1 0 0 0 1-1v-4a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v4a1 1 0 0 0 1 1h3a2 2 0 0 0 2-2v-7.586l.293.293a1 1 0 0 0 1.414-1.414Z"/>

View File

@@ -1,5 +1,6 @@
<?php <?php
use App\Http\Controllers\ImageController;
use Illuminate\Support\Facades\Route; use Illuminate\Support\Facades\Route;
use App\Http\Controllers\CategoryController; use App\Http\Controllers\CategoryController;
use App\Http\Controllers\AlbumController; use App\Http\Controllers\AlbumController;
@@ -7,3 +8,4 @@ use App\Http\Controllers\AlbumController;
Route::get('/', [CategoryController::class, 'index'])->name('index'); Route::get('/', [CategoryController::class, 'index'])->name('index');
Route::get('/category/{category}', [CategoryController::class, 'show'])->name('category.show'); Route::get('/category/{category}', [CategoryController::class, 'show'])->name('category.show');
Route::get('/album/{album}', [AlbumController::class, 'show'])->name('album.show'); Route::get('/album/{album}', [AlbumController::class, 'show'])->name('album.show');
Route::get('/image/{image}', [ImageController::class, 'show'])->name('image.show');