Cambios en vista de visitante, separada logica de productos y catalogos poara manejo individual, creados catalogo.index y catalogo.show. acomodadas rutas del catalogo para evitar errores.

This commit is contained in:
BryamE
2026-01-09 01:34:26 -03:00
parent 5adea83517
commit 59d5cf748d
7 changed files with 139 additions and 41 deletions
+7 -2
View File
@@ -10,7 +10,7 @@ class CatalogoController extends Controller
/** /**
* Muestra los registros de ventas con buscador y paginación. * Muestra los registros de ventas con buscador y paginación.
*/ */
public function catalogo(Request $request) public function index(Request $request)
{ {
// Consulta base // Consulta base
$query = Product::query(); $query = Product::query();
@@ -31,6 +31,11 @@ class CatalogoController extends Controller
$products = $query->paginate(12)->withQueryString(); // withQueryString mantiene la búsqueda al cambiar de página $products = $query->paginate(12)->withQueryString(); // withQueryString mantiene la búsqueda al cambiar de página
// Devuelve la vista // Devuelve la vista
return view('catalogo', compact('products')); return view('catalogo.index', compact('products'));
}
public function show(Product $product)
{
return view('catalogo.show', compact('product'));
} }
} }
@@ -7,11 +7,11 @@
@if ($products->count() > 0) @if ($products->count() > 0)
<div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-6"> <div class="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-6">
@foreach ($products as $prod) @foreach ($products as $product)
<div class="group p-4 border border-neutral-800 rounded-xl hover:border-neon-lime hover:-translate-y-1 transition-all duration-300"> <div class="group p-4 border border-neutral-800 rounded-xl hover:border-neon-lime hover:-translate-y-1 transition-all duration-300">
{{-- Imagen si existe --}} {{-- Imagen si existe --}}
@if (!empty($prod->image_path)) @if (!empty($product->image_path))
<img src="{{ asset('storage/' . $prod->image_path) }}" alt="{{ $prod->name }}" <img src="{{ asset('storage/' . $product->image_path) }}" alt="{{ $product->name }}"
class="w-full h-40 object-cover rounded mb-4"> class="w-full h-40 object-cover rounded mb-4">
@else @else
<div class="w-full border border-neutral-800 h-40 bg-stone-900 flex items-center justify-center rounded mb-4"> <div class="w-full border border-neutral-800 h-40 bg-stone-900 flex items-center justify-center rounded mb-4">
@@ -20,22 +20,22 @@
@endif @endif
{{-- Nombre --}} {{-- Nombre --}}
<h2 class="text-lg font-semibold text-white">{{ $prod->name }}</h2> <h2 class="text-lg font-semibold text-white">{{ $product->name }}</h2>
{{-- Descripción corta --}} {{-- Descripción corta --}}
<div class="h-10 overflow-y-auto [scrollbar-width:none]"> <div class="h-10 overflow-y-auto [scrollbar-width:none]">
@if (!empty($prod->description)) @if (!empty($product->description))
<p class="text-sm text-gray-400 mt-2">{{ $prod->description }}</p> <p class="text-sm text-gray-400 mt-2">{{ $product->description }}</p>
@endif @endif
</div> </div>
{{-- Precio --}} {{-- Precio --}}
@if (!empty($prod->price)) @if (!empty($product->price))
<p class="text-white group-hover:text-neon-lime font-bold mt-3 transition-colors">${{ number_format($prod->price, 2, ',', '.') }}</p> <p class="text-white group-hover:text-neon-lime font-bold mt-3 transition-colors">${{ number_format($product->price, 2, ',', '.') }}</p>
@endif @endif
{{-- Botón --}} {{-- Botón --}}
<a href="{{ route('productos.show', $prod) }}" <a href="{{ route('catalogo.show', $product) }}"
class="mt-4 block w-full bg-neon-lime/80 uppercase text-black font-semibold py-2 rounded-lg text-center shadow-md shadow-neon-lime/10 hover:bg-neutral-900/70 border border-transparent hover:text-neon-lime hover:shadow-neon-lime/20 hover:border-neutral-800 transition-all"> class="mt-4 block w-full bg-neon-lime/80 uppercase text-black font-semibold py-2 rounded-lg text-center shadow-md shadow-neon-lime/10 hover:bg-neutral-900/70 border border-transparent hover:text-neon-lime hover:shadow-neon-lime/20 hover:border-neutral-800 transition-all">
Ver + Ver +
</a> </a>
+105
View File
@@ -0,0 +1,105 @@
<x-layout title="{{ $product->name }} - Lauck">
<div class="container mx-auto px-4 py-8">
<!-- Botón Volver -->
<a href="{{ route('catalogo.index') }}" class="inline-flex items-center text-gray-400 hover:text-white mb-6 transition-colors">
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18"></path></svg>
Volver al Catálogo
</a>
<div class="bg-panel-bg rounded-xl shadow-2xl overflow-hidden border border-neutral-800">
<div class="grid grid-cols-1 md:grid-cols-2">
<!-- COLUMNA IZQUIERDA: IMAGEN (El cuadro verde de tu ejemplo) -->
<div class="bg-neutral-800 relative h-96 md:h-auto min-h-[500px] flex items-center justify-center py-4 group">
@if($product->image_path)
<img src="{{ asset('storage/' . $product->image_path) }}"
alt="{{ $product->name }}"
class="w-full h-full object-contain max-h-[500px] transform drop-shadow-lg">
@else
<div class="text-neutral-700 flex flex-col items-center">
<svg class="w-48 h-48" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="0.5" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z"></path></svg>
<span class="mt-4 text-gray-500 text-sm uppercase tracking-widest">Sin Imagen</span>
</div>
@endif
<!-- Badge de Tipo Flotante -->
<div class="absolute top-6 left-6">
@if($product->type == 'bike')
<span class="bg-black/50 backdrop-blur text-white px-3 py-1 rounded-full text-xs font-bold uppercase tracking-wide border border-white/10">Bicicleta</span>
@else
<span class="bg-black/50 backdrop-blur text-white px-3 py-1 rounded-full text-xs font-bold uppercase tracking-wide border border-white/10">Accesorio</span>
@endif
</div>
</div>
<!-- COLUMNA DERECHA: INFO (El cuadro azul de tu ejemplo) -->
<div class="p-8 md:p-12 flex flex-col justify-center bg-panel-bg">
<!-- Encabezado -->
<div class="mb-6 border-b border-neutral-800 pb-6">
<p class="text-neon-lime text-sm font-bold uppercase tracking-widest mb-2">SKU: {{ $product->sku ?? 'N/A' }}</p>
<h1 class="text-4xl font-black text-white italic mb-2 leading-tight">{{ $product->name }}</h1>
<!-- Stock Status -->
<div class="flex items-center gap-2 mt-4">
@if($product->stock_quantity > 5)
<span class="w-3 h-3 bg-green-500 rounded-full animate-pulse"></span>
<span class="text-green-400 text-sm font-bold">En Stock ({{ $product->stock_quantity }} unid.)</span>
@elseif($product->stock_quantity > 0)
<span class="w-3 h-3 bg-yellow-500 rounded-full animate-pulse"></span>
<span class="text-yellow-400 text-sm font-bold">¡Últimas Unidades! ({{ $product->stock_quantity }})</span>
@else
<span class="w-3 h-3 bg-red-500 rounded-full"></span>
<span class="text-red-400 text-sm font-bold">Agotado</span>
@endif
</div>
</div>
<!-- Precio -->
<div class="mb-8">
<span class="block text-gray-400 text-xs uppercase mb-1">Precio Contado</span>
<div class="flex items-baseline gap-2">
<span class="text-5xl font-black text-white">${{ number_format($product->price, 0, ',', '.') }}</span>
<span class="text-gray-500 font-medium">ARG</span>
</div>
<p class="text-gray-500 text-xs mt-2">* Consultar financiación en el local.</p>
</div>
<!-- Descripción -->
<div class="mb-8">
<h3 class="text-white font-bold uppercase text-sm mb-3">Descripción</h3>
<p class="text-gray-400 leading-relaxed">
{{ $product->description ?? 'Sin descripción detallada disponible para este producto. Por favor, acérquese al local para más información.' }}
</p>
</div>
<!-- Botones de Acción -->
<div class="mt-auto grid grid-cols-1 sm:grid-cols-2 gap-4">
<button class="bg-neon-lime text-neutral-900 font-black py-4 px-6 rounded-lg hover:bg-[#b3e600] transition-all uppercase tracking-wide shadow-lg shadow-neon-lime/20 flex items-center justify-center gap-2 transform hover:-translate-y-1">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z"></path></svg>
Consultar
</button>
<a href="https://wa.me/?text=Hola,%20me%20interesa%20el%20producto:%20{{ $product->name }}" target="_blank" class="bg-neutral-800 text-white font-bold py-4 px-6 rounded-lg hover:bg-neutral-700 border border-neutral-700 transition-all uppercase tracking-wide flex items-center justify-center gap-2">
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 24 24"><path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.008-.57-.008-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413Z"/></svg>
WhatsApp
</a>
</div>
</div>
</div>
</div>
</div>
</x-layout>
{{-- <a href="{{ route('productos.edit', $product ) }}" class="w-full sm:w-auto px-5 py-2 rounded-full text-white font-semibold bg-blue-600 hover:bg-blue-700">Editar</a>
<form action="{{route('productos.destroy',$product)}}" method="post">
@csrf
@method('DELETE')
<button type="submit" class="w-full sm:w-auto px-5 py-2 rounded-full text-white font-semibold bg-red-600 hover:bg-red-700">
Borrar
</button>
</form> --}}
+1 -1
View File
@@ -66,7 +66,7 @@
<!-- Buscador Integrado --> <!-- Buscador Integrado -->
<li class="w-full md:w-auto my-2 md:my-0"> <li class="w-full md:w-auto my-2 md:my-0">
<form action="{{ route('catalogo') }}" method="GET"> <form action="{{ route('catalogo.index') }}" method="GET">
<div class="relative"> <div class="relative">
<input type="text" name="search" <input type="text" name="search"
class="block w-full md:w-48 p-2 ps-3 text-xs text-white border border-neutral-600 rounded-full bg-neutral-800/50 focus:ring-neon-lime focus:border-neon-lime placeholder-gray-500 transition-all focus:w-full md:focus:w-64" class="block w-full md:w-48 p-2 ps-3 text-xs text-white border border-neutral-600 rounded-full bg-neutral-800/50 focus:ring-neon-lime focus:border-neon-lime placeholder-gray-500 transition-all focus:w-full md:focus:w-64"
@@ -46,7 +46,7 @@
</p> </p>
<div class="flex gap-4"> <div class="flex gap-4">
<a href="{{ route('catalogo', ['search' => $item->sku]) }}" class="px-6 py-3 bg-white text-neutral-900 font-bold uppercase tracking-wider rounded hover:bg-gray-200 transition-colors"> <a href="{{ route('catalogo.index', ['search' => $item->sku]) }}" class="px-6 py-3 bg-white text-neutral-900 font-bold uppercase tracking-wider rounded hover:bg-gray-200 transition-colors">
Ver Detalles Ver Detalles
</a> </a>
</div> </div>
+2 -10
View File
@@ -38,16 +38,8 @@
<div class="w-full max-w-5xl mx-auto bg-panel-bg border border-neutral-800 rounded-xl p-8 shadow-lg"> <div class="w-full max-w-5xl mx-auto bg-panel-bg border border-neutral-800 rounded-xl p-8 shadow-lg">
@if(session('success')) <x-ui.alert />
<div class="bg-green-900/50 border border-green-500 text-green-300 px-4 py-3 rounded-lg mb-6 shadow-sm">
{{ session('success') }}
</div>
@endif
@if(session('error'))
<div class="bg-red-900/50 border border-red-500 text-red-300 px-4 py-3 rounded-lg mb-6 shadow-sm">
{{ session('error') }}
</div>
@endif
@if($errors->any()) @if($errors->any())
<div class="bg-red-900/50 border border-red-500 text-red-300 px-4 py-3 rounded-lg mb-6 shadow-sm"> <div class="bg-red-900/50 border border-red-500 text-red-300 px-4 py-3 rounded-lg mb-6 shadow-sm">
<ul class="list-disc list-inside"> <ul class="list-disc list-inside">
+7 -11
View File
@@ -14,17 +14,15 @@ use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Session; use Illuminate\Support\Facades\Session;
Route::get('/',HomeController::class); Route::get('/',HomeController::class);
Route::get('/catalogo', [CatalogoController::class,'catalogo'])->name('catalogo');
Route::get('login', function(){ // Route::get('/catalogo', [CatalogoController::class,'catalogo'])->name('catalogo');
return view('login'); Route::resource('catalogo', CatalogoController::class)->only(['index', 'show'])->parameters(['catalogo' => 'product']);
})->name('login');
Route::post('login', LoginController::class) Route::get('login', function(){ return view('login'); })->name('login');
->middleware('throttle:5,1') Route::post('login', LoginController::class)->middleware('throttle:5,1')->name('login.attempt');
->name('login.attempt');
Route::view('dashboard', 'dashboard')->middleware('auth')->name('dashboard'); Route::view('register', 'register')->name('register');
Route::post('register', RegisterController::class)->name('register.store');
Route::post('logout', function(){ Route::post('logout', function(){
Auth::guard('web')->logout(); Auth::guard('web')->logout();
@@ -35,10 +33,8 @@ Route::post('logout', function(){
return redirect('/'); return redirect('/');
})->name('logout'); })->name('logout');
Route::view('register', 'register')->name('register');
Route::post('register', RegisterController::class)->name('register.store');
Route::middleware(['auth'])->group(function () { Route::middleware(['auth'])->group(function () {
Route::view('dashboard', 'dashboard')->name('dashboard');
Route::resource('clients', ClientController::class); Route::resource('clients', ClientController::class);
Route::resource('productos', ProductosController::class)->parameters([ Route::resource('productos', ProductosController::class)->parameters([
'productos' => 'product' 'productos' => 'product'