From 902b8433d9520d63f1d837bc1c28605adb64fa2a Mon Sep 17 00:00:00 2001 From: Bryam105 Date: Tue, 2 Jun 2026 09:46:53 -0300 Subject: [PATCH] NEW: - Implementada nueva funcion para crear productos destacados por etiquetas, mostrando carrusel con los mismos en la pagina welcome. --- app/Http/Controllers/CatalogoController.php | 13 ++- app/Http/Controllers/HomeController.php | 23 ++--- app/Http/Controllers/ProductosController.php | 19 +++- app/Http/Controllers/TagController.php | 44 +++++++++ app/Models/Product.php | 5 ++ app/Models/Tag.php | 18 ++++ .../2026_06_02_123209_create_tags_table.php | 28 ++++++ ..._06_02_123220_create_product_tag_table.php | 29 ++++++ resources/views/catalogo/index.blade.php | 30 ++++++- resources/views/catalogo/show.blade.php | 11 +++ resources/views/components/navbar.blade.php | 6 ++ .../views/components/ui/carrousel.blade.php | 29 +++--- resources/views/productos/create.blade.php | 90 +++++++++++++++++++ resources/views/productos/edit.blade.php | 90 +++++++++++++++++++ resources/views/tags/index.blade.php | 61 +++++++++++++ resources/views/welcome.blade.php | 15 +++- routes/web.php | 2 + 17 files changed, 480 insertions(+), 33 deletions(-) create mode 100644 app/Http/Controllers/TagController.php create mode 100644 app/Models/Tag.php create mode 100644 database/migrations/2026_06_02_123209_create_tags_table.php create mode 100644 database/migrations/2026_06_02_123220_create_product_tag_table.php create mode 100644 resources/views/tags/index.blade.php diff --git a/app/Http/Controllers/CatalogoController.php b/app/Http/Controllers/CatalogoController.php index e72942b..1858987 100644 --- a/app/Http/Controllers/CatalogoController.php +++ b/app/Http/Controllers/CatalogoController.php @@ -15,9 +15,10 @@ class CatalogoController extends Controller // 1. Atrapamos lo que el usuario escribió o seleccionó $query = $request->input('search'); $type = $request->input('type'); + $tagFilter = $request->input('tag'); // --- CONSULTA PARA LA GRILLA (PAGINADA) --- - $productsQuery = Product::query(); + $productsQuery = Product::with('tags'); $productsQuery->when($query, function ($q) use ($query) { return $q->where('name', 'like', "%{$query}%"); @@ -29,6 +30,12 @@ class CatalogoController extends Controller $productsQuery->where('type', '!=', 'service'); } + if ($tagFilter) { + $productsQuery->whereHas('tags', function($q) use ($tagFilter) { + $q->where('name', $tagFilter); + }); + } + //mostrar si tiene stock mayor a 0 $productsQuery->where('stock_quantity', '>', 0); @@ -40,8 +47,10 @@ class CatalogoController extends Controller ->orderBy('name', 'asc') ->get(); + $allTags = \App\Models\Tag::orderBy('name')->get(); + // Devuelve la vista - return view('catalogo.index', compact('products', 'allProducts')); + return view('catalogo.index', compact('products', 'allProducts', 'allTags')); } public function show(Product $product) diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php index 24379cc..bcf1d1a 100644 --- a/app/Http/Controllers/HomeController.php +++ b/app/Http/Controllers/HomeController.php @@ -9,17 +9,18 @@ class HomeController extends Controller { public function __invoke(Request $request) { - // Si tuvieras un campo 'sales_count', podrías usar ->orderByDesc('sales_count') - $destacados = Product::where('type', 'bike') - ->latest() // Las más nuevas - ->take(5) - ->get(); + // Traer todas las etiquetas con sus productos + $tagsConProductos = \App\Models\Tag::with('products')->get() + ->filter(function ($tag) { + // Solo mantener etiquetas que tengan al menos 1 producto + return $tag->products->count() > 0; + }) + ->map(function ($tag) { + // Limitar a 7 productos como máximo para el carrousel + $tag->setRelation('products', $tag->products->take(7)); + return $tag; + }); - // Si no hay bicis, traemos cualquier cosa para que no se rompa - if ($destacados->isEmpty()) { - $destacados = Product::take(5)->get(); - } - - return view('welcome', compact('destacados')); + return view('welcome', compact('tagsConProductos')); } } diff --git a/app/Http/Controllers/ProductosController.php b/app/Http/Controllers/ProductosController.php index ea104a4..407143d 100644 --- a/app/Http/Controllers/ProductosController.php +++ b/app/Http/Controllers/ProductosController.php @@ -4,6 +4,7 @@ namespace App\Http\Controllers; use App\Models\Product; use App\Models\Supplier; +use App\Models\Tag; use Illuminate\Http\Request; use Illuminate\Validation\Rule; use Illuminate\Support\Facades\Storage; @@ -55,7 +56,8 @@ class ProductosController extends Controller public function create() { $suppliers = Supplier::orderBy('name')->get(); - return view('productos.create', compact('suppliers')); + $tags = Tag::orderBy('name')->get(); + return view('productos.create', compact('suppliers', 'tags')); } public function store(Request $request) @@ -79,7 +81,11 @@ class ProductosController extends Controller } unset($validated['image']); - Product::create($validated); + $product = Product::create($validated); + + if ($request->has('tags')) { + $product->tags()->sync($request->tags); + } return redirect()->route('productos.index') ->with('success', 'Producto creado correctamente.'); @@ -93,7 +99,8 @@ class ProductosController extends Controller public function edit(Product $product) { $suppliers = Supplier::orderBy('name')->get(); - return view('productos.edit', compact('product', 'suppliers')); + $tags = Tag::orderBy('name')->get(); + return view('productos.edit', compact('product', 'suppliers', 'tags')); } public function update(Request $request, Product $product) @@ -123,6 +130,12 @@ class ProductosController extends Controller $product->update($validated); + if ($request->has('tags')) { + $product->tags()->sync($request->tags); + } else { + $product->tags()->detach(); + } + return redirect()->route('productos.index') ->with('success', 'Producto actualizado exitosamente.'); } diff --git a/app/Http/Controllers/TagController.php b/app/Http/Controllers/TagController.php new file mode 100644 index 0000000..4a41140 --- /dev/null +++ b/app/Http/Controllers/TagController.php @@ -0,0 +1,44 @@ +get(); + return view('tags.index', compact('tags')); + } + + public function store(Request $request) + { + $validated = $request->validate([ + 'name' => 'required|string|max:50|unique:tags,name' + ]); + + Tag::create($validated); + + return redirect()->route('tags.index')->with('success', 'Etiqueta creada correctamente.'); + } + + public function update(Request $request, Tag $tag) + { + $validated = $request->validate([ + 'name' => 'required|string|max:50|unique:tags,name,' . $tag->id + ]); + + $tag->update($validated); + + return redirect()->route('tags.index')->with('success', 'Etiqueta actualizada correctamente.'); + } + + public function destroy(Tag $tag) + { + $tag->delete(); + return redirect()->route('tags.index')->with('success', 'Etiqueta eliminada.'); + } +} diff --git a/app/Models/Product.php b/app/Models/Product.php index 4411dd2..7f2bb65 100644 --- a/app/Models/Product.php +++ b/app/Models/Product.php @@ -42,6 +42,11 @@ class Product extends Model { return $this->belongsToMany(Sale::class, 'sale_details'); } + + public function tags() + { + return $this->belongsToMany(Tag::class); + } } /**$user->sales: Te da la lista de todas las compras de ese usuario. diff --git a/app/Models/Tag.php b/app/Models/Tag.php new file mode 100644 index 0000000..2c8916b --- /dev/null +++ b/app/Models/Tag.php @@ -0,0 +1,18 @@ +belongsToMany(Product::class); + } +} diff --git a/database/migrations/2026_06_02_123209_create_tags_table.php b/database/migrations/2026_06_02_123209_create_tags_table.php new file mode 100644 index 0000000..4eab3f7 --- /dev/null +++ b/database/migrations/2026_06_02_123209_create_tags_table.php @@ -0,0 +1,28 @@ +id(); + $table->string('name')->unique(); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('tags'); + } +}; diff --git a/database/migrations/2026_06_02_123220_create_product_tag_table.php b/database/migrations/2026_06_02_123220_create_product_tag_table.php new file mode 100644 index 0000000..ced5f77 --- /dev/null +++ b/database/migrations/2026_06_02_123220_create_product_tag_table.php @@ -0,0 +1,29 @@ +id(); + $table->foreignId('product_id')->constrained()->onDelete('cascade'); + $table->foreignId('tag_id')->constrained()->onDelete('cascade'); + $table->timestamps(); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('product_tag'); + } +}; diff --git a/resources/views/catalogo/index.blade.php b/resources/views/catalogo/index.blade.php index ff3bd4b..0484321 100644 --- a/resources/views/catalogo/index.blade.php +++ b/resources/views/catalogo/index.blade.php @@ -82,7 +82,7 @@ - @if(request('search') || request('type')) + @if(request('search') || request('type') || request('tag')) @endif + + + + @if($allTags->count() > 0) +
+ @foreach($allTags as $t) + + #{{ $t->name }} + + @endforeach +
+ @endif + @if ($products->count() > 0) @@ -113,6 +130,17 @@

