2026-02-06 14:56:56 +02:00
|
|
|
|
@extends('layouts.app')
|
|
|
|
|
|
|
2026-02-08 14:13:22 +02:00
|
|
|
|
@php
|
|
|
|
|
|
$title = 'Discover Products - ' . config('app.name');
|
|
|
|
|
|
@endphp
|
|
|
|
|
|
|
2026-02-06 14:56:56 +02:00
|
|
|
|
@section('content')
|
2026-02-08 14:13:22 +02:00
|
|
|
|
<!-- Hero Section -->
|
|
|
|
|
|
<div class="bg-gradient-to-br from-primary-50 via-white to-accent-50 border-b border-gray-200">
|
|
|
|
|
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12 sm:py-16">
|
|
|
|
|
|
<div class="text-center max-w-3xl mx-auto">
|
|
|
|
|
|
<h1 class="text-4xl sm:text-5xl font-bold text-gray-900 mb-4">
|
|
|
|
|
|
Discover the best tech from Europe
|
|
|
|
|
|
</h1>
|
|
|
|
|
|
<p class="text-lg text-gray-600 mb-8">
|
|
|
|
|
|
Find amazing products built by European makers and companies
|
|
|
|
|
|
</p>
|
2026-02-06 14:56:56 +02:00
|
|
|
|
|
2026-02-08 14:13:22 +02:00
|
|
|
|
<!-- Hero Search -->
|
|
|
|
|
|
<div class="max-w-2xl mx-auto">
|
|
|
|
|
|
<form method="GET" action="{{ route('products.index') }}">
|
|
|
|
|
|
<div class="relative">
|
|
|
|
|
|
<input type="text"
|
|
|
|
|
|
name="search"
|
|
|
|
|
|
value="{{ request('search') }}"
|
|
|
|
|
|
placeholder="Search for products..."
|
|
|
|
|
|
class="w-full px-6 py-4 text-lg border-2 border-gray-300 rounded-full focus:border-primary-500 focus:ring-2 focus:ring-primary-200 transition-all duration-200">
|
|
|
|
|
|
<button type="submit"
|
|
|
|
|
|
class="absolute right-2 top-1/2 -translate-y-1/2 bg-primary-600 text-white px-6 py-2 rounded-full hover:bg-primary-700 transition-colors">
|
|
|
|
|
|
<svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
|
|
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path>
|
|
|
|
|
|
</svg>
|
|
|
|
|
|
</button>
|
2026-02-06 14:56:56 +02:00
|
|
|
|
</div>
|
2026-02-08 14:13:22 +02:00
|
|
|
|
</form>
|
2026-02-06 14:56:56 +02:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2026-02-08 14:13:22 +02:00
|
|
|
|
|
|
|
|
|
|
<!-- Main Content -->
|
|
|
|
|
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
|
|
|
|
|
<!-- Filters & Sorting -->
|
|
|
|
|
|
<div class="mb-8">
|
2026-02-14 16:11:09 +02:00
|
|
|
|
<div class="bg-white rounded-xl shadow-sm border border-gray-200 p-6">
|
2026-02-08 14:13:22 +02:00
|
|
|
|
<form method="GET" action="{{ route('products.index') }}" class="space-y-4 lg:space-y-0" x-data="{ showFilters: false }">
|
|
|
|
|
|
<!-- Filter Toggle (Mobile) -->
|
2026-02-14 16:11:09 +02:00
|
|
|
|
<div class="lg:hidden mb-4">
|
2026-02-08 14:13:22 +02:00
|
|
|
|
<button @click="showFilters = !showFilters"
|
|
|
|
|
|
type="button"
|
2026-02-14 16:11:09 +02:00
|
|
|
|
class="w-full inline-flex items-center justify-between px-4 py-2 border border-gray-300 shadow-sm text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500">
|
|
|
|
|
|
<span class="flex items-center">
|
|
|
|
|
|
<svg class="mr-2 h-5 w-5 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
|
|
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6V4m0 2a2 2 0 100 4m0-4a2 2 0 110 4m-6 8a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4m6 6v10m6-2a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4"></path>
|
|
|
|
|
|
</svg>
|
|
|
|
|
|
Filters & Sort
|
|
|
|
|
|
</span>
|
|
|
|
|
|
<svg class="h-5 w-5 transition-transform" :class="{ 'rotate-180': showFilters }" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
2026-02-08 14:13:22 +02:00
|
|
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 9l-7 7-7-7"></path>
|
|
|
|
|
|
</svg>
|
|
|
|
|
|
</button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- Filters Grid -->
|
|
|
|
|
|
<div :class="{ 'hidden': !showFilters }"
|
2026-02-14 16:11:09 +02:00
|
|
|
|
class="lg:flex lg:items-end lg:gap-4 grid grid-cols-1 sm:grid-cols-2 gap-4 lg:gap-4">
|
2026-02-08 14:13:22 +02:00
|
|
|
|
<!-- Search (hidden on desktop as it's in hero) -->
|
2026-02-14 16:11:09 +02:00
|
|
|
|
<div class="lg:hidden sm:col-span-2">
|
|
|
|
|
|
<label for="mobile-search" class="block text-sm font-medium text-gray-700 mb-2">Search</label>
|
2026-02-08 14:13:22 +02:00
|
|
|
|
<input type="text"
|
2026-02-14 16:11:09 +02:00
|
|
|
|
id="mobile-search"
|
2026-02-08 14:13:22 +02:00
|
|
|
|
name="search"
|
|
|
|
|
|
value="{{ request('search') }}"
|
2026-02-14 16:11:09 +02:00
|
|
|
|
placeholder="Search products..."
|
|
|
|
|
|
class="appearance-none block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-primary-500 focus:border-primary-500 sm:text-sm">
|
2026-02-08 14:13:22 +02:00
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- Category Filter -->
|
2026-02-14 16:11:09 +02:00
|
|
|
|
<div class="lg:flex-1">
|
|
|
|
|
|
<label for="category" class="block text-sm font-medium text-gray-700 mb-2">Category</label>
|
|
|
|
|
|
<select name="category"
|
|
|
|
|
|
id="category"
|
|
|
|
|
|
class="appearance-none block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-primary-500 focus:border-primary-500 sm:text-sm">
|
2026-02-08 14:13:22 +02:00
|
|
|
|
<option value="">All Categories</option>
|
|
|
|
|
|
@foreach($categories as $category)
|
|
|
|
|
|
<option value="{{ $category->id }}" {{ request('category') == $category->id ? 'selected' : '' }}>
|
|
|
|
|
|
{{ $category->name }}
|
|
|
|
|
|
</option>
|
|
|
|
|
|
@endforeach
|
|
|
|
|
|
</select>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- Date Range Filter -->
|
2026-02-14 16:11:09 +02:00
|
|
|
|
<div class="lg:flex-1">
|
|
|
|
|
|
<label for="date_range" class="block text-sm font-medium text-gray-700 mb-2">Time Period</label>
|
|
|
|
|
|
<select name="date_range"
|
|
|
|
|
|
id="date_range"
|
|
|
|
|
|
class="appearance-none block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-primary-500 focus:border-primary-500 sm:text-sm">
|
2026-02-08 14:13:22 +02:00
|
|
|
|
<option value="">All Time</option>
|
|
|
|
|
|
<option value="today" {{ request('date_range') === 'today' ? 'selected' : '' }}>Today</option>
|
|
|
|
|
|
<option value="week" {{ request('date_range') === 'week' ? 'selected' : '' }}>This Week</option>
|
|
|
|
|
|
<option value="month" {{ request('date_range') === 'month' ? 'selected' : '' }}>This Month</option>
|
|
|
|
|
|
<option value="year" {{ request('date_range') === 'year' ? 'selected' : '' }}>This Year</option>
|
|
|
|
|
|
</select>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- Sort By -->
|
2026-02-14 16:11:09 +02:00
|
|
|
|
<div class="lg:flex-1">
|
|
|
|
|
|
<label for="sort" class="block text-sm font-medium text-gray-700 mb-2">Sort By</label>
|
|
|
|
|
|
<select name="sort"
|
|
|
|
|
|
id="sort"
|
|
|
|
|
|
class="appearance-none block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-primary-500 focus:border-primary-500 sm:text-sm">
|
2026-02-08 14:13:22 +02:00
|
|
|
|
<option value="newest" {{ request('sort') === 'newest' || !request('sort') ? 'selected' : '' }}>Newest</option>
|
|
|
|
|
|
<option value="popular" {{ request('sort') === 'popular' ? 'selected' : '' }}>Most Popular</option>
|
|
|
|
|
|
<option value="oldest" {{ request('sort') === 'oldest' ? 'selected' : '' }}>Oldest</option>
|
|
|
|
|
|
</select>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- Action Buttons -->
|
2026-02-14 16:11:09 +02:00
|
|
|
|
<div class="flex gap-2 sm:col-span-2 lg:col-span-auto lg:flex-shrink-0">
|
|
|
|
|
|
<button type="submit"
|
|
|
|
|
|
class="flex-1 lg:flex-none inline-flex items-center justify-center px-4 py-2 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-primary-600 hover:bg-primary-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500">
|
|
|
|
|
|
<svg class="mr-2 h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
|
|
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path>
|
|
|
|
|
|
</svg>
|
2026-02-08 14:13:22 +02:00
|
|
|
|
Apply
|
|
|
|
|
|
</button>
|
2026-02-14 16:11:09 +02:00
|
|
|
|
<a href="{{ route('products.index') }}"
|
|
|
|
|
|
class="flex-1 lg:flex-none inline-flex items-center justify-center px-4 py-2 border border-gray-300 shadow-sm text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500">
|
|
|
|
|
|
<svg class="mr-2 h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
|
|
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
|
|
|
|
|
|
</svg>
|
2026-02-08 14:13:22 +02:00
|
|
|
|
Clear
|
|
|
|
|
|
</a>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- Active Filters Tags -->
|
|
|
|
|
|
@if(request()->hasAny(['search', 'category', 'date_range', 'sort']))
|
|
|
|
|
|
<div class="flex flex-wrap gap-2 pt-4 border-t border-gray-200">
|
|
|
|
|
|
<span class="text-sm font-medium text-gray-700">Active filters:</span>
|
|
|
|
|
|
@if(request('search'))
|
|
|
|
|
|
<span class="inline-flex items-center px-3 py-1 rounded-full text-sm bg-primary-100 text-primary-800">
|
|
|
|
|
|
Search: "{{ request('search') }}"
|
|
|
|
|
|
<a href="{{ route('products.index', request()->except('search')) }}" class="ml-2 hover:text-primary-900">×</a>
|
|
|
|
|
|
</span>
|
|
|
|
|
|
@endif
|
|
|
|
|
|
@if(request('category'))
|
|
|
|
|
|
<span class="inline-flex items-center px-3 py-1 rounded-full text-sm bg-primary-100 text-primary-800">
|
|
|
|
|
|
{{ $categories->find(request('category'))->name ?? 'Unknown' }}
|
|
|
|
|
|
<a href="{{ route('products.index', request()->except('category')) }}" class="ml-2 hover:text-primary-900">×</a>
|
|
|
|
|
|
</span>
|
|
|
|
|
|
@endif
|
|
|
|
|
|
@if(request('date_range'))
|
|
|
|
|
|
<span class="inline-flex items-center px-3 py-1 rounded-full text-sm bg-primary-100 text-primary-800">
|
|
|
|
|
|
{{ ucfirst(request('date_range')) }}
|
|
|
|
|
|
<a href="{{ route('products.index', request()->except('date_range')) }}" class="ml-2 hover:text-primary-900">×</a>
|
|
|
|
|
|
</span>
|
|
|
|
|
|
@endif
|
|
|
|
|
|
@if(request('sort') && request('sort') !== 'newest')
|
|
|
|
|
|
<span class="inline-flex items-center px-3 py-1 rounded-full text-sm bg-primary-100 text-primary-800">
|
|
|
|
|
|
{{ ucfirst(request('sort')) }}
|
|
|
|
|
|
<a href="{{ route('products.index', request()->except('sort')) }}" class="ml-2 hover:text-primary-900">×</a>
|
|
|
|
|
|
</span>
|
|
|
|
|
|
@endif
|
|
|
|
|
|
</div>
|
|
|
|
|
|
@endif
|
|
|
|
|
|
</form>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- Results Summary -->
|
|
|
|
|
|
@if($products->total() > 0)
|
|
|
|
|
|
<div class="mb-6">
|
|
|
|
|
|
<p class="text-sm text-gray-600">
|
|
|
|
|
|
Showing <span class="font-semibold text-gray-900">{{ $products->firstItem() }}</span> to
|
|
|
|
|
|
<span class="font-semibold text-gray-900">{{ $products->lastItem() }}</span> of
|
|
|
|
|
|
<span class="font-semibold text-gray-900">{{ $products->total() }}</span> products
|
|
|
|
|
|
</p>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
@endif
|
|
|
|
|
|
|
|
|
|
|
|
<!-- Products Grid -->
|
|
|
|
|
|
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 mb-8">
|
|
|
|
|
|
@forelse($products as $product)
|
|
|
|
|
|
@include('components.product.card', ['product' => $product])
|
|
|
|
|
|
@empty
|
|
|
|
|
|
<!-- Empty State -->
|
|
|
|
|
|
<div class="col-span-full">
|
|
|
|
|
|
<div class="text-center py-16">
|
|
|
|
|
|
<svg class="mx-auto h-16 w-16 text-gray-400 mb-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
|
|
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9.172 16.172a4 4 0 015.656 0M9 10h.01M15 10h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
|
|
|
|
|
|
</svg>
|
|
|
|
|
|
<h3 class="text-lg font-medium text-gray-900 mb-2">No products found</h3>
|
|
|
|
|
|
<p class="text-gray-600 mb-6">
|
|
|
|
|
|
@if(request()->hasAny(['search', 'category', 'date_range']))
|
|
|
|
|
|
Try adjusting your search or filters to find what you're looking for.
|
|
|
|
|
|
@else
|
|
|
|
|
|
Be the first to submit a product!
|
|
|
|
|
|
@endif
|
|
|
|
|
|
</p>
|
|
|
|
|
|
@auth
|
2026-02-14 16:11:09 +02:00
|
|
|
|
<a href="{{ route('products.create') }}" class="inline-flex items-center px-4 py-2 border border-transparent shadow-sm text-sm font-medium rounded-md text-white bg-primary-600 hover:bg-primary-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary-500">
|
|
|
|
|
|
<svg class="mr-2 h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
2026-02-08 14:13:22 +02:00
|
|
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"></path>
|
|
|
|
|
|
</svg>
|
2026-02-14 16:11:09 +02:00
|
|
|
|
Submit a Product
|
2026-02-08 14:13:22 +02:00
|
|
|
|
</a>
|
|
|
|
|
|
@endauth
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
@endforelse
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- Pagination -->
|
|
|
|
|
|
@if($products->hasPages())
|
|
|
|
|
|
<div class="flex justify-center">
|
|
|
|
|
|
{{ $products->links() }}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
@endif
|
|
|
|
|
|
</div>
|
2026-02-06 14:56:56 +02:00
|
|
|
|
@endsection
|