Tienda en Línea con Filtrado Avanzado
mejora este codigo para que se coexistan: marcasController:const db = require('../db'); // Obtener marcas exports.getMarcas = (req, res) => { console.log("Iniciando consulta de marcas"); const query = ` SELECT id, nombre, descripcion, estado, fecha_creacion FROM marcas WHERE estado = 1 ORDER BY nombre`; db.query(query, (err, results) => { if (err) { console.error("Error en la consulta de marcas:", err); return res.status(500).json({ error: "Error al obtener las marcas", details: err.message }); } // Validación del resultado if (results.length === 0) { console.warn("No se encontraron marcas activas."); return res.status(404).json({ message: "No se encontraron marcas activas." }); } console.log("Marcas encontradas:", results.length); res.json(results); }); }; // Crear una nueva marca exports.createMarca = (req, res) => { const { nombre, descripcion, estado } = req.body; if (!nombre || !descripcion) { return res.status(400).json({ error: "Nombre y descripción son obligatorios." }); } const query = "INSERT INTO marcas (nombre, descripcion, estado) VALUES (?, ?, ?)"; db.query(query, [nombre, descripcion, estado], (err, result) => { if (err) { console.error("Error al insertar la marca:", err); return res.status(500).json({ error: "Error al crear la marca" }); } res.status(201).json({ id: result.insertId, nombre, descripcion, estado }); }); }; // Actualizar una marca exports.updateMarca = (req, res) => { const { id } = req.params; const { nombre, descripcion, estado } = req.body; if (!nombre || !descripcion) { return res.status(400).json({ error: "Nombre y descripción son obligatorios." }); } const query = "UPDATE marcas SET nombre = ?, descripcion = ?, estado = ? WHERE id = ?"; db.query(query, [nombre, descripcion, estado, id], (err) => { if (err) { console.error("Error al actualizar la marca:", err); return res.status(500).json({ error: "Error al actualizar la marca" }); } res.json({ message: "Marca actualizada exitosamente" }); }); }; // Eliminar una marca exports.deleteMarca = (req, res) => { const { id } = req.params; const query = "DELETE FROM marcas WHERE id = ?"; db.query(query, [id], (err) => { if (err) { console.error("Error al eliminar la marca:", err); return res.status(500).json({ error: "Error al eliminar la marca" }); } res.json({ message: "Marca eliminada exitosamente" }); }); }; categorias.jsx:import React, { useState, useEffect } from 'react'; import axios from 'axios'; import { useCart } from '../Cart/CartContext'; import './Categories.css'; function Categorias() { const [categorias, setCategorias] = useState([]); const [productos, setProductos] = useState([]); const [filteredProductos, setFilteredProductos] = useState([]); const [selectedCategory, setSelectedCategory] = useState(''); const [searchTerm, setSearchTerm] = useState(''); const [maxPrice, setMaxPrice] = useState(1000); const [brands, setBrands] = useState([]); const [selectedBrands, setSelectedBrands] = useState([]); const [showCategoryMenu, setShowCategoryMenu] = useState(false); const { addToCart } = useCart(); useEffect(() => { // Función para cargar los datos iniciales const fetchData = async () => { try { // Obtener categorías const categoriasRes = await axios.get('http://localhost:8080/api/categorias'); setCategorias(categoriasRes.data); // Obtener productos const productosRes = await axios.get('http://localhost:8080/api/productos'); setProductos(productosRes.data); setFilteredProductos(productosRes.data); // Obtener marcas const marcasRes = await axios.get('http://localhost:8080/api/marcas'); console.log('Marcas obtenidas:', marcasRes.data); // Para debugging setBrands(marcasRes.data); } catch (error) { console.error('Error al cargar datos:', error); } }; fetchData(); }, []); // Filtros dinámicos useEffect(() => { let filtered = productos; if (selectedCategory) { filtered = filtered.filter((producto) => producto.categoria_id === selectedCategory); } if (searchTerm) { filtered = filtered.filter((producto) => producto.nombre.toLowerCase().includes(searchTerm.toLowerCase()) ); } filtered = filtered.filter((producto) => producto.precio_venta <= maxPrice); if (selectedBrands.length > 0) { filtered = filtered.filter((producto) => selectedBrands.includes(producto.marca_id) ); } setFilteredProductos(filtered); }, [selectedCategory, searchTerm, maxPrice, selectedBrands, productos]); const handleBrandChange = (brandId) => { setSelectedBrands((prev) => prev.includes(brandId) ? prev.filter((b) => b !== brandId) : [...prev, brandId] ); }; return ( <div className="categorias-layout"> {/* Filtros en la columna izquierda */} <div className="filtros-container"> {/* Buscador */} <input type="text" placeholder="Buscar producto..." className="categorias-busqueda" value={searchTerm} onChange={(e) => setSearchTerm(e.target.value)} /> {/* Selector de precio */} <div className="filtro-precio"> <label>Precio máximo: ${maxPrice}</label> <input type="range" min="0" max="2000" value={maxPrice} onChange={(e) => setMaxPrice(Number(e.target.value))} /> </div> {/* Filtro por marcas */} <div className="filtro-marcas"> <h4>Filtrar por marcas</h4> {brands.map((marca) => ( <div key={marca.id} className="marca-checkbox"> <input type="checkbox" id={`marca-${marca.id}`} checked={selectedBrands.includes(marca.id)} onChange={() => handleBrandChange(marca.id)} /> <label htmlFor={`marca-${marca.id}`}>{marca.nombre}</label> </div> ))} </div> </div> {/* Botón para mostrar menú de categorías */} <button className="categorias-hamburguesa" onClick={() => setShowCategoryMenu(!showCategoryMenu)} > Categorías </button> {/* Menú lateral de categorías */} {showCategoryMenu && ( <div className="menu-categorias"> <button className="cerrar-menu" onClick={() => setShowCategoryMenu(false)} > × </button> <ul> <li onClick={() => setSelectedCategory('')}>Todas las categorías</li> {categorias.map((categoria) => ( <li key={categoria.id} onClick={() => { setSelectedCategory(categoria.id); setShowCategoryMenu(false); }} > {categoria.nombre} </li> ))} </ul> </div> )} {/* Productos en la columna derecha */} <div className="productos-container"> {filteredProductos.length > 0 ? ( filteredProductos.map((producto) => ( <div key={producto.id} className="producto-card"> <img src={producto.imagen} alt={producto.nombre} className="producto-imagen" /> <div className="producto-info"> <h3>{producto.nombre}</h3> <p>Precio: ${producto.precio_venta}</p> <button onClick={() => addToCart(producto)}>Comprar</button> </div> </div> )) ) : ( <p>No hay productos para mostrar.</p> )} </div> </div> ); } export default Categorias; db.js:const mysql = require("mysql"); const db = mysql.createPool({ host: "localhost", user: "root", password: "", database: "ecomerce", connectionLimit: 10, waitForConnections: true }); // Verificar la conexión inicial db.getConnection((err, connection) => { if (err) { console.error("Error al conectar con la base de datos:", err); return; } console.log("Conexión exitosa a la base de datos"); connection.release(); }); module.exports = db; server.js:const express = require("express"); const cors = require("cors"); const path = require("path"); const categoriasController = require("./controllers/categoriasController"); const marcasController = require("./controllers/marcasController"); const productosController = require("./controllers/productosController"); const app = express(); const PORT = 8080; app.use(cors()); app.use(express.json()); app.use(express.static(path.join(__dirname, "assets"))); // Rutas de categorías app.get("/api/categorias", categoriasController.getCategorias); // Rutas de marcas app.get("/api/marcas", marcasController.getMarcas); app.post("/api/marcas", marcasController.createMarca); app.put("/api/marcas/:id", marcasController.updateMarca); app.delete("/api/marcas/:id", marcasController.deleteMarca); // Rutas de productos app.get("/api/productos", productosController.getProductos); app.get("/api/productos/:id", productosController.getProducto); app.listen(PORT, () => { console.log(`Servidor corriendo en http://localhost:${PORT}`); });