Files
SkinbaseNova/resources/views/web/categories.blade.php

246 lines
17 KiB
PHP

@extends('layouts.nova')
<?php $useUnifiedSeo = true; ?>
@section('main-class', '')
@section('content')
<?php
$initialPayload = $initialPayload ?? [
'data' => [],
'meta' => ['current_page' => 1, 'last_page' => 1, 'per_page' => 24, 'total' => 0],
'summary' => ['total_categories' => 0, 'total_artworks' => 0],
'popular_categories' => [],
'request' => ['query' => '', 'sort' => 'popular', 'page' => 1, 'per_page' => 24],
];
$categories = $initialPayload['data'] ?? [];
$meta = $initialPayload['meta'] ?? ['current_page' => 1, 'last_page' => 1, 'per_page' => 24, 'total' => 0];
$summary = $initialPayload['summary'] ?? ['total_categories' => 0, 'total_artworks' => 0];
$popularCategories = $initialPayload['popular_categories'] ?? [];
$requestState = $initialPayload['request'] ?? ['query' => '', 'sort' => 'popular', 'page' => 1, 'per_page' => 24];
$query = (string) ($requestState['query'] ?? '');
$sort = (string) ($requestState['sort'] ?? 'popular');
$currentPage = (int) ($meta['current_page'] ?? 1);
$lastPage = (int) ($meta['last_page'] ?? 1);
$buildCategoriesUrl = function (int $page) use ($query, $sort): string {
$params = [];
if ($page > 1) {
$params['page'] = $page;
}
if ($sort !== 'popular') {
$params['sort'] = $sort;
}
if ($query !== '') {
$params['q'] = $query;
}
$queryString = http_build_query($params);
return $queryString === ''
? url('/categories')
: url('/categories') . '?' . $queryString;
};
$categoryStyles = [
'wallpapers' => ['badge' => 'from-cyan-400/90 to-sky-500/90', 'overlay' => 'from-sky-950/10 via-slate-950/12 to-slate-950/92'],
'skins' => ['badge' => 'from-orange-400/90 to-amber-500/90', 'overlay' => 'from-orange-950/10 via-slate-950/12 to-slate-950/92'],
'photography' => ['badge' => 'from-emerald-400/90 to-teal-500/90', 'overlay' => 'from-emerald-950/10 via-slate-950/12 to-slate-950/92'],
'other' => ['badge' => 'from-fuchsia-400/90 to-rose-500/90', 'overlay' => 'from-rose-950/10 via-slate-950/12 to-slate-950/92'],
'default' => ['badge' => 'from-cyan-400/90 to-orange-400/90', 'overlay' => 'from-slate-900/10 via-slate-950/12 to-slate-950/92'],
];
?>
<script id="categories-page-props" type="application/json">
{!! json_encode([
'apiUrl' => route('api.categories.index'),
'pageTitle' => $page_title ?? 'Categories',
'pageDescription' => $page_meta_description ?? null,
'initialData' => $initialPayload,
], JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_HEX_TAG | JSON_HEX_AMP) !!}
</script>
<div id="categories-page-root" class="min-h-screen bg-[radial-gradient(circle_at_top,rgba(34,211,238,0.14),transparent_28%),radial-gradient(circle_at_80%_20%,rgba(249,115,22,0.16),transparent_30%),linear-gradient(180deg,#050b13_0%,#09111c_42%,#050913_100%)]">
<div class="pb-24 text-white">
<section class="relative overflow-hidden">
<div class="absolute inset-x-0 top-0 h-[28rem] bg-[radial-gradient(circle_at_top_left,rgba(34,211,238,0.12),transparent_38%),radial-gradient(circle_at_top_right,rgba(249,115,22,0.14),transparent_34%)]"></div>
<div class="relative w-full px-6 pb-8 pt-14 sm:px-8 sm:pt-20 xl:px-10 2xl:px-14 lg:pt-24">
<div class="grid gap-8 lg:grid-cols-[minmax(0,1.2fr)_20rem] lg:items-end">
<div>
<div class="inline-flex rounded-full border border-white/10 bg-white/[0.04] px-4 py-2 text-xs font-semibold uppercase tracking-[0.24em] text-white/50 backdrop-blur-sm">
Category directory
</div>
<h1 class="mt-5 max-w-4xl text-4xl font-semibold tracking-[-0.05em] text-white sm:text-5xl lg:text-6xl">
{{ $page_title ?? 'Categories' }}
</h1>
<p class="mt-5 max-w-2xl text-base leading-8 text-white/62 sm:text-lg">
{{ $page_meta_description ?? 'Browse all wallpapers, skins, themes and digital art categories' }}
</p>
</div>
<div class="grid gap-4 sm:grid-cols-3 lg:grid-cols-1">
<div class="rounded-[24px] border border-white/10 bg-black/22 p-5 backdrop-blur-md shadow-[0_24px_60px_rgba(0,0,0,0.24)]">
<p class="text-xs font-semibold uppercase tracking-[0.2em] text-white/40">Categories</p>
<p class="mt-3 text-3xl font-semibold tracking-[-0.04em] text-white">{{ number_format((int) ($summary['total_categories'] ?? 0)) }}</p>
</div>
<div class="rounded-[24px] border border-white/10 bg-black/22 p-5 backdrop-blur-md shadow-[0_24px_60px_rgba(0,0,0,0.24)]">
<p class="text-xs font-semibold uppercase tracking-[0.2em] text-white/40">Artworks indexed</p>
<p class="mt-3 text-3xl font-semibold tracking-[-0.04em] text-white">{{ number_format((int) ($summary['total_artworks'] ?? 0)) }}</p>
</div>
<div class="rounded-[24px] border border-white/10 bg-black/22 p-5 backdrop-blur-md shadow-[0_24px_60px_rgba(0,0,0,0.24)]">
<p class="text-xs font-semibold uppercase tracking-[0.2em] text-white/40">View</p>
<p class="mt-3 text-3xl font-semibold tracking-[-0.04em] text-white">Grid</p>
</div>
</div>
</div>
<form method="GET" action="{{ url('/categories') }}" class="mt-10 rounded-[30px] border border-white/10 bg-black/25 p-4 shadow-[0_30px_80px_rgba(0,0,0,0.25)] backdrop-blur-xl sm:p-5">
<div class="grid gap-4 lg:grid-cols-[minmax(0,1fr)_16rem] lg:items-center">
<label class="relative block">
<span class="pointer-events-none absolute left-4 top-1/2 -translate-y-1/2 text-white/35">
<svg viewBox="0 0 20 20" fill="currentColor" aria-hidden="true" class="h-5 w-5">
<path fill-rule="evenodd" d="M8.5 3a5.5 5.5 0 1 0 3.473 9.765l3.63 3.63a.75.75 0 1 0 1.06-1.06l-3.63-3.63A5.5 5.5 0 0 0 8.5 3Zm-4 5.5a4 4 0 1 1 8 0 4 4 0 0 1-8 0Z" clip-rule="evenodd" />
</svg>
</span>
<input
type="search"
name="q"
value="{{ $query }}"
placeholder="Search categories"
aria-label="Search categories"
class="h-14 w-full rounded-2xl border border-white/10 bg-white/[0.04] pl-12 pr-4 text-sm text-white placeholder:text-white/28 focus:border-cyan-300/45 focus:outline-none focus:ring-2 focus:ring-cyan-300/15"
/>
</label>
<label class="block">
<span class="mb-2 block text-xs font-semibold uppercase tracking-[0.2em] text-white/38">Sort by</span>
<select name="sort" aria-label="Sort categories" class="h-14 w-full rounded-2xl border border-white/10 bg-white/[0.04] px-4 text-sm text-white focus:border-orange-300/45 focus:outline-none focus:ring-2 focus:ring-orange-300/12">
<option value="popular" @selected($sort === 'popular') class="bg-slate-950 text-white">Popular</option>
<option value="az" @selected($sort === 'az') class="bg-slate-950 text-white">A-Z</option>
<option value="artworks" @selected($sort === 'artworks') class="bg-slate-950 text-white">Most artworks</option>
</select>
</label>
</div>
</form>
</div>
</section>
<section class="w-full px-6 sm:px-8 xl:px-10 2xl:px-14">
@if ($query === '' && count($popularCategories) > 0)
<div class="mb-10 rounded-[28px] border border-white/10 bg-white/[0.03] p-5 shadow-[0_24px_60px_rgba(0,0,0,0.18)] backdrop-blur-sm">
<div class="flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between">
<div>
<p class="text-xs font-semibold uppercase tracking-[0.22em] text-white/38">Popular categories</p>
<h2 class="mt-2 text-2xl font-semibold tracking-[-0.04em] text-white">Start with the busiest destinations</h2>
</div>
<div class="flex flex-wrap gap-3">
@foreach ($popularCategories as $category)
<a href="{{ $category['url'] }}" class="inline-flex items-center gap-2 rounded-full border border-white/10 bg-black/20 px-4 py-2 text-sm text-white/72 transition hover:border-white/20 hover:bg-white/[0.05] hover:text-white">
<span>{{ $category['name'] }}</span>
<span class="text-white/38">{{ number_format((int) ($category['artwork_count'] ?? 0)) }}</span>
</a>
@endforeach
</div>
</div>
</div>
@endif
<div class="mb-6 flex flex-col gap-3 sm:flex-row sm:items-end sm:justify-between">
<div>
<p class="text-xs font-semibold uppercase tracking-[0.22em] text-white/38">Directory results</p>
<h2 class="mt-2 text-2xl font-semibold tracking-[-0.04em] text-white">{{ number_format((int) ($meta['total'] ?? 0)) }} categories visible</h2>
</div>
<p class="text-sm text-white/52">
@if ((int) ($meta['total'] ?? 0) > 0)
Showing {{ number_format($categories === [] ? 0 : 1) }} to {{ number_format(count($categories)) }} of {{ number_format((int) ($meta['total'] ?? 0)) }} categories.
@else
Browse all wallpapers, skins, themes and digital art categories.
@endif
</p>
</div>
@if ((int) ($meta['total'] ?? 0) === 0)
<div class="rounded-[28px] border border-dashed border-white/14 bg-black/20 px-6 py-14 text-center backdrop-blur-sm">
<p class="text-xs font-semibold uppercase tracking-[0.24em] text-white/35">No matching categories</p>
<h2 class="mt-3 text-2xl font-semibold tracking-[-0.03em] text-white">Nothing matched &quot;{{ $query }}&quot;</h2>
<p class="mx-auto mt-3 max-w-xl text-sm leading-7 text-white/58">
Try a shorter term or switch sorting to browse the full category directory again.
</p>
</div>
@else
<div class="grid grid-cols-1 gap-6 sm:grid-cols-2 md:grid-cols-3 xl:grid-cols-4 2xl:grid-cols-5">
@foreach ($categories as $index => $category)
@php
$contentTypeSlug = $category['content_type']['slug'] ?? 'default';
$contentTypeName = $category['content_type']['name'] ?? 'Category';
$style = $categoryStyles[$contentTypeSlug] ?? $categoryStyles['default'];
@endphp
<a
href="{{ $category['url'] }}"
aria-label="Browse {{ $category['name'] }} category"
class="group relative block cursor-pointer overflow-hidden rounded-2xl transition duration-300 ease-out hover:-translate-y-1 hover:scale-[1.01] hover:shadow-[0_0_28px_rgba(125,211,252,0.16)]"
>
<div class="relative aspect-[4/5] overflow-hidden rounded-2xl border border-white/10 bg-slate-950/80">
<img
src="{{ $category['cover_image'] }}"
alt="Cover artwork for {{ $category['name'] }}"
loading="lazy"
class="h-full w-full object-cover transition duration-500 group-hover:scale-110"
/>
<div class="absolute inset-0 bg-gradient-to-b {{ $style['overlay'] }} transition duration-500 group-hover:from-black/20 group-hover:to-black/90"></div>
<div class="absolute inset-0 bg-[radial-gradient(circle_at_top,rgba(255,255,255,0.22),transparent_42%)] opacity-0 transition duration-500 group-hover:opacity-100"></div>
<div class="absolute inset-x-0 top-0 flex items-center justify-between gap-3 p-4">
<span class="inline-flex rounded-full bg-gradient-to-r {{ $style['badge'] }} px-3 py-1 text-[11px] font-semibold uppercase tracking-[0.2em] text-slate-950 shadow-[0_10px_24px_rgba(0,0,0,0.24)]">
{{ $contentTypeName }}
</span>
<span class="rounded-full border border-white/15 bg-black/25 px-3 py-1 text-[11px] font-medium uppercase tracking-[0.18em] text-white/78 backdrop-blur">
{{ number_format((int) ($category['artwork_count'] ?? 0)) }} artworks
</span>
</div>
<div class="absolute inset-x-0 bottom-0 p-4 sm:p-5">
<div class="rounded-[22px] border border-white/10 bg-black/30 p-4 backdrop-blur-md transition duration-300 group-hover:border-white/20 group-hover:bg-black/42">
<div class="mb-3 h-px w-14 bg-gradient-to-r from-white/70 to-transparent transition duration-300 group-hover:w-24"></div>
<h3 class="text-lg font-semibold tracking-[-0.02em] text-white sm:text-xl">{{ $category['name'] }}</h3>
<p class="mt-2 text-sm leading-6 text-white/65">
Explore {{ $category['name'] }} across wallpapers, skins, themes, and digital art collections.
</p>
</div>
</div>
</div>
</a>
@endforeach
</div>
<div class="mt-10 flex flex-col items-center justify-center gap-3 rounded-[24px] border border-white/8 bg-black/18 px-4 py-5 backdrop-blur-sm">
<p class="text-sm text-white/46">
Loaded through page {{ number_format($currentPage) }} of {{ number_format($lastPage) }}
</p>
<div class="flex flex-wrap items-center justify-center gap-2">
@if ($currentPage > 1)
<a href="{{ $buildCategoriesUrl($currentPage - 1) }}" class="inline-flex items-center justify-center rounded-full border border-white/10 bg-white/[0.04] px-4 py-2 text-sm text-white/72 transition hover:border-white/20 hover:bg-white/[0.08] hover:text-white">Previous</a>
@endif
<span class="inline-flex items-center justify-center rounded-full border border-white/10 bg-black/25 px-4 py-2 text-sm text-white/72">
Page {{ number_format($currentPage) }} / {{ number_format($lastPage) }}
</span>
@if ($currentPage < $lastPage)
<a href="{{ $buildCategoriesUrl($currentPage + 1) }}" class="inline-flex items-center justify-center rounded-full border border-white/10 bg-white/[0.04] px-4 py-2 text-sm text-white/72 transition hover:border-white/20 hover:bg-white/[0.08] hover:text-white">Next</a>
@endif
</div>
</div>
@endif
</section>
</div>
</div>
@vite(['resources/js/Pages/CategoriesPage.jsx'])
@endsection