Agregue middleware a productos Destroy y Edit. Y cambios en la vista de stock.
This commit is contained in:
@@ -0,0 +1,19 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Middleware;
|
||||||
|
|
||||||
|
use Closure;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
|
class CheckAdmin //
|
||||||
|
{
|
||||||
|
public function handle(Request $request, Closure $next): Response
|
||||||
|
{
|
||||||
|
if (auth()->check() && auth()->user()->role === 'admin') {
|
||||||
|
return $next($request);
|
||||||
|
}
|
||||||
|
|
||||||
|
abort(403, 'No tienes permiso para entrar aquí.');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,6 +12,9 @@ return Application::configure(basePath: dirname(__DIR__))
|
|||||||
)
|
)
|
||||||
->withMiddleware(function (Middleware $middleware): void {
|
->withMiddleware(function (Middleware $middleware): void {
|
||||||
//
|
//
|
||||||
|
$middleware->alias([
|
||||||
|
'admin' => \App\Http\Middleware\CheckAdmin::class,
|
||||||
|
]);
|
||||||
})
|
})
|
||||||
->withExceptions(function (Exceptions $exceptions): void {
|
->withExceptions(function (Exceptions $exceptions): void {
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -9,13 +9,16 @@
|
|||||||
<div class="w-full flex flex-col xl:flex-row justify-between items-start xl:items-center gap-4 mb-6">
|
<div class="w-full flex flex-col xl:flex-row justify-between items-start xl:items-center gap-4 mb-6">
|
||||||
|
|
||||||
<!-- Buscador y Filtros -->
|
<!-- Buscador y Filtros -->
|
||||||
<form action="{{ route('productos.index') }}" method="GET" class="w-full xl:w-4/5 flex flex-col md:flex-row gap-3">
|
<form action="{{ route('productos.index') }}" method="GET"
|
||||||
|
class="w-full xl:w-4/5 flex flex-col md:flex-row gap-3">
|
||||||
|
|
||||||
<!-- 1. Buscador por Texto -->
|
<!-- 1. Buscador por Texto -->
|
||||||
<div class="relative w-full md:w-2/5">
|
<div class="relative w-full md:w-2/5">
|
||||||
<div class="absolute inset-y-0 start-0 flex items-center ps-3 pointer-events-none">
|
<div class="absolute inset-y-0 start-0 flex items-center ps-3 pointer-events-none">
|
||||||
<svg class="w-4 h-4 text-gray-600 dark:text-gray-500" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 20 20">
|
<svg class="w-4 h-4 text-gray-600 dark:text-gray-500" aria-hidden="true"
|
||||||
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m19 19-4-4m0-7A7 7 0 1 1 1 8a7 7 0 0 1 14 0Z"/>
|
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="m19 19-4-4m0-7A7 7 0 1 1 1 8a7 7 0 0 1 14 0Z" />
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
<input type="text" name="search" value="{{ request('search') }}"
|
<input type="text" name="search" value="{{ request('search') }}"
|
||||||
@@ -45,19 +48,24 @@
|
|||||||
<select name="stock_status" onchange="this.form.submit()"
|
<select name="stock_status" onchange="this.form.submit()"
|
||||||
class="block w-full p-3 text-sm text-black dark:text-white border border-neutral-300 dark:border-neutral-700 rounded-lg bg-neutral-200 dark:bg-neutral-800 focus:ring-neon-lime focus:border-neon-lime cursor-pointer">
|
class="block w-full p-3 text-sm text-black dark:text-white border border-neutral-300 dark:border-neutral-700 rounded-lg bg-neutral-200 dark:bg-neutral-800 focus:ring-neon-lime focus:border-neon-lime cursor-pointer">
|
||||||
<option value="">Cualquier Stock</option>
|
<option value="">Cualquier Stock</option>
|
||||||
<option value="low" {{ request('stock_status') == 'low' ? 'selected' : '' }} class="text-red-600 dark:text-red-300 font-semibold">Stock en Alerta</option>
|
<option value="low" {{ request('stock_status') == 'low' ? 'selected' : '' }}
|
||||||
<option value="medium" {{ request('stock_status') == 'medium' ? 'selected' : '' }} class="text-yellow-600 dark:text-yellow-300 font-semibold">Stock Bajo</option>
|
class="text-red-600 dark:text-red-300 font-semibold">Stock en Alerta</option>
|
||||||
<option value="ok" {{ request('stock_status') == 'ok' ? 'selected' : '' }} class="text-green-600 dark:text-green-300 font-semibold">Stock Normal</option>
|
<option value="medium" {{ request('stock_status') == 'medium' ? 'selected' : '' }}
|
||||||
|
class="text-yellow-600 dark:text-yellow-300 font-semibold">Stock Bajo</option>
|
||||||
|
<option value="ok" {{ request('stock_status') == 'ok' ? 'selected' : '' }}
|
||||||
|
class="text-green-600 dark:text-green-300 font-semibold">Stock Normal</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Botón Limpiar Filtros -->
|
<!-- Botón Limpiar Filtros -->
|
||||||
@if(request('search') || request('type') || request('stock_status'))
|
@if (request('search') || request('type') || request('stock_status'))
|
||||||
<div class="w-full md:w-auto flex">
|
<div class="w-full md:w-auto flex">
|
||||||
<a href="{{ route('productos.index') }}" title="Limpiar Filtros"
|
<a href="{{ route('productos.index') }}" title="Limpiar Filtros"
|
||||||
class="flex items-center justify-center p-3 text-sm font-bold text-red-600 dark:text-red-400 bg-red-100 dark:bg-red-900/30 rounded-lg hover:bg-red-200 dark:hover:bg-red-900/50 border border-red-200 dark:border-red-800 transition-colors">
|
class="flex items-center justify-center p-3 text-sm font-bold text-red-600 dark:text-red-400 bg-red-100 dark:bg-red-900/30 rounded-lg hover:bg-red-200 dark:hover:bg-red-900/50 border border-red-200 dark:border-red-800 transition-colors">
|
||||||
<svg class="w-5 h-5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
|
<svg class="w-5 h-5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24"
|
||||||
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18 17.94 6M18 18 6.06 6"/>
|
height="24" fill="none" viewBox="0 0 24 24">
|
||||||
|
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
|
||||||
|
d="M6 18 17.94 6M18 18 6.06 6" />
|
||||||
</svg>
|
</svg>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
@@ -65,7 +73,8 @@
|
|||||||
</form>
|
</form>
|
||||||
|
|
||||||
<!-- Botón Nuevo -->
|
<!-- Botón Nuevo -->
|
||||||
<a href="{{ route('productos.create') }}" class="w-full xl:w-auto text-center px-5 py-3 text-sm font-bold text-neon-lime dark:text-neutral-900 bg-neutral-950 dark:bg-neon-lime rounded-lg hover:bg-neutral-900/80 hover:dark:bg-[#b3e600] transition-colors uppercase tracking-wide">
|
<a href="{{ route('productos.create') }}"
|
||||||
|
class="w-full xl:w-auto text-center px-5 py-3 text-sm font-bold text-neon-lime dark:text-neutral-900 bg-neutral-950 dark:bg-neon-lime rounded-lg hover:bg-neutral-900/80 hover:dark:bg-[#b3e600] transition-colors uppercase tracking-wide">
|
||||||
+ Nuevo Producto
|
+ Nuevo Producto
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
@@ -73,7 +82,8 @@
|
|||||||
<!-- Tabla de Productos -->
|
<!-- Tabla de Productos -->
|
||||||
<div class="relative overflow-x-auto shadow-md sm:rounded-lg border border-gray-400 dark:border-neutral-800 w-full">
|
<div class="relative overflow-x-auto shadow-md sm:rounded-lg border border-gray-400 dark:border-neutral-800 w-full">
|
||||||
<table class="w-full text-sm text-left rtl:text-right text-neutral-900 dark:text-white">
|
<table class="w-full text-sm text-left rtl:text-right text-neutral-900 dark:text-white">
|
||||||
<thead class="text-xs text-neutral-800 dark:text-gray-300 uppercase bg-gray-400 dark:bg-neutral-800 border-b border-gray-300 dark:border-neutral-700">
|
<thead
|
||||||
|
class="text-xs text-neutral-800 dark:text-gray-300 uppercase bg-gray-400 dark:bg-neutral-800 border-b border-gray-300 dark:border-neutral-700">
|
||||||
<tr>
|
<tr>
|
||||||
<th scope="col" class="px-6 py-3">Producto</th>
|
<th scope="col" class="px-6 py-3">Producto</th>
|
||||||
<th scope="col" class="px-6 py-3">Tipo</th>
|
<th scope="col" class="px-6 py-3">Tipo</th>
|
||||||
@@ -84,61 +94,108 @@
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@forelse($products as $product)
|
@forelse($products as $product)
|
||||||
<tr class="bg-gray-200/50 dark:bg-neutral-900/50 border-b border-gray-400 dark:border-neutral-800 hover:bg-gray-400 hover:dark:bg-neutral-800 transition-colors group">
|
<tr
|
||||||
<td class="px-6 py-4 font-medium whitespace-nowrap">
|
class="bg-gray-200/50 dark:bg-neutral-900/50 border-b border-gray-400 dark:border-neutral-800 hover:bg-gray-400 hover:dark:bg-neutral-800 transition-colors group">
|
||||||
<div class="text-base font-bold">{{ $product->name }}</div>
|
<td class="px-6 py-4 font-medium whitespace-nowrap">
|
||||||
<div class="text-xs text-gray-600 dark:text-gray-400 font-mono">{{ $product->sku ?? 'Sin SKU' }}</div>
|
<div class="text-base font-bold">{{ $product->name }}</div>
|
||||||
</td>
|
<div class="text-xs text-gray-600 dark:text-gray-400 font-mono">
|
||||||
<td class="px-6 py-4">
|
{{ $product->sku ?? 'Sin SKU' }}</div>
|
||||||
@if($product->type === 'bike') <x-ui.badge color="neon">Bicicleta</x-ui.badge>
|
</td>
|
||||||
@elseif($product->type === 'clothing') <x-ui.badge color="blue">Indumentaria</x-ui.badge>
|
<td class="px-6 py-4">
|
||||||
@elseif($product->type === 'spare') <x-ui.badge color="gray">Repuesto</x-ui.badge>
|
@if ($product->type === 'bike')
|
||||||
@elseif($product->type === 'children') <x-ui.badge color="pink">Infantil</x-ui.badge>
|
<x-ui.badge color="neon">Bicicleta</x-ui.badge>
|
||||||
@elseif($product->type === 'rollers') <x-ui.badge color="purple">Rollers</x-ui.badge>
|
@elseif($product->type === 'clothing')
|
||||||
@elseif($product->type === 'skate') <x-ui.badge color="orange">Skate</x-ui.badge>
|
<x-ui.badge color="blue">Indumentaria</x-ui.badge>
|
||||||
@else <x-ui.badge color="yellow">Accesorio / Otro</x-ui.badge> @endif
|
@elseif($product->type === 'spare')
|
||||||
</td>
|
<x-ui.badge color="gray">Repuesto</x-ui.badge>
|
||||||
<td class="px-6 py-4 font-mono">
|
@elseif($product->type === 'children')
|
||||||
${{ number_format($product->price, 2) }}
|
<x-ui.badge color="pink">Infantil</x-ui.badge>
|
||||||
</td>
|
@elseif($product->type === 'rollers')
|
||||||
<td class="px-6 py-4 text-center">
|
<x-ui.badge color="purple">Rollers</x-ui.badge>
|
||||||
@if($product->stock_quantity < $product->min_stock_alert)
|
@elseif($product->type === 'skate')
|
||||||
<x-ui.badge color="red">{{ $product->stock_quantity }}</x-ui.badge>
|
<x-ui.badge color="orange">Skate</x-ui.badge>
|
||||||
@elseif($product->stock_quantity <= $product->min_stock_alert+5)
|
@else
|
||||||
<x-ui.badge color="yellow">{{ $product->stock_quantity }}</x-ui.badge>
|
<x-ui.badge color="yellow">Accesorio / Otro</x-ui.badge>
|
||||||
@else
|
@endif
|
||||||
<x-ui.badge color="green">{{ $product->stock_quantity }}</x-ui.badge>
|
</td>
|
||||||
@endif
|
<td class="px-6 py-4 font-mono">
|
||||||
</td>
|
${{ number_format($product->price, 2) }}
|
||||||
<td class="px-6 py-4 text-right flex items-center gap-2 justify-end">
|
</td>
|
||||||
<a href="{{ route('productos.show', $product) }}" title="Ver Mas" class="font-semibold p-2 text-green-700 dark:text-green-400 border-2 border-green-700 rounded-lg hover:bg-green-700 dark:hover:bg-green-600 dark:hover:border-green-600 hover:text-white dark:hover:text-white transition-colors">
|
<td class="px-6 py-4 text-center">
|
||||||
<svg class="size-5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
|
@if ($product->stock_quantity < $product->min_stock_alert)
|
||||||
<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"/>
|
<x-ui.badge color="red">{{ $product->stock_quantity }}</x-ui.badge>
|
||||||
<path stroke="currentColor" stroke-width="2" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z"/>
|
@elseif($product->stock_quantity <= $product->min_stock_alert + 5)
|
||||||
</svg>
|
<x-ui.badge color="yellow">{{ $product->stock_quantity }}</x-ui.badge>
|
||||||
</a>
|
@else
|
||||||
<a href="{{ route('productos.edit', $product) }}" title="Editar" class="font-semibold p-2 text-blue-800 dark:text-blue-400 border-2 border-blue-800 rounded-lg hover:bg-blue-800 hover:text-white dark:hover:text-white transition-colors">
|
<x-ui.badge color="green">{{ $product->stock_quantity }}</x-ui.badge>
|
||||||
<svg class="size-5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
|
@endif
|
||||||
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m14.304 4.844 2.852 2.852M7 7H4a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h11a1 1 0 0 0 1-1v-4.5m2.409-9.91a2.017 2.017 0 0 1 0 2.853l-6.844 6.844L8 14l.713-3.565 6.844-6.844a2.015 2.015 0 0 1 2.852 0Z"/>
|
</td>
|
||||||
</svg>
|
<td class="px-6 py-4 text-right flex items-center gap-2 justify-end">
|
||||||
</a>
|
<a href="{{ route('productos.show', $product) }}" title="Ver Mas"
|
||||||
<form action="{{route('productos.destroy',$product)}}" method="post">
|
class="font-semibold p-2 text-green-700 dark:text-green-400 border-2 border-green-700 rounded-lg hover:bg-green-700 dark:hover:bg-green-600 dark:hover:border-green-600 hover:text-white dark:hover:text-white transition-colors">
|
||||||
@csrf
|
<svg class="size-5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"
|
||||||
@method('DELETE')
|
width="24" height="24" fill="none" viewBox="0 0 24 24">
|
||||||
<button title="Eliminar" type="submit" class="w-full sm:w-auto p-2 font-bold dark:font-medium text-red-600 dark:text-red-400 border-2 border-red-600 rounded-lg hover:bg-red-600 hover:text-white dark:hover:text-white transition-colors">
|
<path stroke="currentColor" stroke-width="2"
|
||||||
<svg class="size-5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" viewBox="0 0 24 24">
|
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-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 7h14m-9 3v8m4-8v8M10 3h4a1 1 0 0 1 1 1v3H9V4a1 1 0 0 1 1-1ZM6 7h12v13a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V7Z"/>
|
<path stroke="currentColor" stroke-width="2"
|
||||||
|
d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" />
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</a>
|
||||||
</form>
|
|
||||||
</td>
|
@php
|
||||||
</tr>
|
$isAdmin = auth()->user()?->role === 'admin';
|
||||||
|
$classes = $isAdmin
|
||||||
|
? 'text-blue-800 border-blue-800 hover:bg-blue-800 hover:text-white'
|
||||||
|
: 'border-black-400 text-black-400 opacity-50 cursor-not-allowed dark:border-gray-400 dark:text-gray-400';
|
||||||
|
@endphp
|
||||||
|
|
||||||
|
<a @if ($isAdmin) href="{{ route('productos.edit', $product) }}" @endif
|
||||||
|
title="Editar"
|
||||||
|
class="font-semibold p-2 border-2 rounded-lg transition-colors {{ $classes }}">
|
||||||
|
<svg class="size-5" 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-linecap="round" stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
d="m14.304 4.844 2.852 2.852M7 7H4a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h11a1 1 0 0 0 1-1v-4.5m2.409-9.91a2.017 2.017 0 0 1 0 2.853l-6.844 6.844L8 14l.713-3.565 6.844-6.844a2.015 2.015 0 0 1 2.852 0Z" />
|
||||||
|
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
@if (auth()->user()?->role === 'admin')
|
||||||
|
<form action="{{ route('productos.destroy', $product) }}" method="post"
|
||||||
|
class="inline">
|
||||||
|
@csrf
|
||||||
|
@method('DELETE')
|
||||||
|
<button title="Eliminar" type="submit"
|
||||||
|
onclick="return confirm('¿Estás seguro de eliminar este producto?')"
|
||||||
|
class="w-full sm:w-auto p-2 font-bold dark:font-medium text-red-600 dark:text-red-400 border-2 border-red-600 rounded-lg hover:bg-red-600 hover:text-white dark:hover:text-white transition-colors">
|
||||||
|
<svg class="size-5" 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-linecap="round"
|
||||||
|
stroke-linejoin="round" stroke-width="2"
|
||||||
|
d="M5 7h14m-9 3v8m4-8v8M10 3h4a1 1 0 0 1 1 1v3H9V4a1 1 0 0 1 1-1ZM6 7h12v13a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V7Z" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</form>
|
||||||
|
@else
|
||||||
|
<button title="Eliminar" disabled
|
||||||
|
class="w-full sm:w-auto p-2 border-2 dark:border-gray-400 dark:text-gray-400 border-black-400 text-black-400 rounded-lg cursor-not-allowed opacity-50">
|
||||||
|
<svg class="size-5" 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-linecap="round" stroke-linejoin="round"
|
||||||
|
stroke-width="2"
|
||||||
|
d="M5 7h14m-9 3v8m4-8v8M10 3h4a1 1 0 0 1 1 1v3H9V4a1 1 0 0 1 1-1ZM6 7h12v13a1 1 0 0 1-1 1H7a1 1 0 0 1-1-1V7Z" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
@endif
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
@empty
|
@empty
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="5" class="px-6 py-10 text-center font-semibold">
|
<td colspan="5" class="px-6 py-10 text-center font-semibold">
|
||||||
No se encontraron productos.
|
No se encontraron productos.
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@endforelse
|
@endforelse
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|||||||
+23
-13
@@ -16,41 +16,51 @@ use App\Models\Product;
|
|||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\Session;
|
use Illuminate\Support\Facades\Session;
|
||||||
|
|
||||||
Route::get('/',HomeController::class);
|
// --- RUTAS PÚBLICAS (Cualquiera accede) ---
|
||||||
|
Route::get('/', HomeController::class);
|
||||||
// Route::get('/catalogo', [CatalogoController::class,'catalogo'])->name('catalogo');
|
|
||||||
Route::resource('catalogo', CatalogoController::class)->only(['index', 'show'])->parameters(['catalogo' => 'product']);
|
Route::resource('catalogo', CatalogoController::class)->only(['index', 'show'])->parameters(['catalogo' => 'product']);
|
||||||
|
|
||||||
Route::get('login', function(){ return view('login'); })->name('login');
|
Route::get('login', function(){ return view('login'); })->name('login');
|
||||||
Route::post('login', LoginController::class)->middleware('throttle:5,1')->name('login.attempt');
|
Route::post('login', LoginController::class)->middleware('throttle:5,1')->name('login.attempt');
|
||||||
|
|
||||||
Route::view('register', 'register')->name('register');
|
Route::view('register', 'register')->name('register');
|
||||||
Route::post('register', RegisterController::class)->name('register.store');
|
Route::post('register', RegisterController::class)->name('register.store');
|
||||||
|
|
||||||
Route::post('logout', function(){
|
Route::post('logout', function(){
|
||||||
Auth::guard('web')->logout();
|
Auth::guard('web')->logout();
|
||||||
|
|
||||||
Session::invalidate();
|
Session::invalidate();
|
||||||
Session::regenerateToken();
|
Session::regenerateToken();
|
||||||
|
|
||||||
return redirect('/');
|
return redirect('/');
|
||||||
})->name('logout');
|
})->name('logout');
|
||||||
|
|
||||||
|
|
||||||
|
// --- RUTAS PROTEGIDAS (Requieren Login) ---
|
||||||
Route::middleware(['auth'])->group(function () {
|
Route::middleware(['auth'])->group(function () {
|
||||||
Route::view('dashboard', 'dashboard')->name('dashboard');
|
Route::view('dashboard', 'dashboard')->name('dashboard');
|
||||||
Route::resource('clients', ClientController::class);
|
Route::resource('clients', ClientController::class);
|
||||||
Route::resource('productos', ProductosController::class)->parameters([
|
|
||||||
'productos' => 'product'
|
|
||||||
]);
|
|
||||||
Route::resource('sales', SaleController::class)->only(['index', 'create', 'store', 'show']);
|
Route::resource('sales', SaleController::class)->only(['index', 'create', 'store', 'show']);
|
||||||
// Rutas de Taller
|
Route::get('/agenda', [AgendaController::class, 'index'])->name('agenda');
|
||||||
|
Route::get('/appointments/{appointment}', [AppointmentController::class, 'show'])->name('appointments.show');
|
||||||
|
|
||||||
|
// Taller
|
||||||
Route::controller(TallerController::class)->prefix('taller')->name('taller.')->group(function () {
|
Route::controller(TallerController::class)->prefix('taller')->name('taller.')->group(function () {
|
||||||
Route::get('/', 'index')->name('index');
|
Route::get('/', 'index')->name('index');
|
||||||
Route::get('/create', 'create')->name('create');
|
Route::get('/create', 'create')->name('create');
|
||||||
Route::post('/', 'store')->name('store');
|
Route::post('/', 'store')->name('store');
|
||||||
Route::patch('/{appointment}/status', 'updateStatus')->name('updateStatus');
|
Route::patch('/{appointment}/status', 'updateStatus')->name('updateStatus');
|
||||||
});
|
});
|
||||||
Route::get('/agenda', [AgendaController::class, 'index'])->name('agenda');
|
|
||||||
Route::get('/appointments/{appointment}', [AppointmentController::class, 'show'])
|
// Productos: Rutas de lectura para cualquier usuario logueado
|
||||||
->name('appointments.show');
|
Route::resource('productos', ProductosController::class)
|
||||||
|
->only(['index', 'show'])
|
||||||
|
->parameters(['productos' => 'product']);
|
||||||
|
|
||||||
|
// --- RUTAS DE ADMINISTRADOR (Solo Admin) ---
|
||||||
|
Route::middleware(['admin'])->group(function () {
|
||||||
|
// Solo el admin puede crear, editar o borrar productos
|
||||||
|
Route::resource('productos', ProductosController::class)
|
||||||
|
->only(['create', 'store', 'edit', 'update', 'destroy'])
|
||||||
|
->parameters(['productos' => 'product']);
|
||||||
|
|
||||||
|
// Si tienes más cosas de admin (ej: reportes), van aquí
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user