{{ $product->name }}

+ {{-- Etiquetas --}} + @if($product->tags->count() > 0) +
+ @foreach($product->tags as $t) + + #{{ $t->name }} + + @endforeach +
+ @endif + {{-- Precio --}} @if (!empty($product->price))

${{ number_format($product->price, 2, ',', '.') }}

diff --git a/resources/views/catalogo/show.blade.php b/resources/views/catalogo/show.blade.php index 4fa2ddf..dcf9ceb 100644 --- a/resources/views/catalogo/show.blade.php +++ b/resources/views/catalogo/show.blade.php @@ -50,6 +50,17 @@

SKU: {{ $product->sku ?? 'N/A' }}

{{ $product->name }}

+ {{-- Etiquetas --}} + @if($product->tags->count() > 0) +
+ @foreach($product->tags as $t) + + #{{ $t->name }} + + @endforeach +
+ @endif +
@if($product->stock_quantity > 5) diff --git a/resources/views/components/navbar.blade.php b/resources/views/components/navbar.blade.php index 74b3fef..fa22d09 100644 --- a/resources/views/components/navbar.blade.php +++ b/resources/views/components/navbar.blade.php @@ -41,6 +41,12 @@ Stock +
  • + + Etiquetas + +
  • diff --git a/resources/views/components/ui/carrousel.blade.php b/resources/views/components/ui/carrousel.blade.php index edfe146..9d692ec 100644 --- a/resources/views/components/ui/carrousel.blade.php +++ b/resources/views/components/ui/carrousel.blade.php @@ -1,14 +1,18 @@ -@props(['items']) +@props(['items', 'title' => 'Destacados']) -