>
-
--- ==================================================================
--- VERIFICACIÓN Y CREACIÓN DE TABLA DE LOGS
--- ==================================================================
--- Script para verificar y crear tabla productos_logs si no existe
-
--- Verificar si la tabla productos_logs existe
-SET @table_exists = (
- SELECT COUNT(*)
- FROM information_schema.tables
- WHERE table_schema = DATABASE()
- AND table_name = 'productos_logs'
-);
-
--- Crear tabla productos_logs si no existe (para bases de datos existentes)
-SET @sql = IF(@table_exists = 0,
- 'CREATE TABLE productos_logs (
- id INT PRIMARY KEY AUTO_INCREMENT,
- producto_id INT NOT NULL,
- tipo_cambio ENUM(''precio'', ''stock'', ''activacion'', ''desactivacion'') NOT NULL,
- valor_anterior VARCHAR(50),
- valor_nuevo VARCHAR(50),
- usuario_id INT,
- usuario_tipo ENUM(''admin'', ''empleado'') DEFAULT ''admin'',
- fecha_cambio TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
- ip_usuario VARCHAR(45),
- INDEX idx_producto_logs_fecha (fecha_cambio),
- INDEX idx_producto_logs_producto (producto_id),
- INDEX idx_producto_logs_tipo (tipo_cambio),
- CONSTRAINT FK_PRODUCTO_LOG
- FOREIGN KEY (producto_id) REFERENCES Productos(ID_PRODUCTO) ON DELETE CASCADE
- )',
- 'SELECT ''Tabla productos_logs ya existe'' as mensaje'
-);
-
-PREPARE stmt FROM @sql;
-EXECUTE stmt;
-DEALLOCATE PREPARE stmt;
-
--- ==================================================================
--- VERIFICACIÓN Y CREACIÓN DE TRIGGER
--- ==================================================================
--- Script para verificar y crear trigger si no existe
-
--- Verificar si el trigger existe
-SET @trigger_exists = (
- SELECT COUNT(*)
- FROM information_schema.triggers
- WHERE trigger_schema = DATABASE()
- AND trigger_name = 'tr_actualizar_fecha_producto'
-);
-
--- Crear trigger si no existe
-SET @sql_trigger = IF(@trigger_exists = 0,
- 'CREATE TRIGGER tr_actualizar_fecha_producto
- BEFORE UPDATE ON Productos
- FOR EACH ROW
- BEGIN
- SET NEW.FECHA_ULTIMA_MODIFICACION = CURRENT_TIMESTAMP;
- END',
- 'SELECT ''Trigger tr_actualizar_fecha_producto ya existe'' as mensaje'
-);
-
-PREPARE stmt_trigger FROM @sql_trigger;
-EXECUTE stmt_trigger;
-DEALLOCATE PREPARE stmt_trigger;
-
--- ==================================================================
--- CONSULTAS DE MANTENIMIENTO Y VERIFICACIÓN
--- ==================================================================
-
--- Verificar estructura de tabla Productos
-SELECT
- COLUMN_NAME as 'Campo',
- COLUMN_TYPE as 'Tipo',
- IS_NULLABLE as 'Nulo',
- COLUMN_DEFAULT as 'Por_Defecto',
- EXTRA as 'Extra'
-FROM information_schema.COLUMNS
-WHERE TABLE_SCHEMA = DATABASE()
-AND TABLE_NAME = 'Productos'
-ORDER BY ORDINAL_POSITION;
-
--- Verificar existencia de tabla productos_logs
-SELECT
- TABLE_NAME as 'Tabla',
- TABLE_ROWS as 'Filas',
- CREATE_TIME as 'Fecha_Creacion'
-FROM information_schema.TABLES
-WHERE TABLE_SCHEMA = DATABASE()
-AND TABLE_NAME IN ('Productos', 'productos_logs');
-
--- Verificar triggers relacionados con Productos
-SELECT
- TRIGGER_NAME as 'Trigger',
- EVENT_MANIPULATION as 'Evento',
- EVENT_OBJECT_TABLE as 'Tabla',
- TRIGGER_BODY as 'Accion'
-FROM information_schema.TRIGGERS
-WHERE TRIGGER_SCHEMA = DATABASE()
-AND EVENT_OBJECT_TABLE = 'Productos';
-
--- Verificar índices de la tabla productos_logs
-SELECT
- INDEX_NAME as 'Indice',
- COLUMN_NAME as 'Columna',
- NON_UNIQUE as 'No_Unico'
-FROM information_schema.STATISTICS
-WHERE TABLE_SCHEMA = DATABASE()
-AND TABLE_NAME = 'productos_logs'
-ORDER BY INDEX_NAME, SEQ_IN_INDEX;
-
--- ==================================================================
--- CONSULTAS DE PRUEBA PARA LOGS
--- ==================================================================
-
--- Consulta para ver logs recientes (ejecutar después de hacer cambios)
--- SELECT * FROM productos_logs ORDER BY fecha_cambio DESC LIMIT 10;
-
--- Consulta para ver cambios de un producto específico
--- SELECT
--- pl.*,
--- p.NOMBRE_PRODUCTO
--- FROM productos_logs pl
--- JOIN Productos p ON pl.producto_id = p.ID_PRODUCTO
--- WHERE pl.producto_id = 1
--- ORDER BY pl.fecha_cambio DESC;
-
--- Consulta para ver estadísticas de cambios
--- SELECT
--- tipo_cambio,
--- COUNT(*) as total_cambios,
--- DATE(fecha_cambio) as fecha
--- FROM productos_logs
--- GROUP BY tipo_cambio, DATE(fecha_cambio)
--- ORDER BY fecha DESC, tipo_cambio;
-
--- ==================================================================
--- SCRIPT DE LIMPIEZA (OPCIONAL)
--- ==================================================================
-
--- Limpiar logs antiguos (ejecutar solo si es necesario)
--- DELETE FROM productos_logs WHERE fecha_cambio < DATE_SUB(NOW(), INTERVAL 90 DAY);
-
--- Resetear AUTO_INCREMENT de la tabla logs
--- ALTER TABLE productos_logs AUTO_INCREMENT = 1;
-
--- ============================================================
--- MIGRACIÓN: Agregar columna FECHA_REGISTRO a tabla Empleados
--- ============================================================
-
--- Verificar y agregar columna FECHA_REGISTRO a la tabla Empleados si no existe
-SET @sql = (SELECT IF(
- (SELECT COUNT(*) FROM information_schema.COLUMNS
- WHERE TABLE_SCHEMA = DATABASE()
- AND TABLE_NAME = 'Empleados'
- AND COLUMN_NAME = 'FECHA_REGISTRO') = 0,
- 'ALTER TABLE Empleados ADD COLUMN FECHA_REGISTRO TIMESTAMP DEFAULT CURRENT_TIMESTAMP',
- 'SELECT "La columna FECHA_REGISTRO ya existe en la tabla Empleados" as mensaje'
-));
-
-PREPARE stmt FROM @sql;
-EXECUTE stmt;
-DEALLOCATE PREPARE stmt;
-
--- ============================================================
--- MIGRACIÓN: Agregar columna DESCRIPCION_PRODUCTO a tabla Productos
--- ============================================================
-
--- Verificar y agregar columna DESCRIPCION_PRODUCTO a la tabla Productos si no existe
-SET @sql = (SELECT IF(
- (SELECT COUNT(*) FROM information_schema.COLUMNS
- WHERE TABLE_SCHEMA = DATABASE()
- AND TABLE_NAME = 'Productos'
- AND COLUMN_NAME = 'DESCRIPCION_PRODUCTO') = 0,
- 'ALTER TABLE Productos ADD COLUMN DESCRIPCION_PRODUCTO TEXT AFTER NOMBRE_PRODUCTO',
- 'SELECT "La columna DESCRIPCION_PRODUCTO ya existe en la tabla Productos" as mensaje'
-));
-
-PREPARE stmt FROM @sql;
-EXECUTE stmt;
-DEALLOCATE PREPARE stmt;
-
--- ==================================================================
--- VERIFICACIÓN DE ESTRUCTURA FINAL
--- ==================================================================
-
--- Verificar que todas las tablas principales existen
-SELECT
- TABLE_NAME as 'Tabla_Existente'
-FROM information_schema.TABLES
-WHERE TABLE_SCHEMA = DATABASE()
-AND TABLE_NAME IN ('Productos', 'Detalle_Pedidos', 'Pedidos', 'Empleados', 'Clientes', 'Administradores')
-ORDER BY TABLE_NAME;
-
--- Verificar estructura de tabla Productos (debe incluir DESCRIPCION_PRODUCTO)
-SELECT
- COLUMN_NAME as 'Columna',
- DATA_TYPE as 'Tipo',
- IS_NULLABLE as 'Permite_NULL'
-FROM information_schema.COLUMNS
-WHERE TABLE_SCHEMA = DATABASE()
-AND TABLE_NAME = 'Productos'
-ORDER BY ORDINAL_POSITION;
-
--- Verificar estructura de tabla Detalle_Pedidos (debe tener solo columnas esenciales)
-SELECT
- COLUMN_NAME as 'Columna',
- DATA_TYPE as 'Tipo',
- IS_NULLABLE as 'Permite_NULL'
-FROM information_schema.COLUMNS
-WHERE TABLE_SCHEMA = DATABASE()
-AND TABLE_NAME = 'Detalle_Pedidos'
-ORDER BY ORDINAL_POSITION;
-
--- ==================================================================
--- FIN DE ACTUALIZACIONES DEL SISTEMA
--- ==================================================================
-
-COMMIT;
diff --git a/files/README_API_SSE.md b/files/README_API_SSE.md
deleted file mode 100644
index 617fdac..0000000
--- a/files/README_API_SSE.md
+++ /dev/null
@@ -1,205 +0,0 @@
-# Sistema de Actualización en Tiempo Real para Panadería
-
-## Resumen
-Se ha implementado un sistema completo de API REST y Server-Sent Events (SSE) para mantener sincronizados los precios y stock entre el dashboard del administrador y el menú del cliente.
-
-## Archivos Creados/Modificados
-
-### 1. Base de Datos
-- **crear_tabla_logs.sql**: Tabla para logging de cambios en productos
-- **actualizar_producto_stock_precio.php**: Actualizado para incluir logging
-
-### 2. API REST
-- **api_productos_admin.php**: API REST completa para gestión de productos
-
-### 3. Server-Sent Events
-- **sse_menu_updates.php**: Endpoint SSE para notificaciones en tiempo real
-
-### 4. JavaScript del Cliente
-- **js/menu-updater.js**: Cliente para recibir actualizaciones SSE en el menú
-- **js/admin-products.js**: Interfaz de administración de productos
-
-## Pasos de Implementación
-
-### 1. Ejecutar Script de Base de Datos
-```sql
--- Ejecutar en MySQL/phpMyAdmin
-source crear_tabla_logs.sql;
-```
-
-### 2. Incluir JavaScript en las Páginas
-
-#### En el Menú del Cliente (menu.php, dashboard_cliente.php)
-```html
-
-```
-
-#### En el Dashboard del Administrador (dashboard_admin.php)
-```html
-
-```
-
-### 3. Estructura HTML Requerida
-
-#### Para el Menú del Cliente
-```html
-
-
Nombre del Producto
-
$5000
-
Stock: 10
-
-```
-
-#### Para el Dashboard del Admin
-```html
-
-
-
-
-
-
-```
-
-## Funcionalidades Implementadas
-
-### API REST Endpoints
-
-#### GET `/api_productos_admin.php`
-- Obtener todos los productos (con paginación)
-- Obtener producto específico: `?id=1`
-- Incluir logs: `?id=1&incluir_logs=1`
-- Filtros: `?categoria=1&buscar=pan&activos_solo=1`
-
-#### POST `/api_productos_admin.php`
-- Crear nuevo producto
-```json
-{
- "nombre_producto": "Pan Baguette",
- "precio_producto": 2500,
- "stock_min": 20,
- "fecha_vencimiento": "2025-07-10",
- "tipo_producto_marca": "Artesanal",
- "id_categoria_producto": 1
-}
-```
-
-#### PATCH `/api_productos_admin.php`
-- Actualizar precio: `{"id": 1, "campo": "precio", "valor": 3000}`
-- Actualizar stock: `{"id": 1, "campo": "stock", "valor": 15}`
-- Activar/desactivar: `{"id": 1, "campo": "activo", "valor": 1}`
-
-#### PUT `/api_productos_admin.php`
-- Actualizar producto completo
-
-#### DELETE `/api_productos_admin.php`
-- Soft delete: `{"id": 1}`
-- Hard delete: `{"id": 1, "forzar": true}`
-
-### Server-Sent Events
-
-#### Conexión
-```javascript
-// Automática al cargar la página
-// Manual:
-const updater = new MenuUpdater({
- onMenuUpdate: function(data) {
- console.log('Actualización recibida:', data);
- }
-});
-```
-
-#### Eventos Recibidos
-- `connected`: Conexión establecida
-- `menu_update`: Cambios en productos detectados
-- `heartbeat`: Verificación de conexión (cada 30s)
-- `disconnected`: Conexión cerrada
-- `error`: Error en el servidor
-
-## Configuración del Servidor
-
-### Requisitos
-- PHP 7.4+
-- MySQL 5.7+
-- Extensiones: mysqli, json
-
-### Configuración Recomendada
-```ini
-; php.ini
-max_execution_time = 300
-memory_limit = 256M
-```
-
-### Apache/Nginx
-Asegurar que SSE no sea bloqueado por proxy/cache:
-```apache
-# .htaccess
-
- Header always set Cache-Control "no-cache, no-store, must-revalidate"
- Header always set Pragma "no-cache"
- Header always set Expires "0"
-
-```
-
-## Seguridad
-
-### Validaciones Implementadas
-- Verificación de sesión de administrador
-- Validación de tipos de datos
-- Sanitización de entradas
-- Logging de cambios con IP y usuario
-
-### Headers de Seguridad
-```php
-header('Content-Type: application/json');
-header('X-Content-Type-Options: nosniff');
-header('X-Frame-Options: DENY');
-```
-
-## Monitoreo y Logs
-
-### Tabla productos_logs
-- Registra todos los cambios en productos
-- Incluye IP del usuario y timestamp
-- Tipos: precio, stock, activacion, desactivacion
-
-### Consultas Útiles
-```sql
--- Ver cambios recientes
-SELECT * FROM productos_logs
-ORDER BY fecha_cambio DESC
-LIMIT 50;
-
--- Cambios por producto
-SELECT pl.*, p.NOMBRE_PRODUCTO
-FROM productos_logs pl
-JOIN Productos p ON pl.producto_id = p.ID_PRODUCTO
-WHERE pl.producto_id = 1;
-```
-
-## Resolución de Problemas
-
-### SSE No Funciona
-1. Verificar que el navegador soporte EventSource
-2. Revisar configuración de proxy/firewall
-3. Comprobar logs de PHP por errores
-4. Verificar permisos de archivo
-
-### API No Responde
-1. Verificar sesión de administrador
-2. Comprobar conexión a base de datos
-3. Revisar logs de errores de PHP
-4. Validar formato JSON de las peticiones
-
-### Actualizations No Se Ven
-1. Verificar estructura HTML (data-producto-id)
-2. Comprobar consola del navegador por errores
-3. Verificar que el trigger de base de datos esté activo
-4. Comprobar que FECHA_ULTIMA_MODIFICACION se actualice
-
-## Próximas Mejoras
-
-1. **Websockets**: Para comunicación bidireccional
-2. **Push Notifications**: Para notificaciones móviles
-3. **Cache Redis**: Para mejor rendimiento
-4. **Métricas**: Dashboard de analytics de cambios
-5. **Backup Automático**: Antes de cambios críticos
diff --git a/files/SOLUCION_ERROR_FECHA_REGISTRO.md b/files/SOLUCION_ERROR_FECHA_REGISTRO.md
deleted file mode 100644
index e69de29..0000000
diff --git a/files/actualizar_ingrediente_ajax.php b/files/actualizar_ingrediente_ajax.php
deleted file mode 100644
index eac9c63..0000000
--- a/files/actualizar_ingrediente_ajax.php
+++ /dev/null
@@ -1,134 +0,0 @@
- false,
- 'error' => 'No autorizado'
- ]);
- exit();
-}
-
-require_once 'conexion.php';
-
-try {
- // Verificar método de petición
- if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
- throw new Exception("Método no permitido");
- }
-
- // Verificar conexión
- if (!$conexion) {
- throw new Exception("No se pudo conectar a la base de datos");
- }
-
- // Obtener datos JSON
- $input = json_decode(file_get_contents('php://input'), true);
-
- if (!$input) {
- throw new Exception("Datos JSON inválidos");
- }
-
- // Validar datos requeridos
- if (!isset($input['id']) || !isset($input['campo']) || !isset($input['valor'])) {
- throw new Exception("Faltan datos requeridos: id, campo, valor");
- }
-
- $ingrediente_id = intval($input['id']);
- $campo = trim($input['campo']);
- $valor = trim($input['valor']);
-
- // Validar ID del ingrediente
- if ($ingrediente_id <= 0) {
- throw new Exception("ID de ingrediente inválido");
- }
-
- // Validar que el ingrediente existe
- $stmt_check = $conexion->prepare("SELECT ID_INGREDIENTE, NOMBRE_INGREDIENTE FROM Ingredientes WHERE ID_INGREDIENTE = ?");
- $stmt_check->bind_param("i", $ingrediente_id);
- $stmt_check->execute();
- $result_check = $stmt_check->get_result();
-
- if ($result_check->num_rows === 0) {
- throw new Exception("Ingrediente no encontrado");
- }
-
- $ingrediente_info = $result_check->fetch_assoc();
-
- // Validar y procesar según el campo a actualizar
- switch ($campo) {
- case 'stock':
- case 'cantidad':
- $nuevo_stock = intval($valor);
- if ($nuevo_stock < 0) {
- throw new Exception("El stock no puede ser negativo");
- }
-
- $sql = "UPDATE Ingredientes SET CANTIDAD_INGREDIENTE = ? WHERE ID_INGREDIENTE = ?";
- $stmt = $conexion->prepare($sql);
- $stmt->bind_param("ii", $nuevo_stock, $ingrediente_id);
-
- $mensaje_exito = "Stock del ingrediente '{$ingrediente_info['NOMBRE_INGREDIENTE']}' actualizado a {$nuevo_stock}";
- break;
-
- case 'precio':
- case 'precio_compra':
- $nuevo_precio = floatval($valor);
- if ($nuevo_precio < 0) {
- throw new Exception("El precio no puede ser negativo");
- }
-
- $sql = "UPDATE Ingredientes SET PRECIO_COMPRA = ? WHERE ID_INGREDIENTE = ?";
- $stmt = $conexion->prepare($sql);
- $stmt->bind_param("di", $nuevo_precio, $ingrediente_id);
-
- $mensaje_exito = "Precio de compra del ingrediente '{$ingrediente_info['NOMBRE_INGREDIENTE']}' actualizado a $" . number_format($nuevo_precio, 2);
- break;
-
- default:
- throw new Exception("Campo no válido para actualización: {$campo}");
- }
-
- // Ejecutar la actualización
- if (!$stmt->execute()) {
- throw new Exception("Error al actualizar: " . $stmt->error);
- }
-
- if ($stmt->affected_rows === 0) {
- throw new Exception("No se realizaron cambios. Verifique que el valor sea diferente al actual.");
- }
-
- // Registrar en logs (opcional - se puede implementar después)
- // log_cambio_ingrediente($ingrediente_id, $campo, $valor_anterior, $valor, $_SESSION['usuario_id']);
-
- // Respuesta exitosa
- echo json_encode([
- 'success' => true,
- 'mensaje' => $mensaje_exito,
- 'ingrediente_id' => $ingrediente_id,
- 'campo_actualizado' => $campo,
- 'nuevo_valor' => $valor
- ]);
-
-} catch (Exception $e) {
- error_log("Error en actualizar_ingrediente_ajax.php: " . $e->getMessage());
-
- http_response_code(400);
- echo json_encode([
- 'success' => false,
- 'error' => $e->getMessage()
- ]);
-}
-?>
diff --git a/files/actualizar_producto_stock_precio.php b/files/actualizar_producto_stock_precio.php
deleted file mode 100644
index 9b0a05b..0000000
--- a/files/actualizar_producto_stock_precio.php
+++ /dev/null
@@ -1,166 +0,0 @@
- false, 'message' => 'No autorizado']);
- exit();
-}
-
-require_once 'conexion.php';
-
-// Función para registrar cambios en el log
-function registrarCambio($conexion, $producto_id, $tipo_cambio, $valor_anterior, $valor_nuevo, $usuario_id, $ip_usuario) {
- $stmt = $conexion->prepare("INSERT INTO productos_logs (producto_id, tipo_cambio, valor_anterior, valor_nuevo, usuario_id, usuario_tipo, ip_usuario) VALUES (?, ?, ?, ?, ?, 'admin', ?)");
- $stmt->bind_param("isssss", $producto_id, $tipo_cambio, $valor_anterior, $valor_nuevo, $usuario_id, $ip_usuario);
- $stmt->execute();
-}
-
-// Verificar que sea una petición POST
-if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
- header('Content-Type: application/json');
- echo json_encode(['success' => false, 'message' => 'Método no permitido']);
- exit();
-}
-
-// Obtener los datos del POST
-$producto_id = intval($_POST['producto_id'] ?? 0);
-$accion = $_POST['accion'] ?? '';
-$nuevo_valor = $_POST['nuevo_valor'] ?? '';
-
-// Obtener información del usuario y IP
-$usuario_id = $_SESSION['usuario_id'] ?? 0;
-$ip_usuario = $_SERVER['REMOTE_ADDR'] ?? 'unknown';
-
-// Validar datos
-if ($producto_id <= 0 || empty($accion)) {
- header('Content-Type: application/json');
- echo json_encode(['success' => false, 'message' => 'Datos incompletos']);
- exit();
-}
-
-try {
- // Verificar que el producto existe
- $stmt = $conexion->prepare("SELECT ID_PRODUCTO, NOMBRE_PRODUCTO, PRECIO_PRODUCTO, PRODUCTO_STOCK_MIN FROM Productos WHERE ID_PRODUCTO = ?");
- $stmt->bind_param("i", $producto_id);
- $stmt->execute();
- $producto = $stmt->get_result()->fetch_assoc();
-
- if (!$producto) {
- header('Content-Type: application/json');
- echo json_encode(['success' => false, 'message' => 'Producto no encontrado']);
- exit();
- }
-
- $response = ['success' => false, 'message' => ''];
-
- switch ($accion) {
- case 'actualizar_precio':
- $nuevo_precio = floatval($nuevo_valor);
- if ($nuevo_precio <= 0) {
- $response['message'] = 'El precio debe ser mayor a 0';
- break;
- }
-
- $stmt = $conexion->prepare("UPDATE Productos SET PRECIO_PRODUCTO = ? WHERE ID_PRODUCTO = ?");
- $stmt->bind_param("di", $nuevo_precio, $producto_id);
-
- if ($stmt->execute()) {
- // Registrar el cambio en el log
- registrarCambio($conexion, $producto_id, 'precio', $producto['PRECIO_PRODUCTO'], $nuevo_precio, $usuario_id, $ip_usuario);
-
- $response['success'] = true;
- $response['message'] = 'Precio actualizado correctamente';
- $response['nuevo_precio'] = $nuevo_precio;
- } else {
- $response['message'] = 'Error al actualizar el precio';
- }
- break;
-
- case 'actualizar_stock':
- $nuevo_stock = intval($nuevo_valor);
- if ($nuevo_stock < 0) {
- $response['message'] = 'El stock no puede ser negativo';
- break;
- }
-
- $stmt = $conexion->prepare("UPDATE Productos SET PRODUCTO_STOCK_MIN = ? WHERE ID_PRODUCTO = ?");
- $stmt->bind_param("ii", $nuevo_stock, $producto_id);
-
- if ($stmt->execute()) {
- // Registrar el cambio en el log
- registrarCambio($conexion, $producto_id, 'stock', $producto['PRODUCTO_STOCK_MIN'], $nuevo_stock, $usuario_id, $ip_usuario);
-
- $response['success'] = true;
- $response['message'] = 'Stock actualizado correctamente';
- $response['nuevo_stock'] = $nuevo_stock;
- } else {
- $response['message'] = 'Error al actualizar el stock';
- }
- break;
-
- case 'incrementar_stock':
- $incremento = intval($nuevo_valor);
- if ($incremento <= 0) {
- $response['message'] = 'El incremento debe ser mayor a 0';
- break;
- }
-
- $nuevo_stock = $producto['PRODUCTO_STOCK_MIN'] + $incremento;
- $stmt = $conexion->prepare("UPDATE Productos SET PRODUCTO_STOCK_MIN = ? WHERE ID_PRODUCTO = ?");
- $stmt->bind_param("ii", $nuevo_stock, $producto_id);
-
- if ($stmt->execute()) {
- // Registrar el cambio en el log
- registrarCambio($conexion, $producto_id, 'stock', $producto['PRODUCTO_STOCK_MIN'], $nuevo_stock, $usuario_id, $ip_usuario);
-
- $response['success'] = true;
- $response['message'] = "Stock incrementado en $incremento unidades";
- $response['nuevo_stock'] = $nuevo_stock;
- } else {
- $response['message'] = 'Error al incrementar el stock';
- }
- break;
-
- case 'decrementar_stock':
- $decremento = intval($nuevo_valor);
- if ($decremento <= 0) {
- $response['message'] = 'El decremento debe ser mayor a 0';
- break;
- }
-
- $nuevo_stock = $producto['PRODUCTO_STOCK_MIN'] - $decremento;
- if ($nuevo_stock < 0) {
- $response['message'] = 'El stock no puede ser negativo';
- break;
- }
-
- $stmt = $conexion->prepare("UPDATE Productos SET PRODUCTO_STOCK_MIN = ? WHERE ID_PRODUCTO = ?");
- $stmt->bind_param("ii", $nuevo_stock, $producto_id);
-
- if ($stmt->execute()) {
- // Registrar el cambio en el log
- registrarCambio($conexion, $producto_id, 'stock', $producto['PRODUCTO_STOCK_MIN'], $nuevo_stock, $usuario_id, $ip_usuario);
-
- $response['success'] = true;
- $response['message'] = "Stock decrementado en $decremento unidades";
- $response['nuevo_stock'] = $nuevo_stock;
- } else {
- $response['message'] = 'Error al decrementar el stock';
- }
- break;
-
- default:
- $response['message'] = 'Acción no válida';
- break;
- }
-
- header('Content-Type: application/json');
- echo json_encode($response);
-
-} catch (Exception $e) {
- header('Content-Type: application/json');
- echo json_encode(['success' => false, 'message' => 'Error del servidor: ' . $e->getMessage()]);
-}
-?>
diff --git a/files/actualizar_tabla_empleados.php b/files/actualizar_tabla_empleados.php
deleted file mode 100644
index 6d9d4b3..0000000
--- a/files/actualizar_tabla_empleados.php
+++ /dev/null
@@ -1,133 +0,0 @@
-🔧 Verificación y Actualización de Tabla Empleados";
-
-// Verificar conexión
-if ($conexion->connect_error) {
- echo "❌ Error de conexión: " . $conexion->connect_error . "
";
- exit();
-}
-
-echo "✅ Conexión exitosa a la base de datos
";
-
-try {
- // Verificar estructura actual
- $query = "DESCRIBE Empleados";
- $result = $conexion->query($query);
-
- $campos_existentes = [];
- echo "📋 Estructura actual de la tabla Empleados:
";
- echo "";
- echo "| Campo | Tipo | Null | Key | Default | Extra |
";
-
- while ($row = $result->fetch_assoc()) {
- $campos_existentes[] = $row['Field'];
- echo "";
- echo "| " . $row['Field'] . " | ";
- echo "" . $row['Type'] . " | ";
- echo "" . $row['Null'] . " | ";
- echo "" . $row['Key'] . " | ";
- echo "" . $row['Default'] . " | ";
- echo "" . $row['Extra'] . " | ";
- echo "
";
- }
- echo "
";
-
- // Verificar si existen los campos necesarios
- $campos_requeridos = ['EMAIL_EMPLEADO', 'CONTRASEÑA_EMPLEADO', 'SALT_EMPLEADO'];
- $campos_faltantes = [];
-
- foreach ($campos_requeridos as $campo) {
- if (!in_array($campo, $campos_existentes)) {
- $campos_faltantes[] = $campo;
- }
- }
-
- if (empty($campos_faltantes)) {
- echo "✅ Todos los campos requeridos están presentes
";
- } else {
- echo "⚠️ Campos faltantes encontrados:
";
- echo "";
- foreach ($campos_faltantes as $campo) {
- echo "- $campo
";
- }
- echo "
";
-
- echo "🔨 Agregando campos faltantes...
";
-
- // Agregar campos faltantes
- if (in_array('EMAIL_EMPLEADO', $campos_faltantes)) {
- $alter_query = "ALTER TABLE Empleados ADD COLUMN EMAIL_EMPLEADO VARCHAR(100) UNIQUE";
- if ($conexion->query($alter_query)) {
- echo "✅ Campo EMAIL_EMPLEADO agregado exitosamente
";
- } else {
- echo "❌ Error al agregar EMAIL_EMPLEADO: " . $conexion->error . "
";
- }
- }
-
- if (in_array('CONTRASEÑA_EMPLEADO', $campos_faltantes)) {
- $alter_query = "ALTER TABLE Empleados ADD COLUMN CONTRASEÑA_EMPLEADO VARCHAR(255)";
- if ($conexion->query($alter_query)) {
- echo "✅ Campo CONTRASEÑA_EMPLEADO agregado exitosamente
";
- } else {
- echo "❌ Error al agregar CONTRASEÑA_EMPLEADO: " . $conexion->error . "
";
- }
- }
-
- if (in_array('SALT_EMPLEADO', $campos_faltantes)) {
- $alter_query = "ALTER TABLE Empleados ADD COLUMN SALT_EMPLEADO VARCHAR(32)";
- if ($conexion->query($alter_query)) {
- echo "✅ Campo SALT_EMPLEADO agregado exitosamente
";
- } else {
- echo "❌ Error al agregar SALT_EMPLEADO: " . $conexion->error . "
";
- }
- }
-
- // Agregar campo FECHA_REGISTRO si no existe
- if (!in_array('FECHA_REGISTRO', $campos_existentes)) {
- $alter_query = "ALTER TABLE Empleados ADD COLUMN FECHA_REGISTRO TIMESTAMP DEFAULT CURRENT_TIMESTAMP";
- if ($conexion->query($alter_query)) {
- echo "✅ Campo FECHA_REGISTRO agregado exitosamente
";
- } else {
- echo "❌ Error al agregar FECHA_REGISTRO: " . $conexion->error . "
";
- }
- }
-
- echo "📋 Estructura actualizada:
";
- $query = "DESCRIBE Empleados";
- $result = $conexion->query($query);
-
- echo "";
- echo "| Campo | Tipo | Null | Key | Default | Extra |
";
-
- while ($row = $result->fetch_assoc()) {
- echo "";
- echo "| " . $row['Field'] . " | ";
- echo "" . $row['Type'] . " | ";
- echo "" . $row['Null'] . " | ";
- echo "" . $row['Key'] . " | ";
- echo "" . $row['Default'] . " | ";
- echo "" . $row['Extra'] . " | ";
- echo "
";
- }
- echo "
";
- }
-
-} catch (Exception $e) {
- echo "❌ Error: " . $e->getMessage() . "
";
-}
-
-$conexion->close();
-
-echo "
";
-echo "💡 Información:
";
-echo "";
-echo "- EMAIL_EMPLEADO: Campo único para el email del empleado
";
-echo "- CONTRASEÑA_EMPLEADO: Campo para almacenar la contraseña hasheada con SHA256
";
-echo "- SALT_EMPLEADO: Campo para almacenar el salt usado en el hash
";
-echo "- FECHA_REGISTRO: Campo para registrar cuándo se agregó el empleado
";
-echo "- Sistema de hash: SHA256 + Salt (compatible con el sistema existente)
";
-echo "
";
-?>
diff --git a/files/agregar_empleado_ajax.php b/files/agregar_empleado_ajax.php
deleted file mode 100644
index 85fad52..0000000
--- a/files/agregar_empleado_ajax.php
+++ /dev/null
@@ -1,127 +0,0 @@
- false, 'mensaje' => 'Acceso no autorizado']);
- exit();
-}
-
-// Headers de respuesta JSON
-header('Content-Type: application/json');
-
-// Verificar método POST
-if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
- echo json_encode(['success' => false, 'mensaje' => 'Método no permitido']);
- exit();
-}
-
-// Incluir conexión a la base de datos
-require_once 'conexion.php';
-
-try {
- // Verificar conexión
- if (!$conexion) {
- throw new Exception('Error de conexión a la base de datos');
- }
-
- // Obtener y validar datos del formulario
- $nombre = trim($_POST['nombre'] ?? '');
- $email = trim($_POST['email'] ?? '');
- $password = trim($_POST['password'] ?? '');
-
- // Validaciones
- if (empty($nombre)) {
- throw new Exception('El nombre es requerido');
- }
-
- if (empty($email)) {
- throw new Exception('El email es requerido');
- }
-
- if (empty($password)) {
- throw new Exception('La contraseña es requerida');
- }
-
- if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
- throw new Exception('El email no tiene un formato válido');
- }
-
- if (strlen($password) < 6) {
- throw new Exception('La contraseña debe tener al menos 6 caracteres');
- }
-
- // Verificar si el email ya existe
- $consulta_verificar = "SELECT ID_EMPLEADO FROM Empleados WHERE EMAIL_EMPLEADO = ? OR NOMBRE_EMPLEADO = ?";
- $stmt_verificar = $conexion->prepare($consulta_verificar);
-
- if (!$stmt_verificar) {
- throw new Exception('Error al preparar la consulta de verificación: ' . $conexion->error);
- }
-
- $stmt_verificar->bind_param('ss', $email, $nombre);
- $stmt_verificar->execute();
- $resultado_verificar = $stmt_verificar->get_result();
-
- if ($resultado_verificar->num_rows > 0) {
- throw new Exception('Ya existe un empleado con este email o nombre');
- }
-
- $stmt_verificar->close();
-
- // Generar salt y hashear la contraseña (compatible con el sistema existente)
- $salt = bin2hex(random_bytes(16)); // Generar salt aleatorio
- $password_hash = hash('sha256', $password . $salt);
-
- // Verificar si la columna FECHA_REGISTRO existe en la tabla
- $check_column = "SHOW COLUMNS FROM Empleados LIKE 'FECHA_REGISTRO'";
- $column_result = $conexion->query($check_column);
- $fecha_registro_exists = ($column_result && $column_result->num_rows > 0);
-
- // Insertar el nuevo empleado (con o sin FECHA_REGISTRO dependiendo de si existe)
- if ($fecha_registro_exists) {
- $consulta_insertar = "INSERT INTO Empleados (NOMBRE_EMPLEADO, EMAIL_EMPLEADO, CONTRASEÑA_EMPLEADO, SALT_EMPLEADO, ACTIVO_EMPLEADO, FECHA_REGISTRO)
- VALUES (?, ?, ?, ?, 1, NOW())";
- } else {
- $consulta_insertar = "INSERT INTO Empleados (NOMBRE_EMPLEADO, EMAIL_EMPLEADO, CONTRASEÑA_EMPLEADO, SALT_EMPLEADO, ACTIVO_EMPLEADO)
- VALUES (?, ?, ?, ?, 1)";
- }
-
- $stmt_insertar = $conexion->prepare($consulta_insertar);
-
- if (!$stmt_insertar) {
- throw new Exception('Error al preparar la consulta de inserción: ' . $conexion->error);
- }
-
- $stmt_insertar->bind_param('ssss', $nombre, $email, $password_hash, $salt);
-
- if ($stmt_insertar->execute()) {
- $nuevo_id = $conexion->insert_id;
-
- echo json_encode([
- 'success' => true,
- 'mensaje' => 'Empleado agregado exitosamente',
- 'empleado' => [
- 'id' => $nuevo_id,
- 'nombre' => htmlspecialchars($nombre),
- 'email' => htmlspecialchars($email)
- ]
- ]);
- } else {
- throw new Exception('Error al insertar el empleado: ' . $stmt_insertar->error);
- }
-
- $stmt_insertar->close();
-
-} catch (Exception $e) {
- echo json_encode([
- 'success' => false,
- 'mensaje' => $e->getMessage()
- ]);
-}
-
-// Cerrar conexión
-if (isset($conexion)) {
- $conexion->close();
-}
-?>
diff --git a/files/agregar_empleado_ajax_pdo.php b/files/agregar_empleado_ajax_pdo.php
deleted file mode 100644
index a078cda..0000000
--- a/files/agregar_empleado_ajax_pdo.php
+++ /dev/null
@@ -1,119 +0,0 @@
- false, 'mensaje' => 'Acceso no autorizado']);
- exit();
-}
-
-// Headers de respuesta JSON
-header('Content-Type: application/json');
-
-// Verificar método POST
-if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
- echo json_encode(['success' => false, 'mensaje' => 'Método no permitido']);
- exit();
-}
-
-try {
- // Conexión PDO (igual que en el login)
- $dsn = "mysql:host=localhost;dbname=proyectopanaderia;charset=utf8";
- $username = "root";
- $password = "";
-
- $pdo_conexion = new PDO($dsn, $username, $password);
- $pdo_conexion->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
-
- // Obtener y validar datos del formulario
- $nombre = trim($_POST['nombre'] ?? '');
- $email = trim($_POST['email'] ?? '');
- $password_input = trim($_POST['password'] ?? '');
-
- // Validaciones
- if (empty($nombre)) {
- throw new Exception('El nombre es requerido');
- }
-
- if (empty($email)) {
- throw new Exception('El email es requerido');
- }
-
- if (empty($password_input)) {
- throw new Exception('La contraseña es requerida');
- }
-
- if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
- throw new Exception('El email no tiene un formato válido');
- }
-
- if (strlen($password_input) < 6) {
- throw new Exception('La contraseña debe tener al menos 6 caracteres');
- }
-
- // Verificar si el email o nombre ya existe
- $consulta_verificar = "SELECT ID_EMPLEADO FROM Empleados WHERE EMAIL_EMPLEADO = :email OR NOMBRE_EMPLEADO = :nombre";
- $stmt_verificar = $pdo_conexion->prepare($consulta_verificar);
- $stmt_verificar->bindParam(':email', $email, PDO::PARAM_STR);
- $stmt_verificar->bindParam(':nombre', $nombre, PDO::PARAM_STR);
- $stmt_verificar->execute();
-
- if ($stmt_verificar->rowCount() > 0) {
- throw new Exception('Ya existe un empleado con este email o nombre');
- }
-
- // Generar salt y hashear la contraseña (exactamente como en el sistema existente)
- $salt = bin2hex(random_bytes(16));
- $password_hash = hash('sha256', $password_input . $salt);
-
- // Insertar el nuevo empleado
- $consulta_insertar = "INSERT INTO Empleados (NOMBRE_EMPLEADO, EMAIL_EMPLEADO, CONTRASEÑA_EMPLEADO, SALT_EMPLEADO, ACTIVO_EMPLEADO, FECHA_REGISTRO)
- VALUES (:nombre, :email, :password_hash, :salt, 1, NOW())";
-
- $stmt_insertar = $pdo_conexion->prepare($consulta_insertar);
- $stmt_insertar->bindParam(':nombre', $nombre, PDO::PARAM_STR);
- $stmt_insertar->bindParam(':email', $email, PDO::PARAM_STR);
- $stmt_insertar->bindParam(':password_hash', $password_hash, PDO::PARAM_STR);
- $stmt_insertar->bindParam(':salt', $salt, PDO::PARAM_STR);
-
- if ($stmt_insertar->execute()) {
- $nuevo_id = $pdo_conexion->lastInsertId();
-
- // Verificar inmediatamente el login
- $consulta_verificar_login = "SELECT ID_EMPLEADO, NOMBRE_EMPLEADO, CONTRASEÑA_EMPLEADO, SALT_EMPLEADO, ACTIVO_EMPLEADO, EMAIL_EMPLEADO
- FROM Empleados
- WHERE (NOMBRE_EMPLEADO = :usuario OR EMAIL_EMPLEADO = :usuario) AND ACTIVO_EMPLEADO = 1";
-
- $stmt_verificar_login = $pdo_conexion->prepare($consulta_verificar_login);
- $stmt_verificar_login->bindParam(':usuario', $email, PDO::PARAM_STR);
- $stmt_verificar_login->execute();
-
- $user_data = $stmt_verificar_login->fetch(PDO::FETCH_ASSOC);
-
- $login_test = false;
- if ($user_data) {
- $hash_verificacion = hash('sha256', $password_input . $user_data['SALT_EMPLEADO']);
- $login_test = ($hash_verificacion === $user_data['CONTRASEÑA_EMPLEADO']);
- }
-
- echo json_encode([
- 'success' => true,
- 'mensaje' => 'Empleado agregado exitosamente',
- 'empleado' => [
- 'id' => $nuevo_id,
- 'nombre' => htmlspecialchars($nombre),
- 'email' => htmlspecialchars($email)
- ],
- 'login_test' => $login_test ? 'Login funcionará correctamente' : 'ADVERTENCIA: Puede haber problema con el login'
- ]);
- } else {
- throw new Exception('Error al insertar el empleado');
- }
-
-} catch (Exception $e) {
- echo json_encode([
- 'success' => false,
- 'mensaje' => $e->getMessage()
- ]);
-}
-?>
diff --git a/files/agregar_ingrediente_ajax.php b/files/agregar_ingrediente_ajax.php
deleted file mode 100644
index 8245552..0000000
--- a/files/agregar_ingrediente_ajax.php
+++ /dev/null
@@ -1,152 +0,0 @@
- false,
- 'error' => 'No autorizado'
- ]);
- exit();
-}
-
-require_once 'conexion.php';
-
-try {
- // Validar que se recibieron los datos por POST
- if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
- throw new Exception('Método no permitido');
- }
-
- // Obtener y validar datos
- $nombre = trim($_POST['nombre'] ?? '');
- $cantidad = intval($_POST['cantidad'] ?? 0);
- $precio_compra = floatval($_POST['precio_compra'] ?? 0);
- $categoria = intval($_POST['categoria'] ?? 0);
- $proveedor = intval($_POST['proveedor'] ?? 0);
- $fecha_vencimiento = $_POST['fecha_vencimiento'] ?? '';
- $fecha_entrega = $_POST['fecha_entrega'] ?? '';
- $referencia = trim($_POST['referencia'] ?? '');
-
- // Validaciones
- if (empty($nombre)) {
- throw new Exception('El nombre del ingrediente es obligatorio');
- }
-
- if ($cantidad < 0) {
- throw new Exception('La cantidad no puede ser negativa');
- }
-
- if ($precio_compra < 0) {
- throw new Exception('El precio de compra no puede ser negativo');
- }
-
- if ($categoria <= 0) {
- throw new Exception('Debe seleccionar una categoría');
- }
-
- // El proveedor es opcional
- if ($proveedor <= 0) {
- $proveedor = null;
- }
-
- if (empty($fecha_vencimiento)) {
- throw new Exception('La fecha de vencimiento es obligatoria');
- }
-
- if (empty($fecha_entrega)) {
- throw new Exception('La fecha de entrega es obligatoria');
- }
-
- if (empty($referencia)) {
- throw new Exception('La referencia es obligatoria');
- }
-
- // Validar formato de fechas
- $fecha_venc_obj = DateTime::createFromFormat('Y-m-d', $fecha_vencimiento);
- $fecha_ent_obj = DateTime::createFromFormat('Y-m-d', $fecha_entrega);
-
- if (!$fecha_venc_obj || !$fecha_ent_obj) {
- throw new Exception('Formato de fecha inválido');
- }
-
- // Validar que la fecha de vencimiento sea futura
- $hoy = new DateTime();
- if ($fecha_venc_obj <= $hoy) {
- throw new Exception('La fecha de vencimiento debe ser futura');
- }
-
- // Verificar que la categoría existe
- $stmt = $conexion->prepare("SELECT ID_CATEGORIA FROM Categoria_Ingredientes WHERE ID_CATEGORIA = ?");
- $stmt->bind_param("i", $categoria);
- $stmt->execute();
- if ($stmt->get_result()->num_rows === 0) {
- throw new Exception('La categoría seleccionada no existe');
- }
-
- // Verificar que el proveedor existe y está activo (solo si se especificó)
- if ($proveedor !== null) {
- $stmt = $conexion->prepare("SELECT ID_PROVEEDOR FROM Proveedores WHERE ID_PROVEEDOR = ? AND ACTIVO_PROV = 1");
- $stmt->bind_param("i", $proveedor);
- $stmt->execute();
- if ($stmt->get_result()->num_rows === 0) {
- throw new Exception('El proveedor seleccionado no existe o no está activo');
- }
- }
-
- // Insertar el ingrediente
- $stmt = $conexion->prepare("INSERT INTO Ingredientes (
- ID_PROVEEDOR,
- ID_CATEGORIA,
- NOMBRE_INGREDIENTE,
- CANTIDAD_INGREDIENTE,
- PRECIO_COMPRA,
- FECHA_VENCIMIENTO,
- REFERENCIA_INGREDIENTE,
- FECHA_ENTREGA_INGREDIENTE
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
-
- $stmt->bind_param("iisidsss",
- $proveedor,
- $categoria,
- $nombre,
- $cantidad,
- $precio_compra,
- $cantidad,
- $fecha_vencimiento,
- $referencia,
- $fecha_entrega
- );
-
- if ($stmt->execute()) {
- $id_ingrediente = $conexion->insert_id;
-
- echo json_encode([
- 'success' => true,
- 'mensaje' => 'Ingrediente agregado exitosamente',
- 'id' => $id_ingrediente
- ]);
- } else {
- throw new Exception('Error al insertar el ingrediente: ' . $stmt->error);
- }
-
-} catch (Exception $e) {
- echo json_encode([
- 'success' => false,
- 'mensaje' => $e->getMessage()
- ]);
-}
-
-$conexion->close();
-?>
diff --git a/files/agregar_producto.php b/files/agregar_producto.php
deleted file mode 100644
index 6e40763..0000000
--- a/files/agregar_producto.php
+++ /dev/null
@@ -1,238 +0,0 @@
-prepare($consulta);
-
- // Vincular parámetros
- $stmt->bindParam(':nombre_producto', $nombre_producto, PDO::PARAM_STR);
- $stmt->bindParam(':stock_min', $stock_min, PDO::PARAM_INT);
- $stmt->bindParam(':precio_producto', $precio_producto, PDO::PARAM_STR);
- $stmt->bindParam(':fecha_vencimiento', $fecha_vencimiento, PDO::PARAM_STR);
- $stmt->bindParam(':fecha_ingreso', date('Y-m-d'), PDO::PARAM_STR);
- $stmt->bindParam(':tipo_producto_marca', $tipo_producto_marca, PDO::PARAM_STR);
-
- // Ejecutar la consulta
- if ($stmt->execute()) {
- $id_producto_creado = $pdo_conexion->lastInsertId();
- $mensaje = "¡Producto agregado exitosamente! ID del producto: {$id_producto_creado}";
- $tipo_mensaje = "success";
- } else {
- $mensaje = "Error: No se pudo agregar el producto.";
- $tipo_mensaje = "error";
- }
-
- } catch (PDOException $e) {
- $mensaje = "Error en la base de datos: " . $e->getMessage();
- $tipo_mensaje = "error";
- }
- } else {
- // Hay errores de validación
- $mensaje = "Errores encontrados:
• " . implode("
• ", $errores);
- $tipo_mensaje = "error";
- }
-} else {
- // Si se accede directamente sin POST, redirigir
- header("Location: productostabla.php");
- exit();
-}
-?>
-
-
-
-
-
-
- Agregar Producto - Panadería
-
-
-
-
-
-
✓
-
¡Producto Agregado Exitosamente!
-
-
-
-
-
-
-
Detalles del Producto Agregado:
-
Nombre:
-
Precio: $
-
Stock Mínimo:
-
Marca/Tipo:
-
Fecha de Vencimiento:
-
Fecha de Ingreso:
-
-
-
-
✗
-
Error al Agregar Producto
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ⏱️ Por favor, lea la información mostrada arriba antes de continuar.
- Los botones se activarán en 5 segundos.
-
-
-
-
-
-
diff --git a/files/agregar_producto_ajax.php b/files/agregar_producto_ajax.php
deleted file mode 100644
index 5cd6b17..0000000
--- a/files/agregar_producto_ajax.php
+++ /dev/null
@@ -1,99 +0,0 @@
-prepare($sql);
-
- if (!$stmt) {
- throw new Exception('Error en la preparación de la consulta: ' . $conexion->error);
- }
-
- $fecha_ingreso = date('Y-m-d');
- $stmt->bind_param('sidsss', $nombre, $stock, $precio, $fecha_vencimiento, $fecha_ingreso, $categoria);
-
- if ($stmt->execute()) {
- // Obtener el ID del producto recién insertado
- $producto_id = $conexion->insert_id;
-
- echo json_encode([
- 'success' => true,
- 'mensaje' => 'Producto agregado exitosamente',
- 'detalles' => [
- 'id' => $producto_id,
- 'nombre' => htmlspecialchars($nombre),
- 'precio' => number_format($precio, 2),
- 'stock' => $stock,
- 'categoria' => htmlspecialchars($categoria),
- 'fecha_vencimiento' => date('d/m/Y', strtotime($fecha_vencimiento)),
- 'fecha_ingreso' => date('d/m/Y')
- ]
- ]);
- } else {
- throw new Exception('Error al insertar el producto: ' . $stmt->error);
- }
-
- $stmt->close();
-
- } catch (Exception $e) {
- echo json_encode([
- 'success' => false,
- 'mensaje' => $e->getMessage()
- ]);
- }
-} else {
- echo json_encode([
- 'success' => false,
- 'mensaje' => 'Método de solicitud no válido'
- ]);
-}
-
-$conexion->close();
-?>
diff --git a/files/api_productos_admin.php b/files/api_productos_admin.php
deleted file mode 100644
index 3a6ebed..0000000
--- a/files/api_productos_admin.php
+++ /dev/null
@@ -1,456 +0,0 @@
- false, 'message' => 'No autorizado']);
- exit();
-}
-
-require_once 'conexion.php';
-
-// Función para registrar cambios en el log
-function registrarCambio($conexion, $producto_id, $tipo_cambio, $valor_anterior, $valor_nuevo, $usuario_id, $ip_usuario) {
- $stmt = $conexion->prepare("INSERT INTO productos_logs (producto_id, tipo_cambio, valor_anterior, valor_nuevo, usuario_id, usuario_tipo, ip_usuario) VALUES (?, ?, ?, ?, ?, 'admin', ?)");
- $stmt->bind_param("isssss", $producto_id, $tipo_cambio, $valor_anterior, $valor_nuevo, $usuario_id, $ip_usuario);
- return $stmt->execute();
-}
-
-// Obtener información del usuario
-$usuario_id = $_SESSION['usuario_id'] ?? 0;
-$ip_usuario = $_SERVER['REMOTE_ADDR'] ?? 'unknown';
-
-// Manejar diferentes métodos HTTP
-$method = $_SERVER['REQUEST_METHOD'];
-$request_uri = $_SERVER['REQUEST_URI'];
-$path_parts = explode('/', trim(parse_url($request_uri, PHP_URL_PATH), '/'));
-
-try {
- switch ($method) {
- case 'GET':
- handleGet();
- break;
- case 'POST':
- handlePost();
- break;
- case 'PUT':
- handlePut();
- break;
- case 'PATCH':
- handlePatch();
- break;
- case 'DELETE':
- handleDelete();
- break;
- default:
- http_response_code(405);
- echo json_encode(['success' => false, 'message' => 'Método no permitido']);
- break;
- }
-} catch (Exception $e) {
- http_response_code(500);
- echo json_encode(['success' => false, 'message' => 'Error del servidor: ' . $e->getMessage()]);
-}
-
-/**
- * GET - Obtener productos o producto específico
- */
-function handleGet() {
- global $conexion;
-
- $producto_id = $_GET['id'] ?? null;
- $incluir_logs = $_GET['incluir_logs'] ?? false;
-
- if ($producto_id) {
- // Obtener producto específico
- $stmt = $conexion->prepare("
- SELECT p.*, c.NOMBRE_CATEGORIA_PRODUCTO as categoria_nombre,
- a.NOMBRE_ADMIN as admin_nombre
- FROM Productos p
- LEFT JOIN Categoria_Productos c ON p.ID_CATEGORIA_PRODUCTO = c.ID_CATEGORIA_PRODUCTO
- LEFT JOIN Administradores a ON p.ID_ADMIN = a.ID_ADMIN
- WHERE p.ID_PRODUCTO = ?
- ");
- $stmt->bind_param("i", $producto_id);
- $stmt->execute();
- $producto = $stmt->get_result()->fetch_assoc();
-
- if (!$producto) {
- http_response_code(404);
- echo json_encode(['success' => false, 'message' => 'Producto no encontrado']);
- return;
- }
-
- $response = ['success' => true, 'data' => $producto];
-
- // Incluir logs si se solicita
- if ($incluir_logs) {
- $stmt = $conexion->prepare("
- SELECT * FROM productos_logs
- WHERE producto_id = ?
- ORDER BY fecha_cambio DESC
- LIMIT 50
- ");
- $stmt->bind_param("i", $producto_id);
- $stmt->execute();
- $logs = $stmt->get_result()->fetch_all(MYSQLI_ASSOC);
- $response['logs'] = $logs;
- }
-
- echo json_encode($response);
- } else {
- // Obtener todos los productos
- $activos_solo = $_GET['activos_solo'] ?? false;
- $categoria = $_GET['categoria'] ?? null;
- $buscar = $_GET['buscar'] ?? null;
- $page = max(1, intval($_GET['page'] ?? 1));
- $limit = min(100, max(10, intval($_GET['limit'] ?? 20)));
- $offset = ($page - 1) * $limit;
-
- $where_conditions = [];
- $params = [];
- $param_types = "";
-
- if ($activos_solo) {
- $where_conditions[] = "p.ACTIVO = 1";
- }
-
- if ($categoria) {
- $where_conditions[] = "p.ID_CATEGORIA_PRODUCTO = ?";
- $params[] = $categoria;
- $param_types .= "i";
- }
-
- if ($buscar) {
- $where_conditions[] = "p.NOMBRE_PRODUCTO LIKE ?";
- $params[] = "%$buscar%";
- $param_types .= "s";
- }
-
- $where_clause = $where_conditions ? "WHERE " . implode(" AND ", $where_conditions) : "";
-
- // Contar total de productos
- $count_query = "
- SELECT COUNT(*) as total
- FROM Productos p
- LEFT JOIN Categoria_Productos c ON p.ID_CATEGORIA_PRODUCTO = c.ID_CATEGORIA_PRODUCTO
- $where_clause
- ";
-
- if ($params) {
- $stmt = $conexion->prepare($count_query);
- $stmt->bind_param($param_types, ...$params);
- $stmt->execute();
- $total = $stmt->get_result()->fetch_assoc()['total'];
- } else {
- $total = $conexion->query($count_query)->fetch_assoc()['total'];
- }
-
- // Obtener productos paginados
- $query = "
- SELECT p.*, c.NOMBRE_CATEGORIA_PRODUCTO as categoria_nombre,
- a.NOMBRE_ADMIN as admin_nombre
- FROM Productos p
- LEFT JOIN Categoria_Productos c ON p.ID_CATEGORIA_PRODUCTO = c.ID_CATEGORIA_PRODUCTO
- LEFT JOIN Administradores a ON p.ID_ADMIN = a.ID_ADMIN
- $where_clause
- ORDER BY p.FECHA_ULTIMA_MODIFICACION DESC
- LIMIT ? OFFSET ?
- ";
-
- $params[] = $limit;
- $params[] = $offset;
- $param_types .= "ii";
-
- $stmt = $conexion->prepare($query);
- if ($params) {
- $stmt->bind_param($param_types, ...$params);
- }
- $stmt->execute();
- $productos = $stmt->get_result()->fetch_all(MYSQLI_ASSOC);
-
- echo json_encode([
- 'success' => true,
- 'data' => $productos,
- 'pagination' => [
- 'page' => $page,
- 'limit' => $limit,
- 'total' => $total,
- 'pages' => ceil($total / $limit)
- ]
- ]);
- }
-}
-
-/**
- * POST - Crear nuevo producto
- */
-function handlePost() {
- global $conexion, $usuario_id, $ip_usuario;
-
- $input = json_decode(file_get_contents('php://input'), true);
-
- $required_fields = ['nombre_producto', 'precio_producto', 'stock_min', 'fecha_vencimiento', 'tipo_producto_marca', 'id_categoria_producto'];
-
- foreach ($required_fields as $field) {
- if (!isset($input[$field]) || empty($input[$field])) {
- http_response_code(400);
- echo json_encode(['success' => false, 'message' => "Campo requerido: $field"]);
- return;
- }
- }
-
- // Validaciones
- if (floatval($input['precio_producto']) <= 0) {
- http_response_code(400);
- echo json_encode(['success' => false, 'message' => 'El precio debe ser mayor a 0']);
- return;
- }
-
- if (intval($input['stock_min']) < 0) {
- http_response_code(400);
- echo json_encode(['success' => false, 'message' => 'El stock no puede ser negativo']);
- return;
- }
-
- $stmt = $conexion->prepare("
- INSERT INTO Productos (
- ID_ADMIN, ID_CATEGORIA_PRODUCTO, NOMBRE_PRODUCTO,
- PRODUCTO_STOCK_MIN, PRECIO_PRODUCTO, FECHA_VENCIMIENTO_PRODUCTO,
- FECHA_INGRESO_PRODUCTO, TIPO_PRODUCTO_MARCA, ACTIVO
- ) VALUES (?, ?, ?, ?, ?, ?, CURDATE(), ?, 1)
- ");
-
- $stmt->bind_param("iiisdss",
- $usuario_id,
- $input['id_categoria_producto'],
- $input['nombre_producto'],
- $input['stock_min'],
- $input['precio_producto'],
- $input['fecha_vencimiento'],
- $input['tipo_producto_marca']
- );
-
- if ($stmt->execute()) {
- $nuevo_id = $conexion->insert_id;
-
- // Registrar creación en logs
- registrarCambio($conexion, $nuevo_id, 'precio', '0', $input['precio_producto'], $usuario_id, $ip_usuario);
- registrarCambio($conexion, $nuevo_id, 'stock', '0', $input['stock_min'], $usuario_id, $ip_usuario);
-
- http_response_code(201);
- echo json_encode([
- 'success' => true,
- 'message' => 'Producto creado correctamente',
- 'data' => ['id' => $nuevo_id]
- ]);
- } else {
- http_response_code(500);
- echo json_encode(['success' => false, 'message' => 'Error al crear el producto']);
- }
-}
-
-/**
- * PUT - Actualizar producto completo
- */
-function handlePut() {
- global $conexion, $usuario_id, $ip_usuario;
-
- $input = json_decode(file_get_contents('php://input'), true);
- $producto_id = intval($input['id'] ?? 0);
-
- if ($producto_id <= 0) {
- http_response_code(400);
- echo json_encode(['success' => false, 'message' => 'ID de producto requerido']);
- return;
- }
-
- // Obtener datos actuales del producto
- $stmt = $conexion->prepare("SELECT * FROM Productos WHERE ID_PRODUCTO = ?");
- $stmt->bind_param("i", $producto_id);
- $stmt->execute();
- $producto_actual = $stmt->get_result()->fetch_assoc();
-
- if (!$producto_actual) {
- http_response_code(404);
- echo json_encode(['success' => false, 'message' => 'Producto no encontrado']);
- return;
- }
-
- $stmt = $conexion->prepare("
- UPDATE Productos SET
- ID_CATEGORIA_PRODUCTO = ?, NOMBRE_PRODUCTO = ?,
- PRODUCTO_STOCK_MIN = ?, PRECIO_PRODUCTO = ?,
- FECHA_VENCIMIENTO_PRODUCTO = ?, TIPO_PRODUCTO_MARCA = ?
- WHERE ID_PRODUCTO = ?
- ");
-
- $stmt->bind_param("isiissi",
- $input['id_categoria_producto'],
- $input['nombre_producto'],
- $input['stock_min'],
- $input['precio_producto'],
- $input['fecha_vencimiento'],
- $input['tipo_producto_marca'],
- $producto_id
- );
-
- if ($stmt->execute()) {
- // Registrar cambios específicos
- if ($producto_actual['PRECIO_PRODUCTO'] != $input['precio_producto']) {
- registrarCambio($conexion, $producto_id, 'precio', $producto_actual['PRECIO_PRODUCTO'], $input['precio_producto'], $usuario_id, $ip_usuario);
- }
-
- if ($producto_actual['PRODUCTO_STOCK_MIN'] != $input['stock_min']) {
- registrarCambio($conexion, $producto_id, 'stock', $producto_actual['PRODUCTO_STOCK_MIN'], $input['stock_min'], $usuario_id, $ip_usuario);
- }
-
- echo json_encode(['success' => true, 'message' => 'Producto actualizado correctamente']);
- } else {
- http_response_code(500);
- echo json_encode(['success' => false, 'message' => 'Error al actualizar el producto']);
- }
-}
-
-/**
- * PATCH - Actualización parcial (precio/stock específicos)
- */
-function handlePatch() {
- global $conexion, $usuario_id, $ip_usuario;
-
- $input = json_decode(file_get_contents('php://input'), true);
- $producto_id = intval($input['id'] ?? 0);
- $campo = $input['campo'] ?? '';
- $valor = $input['valor'] ?? '';
-
- if ($producto_id <= 0 || empty($campo)) {
- http_response_code(400);
- echo json_encode(['success' => false, 'message' => 'ID de producto y campo requeridos']);
- return;
- }
-
- // Obtener producto actual
- $stmt = $conexion->prepare("SELECT PRECIO_PRODUCTO, PRODUCTO_STOCK_MIN FROM Productos WHERE ID_PRODUCTO = ?");
- $stmt->bind_param("i", $producto_id);
- $stmt->execute();
- $producto = $stmt->get_result()->fetch_assoc();
-
- if (!$producto) {
- http_response_code(404);
- echo json_encode(['success' => false, 'message' => 'Producto no encontrado']);
- return;
- }
-
- switch ($campo) {
- case 'precio':
- $nuevo_precio = floatval($valor);
- if ($nuevo_precio <= 0) {
- http_response_code(400);
- echo json_encode(['success' => false, 'message' => 'El precio debe ser mayor a 0']);
- return;
- }
-
- $stmt = $conexion->prepare("UPDATE Productos SET PRECIO_PRODUCTO = ? WHERE ID_PRODUCTO = ?");
- $stmt->bind_param("di", $nuevo_precio, $producto_id);
-
- if ($stmt->execute()) {
- registrarCambio($conexion, $producto_id, 'precio', $producto['PRECIO_PRODUCTO'], $nuevo_precio, $usuario_id, $ip_usuario);
- echo json_encode(['success' => true, 'message' => 'Precio actualizado correctamente', 'nuevo_valor' => $nuevo_precio]);
- } else {
- http_response_code(500);
- echo json_encode(['success' => false, 'message' => 'Error al actualizar precio']);
- }
- break;
-
- case 'stock':
- $nuevo_stock = intval($valor);
- if ($nuevo_stock < 0) {
- http_response_code(400);
- echo json_encode(['success' => false, 'message' => 'El stock no puede ser negativo']);
- return;
- }
-
- $stmt = $conexion->prepare("UPDATE Productos SET PRODUCTO_STOCK_MIN = ? WHERE ID_PRODUCTO = ?");
- $stmt->bind_param("ii", $nuevo_stock, $producto_id);
-
- if ($stmt->execute()) {
- registrarCambio($conexion, $producto_id, 'stock', $producto['PRODUCTO_STOCK_MIN'], $nuevo_stock, $usuario_id, $ip_usuario);
- echo json_encode(['success' => true, 'message' => 'Stock actualizado correctamente', 'nuevo_valor' => $nuevo_stock]);
- } else {
- http_response_code(500);
- echo json_encode(['success' => false, 'message' => 'Error al actualizar stock']);
- }
- break;
-
- case 'activo':
- $activo = intval($valor);
- $tipo_log = $activo ? 'activacion' : 'desactivacion';
-
- $stmt = $conexion->prepare("UPDATE Productos SET ACTIVO = ? WHERE ID_PRODUCTO = ?");
- $stmt->bind_param("ii", $activo, $producto_id);
-
- if ($stmt->execute()) {
- registrarCambio($conexion, $producto_id, $tipo_log, $activo ? '0' : '1', $activo, $usuario_id, $ip_usuario);
- echo json_encode(['success' => true, 'message' => 'Estado actualizado correctamente', 'nuevo_valor' => $activo]);
- } else {
- http_response_code(500);
- echo json_encode(['success' => false, 'message' => 'Error al actualizar estado']);
- }
- break;
-
- default:
- http_response_code(400);
- echo json_encode(['success' => false, 'message' => 'Campo no válido']);
- break;
- }
-}
-
-/**
- * DELETE - Eliminar producto (soft delete)
- */
-function handleDelete() {
- global $conexion, $usuario_id, $ip_usuario;
-
- $input = json_decode(file_get_contents('php://input'), true);
- $producto_id = intval($input['id'] ?? 0);
- $forzar_eliminacion = $input['forzar'] ?? false;
-
- if ($producto_id <= 0) {
- http_response_code(400);
- echo json_encode(['success' => false, 'message' => 'ID de producto requerido']);
- return;
- }
-
- if ($forzar_eliminacion) {
- // Eliminación física
- $stmt = $conexion->prepare("DELETE FROM Productos WHERE ID_PRODUCTO = ?");
- $stmt->bind_param("i", $producto_id);
-
- if ($stmt->execute()) {
- echo json_encode(['success' => true, 'message' => 'Producto eliminado permanentemente']);
- } else {
- http_response_code(500);
- echo json_encode(['success' => false, 'message' => 'Error al eliminar producto']);
- }
- } else {
- // Soft delete
- $stmt = $conexion->prepare("UPDATE Productos SET ACTIVO = 0 WHERE ID_PRODUCTO = ?");
- $stmt->bind_param("i", $producto_id);
-
- if ($stmt->execute()) {
- registrarCambio($conexion, $producto_id, 'desactivacion', '1', '0', $usuario_id, $ip_usuario);
- echo json_encode(['success' => true, 'message' => 'Producto desactivado correctamente']);
- } else {
- http_response_code(500);
- echo json_encode(['success' => false, 'message' => 'Error al desactivar producto']);
- }
- }
-}
-?>
diff --git a/files/borrar_producto.php b/files/borrar_producto.php
deleted file mode 100644
index 687acc0..0000000
--- a/files/borrar_producto.php
+++ /dev/null
@@ -1,283 +0,0 @@
-alert('Método no permitido. Use POST.'); window.history.back();";
- exit();
-}
-
-// Verificar si se recibió el ID del producto
-if (isset($_POST['id']) && !empty($_POST['id'])) {
- $id_producto = $_POST['id'];
-
- try {
- // Primero, obtener los datos del producto antes de eliminarlo para mostrar confirmación
- $consulta_producto = "SELECT NOMBRE_PRODUCTO FROM Productos WHERE ID_PRODUCTO = ?";
- $stmt_producto = $conexion->prepare($consulta_producto);
- $stmt_producto->bind_param('i', $id_producto);
- $stmt_producto->execute();
- $resultado = $stmt_producto->get_result();
- $producto = $resultado->fetch_assoc();
-
- if ($producto) {
- $nombre_producto = $producto['NOMBRE_PRODUCTO'];
-
- // Verificar si el producto tiene referencias en otras tablas
- $consulta_referencias = "SELECT COUNT(*) as total FROM Detalle_Pedidos WHERE ID_PRODUCTO = ?";
- $stmt_referencias = $conexion->prepare($consulta_referencias);
- $stmt_referencias->bind_param('i', $id_producto);
- $stmt_referencias->execute();
- $resultado_ref = $stmt_referencias->get_result();
- $referencias = $resultado_ref->fetch_assoc();
-
- if ($referencias['total'] > 0) {
- // El producto tiene referencias, no se puede eliminar
- $mensaje = "No se puede eliminar el producto '{$nombre_producto}' porque está asociado a {$referencias['total']} pedido(s). Para eliminarlo, primero debe eliminar o modificar los pedidos que lo contienen.";
- $tipo_mensaje = "warning";
- $mostrar_opciones = true;
- } else {
- // El producto no tiene referencias, se puede eliminar
- $consulta_eliminar = "DELETE FROM Productos WHERE ID_PRODUCTO = ?";
- $stmt_eliminar = $conexion->prepare($consulta_eliminar);
- $stmt_eliminar->bind_param('i', $id_producto);
-
- if ($stmt_eliminar->execute()) {
- $mensaje = "El producto '{$nombre_producto}' ha sido eliminado exitosamente.";
- $tipo_mensaje = "success";
- $mostrar_opciones = false;
- } else {
- $mensaje = "Error: No se pudo eliminar el producto.";
- $tipo_mensaje = "error";
- $mostrar_opciones = false;
- }
- }
- } else {
- $mensaje = "Error: El producto no existe.";
- $tipo_mensaje = "error";
- }
-
- } catch (Exception $e) {
- // Verificar si es un error de restricción de clave foránea
- if (strpos($e->getMessage(), '1451') !== false) {
- $mensaje = "No se puede eliminar el producto porque está siendo utilizado en pedidos activos. Para eliminarlo, primero debe eliminar o modificar los pedidos que lo contienen.";
- $tipo_mensaje = "warning";
- $mostrar_opciones = true;
- } else {
- $mensaje = "Error en la base de datos: " . $e->getMessage();
- $tipo_mensaje = "error";
- $mostrar_opciones = false;
- }
- }
-} else {
- $mensaje = "Error: ID de producto no válido.";
- $tipo_mensaje = "error";
- $mostrar_opciones = false;
-}
-?>
-
-
-
-
-
-
- Eliminar Producto - Panadería
-
-
-
-
-
-
✓
-
Eliminación Exitosa
-
-
✗
-
Error en la Eliminación
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ⏱️ Por favor, lee toda la información mostrada arriba antes de continuar.
- Los botones se activarán en 5 segundos.
-
-
-
-
-
-
diff --git a/files/cambiar_estado_pedido.php b/files/cambiar_estado_pedido.php
deleted file mode 100644
index 630ebac..0000000
--- a/files/cambiar_estado_pedido.php
+++ /dev/null
@@ -1,91 +0,0 @@
- false, 'message' => 'Acceso denegado']);
- exit();
-}
-
-// Establecer el tipo de contenido como JSON
-header('Content-Type: application/json');
-
-// Obtener datos del POST
-$input = json_decode(file_get_contents('php://input'), true);
-
-if (!$input || !isset($input['pedido_id']) || !isset($input['nuevo_estado'])) {
- echo json_encode(['success' => false, 'message' => 'Datos incompletos']);
- exit();
-}
-
-$pedido_id = (int)$input['pedido_id'];
-$nuevo_estado = (int)$input['nuevo_estado'];
-
-// Validar que el estado sea válido (1-5)
-if ($nuevo_estado < 1 || $nuevo_estado > 5) {
- echo json_encode(['success' => false, 'message' => 'Estado inválido']);
- exit();
-}
-
-try {
- // Verificar que el pedido existe
- $check_query = "SELECT ID_PEDIDO FROM Pedidos WHERE ID_PEDIDO = ?";
- $check_stmt = mysqli_prepare($conexion, $check_query);
-
- if (!$check_stmt) {
- throw new Exception("Error preparando consulta de verificación: " . mysqli_error($conexion));
- }
-
- mysqli_stmt_bind_param($check_stmt, 'i', $pedido_id);
- mysqli_stmt_execute($check_stmt);
- $result = mysqli_stmt_get_result($check_stmt);
-
- if (mysqli_num_rows($result) == 0) {
- echo json_encode(['success' => false, 'message' => 'Pedido no encontrado']);
- exit();
- }
-
- // Actualizar el estado del pedido
- $update_query = "UPDATE Pedidos SET ID_ESTADO_PEDIDO = ? WHERE ID_PEDIDO = ?";
- $update_stmt = mysqli_prepare($conexion, $update_query);
-
- if (!$update_stmt) {
- throw new Exception("Error preparando consulta de actualización: " . mysqli_error($conexion));
- }
-
- mysqli_stmt_bind_param($update_stmt, 'ii', $nuevo_estado, $pedido_id);
-
- if (mysqli_stmt_execute($update_stmt)) {
- // Obtener el nombre del estado para el log
- $estados = [
- 1 => 'Pendiente',
- 2 => 'En Preparación',
- 3 => 'Listo para Entrega',
- 4 => 'Entregado',
- 5 => 'Cancelado'
- ];
-
- $nombre_estado = $estados[$nuevo_estado];
-
- // Log de la acción (opcional)
- error_log("Admin {$_SESSION['usuario_nombre']} cambió el estado del pedido #{$pedido_id} a {$nombre_estado}");
-
- echo json_encode([
- 'success' => true,
- 'message' => "Estado del pedido #{$pedido_id} actualizado a {$nombre_estado}"
- ]);
- } else {
- throw new Exception("Error al actualizar el estado: " . mysqli_error($conexion));
- }
-
-} catch (Exception $e) {
- error_log("Error en cambiar_estado_pedido.php: " . $e->getMessage());
- echo json_encode(['success' => false, 'message' => 'Error interno del servidor']);
-}
-?>
diff --git a/files/cambiar_estado_pedido_ajax.php b/files/cambiar_estado_pedido_ajax.php
deleted file mode 100644
index 6b8d7d5..0000000
--- a/files/cambiar_estado_pedido_ajax.php
+++ /dev/null
@@ -1,118 +0,0 @@
- session_id(),
- 'usuario_logueado' => $_SESSION['usuario_logueado'] ?? 'NO_SET',
- 'usuario_tipo' => $_SESSION['usuario_tipo'] ?? 'NO_SET',
- 'all_session' => $_SESSION
- ];
-
- error_log("AJAX Auth Failed Cambiar Estado - Debug: " . json_encode($debug_info));
-
- http_response_code(401);
- echo json_encode([
- 'success' => false,
- 'mensaje' => 'No autorizado para cambiar estados.'
- ]);
- exit();
-}
-
-require_once 'conexion.php';
-
-try {
- // Verificar conexión
- if (!$conexion) {
- throw new Exception("No se pudo conectar a la base de datos");
- }
-
- // Obtener datos de la petición
- $input = file_get_contents('php://input');
- $data = json_decode($input, true);
-
- if (!$data) {
- throw new Exception("Datos de entrada inválidos");
- }
-
- $pedido_id = isset($data['pedido_id']) ? intval($data['pedido_id']) : 0;
- $nuevo_estado = isset($data['nuevo_estado']) ? intval($data['nuevo_estado']) : 0;
-
- // Validar datos
- if ($pedido_id <= 0) {
- throw new Exception("ID de pedido inválido");
- }
-
- if ($nuevo_estado < 1 || $nuevo_estado > 5) {
- throw new Exception("Estado inválido");
- }
-
- error_log("Cambiando estado - Pedido: $pedido_id, Nuevo estado: $nuevo_estado, Empleado: " . $_SESSION['usuario_id']);
-
- // Verificar que el pedido existe
- $stmt = $conexion->prepare("SELECT ID_PEDIDO, ID_ESTADO_PEDIDO, ID_EMPLEADO FROM Pedidos WHERE ID_PEDIDO = ?");
- $stmt->bind_param("i", $pedido_id);
- $stmt->execute();
- $result = $stmt->get_result();
- $pedido = $result->fetch_assoc();
-
- if (!$pedido) {
- throw new Exception("Pedido no encontrado");
- }
-
- // Si el pedido no tiene empleado asignado, asignarlo al empleado actual
- if (empty($pedido['ID_EMPLEADO'])) {
- $stmt = $conexion->prepare("UPDATE Pedidos SET ID_EMPLEADO = ? WHERE ID_PEDIDO = ?");
- $stmt->bind_param("ii", $_SESSION['usuario_id'], $pedido_id);
- $stmt->execute();
-
- error_log("Pedido $pedido_id asignado al empleado " . $_SESSION['usuario_id']);
- }
-
- // Actualizar el estado del pedido
- $stmt = $conexion->prepare("UPDATE Pedidos SET ID_ESTADO_PEDIDO = ? WHERE ID_PEDIDO = ?");
- $stmt->bind_param("ii", $nuevo_estado, $pedido_id);
-
- if (!$stmt->execute()) {
- throw new Exception("Error al actualizar el estado del pedido");
- }
-
- // Obtener el nombre del nuevo estado
- $stmt = $conexion->prepare("SELECT NOMBRE_ESTADO FROM Estado_Pedidos WHERE ID_ESTADO_PEDIDO = ?");
- $stmt->bind_param("i", $nuevo_estado);
- $stmt->execute();
- $result = $stmt->get_result();
- $estado = $result->fetch_assoc();
-
- $nombre_estado = $estado ? $estado['NOMBRE_ESTADO'] : "Estado $nuevo_estado";
-
- error_log("Estado cambiado exitosamente - Pedido: $pedido_id, Nuevo estado: $nombre_estado");
-
- echo json_encode([
- 'success' => true,
- 'mensaje' => "Estado del pedido #$pedido_id cambiado a '$nombre_estado'",
- 'pedido_id' => $pedido_id,
- 'nuevo_estado' => $nuevo_estado,
- 'nombre_estado' => $nombre_estado
- ]);
-
-} catch (Exception $e) {
- error_log("Error en cambiar_estado_pedido_ajax.php: " . $e->getMessage());
- echo json_encode([
- 'success' => false,
- 'mensaje' => 'Error: ' . $e->getMessage()
- ]);
-}
-?>
diff --git a/files/conexion.php b/files/conexion.php
deleted file mode 100644
index a4bf18b..0000000
--- a/files/conexion.php
+++ /dev/null
@@ -1,25 +0,0 @@
-connect_error) {
- die("Error de conexión: " . $conexion->connect_error);
-}
-
-// Establecer charset
-$conexion->set_charset("utf8");
-
-// Opcional: mantener compatibilidad con PDO para otros archivos que lo usen
-try {
- $pdo_conexion = new PDO("mysql:host=$servidor;dbname=$base_datos;charset=utf8", $usuario, $password);
- $pdo_conexion->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
-} catch(PDOException $e) {
- die("Error de conexión PDO: " . $e->getMessage());
-}
-?>
diff --git a/files/crear_tabla_logs.sql b/files/crear_tabla_logs.sql
deleted file mode 100644
index d2a7957..0000000
--- a/files/crear_tabla_logs.sql
+++ /dev/null
@@ -1,63 +0,0 @@
--- ==================================================================
--- TABLA DE LOGS PARA CAMBIOS EN PRODUCTOS
--- ==================================================================
--- Ejecutar esta consulta para crear la tabla de logs
-
-USE ProyectoPanaderia;
-
--- Primero verificar y mostrar la estructura de la tabla Productos
-DESCRIBE Productos;
-
--- Crear tabla de logs SIN la restricción de clave foránea primero
-DROP TABLE IF EXISTS productos_logs;
-
-CREATE TABLE productos_logs (
- id INT PRIMARY KEY AUTO_INCREMENT,
- producto_id INT NOT NULL,
- tipo_cambio ENUM('precio', 'stock', 'activacion', 'desactivacion') NOT NULL,
- valor_anterior VARCHAR(50),
- valor_nuevo VARCHAR(50),
- usuario_id INT,
- usuario_tipo ENUM('admin', 'empleado') DEFAULT 'admin',
- fecha_cambio TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
- ip_usuario VARCHAR(45)
-);
-
--- Crear índices para mejor rendimiento
-CREATE INDEX idx_producto_logs_fecha ON productos_logs(fecha_cambio);
-CREATE INDEX idx_producto_logs_producto ON productos_logs(producto_id);
-CREATE INDEX idx_producto_logs_tipo ON productos_logs(tipo_cambio);
-
--- Ahora intentar agregar la clave foránea (opcional, puede fallar si hay problemas de integridad)
--- Si falla, la tabla funcionará igual pero sin restricción de integridad referencial
-SET FOREIGN_KEY_CHECKS = 0;
-ALTER TABLE productos_logs
-ADD CONSTRAINT fk_productos_logs_producto
-FOREIGN KEY (producto_id) REFERENCES Productos(ID_PRODUCTO) ON DELETE CASCADE;
-SET FOREIGN_KEY_CHECKS = 1;
-
--- Verificar que la tabla se creó correctamente
-DESCRIBE productos_logs;
-
--- Trigger para actualizar FECHA_ULTIMA_MODIFICACION en Productos automáticamente
--- Primero eliminar el trigger si existe
-DROP TRIGGER IF EXISTS actualizar_fecha_producto;
-
-DELIMITER //
-CREATE TRIGGER actualizar_fecha_producto
- BEFORE UPDATE ON Productos
- FOR EACH ROW
-BEGIN
- SET NEW.FECHA_ULTIMA_MODIFICACION = CURRENT_TIMESTAMP;
-END//
-DELIMITER ;
-
--- Verificar que el trigger se creó
-SHOW TRIGGERS LIKE 'actualizar_fecha_producto';
-
--- Insertar un registro de prueba para verificar funcionamiento
-INSERT INTO productos_logs (producto_id, tipo_cambio, valor_anterior, valor_nuevo, usuario_id, usuario_tipo, ip_usuario)
-VALUES (1, 'precio', '1000', '1200', 1, 'admin', '127.0.0.1');
-
--- Mostrar el registro insertado
-SELECT * FROM productos_logs ORDER BY id DESC LIMIT 1;
diff --git a/files/dashboard_admin.php b/files/dashboard_admin.php
deleted file mode 100644
index 392a334..0000000
--- a/files/dashboard_admin.php
+++ /dev/null
@@ -1,1615 +0,0 @@
-prepare("SELECT COUNT(*) as total FROM Productos");
- if (!$stmt) {
- throw new Exception("Error preparando consulta de productos: " . $conexion->error);
- }
- $stmt->execute();
- $result = $stmt->get_result();
- if ($result) {
- $total_productos = $result->fetch_assoc()['total'];
- }
-
- $stmt = $conexion->prepare("SELECT COUNT(*) as total FROM Productos WHERE ACTIVO = 1");
- if ($stmt) {
- $stmt->execute();
- $result = $stmt->get_result();
- if ($result) {
- $productos_activos = $result->fetch_assoc()['total'];
- }
- }
-
- $stmt = $conexion->prepare("SELECT COUNT(*) as total FROM Empleados WHERE ACTIVO_EMPLEADO = 1");
- if ($stmt) {
- $stmt->execute();
- $result = $stmt->get_result();
- if ($result) {
- $empleados_activos = $result->fetch_assoc()['total'];
- }
- }
-
- // Contar clientes activos
- $stmt = $conexion->prepare("SELECT COUNT(*) as total FROM Clientes WHERE ACTIVO_CLI = 1");
- if ($stmt) {
- $stmt->execute();
- $result = $stmt->get_result();
- if ($result) {
- $clientes_activos = $result->fetch_assoc()['total'];
- }
- }
-
- // Contar pedidos del día
- $stmt = $conexion->prepare("SELECT COUNT(*) as total FROM Pedidos WHERE DATE(FECHA_INGRESO) = CURDATE()");
- if ($stmt) {
- $stmt->execute();
- $result = $stmt->get_result();
- if ($result) {
- $pedidos_hoy = $result->fetch_assoc()['total'];
- }
- }
-
-} catch (Exception $e) {
- $error_message = "Error obteniendo estadísticas: " . $e->getMessage();
- error_log($error_message);
-}
-?>
-
-
-
-
-
-
-
-
-
-
-
- Dashboard Administrador - El Castillo del Pan
-
-
-
-
-
-
-
-
-
-
-
- Error del Sistema:
-
-
-
-
-
-
-
-
-
-
-
-
Total Productos
-
-
-
-
-
-
-
Productos Activos
-
-
-
-
-
-
-
Empleados Activos
-
-
-
-
-
-
-
Clientes Activos
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Cargando...
-
-
Cargando empleados...
-
-
-
-
-
-
- | ID |
- Nombre |
- Email |
- Estado |
- Acciones |
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
0
- Total Ingredientes
-
-
-
-
-
-
-
0
- Proveedores Activos
-
-
-
-
-
-
-
0
- Stock Bajo (≤ 10)
-
-
-
-
-
-
-
$0
- Valor Inventario
-
-
-
-
-
-
-
-
-
-
-
-
-
- Cargando...
-
-
Cargando ingredientes...
-
-
-
-
-
-
- | ID |
- Ingrediente |
- Categoría |
- Proveedor |
- Stock |
- Precio Compra |
- Valor Total |
- Referencia |
- Vencimiento |
- Acciones |
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/files/dashboard_cliente.php b/files/dashboard_cliente.php
deleted file mode 100644
index 40f11c5..0000000
--- a/files/dashboard_cliente.php
+++ /dev/null
@@ -1,317 +0,0 @@
-prepare("SELECT COUNT(*) as total FROM Pedidos WHERE ID_CLIENTE = ?");
- $stmt->bind_param("i", $_SESSION['usuario_id']);
- $stmt->execute();
- $mis_pedidos_total = $stmt->get_result()->fetch_assoc()['total'];
-
- // Contar mis pedidos pendientes
- $stmt = $conexion->prepare("
- SELECT COUNT(*) as total
- FROM Pedidos
- WHERE ID_CLIENTE = ? AND ID_ESTADO_PEDIDO IN (1, 2, 3)
- ");
- $stmt->bind_param("i", $_SESSION['usuario_id']);
- $stmt->execute();
- $mis_pedidos_pendientes = $stmt->get_result()->fetch_assoc()['total'];
-
- // Obtener mis pedidos recientes
- $stmt = $conexion->prepare("
- SELECT p.ID_PEDIDO, e.NOMBRE_EMPLEADO, ep.NOMBRE_ESTADO,
- p.FECHA_INGRESO, p.FECHA_ENTREGA, p.TOTAL_PRODUCTO
- FROM Pedidos p
- INNER JOIN Empleados e ON p.ID_EMPLEADO = e.ID_EMPLEADO
- INNER JOIN Estado_Pedidos ep ON p.ID_ESTADO_PEDIDO = ep.ID_ESTADO_PEDIDO
- WHERE p.ID_CLIENTE = ?
- ORDER BY p.FECHA_INGRESO DESC
- LIMIT 5
- ");
- $stmt->bind_param("i", $_SESSION['usuario_id']);
- $stmt->execute();
- $mis_pedidos_recientes = $stmt->get_result();
-
-} catch (Exception $e) {
- error_log("Error obteniendo estadísticas del cliente: " . $e->getMessage());
-}
-?>
-
-
-
-
-
-
-
-
-
- Dashboard Cliente - Panadería
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Bienvenido, !
-
Gestiona tus pedidos y explora nuestros deliciosos productos
-
-
-
-
-
-
- num_rows > 0): ?>
-
-
-
- fetch_assoc()): ?>
-
-
-
Pedido #
-
Por:
-
Fecha:
-
Total: $
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/files/dashboard_empleado.php b/files/dashboard_empleado.php
deleted file mode 100644
index 95343d6..0000000
--- a/files/dashboard_empleado.php
+++ /dev/null
@@ -1,1635 +0,0 @@
-prepare("
- SELECT COUNT(*) as total
- FROM Pedidos
- WHERE ID_EMPLEADO = ? AND DATE(FECHA_INGRESO) = CURDATE()
- ");
- if ($stmt) {
- $stmt->bind_param("i", $_SESSION['usuario_id']);
- $stmt->execute();
- $result = $stmt->get_result();
- if ($result) {
- $mis_pedidos_hoy = $result->fetch_assoc()['total'];
- }
- }
-
- // Contar mis pedidos pendientes
- $stmt = $conexion->prepare("
- SELECT COUNT(*) as total
- FROM Pedidos
- WHERE ID_EMPLEADO = ? AND ID_ESTADO_PEDIDO IN (1, 2)
- ");
- if ($stmt) {
- $stmt->bind_param("i", $_SESSION['usuario_id']);
- $stmt->execute();
- $result = $stmt->get_result();
- if ($result) {
- $mis_pedidos_pendientes = $result->fetch_assoc()['total'];
- }
- }
-
- // Contar productos disponibles - usar tabla correcta
- $stmt = $conexion->prepare("SELECT COUNT(*) as total FROM Productos WHERE ACTIVO = 1");
- if ($stmt) {
- $stmt->execute();
- $result = $stmt->get_result();
- if ($result) {
- $productos_disponibles = $result->fetch_assoc()['total'];
- }
- }
-
- // Contar total de pedidos asignados
- $stmt = $conexion->prepare("SELECT COUNT(*) as total FROM Pedidos WHERE ID_EMPLEADO = ?");
- if ($stmt) {
- $stmt->bind_param("i", $_SESSION['usuario_id']);
- $stmt->execute();
- $result = $stmt->get_result();
- if ($result) {
- $total_pedidos = $result->fetch_assoc()['total'];
- }
- }
-
- // Contar pedidos completados hoy
- $stmt = $conexion->prepare("
- SELECT COUNT(*) as total
- FROM Pedidos
- WHERE ID_EMPLEADO = ? AND ID_ESTADO_PEDIDO = 4 AND DATE(FECHA_INGRESO) = CURDATE()
- ");
- if ($stmt) {
- $stmt->bind_param("i", $_SESSION['usuario_id']);
- $stmt->execute();
- $result = $stmt->get_result();
- if ($result) {
- $pedidos_completados_hoy = $result->fetch_assoc()['total'];
- }
- }
-
-} catch (Exception $e) {
- $error_message = "Error obteniendo estadísticas: " . $e->getMessage();
- error_log($error_message);
-}
-?>
-
-
-
-
-
-
-
-
-
-
-
-
-
- Dashboard Empleado - El Castillo del Pan
-
-
-
-
-
-
-
-
-
-
-
-
- Error del Sistema:
-
-
-
-
-
-
-
-
-
Consulta y gestiona los pedidos del sistema. Cambia el estado de los pedidos de Pendiente → En Preparación → Listo para Entrega → Entregado
-
-
-
-
-
-
-
-
Revisa el estado actual del inventario de productos
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Cargando...
-
-
Cargando pedidos...
-
-
-
-
-
-
-
-
- | ID |
- Cliente |
- Empleado |
- Fecha Ingreso |
- Fecha Entrega |
- Total |
- Estado |
- Acciones |
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Cargando...
-
-
Cargando inventario...
-
-
-
-
-
-
-
-
- | ID |
- Nombre |
- Categoría |
- Precio |
- Stock Mínimo |
- Vencimiento |
- Estado |
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Cargando...
-
-
Cargando detalle del pedido...
-
-
-
-
-
-
-
-
-
-
-
ID Pedido:
-
Estado:
-
Fecha Ingreso:
-
Fecha Entrega:
-
Empleado Asignado:
-
-
-
-
-
-
-
-
Cliente:
-
Email:
-
Teléfono:
-
-
-
-
-
-
-
-
-
-
-
-
-
- | ID |
- Producto |
- Cantidad |
- Precio Unit. |
- Subtotal |
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Total de Items:
-
-
-
- Productos Diferentes:
-
-
-
-
- TOTAL:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/files/eliminar_empleado_ajax.php b/files/eliminar_empleado_ajax.php
deleted file mode 100644
index ab17b54..0000000
--- a/files/eliminar_empleado_ajax.php
+++ /dev/null
@@ -1,122 +0,0 @@
- false, 'mensaje' => 'Acceso no autorizado']);
- exit();
-}
-
-// Headers de respuesta JSON
-header('Content-Type: application/json');
-
-// Verificar método POST
-if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
- echo json_encode(['success' => false, 'mensaje' => 'Método no permitido']);
- exit();
-}
-
-// Incluir conexión a la base de datos
-require_once 'conexion.php';
-
-try {
- // Verificar conexión
- if (!$conexion) {
- throw new Exception('Error de conexión a la base de datos');
- }
-
- // Obtener datos JSON del cuerpo de la petición
- $raw_input = file_get_contents('php://input');
- $input = json_decode($raw_input, true);
-
- if (json_last_error() !== JSON_ERROR_NONE) {
- throw new Exception('Error al decodificar JSON: ' . json_last_error_msg());
- }
-
- if (!$input || !isset($input['id'])) {
- throw new Exception('ID de empleado requerido');
- }
-
- // Validar ID del empleado
- $empleado_id = filter_var($input['id'], FILTER_VALIDATE_INT);
-
- if ($empleado_id === false || $empleado_id <= 0) {
- throw new Exception('ID de empleado inválido');
- }
-
- // Verificar que el empleado existe
- $consulta_verificar = "SELECT ID_EMPLEADO, NOMBRE_EMPLEADO FROM Empleados WHERE ID_EMPLEADO = ?";
- $stmt_verificar = $conexion->prepare($consulta_verificar);
-
- if (!$stmt_verificar) {
- throw new Exception('Error al preparar la consulta de verificación: ' . $conexion->error);
- }
-
- $stmt_verificar->bind_param('i', $empleado_id);
- $stmt_verificar->execute();
- $resultado_verificar = $stmt_verificar->get_result();
-
- if ($resultado_verificar->num_rows === 0) {
- throw new Exception('Empleado no encontrado');
- }
-
- $empleado = $resultado_verificar->fetch_assoc();
- $stmt_verificar->close();
-
- // Verificar si el empleado es administrador (prevenir eliminación accidental)
- $consulta_admin = "SELECT ID_ADMIN FROM Administradores WHERE EMAIL_ADMIN = (SELECT EMAIL_EMPLEADO FROM Empleados WHERE ID_EMPLEADO = ?)";
- $stmt_admin = $conexion->prepare($consulta_admin);
-
- if ($stmt_admin) {
- $stmt_admin->bind_param('i', $empleado_id);
- $stmt_admin->execute();
- $resultado_admin = $stmt_admin->get_result();
-
- if ($resultado_admin->num_rows > 0) {
- throw new Exception('No se puede eliminar un empleado que también es administrador');
- }
-
- $stmt_admin->close();
- }
-
- // Eliminar el empleado
- $consulta_eliminar = "DELETE FROM Empleados WHERE ID_EMPLEADO = ?";
- $stmt_eliminar = $conexion->prepare($consulta_eliminar);
-
- if (!$stmt_eliminar) {
- throw new Exception('Error al preparar la consulta de eliminación: ' . $conexion->error);
- }
-
- $stmt_eliminar->bind_param('i', $empleado_id);
-
- if ($stmt_eliminar->execute()) {
- if ($stmt_eliminar->affected_rows > 0) {
- echo json_encode([
- 'success' => true,
- 'mensaje' => 'Empleado eliminado exitosamente',
- 'empleado' => [
- 'id' => $empleado_id,
- 'nombre' => htmlspecialchars($empleado['NOMBRE_EMPLEADO'])
- ]
- ]);
- } else {
- throw new Exception('No se pudo eliminar el empleado');
- }
- } else {
- throw new Exception('Error al eliminar el empleado: ' . $stmt_eliminar->error);
- }
-
- $stmt_eliminar->close();
-
-} catch (Exception $e) {
- echo json_encode([
- 'success' => false,
- 'mensaje' => $e->getMessage()
- ]);
-}
-
-// Cerrar conexión
-if (isset($conexion)) {
- $conexion->close();
-}
-?>
diff --git a/files/eliminar_forzado.php b/files/eliminar_forzado.php
deleted file mode 100644
index 88d2e99..0000000
--- a/files/eliminar_forzado.php
+++ /dev/null
@@ -1,324 +0,0 @@
-prepare($consulta_producto);
- $stmt_producto->bindParam(':id', $id_producto, PDO::PARAM_INT);
- $stmt_producto->execute();
- $producto = $stmt_producto->fetch(PDO::FETCH_ASSOC);
-
- if ($producto) {
- $nombre_producto = $producto['NOMBRE_PRODUCTO'];
-
- // Verificar si tiene referencias (para informar al usuario)
- $consulta_referencias = "SELECT COUNT(*) as total FROM detalle_pedidos WHERE ID_PRODUCTO = :id";
- $stmt_referencias = $pdo_conexion->prepare($consulta_referencias);
- $stmt_referencias->bindParam(':id', $id_producto, PDO::PARAM_INT);
- $stmt_referencias->execute();
- $referencias = $stmt_referencias->fetch(PDO::FETCH_ASSOC);
-
- // ELIMINACIÓN FORZADA - Ignora las restricciones de clave foránea
- // Primero deshabilitar temporalmente las verificaciones de clave foránea
- $pdo_conexion->exec("SET FOREIGN_KEY_CHECKS = 0");
-
- // Eliminar el producto
- $consulta_eliminar = "DELETE FROM Productos WHERE ID_PRODUCTO = :id";
- $stmt_eliminar = $pdo_conexion->prepare($consulta_eliminar);
- $stmt_eliminar->bindParam(':id', $id_producto, PDO::PARAM_INT);
-
- if ($stmt_eliminar->execute()) {
- // Reactivar las verificaciones de clave foránea
- $pdo_conexion->exec("SET FOREIGN_KEY_CHECKS = 1");
-
- $mensaje = "El producto '{$nombre_producto}' ha sido ELIMINADO PERMANENTEMENTE.";
- $tipo_mensaje = "success";
- $referencias_afectadas = $referencias['total'];
- } else {
- // Reactivar las verificaciones de clave foránea en caso de error
- $pdo_conexion->exec("SET FOREIGN_KEY_CHECKS = 1");
- $mensaje = "Error: No se pudo eliminar el producto.";
- $tipo_mensaje = "error";
- $referencias_afectadas = 0;
- }
- } else {
- $mensaje = "Error: El producto no existe.";
- $tipo_mensaje = "error";
- $referencias_afectadas = 0;
- }
-
- } catch (PDOException $e) {
- // Asegurar que las verificaciones de clave foránea se reactiven en caso de error
- try {
- $pdo_conexion->exec("SET FOREIGN_KEY_CHECKS = 1");
- } catch (Exception $ex) {
- // Ignorar errores al reactivar
- }
-
- $mensaje = "Error en la base de datos: " . $e->getMessage();
- $tipo_mensaje = "error";
- $referencias_afectadas = 0;
- }
-} else {
- $mensaje = "Error: ID de producto no válido.";
- $tipo_mensaje = "error";
- $referencias_afectadas = 0;
-}
-?>
-
-
-
-
-
-
- Eliminación Forzada - Panadería
-
-
-
-
-
-
⚠️
-
Producto Eliminado Permanentemente
-
-
-
-
-
- 0): ?>
-
-
🚨 ADVERTENCIA CRÍTICA:
-
Este producto tenía referencia(s) en pedidos.
-
La eliminación forzada puede haber causado:
-
- - ❌ Pedidos con productos "huérfanos" (referencias rotas)
- - ❌ Posibles errores en reportes de ventas
- - ❌ Inconsistencias en el historial de transacciones
- - ❌ Problemas en cálculos de inventario
-
-
Recomendación: Revise inmediatamente la tabla de pedidos para verificar la integridad de los datos.
-
-
-
-
✅ Eliminación Segura:
-
El producto no tenía referencias en otras tablas, por lo que la eliminación no causó inconsistencias en la base de datos.
-
-
-
-
-
Detalles del Producto Eliminado:
-
Nombre:
-
ID:
-
Fecha de Eliminación:
-
Referencias Afectadas:
-
-
-
-
✗
-
Error en la Eliminación
-
-
-
-
-
-
-
-
-
-
-
- ⏱️ Por favor, lee toda la información mostrada arriba antes de continuar.
- El botón se activará en 5 segundos.
-
-
- 0): ?>
-
-
🔧 Acciones Recomendadas:
-
- - Revisar la tabla de pedidos para identificar referencias rotas
- - Contactar al administrador de la base de datos
- - Considerar implementar un proceso de limpieza de datos
- - En el futuro, use la opción "Desactivar" en lugar de eliminar
-
-
-
-
-
-
-
-
diff --git a/files/eliminar_forzado_ajax.php b/files/eliminar_forzado_ajax.php
deleted file mode 100644
index 8a11398..0000000
--- a/files/eliminar_forzado_ajax.php
+++ /dev/null
@@ -1,65 +0,0 @@
- false,
- 'mensaje' => 'Método no permitido. Use POST.'
- ]);
- exit();
-}
-
-// Verificar si se recibió el ID del producto
-if (isset($_POST['id']) && !empty($_POST['id'])) {
- $id_producto = $_POST['id'];
-
- try {
- // Primero, obtener los datos del producto
- $consulta_producto = "SELECT NOMBRE_PRODUCTO FROM Productos WHERE ID_PRODUCTO = ?";
- $stmt_producto = $conexion->prepare($consulta_producto);
- $stmt_producto->bind_param("i", $id_producto);
- $stmt_producto->execute();
- $resultado = $stmt_producto->get_result();
- $producto = $resultado->fetch_assoc();
-
- if ($producto) {
- $nombre_producto = $producto['NOMBRE_PRODUCTO'];
-
- // Realizar eliminación forzada
- $consulta_eliminar = "DELETE FROM Productos WHERE ID_PRODUCTO = ?";
- $stmt_eliminar = $conexion->prepare($consulta_eliminar);
- $stmt_eliminar->bind_param("i", $id_producto);
-
- if ($stmt_eliminar->execute()) {
- echo json_encode([
- 'success' => true,
- 'mensaje' => "⚠️ ELIMINACIÓN FORZADA COMPLETADA
El producto '{$nombre_producto}' ha sido eliminado permanentemente del sistema.
🚨 Nota: Si este producto tenía referencias en pedidos, esas referencias han sido rotas y pueden causar errores en el sistema."
- ]);
- } else {
- echo json_encode([
- 'success' => false,
- 'mensaje' => "Error: No se pudo eliminar el producto."
- ]);
- }
- } else {
- echo json_encode([
- 'success' => false,
- 'mensaje' => "Error: El producto no existe."
- ]);
- }
-
- } catch (Exception $e) {
- echo json_encode([
- 'success' => false,
- 'mensaje' => "Error en la base de datos: " . $e->getMessage()
- ]);
- }
-} else {
- echo json_encode([
- 'success' => false,
- 'mensaje' => "Error: Parámetros no válidos."
- ]);
-}
-?>
diff --git a/files/eliminar_ingrediente_ajax.php b/files/eliminar_ingrediente_ajax.php
deleted file mode 100644
index 99ccb50..0000000
--- a/files/eliminar_ingrediente_ajax.php
+++ /dev/null
@@ -1,61 +0,0 @@
-prepare("SELECT NOMBRE_INGREDIENTE FROM Ingredientes WHERE ID_INGREDIENTE = ?");
- $stmt->bind_param("i", $id_ingrediente);
- $stmt->execute();
- $resultado = $stmt->get_result();
-
- if ($resultado->num_rows === 0) {
- throw new Exception('El ingrediente no existe');
- }
-
- $ingrediente = $resultado->fetch_assoc();
-
- // Eliminar el ingrediente
- $stmt = $conexion->prepare("DELETE FROM Ingredientes WHERE ID_INGREDIENTE = ?");
- $stmt->bind_param("i", $id_ingrediente);
-
- if ($stmt->execute()) {
- if ($stmt->affected_rows > 0) {
- echo json_encode([
- 'success' => true,
- 'mensaje' => 'Ingrediente "' . $ingrediente['NOMBRE_INGREDIENTE'] . '" eliminado exitosamente'
- ]);
- } else {
- throw new Exception('No se pudo eliminar el ingrediente');
- }
- } else {
- throw new Exception('Error al eliminar el ingrediente: ' . $stmt->error);
- }
-
-} catch (Exception $e) {
- echo json_encode([
- 'success' => false,
- 'mensaje' => $e->getMessage()
- ]);
-}
-
-$conexion->close();
-?>
diff --git a/files/eliminar_producto_ajax.php b/files/eliminar_producto_ajax.php
deleted file mode 100644
index fc2c63b..0000000
--- a/files/eliminar_producto_ajax.php
+++ /dev/null
@@ -1,87 +0,0 @@
- false,
- 'mensaje' => 'Método no permitido. Use POST.'
- ]);
- exit();
-}
-
-// Verificar si se recibió el ID del producto
-if (isset($_POST['id']) && !empty($_POST['id'])) {
- $id_producto = $_POST['id'];
-
- try {
- // Primero, obtener los datos del producto
- $consulta_producto = "SELECT NOMBRE_PRODUCTO FROM Productos WHERE ID_PRODUCTO = ?";
- $stmt_producto = $conexion->prepare($consulta_producto);
- $stmt_producto->bind_param("i", $id_producto);
- $stmt_producto->execute();
- $resultado = $stmt_producto->get_result();
- $producto = $resultado->fetch_assoc();
-
- if ($producto) {
- $nombre_producto = $producto['NOMBRE_PRODUCTO'];
-
- // Verificar si el producto tiene referencias en otras tablas
- $consulta_referencias = "SELECT COUNT(*) as total FROM Detalle_Pedidos WHERE ID_PRODUCTO = ?";
- $stmt_referencias = $conexion->prepare($consulta_referencias);
- $stmt_referencias->bind_param("i", $id_producto);
- $stmt_referencias->execute();
- $resultado_ref = $stmt_referencias->get_result();
- $referencias = $resultado_ref->fetch_assoc();
-
- if ($referencias['total'] > 0) {
- // El producto tiene referencias, no se puede eliminar
- echo json_encode([
- 'success' => false,
- 'hasReferences' => true,
- 'mensaje' => "No se puede eliminar el producto '{$nombre_producto}' porque está asociado a {$referencias['total']} pedido(s).
🔄 Opciones:
• Desactivar el producto en lugar de eliminarlo
• Eliminar o modificar los pedidos que lo contienen
• Realizar eliminación forzada (⚠️ Riesgo de datos corruptos)"
- ]);
- } else {
- // El producto no tiene referencias, se puede eliminar
- $consulta_eliminar = "DELETE FROM Productos WHERE ID_PRODUCTO = ?";
- $stmt_eliminar = $conexion->prepare($consulta_eliminar);
- $stmt_eliminar->bind_param("i", $id_producto);
-
- if ($stmt_eliminar->execute()) {
- echo json_encode([
- 'success' => true,
- 'hasReferences' => false,
- 'mensaje' => "El producto '{$nombre_producto}' ha sido eliminado exitosamente."
- ]);
- } else {
- echo json_encode([
- 'success' => false,
- 'hasReferences' => false,
- 'mensaje' => "Error: No se pudo eliminar el producto."
- ]);
- }
- }
- } else {
- echo json_encode([
- 'success' => false,
- 'hasReferences' => false,
- 'mensaje' => "Error: El producto no existe."
- ]);
- }
-
- } catch (Exception $e) {
- echo json_encode([
- 'success' => false,
- 'hasReferences' => false,
- 'mensaje' => "Error en la base de datos: " . $e->getMessage()
- ]);
- }
-} else {
- echo json_encode([
- 'success' => false,
- 'hasReferences' => false,
- 'mensaje' => "Error: Parámetros no válidos."
- ]);
-}
-?>
diff --git a/files/employee_login_test.php b/files/employee_login_test.php
deleted file mode 100644
index 5d66154..0000000
--- a/files/employee_login_test.php
+++ /dev/null
@@ -1,110 +0,0 @@
-Employee Login Debug";
-
-// Clear any existing session
-session_destroy();
-session_start();
-
-echo "Step 1: Session cleared and restarted
";
-echo "Session ID: " . session_id() . "
";
-
-// Simulate the login process for an employee
-require_once 'conexion.php';
-
-$test_employee = 'admin'; // or whatever employee username exists
-$test_password = 'admin123'; // or whatever password
-
-echo "Step 2: Testing Employee Login
";
-echo "Testing user: $test_employee
";
-
-try {
- $consulta = "SELECT ID_EMPLEADO, NOMBRE_EMPLEADO, CONTRASEÑA_EMPLEADO, SALT_EMPLEADO, ACTIVO_EMPLEADO, EMAIL_EMPLEADO
- FROM Empleados
- WHERE (NOMBRE_EMPLEADO = :usuario OR EMAIL_EMPLEADO = :usuario) AND ACTIVO_EMPLEADO = 1";
-
- $stmt = $pdo_conexion->prepare($consulta);
- $stmt->bindParam(':usuario', $test_employee, PDO::PARAM_STR);
- $stmt->execute();
-
- $user_data = $stmt->fetch(PDO::FETCH_ASSOC);
-
- if ($user_data) {
- echo "✓ Employee found: " . $user_data['NOMBRE_EMPLEADO'] . "
";
-
- // Test password
- $password_hash = $user_data['CONTRASEÑA_EMPLEADO'];
- $salt = $user_data['SALT_EMPLEADO'];
-
- $password_valid = false;
-
- if (!empty($salt) && !empty($password_hash)) {
- $hash_to_check = hash('sha256', $test_password . $salt);
- if ($hash_to_check === $password_hash) {
- $password_valid = true;
- }
- } elseif (!empty($password_hash)) {
- if ($test_password === $password_hash) {
- $password_valid = true;
- }
- }
-
- if ($password_valid) {
- echo "✓ Password valid
";
-
- // Set session like the real login process
- $_SESSION['usuario_logueado'] = true;
- $_SESSION['usuario_tipo'] = 'empleado';
- $_SESSION['usuario_id'] = $user_data['ID_EMPLEADO'];
- $_SESSION['usuario_nombre'] = $user_data['NOMBRE_EMPLEADO'];
- $_SESSION['user_name'] = $user_data['NOMBRE_EMPLEADO'];
- $_SESSION['role'] = 'empleado';
-
- echo "✓ Session set
";
- echo "Session data:\n" . print_r($_SESSION, true) . "
";
-
- echo "Step 3: Testing AJAX Endpoint
";
-
- // Test if this session works with the AJAX endpoint
- echo '';
- echo '';
-
- } else {
- echo "✗ Password invalid
";
- }
-
- } else {
- echo "✗ Employee not found
";
- }
-
-} catch (Exception $e) {
- echo "✗ Error: " . $e->getMessage() . "
";
-}
-
-echo "
";
-echo "Navigation
";
-echo 'Go to Employee Dashboard
';
-echo 'Go to Login
';
-echo 'Session Debug
';
-?>
diff --git a/files/gestionar_producto.php b/files/gestionar_producto.php
deleted file mode 100644
index ac50aac..0000000
--- a/files/gestionar_producto.php
+++ /dev/null
@@ -1,498 +0,0 @@
-pdo = $pdo;
- }
-
- /**
- * Descuenta stock de un producto
- */
- public function descontarStock($id_producto, $cantidad) {
- try {
- $this->pdo->beginTransaction();
-
- // Verificar stock actual del producto
- $stmt = $this->pdo->prepare("
- SELECT STOCK_ACTUAL, PRODUCTO_STOCK_MIN, NOMBRE_PRODUCTO, ACTIVO
- FROM Productos
- WHERE ID_PRODUCTO = ? AND ACTIVO = 1
- FOR UPDATE
- ");
- $stmt->execute([$id_producto]);
- $producto = $stmt->fetch(PDO::FETCH_ASSOC);
-
- if (!$producto) {
- throw new Exception("Producto no encontrado o inactivo");
- }
-
- // Verificar si hay suficiente stock
- if ($producto['STOCK_ACTUAL'] < $cantidad) {
- throw new Exception("Stock insuficiente. Stock disponible: " . $producto['STOCK_ACTUAL']);
- }
-
- // Actualizar stock
- $nuevo_stock = $producto['STOCK_ACTUAL'] - $cantidad;
- $stmt = $this->pdo->prepare("
- UPDATE Productos
- SET STOCK_ACTUAL = ?
- WHERE ID_PRODUCTO = ?
- ");
- $stmt->execute([$nuevo_stock, $id_producto]);
-
- // Registrar movimiento en historial (opcional)
- $this->registrarMovimiento($id_producto, 'SALIDA', $cantidad, $producto['STOCK_ACTUAL'], $nuevo_stock, 'Venta/Pedido');
-
- $this->pdo->commit();
-
- return [
- 'success' => true,
- 'message' => 'Stock actualizado correctamente',
- 'producto' => $producto['NOMBRE_PRODUCTO'],
- 'stock_anterior' => $producto['STOCK_ACTUAL'],
- 'stock_actual' => $nuevo_stock,
- 'alerta_stock_minimo' => ($nuevo_stock <= $producto['PRODUCTO_STOCK_MIN'])
- ];
-
- } catch (Exception $e) {
- $this->pdo->rollBack();
- return [
- 'success' => false,
- 'message' => $e->getMessage()
- ];
- }
- }
-
- /**
- * Aumenta stock de un producto
- */
- public function aumentarStock($id_producto, $cantidad, $motivo = 'Reposición') {
- try {
- $this->pdo->beginTransaction();
-
- $stmt = $this->pdo->prepare("
- SELECT STOCK_ACTUAL, NOMBRE_PRODUCTO, ACTIVO
- FROM Productos
- WHERE ID_PRODUCTO = ?
- FOR UPDATE
- ");
- $stmt->execute([$id_producto]);
- $producto = $stmt->fetch(PDO::FETCH_ASSOC);
-
- if (!$producto) {
- throw new Exception("Producto no encontrado");
- }
-
- $nuevo_stock = $producto['STOCK_ACTUAL'] + $cantidad;
- $stmt = $this->pdo->prepare("
- UPDATE Productos
- SET STOCK_ACTUAL = ?
- WHERE ID_PRODUCTO = ?
- ");
- $stmt->execute([$nuevo_stock, $id_producto]);
-
- $this->registrarMovimiento($id_producto, 'ENTRADA', $cantidad, $producto['STOCK_ACTUAL'], $nuevo_stock, $motivo);
-
- $this->pdo->commit();
-
- return [
- 'success' => true,
- 'message' => 'Stock aumentado correctamente',
- 'producto' => $producto['NOMBRE_PRODUCTO'],
- 'stock_anterior' => $producto['STOCK_ACTUAL'],
- 'stock_actual' => $nuevo_stock
- ];
-
- } catch (Exception $e) {
- $this->pdo->rollBack();
- return [
- 'success' => false,
- 'message' => $e->getMessage()
- ];
- }
- }
-
- /**
- * Registra movimiento de stock
- */
- private function registrarMovimiento($id_producto, $tipo, $cantidad, $stock_anterior, $stock_nuevo, $motivo) {
- try {
- $stmt = $this->pdo->prepare("
- INSERT INTO MovimientosStock (ID_PRODUCTO, TIPO_MOVIMIENTO, CANTIDAD, STOCK_ANTERIOR, STOCK_NUEVO, MOTIVO)
- VALUES (?, ?, ?, ?, ?, ?)
- ");
- $stmt->execute([$id_producto, $tipo, $cantidad, $stock_anterior, $stock_nuevo, $motivo]);
- } catch (Exception $e) {
- // Si no existe la tabla de movimientos, no hacer nada
- }
- }
-
- /**
- * Obtiene información del stock
- */
- public function obtenerInfoStock($id_producto) {
- $stmt = $this->pdo->prepare("
- SELECT ID_PRODUCTO, NOMBRE_PRODUCTO, STOCK_ACTUAL, PRODUCTO_STOCK_MIN,
- CASE
- WHEN STOCK_ACTUAL = 0 THEN 'SIN STOCK'
- WHEN STOCK_ACTUAL <= PRODUCTO_STOCK_MIN THEN 'CRÍTICO'
- WHEN STOCK_ACTUAL <= (PRODUCTO_STOCK_MIN * 2) THEN 'BAJO'
- ELSE 'NORMAL'
- END as ESTADO_STOCK
- FROM Productos
- WHERE ID_PRODUCTO = ?
- ");
- $stmt->execute([$id_producto]);
- return $stmt->fetch(PDO::FETCH_ASSOC);
- }
-}
-
-// Inicializar el gestor de stock
-$stockManager = new StockManager($pdo_conexion);
-
-// Verificar si se recibió el ID del producto
-if (isset($_GET['id']) && !empty($_GET['id'])) {
- $id_producto = $_GET['id'];
-
- try {
- // Obtener información del producto
- $consulta_producto = "SELECT * FROM Productos WHERE ID_PRODUCTO = :id";
- $stmt_producto = $pdo_conexion->prepare($consulta_producto);
- $stmt_producto->bindParam(':id', $id_producto, PDO::PARAM_INT);
- $stmt_producto->execute();
- $producto = $stmt_producto->fetch(PDO::FETCH_ASSOC);
-
- if ($producto) {
- // Verificar referencias en detalle_pedidos
- $consulta_referencias = "SELECT COUNT(*) as total FROM detalle_pedidos WHERE ID_PRODUCTO = :id";
- $stmt_referencias = $pdo_conexion->prepare($consulta_referencias);
- $stmt_referencias->bindParam(':id', $id_producto, PDO::PARAM_INT);
- $stmt_referencias->execute();
- $referencias = $stmt_referencias->fetch(PDO::FETCH_ASSOC);
-
- // Obtener información del stock
- $info_stock = $stockManager->obtenerInfoStock($id_producto);
-
- // Procesar acciones
- $mensaje = "";
- $tipo_mensaje = "";
-
- if (isset($_POST['accion'])) {
- switch ($_POST['accion']) {
- case 'descontar_stock':
- if (isset($_POST['cantidad']) && is_numeric($_POST['cantidad']) && $_POST['cantidad'] > 0) {
- $cantidad = (int)$_POST['cantidad'];
- $resultado = $stockManager->descontarStock($id_producto, $cantidad);
-
- if ($resultado['success']) {
- $mensaje = "Stock descontado exitosamente. ";
- $mensaje .= "Producto: " . $resultado['producto'] . ". ";
- $mensaje .= "Stock anterior: " . $resultado['stock_anterior'] . ". ";
- $mensaje .= "Stock actual: " . $resultado['stock_actual'] . ".";
-
- if ($resultado['alerta_stock_minimo']) {
- $mensaje .= " ⚠️ ALERTA: Stock por debajo del mínimo!";
- }
-
- $tipo_mensaje = "success";
- } else {
- $mensaje = "Error al descontar stock: " . $resultado['message'];
- $tipo_mensaje = "error";
- }
-
- // Refrescar información del producto
- $stmt_producto->execute();
- $producto = $stmt_producto->fetch(PDO::FETCH_ASSOC);
- $info_stock = $stockManager->obtenerInfoStock($id_producto);
- } else {
- $mensaje = "Cantidad inválida para descontar.";
- $tipo_mensaje = "error";
- }
- break;
-
- case 'aumentar_stock':
- if (isset($_POST['cantidad']) && is_numeric($_POST['cantidad']) && $_POST['cantidad'] > 0) {
- $cantidad = (int)$_POST['cantidad'];
- $motivo = isset($_POST['motivo']) ? $_POST['motivo'] : 'Reposición manual';
- $resultado = $stockManager->aumentarStock($id_producto, $cantidad, $motivo);
-
- if ($resultado['success']) {
- $mensaje = "Stock aumentado exitosamente. ";
- $mensaje .= "Producto: " . $resultado['producto'] . ". ";
- $mensaje .= "Stock anterior: " . $resultado['stock_anterior'] . ". ";
- $mensaje .= "Stock actual: " . $resultado['stock_actual'] . ".";
- $tipo_mensaje = "success";
- } else {
- $mensaje = "Error al aumentar stock: " . $resultado['message'];
- $tipo_mensaje = "error";
- }
-
- // Refrescar información del producto
- $stmt_producto->execute();
- $producto = $stmt_producto->fetch(PDO::FETCH_ASSOC);
- $info_stock = $stockManager->obtenerInfoStock($id_producto);
- } else {
- $mensaje = "Cantidad inválida para aumentar.";
- $tipo_mensaje = "error";
- }
- break;
-
- case 'reducir_stock':
- $consulta_update = "UPDATE Productos SET PRODUCTO_STOCK_MIN = 0 WHERE ID_PRODUCTO = :id";
- $stmt_update = $pdo_conexion->prepare($consulta_update);
- $stmt_update->bindParam(':id', $id_producto, PDO::PARAM_INT);
-
- if ($stmt_update->execute()) {
- $mensaje = "Stock mínimo del producto reducido a 0. El producto seguirá visible pero marcado como sin stock.";
- $tipo_mensaje = "success";
- // Refrescar datos del producto
- $stmt_producto->execute();
- $producto = $stmt_producto->fetch(PDO::FETCH_ASSOC);
- $info_stock = $stockManager->obtenerInfoStock($id_producto);
- } else {
- $mensaje = "Error al actualizar el producto.";
- $tipo_mensaje = "error";
- }
- break;
-
- case 'desactivar':
- $consulta_update = "UPDATE Productos SET ACTIVO = 0 WHERE ID_PRODUCTO = :id";
- $stmt_update = $pdo_conexion->prepare($consulta_update);
- $stmt_update->bindParam(':id', $id_producto, PDO::PARAM_INT);
-
- if ($stmt_update->execute()) {
- $mensaje = "Producto desactivado exitosamente. Ya no aparecerá en búsquedas pero conserva todas sus referencias.";
- $tipo_mensaje = "success";
- // Refrescar datos del producto
- $stmt_producto->execute();
- $producto = $stmt_producto->fetch(PDO::FETCH_ASSOC);
- } else {
- $mensaje = "Error al desactivar el producto.";
- $tipo_mensaje = "error";
- }
- break;
-
- case 'activar':
- $consulta_update = "UPDATE Productos SET ACTIVO = 1 WHERE ID_PRODUCTO = :id";
- $stmt_update = $pdo_conexion->prepare($consulta_update);
- $stmt_update->bindParam(':id', $id_producto, PDO::PARAM_INT);
-
- if ($stmt_update->execute()) {
- $mensaje = "Producto activado exitosamente. Ahora está disponible para nuevos pedidos.";
- $tipo_mensaje = "success";
- // Refrescar datos del producto
- $stmt_producto->execute();
- $producto = $stmt_producto->fetch(PDO::FETCH_ASSOC);
- } else {
- $mensaje = "Error al activar el producto.";
- $tipo_mensaje = "error";
- }
- break;
- }
- }
- } else {
- header("Location: productostabla.php");
- exit();
- }
-
- } catch (PDOException $e) {
- $mensaje = "Error en la base de datos: " . $e->getMessage();
- $tipo_mensaje = "error";
- }
-} else {
- header("Location: productostabla.php");
- exit();
-}
-?>
-
-
-
-
-
- Gestionar Producto - Panadería
-
-
-
-
Gestión de Producto
-
-
-
-
-
-
-
-
-
Información del Producto
-
ID:
-
Nombre:
-
Precio: $
-
Stock Mínimo:
-
Marca/Tipo:
-
Fecha de Vencimiento:
-
Estado:
-
- ✓ Activo
-
- ✗ Inactivo
-
-
-
-
-
-
-
-
📦 Información de Stock
-
Stock Actual: unidades
-
Stock Mínimo: unidades
-
Estado:
-
-
-
-
-
-
-
⚠️ ¡Atención! Stock crítico - Considerar reabastecer
-
-
⚠️ Stock bajo - Planificar reabastecimiento
-
-
-
-
-
-
-
- 0): ?>
-
-
⚠️ Producto con Referencias
-
Este producto está siendo utilizado en pedido(s). No se puede eliminar directamente.
-
-
-
Opciones Disponibles
-
-
-
-
❌ Desactivar Producto
-
Oculta el producto de búsquedas manteniendo todas las referencias intactas.
-
-
-
✅ Activar Producto
-
Hace el producto visible y disponible para nuevos pedidos.
-
-
-
-
-
-
🔄 Reducir Stock Mínimo a 0
-
Marca el producto como sin stock mínimo manteniendo el historial de pedidos.
-
-
-
-
-
📋 Ver Pedidos Relacionados
-
Consulta qué pedidos contienen este producto.
-
- Ver Pedidos
-
-
-
-
-
-
✅ Producto sin Referencias
-
Este producto no está siendo utilizado en ningún pedido. Se puede eliminar de forma segura.
-
-
-
-
-
-
-
-
-
⚠️ Zona Peligrosa
-
- La eliminación forzada ignora todas las restricciones y puede causar inconsistencias en la base de datos.
-
-
- 🗑️ Forzar Eliminación
-
-
-
-
-
\ No newline at end of file
diff --git a/files/gestionar_producto_modal.php b/files/gestionar_producto_modal.php
deleted file mode 100644
index 9b1f933..0000000
--- a/files/gestionar_producto_modal.php
+++ /dev/null
@@ -1,555 +0,0 @@
-prepare($consulta_producto);
- $stmt_producto->bindParam(':id', $id_producto, PDO::PARAM_INT);
- $stmt_producto->execute();
- $producto = $stmt_producto->fetch(PDO::FETCH_ASSOC);
-
- if (!$producto) {
- header("Location: productostabla.php");
- exit();
- }
-
- // Verificar referencias en detalle_pedidos
- $consulta_referencias = "SELECT COUNT(*) as total FROM detalle_pedidos WHERE ID_PRODUCTO = :id";
- $stmt_referencias = $pdo_conexion->prepare($consulta_referencias);
- $stmt_referencias->bindParam(':id', $id_producto, PDO::PARAM_INT);
- $stmt_referencias->execute();
- $referencias = $stmt_referencias->fetch(PDO::FETCH_ASSOC);
-
- } catch (PDOException $e) {
- header("Location: productostabla.php");
- exit();
- }
-} else {
- header("Location: productostabla.php");
- exit();
-}
-?>
-
-
-
-
-
-
- Gestionar Producto - Panadería
-
-
-
-
-
-
-
-
-
-
-
- info
- Información General
-
-
- Precio:
- $
-
-
- Stock:
- unidades
-
-
- Categoría:
-
-
-
- Estado:
-
-
-
- check_circle
- Activo
-
-
-
- cancel
- Inactivo
-
-
-
-
-
-
-
-
- schedule
- Fechas y Vencimiento
-
-
- Fecha de Vencimiento:
-
-
-
- Referencias en Pedidos:
-
- 0): ?>
-
- pedido(s)
-
-
-
- Sin referencias
-
-
-
-
-
-
-
- 0): ?>
-
-
- warning
- Producto con Referencias
-
-
Este producto está siendo utilizado en pedido(s). No se puede eliminar directamente.
-
-
-
-
-
-
-
- delete
- Eliminar Producto
-
-
Elimina permanentemente el producto. Esta acción no se puede deshacer.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
✓
-
-
-
-
-
- ⏱️ Esta ventana se cerrará automáticamente en 5 segundos.
-
-
-
-
-
-
-
-
diff --git a/files/img/992710.png b/files/img/992710.png
deleted file mode 100644
index 1dade7e..0000000
Binary files a/files/img/992710.png and /dev/null differ
diff --git a/files/img/Local.png b/files/img/Local.png
deleted file mode 100644
index c1ed2cf..0000000
Binary files a/files/img/Local.png and /dev/null differ
diff --git a/files/img/PAN-INTEGRAL.jpg b/files/img/PAN-INTEGRAL.jpg
deleted file mode 100644
index 879660a..0000000
Binary files a/files/img/PAN-INTEGRAL.jpg and /dev/null differ
diff --git a/files/img/Pan1.jpg b/files/img/Pan1.jpg
deleted file mode 100644
index dd4bfca..0000000
Binary files a/files/img/Pan1.jpg and /dev/null differ
diff --git a/files/img/arequipe-alpina.png b/files/img/arequipe-alpina.png
deleted file mode 100644
index 508908f..0000000
Binary files a/files/img/arequipe-alpina.png and /dev/null differ
diff --git a/files/img/baguette.jpg b/files/img/baguette.jpg
deleted file mode 100644
index 5121398..0000000
Binary files a/files/img/baguette.jpg and /dev/null differ
diff --git a/files/img/brazoreina1.jpg b/files/img/brazoreina1.jpg
deleted file mode 100644
index 5183e0a..0000000
Binary files a/files/img/brazoreina1.jpg and /dev/null differ
diff --git a/files/img/browni-con-nueces.jpg b/files/img/browni-con-nueces.jpg
deleted file mode 100644
index 2d6b6f2..0000000
Binary files a/files/img/browni-con-nueces.jpg and /dev/null differ
diff --git a/files/img/brownie1.jpg b/files/img/brownie1.jpg
deleted file mode 100644
index 0ecee86..0000000
Binary files a/files/img/brownie1.jpg and /dev/null differ
diff --git a/files/img/categoria/flan de caramelo.jpeg b/files/img/categoria/flan de caramelo.jpeg
deleted file mode 100644
index 39d4910..0000000
Binary files a/files/img/categoria/flan de caramelo.jpeg and /dev/null differ
diff --git a/files/img/categoria/galleta avena.jpeg b/files/img/categoria/galleta avena.jpeg
deleted file mode 100644
index b5d648b..0000000
Binary files a/files/img/categoria/galleta avena.jpeg and /dev/null differ
diff --git a/files/img/categoria/galleta chocolate.jpeg b/files/img/categoria/galleta chocolate.jpeg
deleted file mode 100644
index 05fce90..0000000
Binary files a/files/img/categoria/galleta chocolate.jpeg and /dev/null differ
diff --git a/files/img/categoria/galleta integral.jpeg b/files/img/categoria/galleta integral.jpeg
deleted file mode 100644
index 2f71315..0000000
Binary files a/files/img/categoria/galleta integral.jpeg and /dev/null differ
diff --git a/files/img/categoria/galleta mantequilla.jpeg b/files/img/categoria/galleta mantequilla.jpeg
deleted file mode 100644
index 8d1d193..0000000
Binary files a/files/img/categoria/galleta mantequilla.jpeg and /dev/null differ
diff --git a/files/img/categoria/galleta vainilla.jpeg b/files/img/categoria/galleta vainilla.jpeg
deleted file mode 100644
index f2d6d98..0000000
Binary files a/files/img/categoria/galleta vainilla.jpeg and /dev/null differ
diff --git a/files/img/categoria/hojaldre bocadillo.jpeg b/files/img/categoria/hojaldre bocadillo.jpeg
deleted file mode 100644
index c9db65d..0000000
Binary files a/files/img/categoria/hojaldre bocadillo.jpeg and /dev/null differ
diff --git a/files/img/categoria/hojaldre pollo.jpeg b/files/img/categoria/hojaldre pollo.jpeg
deleted file mode 100644
index 3182845..0000000
Binary files a/files/img/categoria/hojaldre pollo.jpeg and /dev/null differ
diff --git a/files/img/categoria/hojaldre queso.jpeg b/files/img/categoria/hojaldre queso.jpeg
deleted file mode 100644
index 7b42ddc..0000000
Binary files a/files/img/categoria/hojaldre queso.jpeg and /dev/null differ
diff --git a/files/img/categoria/merengon.jpeg b/files/img/categoria/merengon.jpeg
deleted file mode 100644
index 59b10b6..0000000
Binary files a/files/img/categoria/merengon.jpeg and /dev/null differ
diff --git a/files/img/categoria/milhoja.jpeg b/files/img/categoria/milhoja.jpeg
deleted file mode 100644
index 34ff6ef..0000000
Binary files a/files/img/categoria/milhoja.jpeg and /dev/null differ
diff --git a/files/img/categoria/napoleon.jpeg b/files/img/categoria/napoleon.jpeg
deleted file mode 100644
index af1f734..0000000
Binary files a/files/img/categoria/napoleon.jpeg and /dev/null differ
diff --git "a/files/img/categoria/pan alin\314\203ado.jpeg" "b/files/img/categoria/pan alin\314\203ado.jpeg"
deleted file mode 100644
index c997f05..0000000
Binary files "a/files/img/categoria/pan alin\314\203ado.jpeg" and /dev/null differ
diff --git a/files/img/categoria/pan blandito .jpeg b/files/img/categoria/pan blandito .jpeg
deleted file mode 100644
index f00869c..0000000
Binary files a/files/img/categoria/pan blandito .jpeg and /dev/null differ
diff --git a/files/img/categoria/pan campesino.jpeg b/files/img/categoria/pan campesino.jpeg
deleted file mode 100644
index fb1454c..0000000
Binary files a/files/img/categoria/pan campesino.jpeg and /dev/null differ
diff --git a/files/img/categoria/pan coco.jpeg b/files/img/categoria/pan coco.jpeg
deleted file mode 100644
index 941fa72..0000000
Binary files a/files/img/categoria/pan coco.jpeg and /dev/null differ
diff --git a/files/img/categoria/pan frances.jpeg b/files/img/categoria/pan frances.jpeg
deleted file mode 100644
index 3c7ec0f..0000000
Binary files a/files/img/categoria/pan frances.jpeg and /dev/null differ
diff --git a/files/img/categoria/pan maiz.jpeg b/files/img/categoria/pan maiz.jpeg
deleted file mode 100644
index 2c63dae..0000000
Binary files a/files/img/categoria/pan maiz.jpeg and /dev/null differ
diff --git a/files/img/categoria/pan queso.jpeg b/files/img/categoria/pan queso.jpeg
deleted file mode 100644
index 7f04f23..0000000
Binary files a/files/img/categoria/pan queso.jpeg and /dev/null differ
diff --git a/files/img/categoria/pan rollo.jpeg b/files/img/categoria/pan rollo.jpeg
deleted file mode 100644
index 4bb0829..0000000
Binary files a/files/img/categoria/pan rollo.jpeg and /dev/null differ
diff --git a/files/img/categoria/pandebono.jpeg b/files/img/categoria/pandebono.jpeg
deleted file mode 100644
index 49e7df1..0000000
Binary files a/files/img/categoria/pandebono.jpeg and /dev/null differ
diff --git a/files/img/categoria/pastel carne.jpeg b/files/img/categoria/pastel carne.jpeg
deleted file mode 100644
index 8f14805..0000000
Binary files a/files/img/categoria/pastel carne.jpeg and /dev/null differ
diff --git a/files/img/categoria/tamal de pollo .jpeg b/files/img/categoria/tamal de pollo .jpeg
deleted file mode 100644
index 5cf6a5b..0000000
Binary files a/files/img/categoria/tamal de pollo .jpeg and /dev/null differ
diff --git a/files/img/categoria/tamal santandereano .jpeg b/files/img/categoria/tamal santandereano .jpeg
deleted file mode 100644
index de8911d..0000000
Binary files a/files/img/categoria/tamal santandereano .jpeg and /dev/null differ
diff --git a/files/img/categoria/tamal tolimense.jpeg b/files/img/categoria/tamal tolimense.jpeg
deleted file mode 100644
index 112b376..0000000
Binary files a/files/img/categoria/tamal tolimense.jpeg and /dev/null differ
diff --git a/files/img/categoria/torta chocolate.jpeg b/files/img/categoria/torta chocolate.jpeg
deleted file mode 100644
index 01800c2..0000000
Binary files a/files/img/categoria/torta chocolate.jpeg and /dev/null differ
diff --git a/files/img/categoria/torta tres leches.jpeg b/files/img/categoria/torta tres leches.jpeg
deleted file mode 100644
index 6406f12..0000000
Binary files a/files/img/categoria/torta tres leches.jpeg and /dev/null differ
diff --git a/files/img/categoria/torta zanahoria.jpeg b/files/img/categoria/torta zanahoria.jpeg
deleted file mode 100644
index 0e71597..0000000
Binary files a/files/img/categoria/torta zanahoria.jpeg and /dev/null differ
diff --git a/files/img/categoria/tres leches vaso .jpeg b/files/img/categoria/tres leches vaso .jpeg
deleted file mode 100644
index ff39005..0000000
Binary files a/files/img/categoria/tres leches vaso .jpeg and /dev/null differ
diff --git a/files/img/cheesecake-frutos-rojos.jpg b/files/img/cheesecake-frutos-rojos.jpg
deleted file mode 100644
index 36ebc57..0000000
Binary files a/files/img/cheesecake-frutos-rojos.jpg and /dev/null differ
diff --git a/files/img/chicharrona.png b/files/img/chicharrona.png
deleted file mode 100644
index 23b7561..0000000
Binary files a/files/img/chicharrona.png and /dev/null differ
diff --git a/files/img/croissant1.jpg b/files/img/croissant1.jpg
deleted file mode 100644
index 0f3c958..0000000
Binary files a/files/img/croissant1.jpg and /dev/null differ
diff --git a/files/img/croissants.jpg b/files/img/croissants.jpg
deleted file mode 100644
index 2ffc6b8..0000000
Binary files a/files/img/croissants.jpg and /dev/null differ
diff --git a/files/img/empanadas.png b/files/img/empanadas.png
deleted file mode 100644
index 268d546..0000000
Binary files a/files/img/empanadas.png and /dev/null differ
diff --git a/files/img/galleta1.jpg b/files/img/galleta1.jpg
deleted file mode 100644
index dba5b74..0000000
Binary files a/files/img/galleta1.jpg and /dev/null differ
diff --git a/files/img/galletas-de-avena-con-pasas-y-nuez.jpg b/files/img/galletas-de-avena-con-pasas-y-nuez.jpg
deleted file mode 100644
index 89cb9c3..0000000
Binary files a/files/img/galletas-de-avena-con-pasas-y-nuez.jpg and /dev/null differ
diff --git a/files/img/galletasmantequilla.jpg b/files/img/galletasmantequilla.jpg
deleted file mode 100644
index 338de8e..0000000
Binary files a/files/img/galletasmantequilla.jpg and /dev/null differ
diff --git a/files/img/galletatresojos.png b/files/img/galletatresojos.png
deleted file mode 100644
index d616ab7..0000000
Binary files a/files/img/galletatresojos.png and /dev/null differ
diff --git a/files/img/hojaldre1.jpg b/files/img/hojaldre1.jpg
deleted file mode 100644
index 288ac40..0000000
Binary files a/files/img/hojaldre1.jpg and /dev/null differ
diff --git a/files/img/iconoboton1.jpg b/files/img/iconoboton1.jpg
deleted file mode 100644
index a04dc73..0000000
Binary files a/files/img/iconoboton1.jpg and /dev/null differ
diff --git a/files/img/jugo.jpg b/files/img/jugo.jpg
deleted file mode 100644
index 4b790b2..0000000
Binary files a/files/img/jugo.jpg and /dev/null differ
diff --git a/files/img/kumiss.1.png b/files/img/kumiss.1.png
deleted file mode 100644
index 64c516b..0000000
Binary files a/files/img/kumiss.1.png and /dev/null differ
diff --git a/files/img/logo proyecto.jpeg b/files/img/logo proyecto.jpeg
deleted file mode 100644
index 0026376..0000000
Binary files a/files/img/logo proyecto.jpeg and /dev/null differ
diff --git a/files/img/logoprincipal.jpg b/files/img/logoprincipal.jpg
deleted file mode 100644
index 0026376..0000000
Binary files a/files/img/logoprincipal.jpg and /dev/null differ
diff --git a/files/img/miloha_de_arequipe.jpg b/files/img/miloha_de_arequipe.jpg
deleted file mode 100644
index 2b5bb4e..0000000
Binary files a/files/img/miloha_de_arequipe.jpg and /dev/null differ
diff --git a/files/img/muffins1.jpg b/files/img/muffins1.jpg
deleted file mode 100644
index 8b5766b..0000000
Binary files a/files/img/muffins1.jpg and /dev/null differ
diff --git a/files/img/naranja.jpg b/files/img/naranja.jpg
deleted file mode 100644
index 49e6a48..0000000
Binary files a/files/img/naranja.jpg and /dev/null differ
diff --git a/files/img/naranjaponque.jpg b/files/img/naranjaponque.jpg
deleted file mode 100644
index f4ed502..0000000
Binary files a/files/img/naranjaponque.jpg and /dev/null differ
diff --git a/files/img/pan-con-masa-madre-.jpg b/files/img/pan-con-masa-madre-.jpg
deleted file mode 100644
index c5ddfe0..0000000
Binary files a/files/img/pan-con-masa-madre-.jpg and /dev/null differ
diff --git a/files/img/pan-de-molde.jpg b/files/img/pan-de-molde.jpg
deleted file mode 100644
index c934fc2..0000000
Binary files a/files/img/pan-de-molde.jpg and /dev/null differ
diff --git a/files/img/pan-rtzqhi1ok4k1bxlo.jpg b/files/img/pan-rtzqhi1ok4k1bxlo.jpg
deleted file mode 100644
index 5e48815..0000000
Binary files a/files/img/pan-rtzqhi1ok4k1bxlo.jpg and /dev/null differ
diff --git a/files/img/panabuela1.jpg b/files/img/panabuela1.jpg
deleted file mode 100644
index 87ef700..0000000
Binary files a/files/img/panabuela1.jpg and /dev/null differ
diff --git a/files/img/panbaguette1.jpg b/files/img/panbaguette1.jpg
deleted file mode 100644
index 5ff2ab2..0000000
Binary files a/files/img/panbaguette1.jpg and /dev/null differ
diff --git a/files/img/panblando.jpeg b/files/img/panblando.jpeg
deleted file mode 100644
index 29e595a..0000000
Binary files a/files/img/panblando.jpeg and /dev/null differ
diff --git a/files/img/pancampesino.png b/files/img/pancampesino.png
deleted file mode 100644
index a3b9481..0000000
Binary files a/files/img/pancampesino.png and /dev/null differ
diff --git a/files/img/pandebono.png b/files/img/pandebono.png
deleted file mode 100644
index 4cc61dd..0000000
Binary files a/files/img/pandebono.png and /dev/null differ
diff --git a/files/img/pangrande1.jpg b/files/img/pangrande1.jpg
deleted file mode 100644
index cd2c2ab..0000000
Binary files a/files/img/pangrande1.jpg and /dev/null differ
diff --git a/files/img/panhamburguesa.jpg b/files/img/panhamburguesa.jpg
deleted file mode 100644
index 9cd6656..0000000
Binary files a/files/img/panhamburguesa.jpg and /dev/null differ
diff --git a/files/img/pantrenza.jpg b/files/img/pantrenza.jpg
deleted file mode 100644
index b18b142..0000000
Binary files a/files/img/pantrenza.jpg and /dev/null differ
diff --git a/files/img/panunidad1.jpg b/files/img/panunidad1.jpg
deleted file mode 100644
index e7e4f31..0000000
Binary files a/files/img/panunidad1.jpg and /dev/null differ
diff --git a/files/img/panunidad2.jpg b/files/img/panunidad2.jpg
deleted file mode 100644
index 051ad0d..0000000
Binary files a/files/img/panunidad2.jpg and /dev/null differ
diff --git a/files/img/ponquenaranja.png b/files/img/ponquenaranja.png
deleted file mode 100644
index b2f3ba2..0000000
Binary files a/files/img/ponquenaranja.png and /dev/null differ
diff --git a/files/img/postreleche.jpg b/files/img/postreleche.jpg
deleted file mode 100644
index e6ce8bc..0000000
Binary files a/files/img/postreleche.jpg and /dev/null differ
diff --git a/files/img/tamal1.jpg b/files/img/tamal1.jpg
deleted file mode 100644
index b9aa2fa..0000000
Binary files a/files/img/tamal1.jpg and /dev/null differ
diff --git a/files/img/tamales.jpg b/files/img/tamales.jpg
deleted file mode 100644
index b8b8d92..0000000
Binary files a/files/img/tamales.jpg and /dev/null differ
diff --git a/files/img/torta1.jpg b/files/img/torta1.jpg
deleted file mode 100644
index d457539..0000000
Binary files a/files/img/torta1.jpg and /dev/null differ
diff --git a/files/img/torta2.jpg b/files/img/torta2.jpg
deleted file mode 100644
index b04e62f..0000000
Binary files a/files/img/torta2.jpg and /dev/null differ
diff --git a/files/img/tortachocolate.jpg b/files/img/tortachocolate.jpg
deleted file mode 100644
index 18ca9b6..0000000
Binary files a/files/img/tortachocolate.jpg and /dev/null differ
diff --git a/files/img/tortatresleches.png b/files/img/tortatresleches.png
deleted file mode 100644
index 72fa823..0000000
Binary files a/files/img/tortatresleches.png and /dev/null differ
diff --git a/files/img/yogurt1.jpg b/files/img/yogurt1.jpg
deleted file mode 100644
index 3d4c174..0000000
Binary files a/files/img/yogurt1.jpg and /dev/null differ
diff --git a/files/imprimir_pedido.php b/files/imprimir_pedido.php
deleted file mode 100644
index be50486..0000000
--- a/files/imprimir_pedido.php
+++ /dev/null
@@ -1,232 +0,0 @@
-
-
-
-
-
-
-
- Pedido # - Panadería
-
-
-
-
-
-
-
-
Información del Cliente
-
Nombre:
-
Email:
-
-
Teléfono:
-
-
-
-
-
Información del Pedido
-
Número de Pedido: #
-
Fecha:
-
Estado:
-
-
-
-
-
-
-
-
- | Producto |
- Cantidad |
- Precio Unitario |
- Subtotal |
-
-
-
-
-
- |
- |
- $ |
- $ |
-
-
-
-
-
- | TOTAL: |
- $ |
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/files/js/admin-products.js b/files/js/admin-products.js
deleted file mode 100644
index 4ff5894..0000000
--- a/files/js/admin-products.js
+++ /dev/null
@@ -1,462 +0,0 @@
-/**
- * JavaScript para el Dashboard del Administrador
- * Integración con la API REST de productos
- */
-
-class AdminProductManager {
- constructor() {
- this.apiUrl = 'api_productos_admin.php';
- this.initializeEventListeners();
- this.loadProductos();
- }
-
- /**
- * Inicializar event listeners
- */
- initializeEventListeners() {
- // Formulario de actualización rápida de precios
- document.addEventListener('click', (e) => {
- if (e.target.matches('.btn-actualizar-precio')) {
- this.mostrarModalActualizarPrecio(e.target.dataset.productoId);
- }
-
- if (e.target.matches('.btn-actualizar-stock')) {
- this.mostrarModalActualizarStock(e.target.dataset.productoId);
- }
-
- if (e.target.matches('.btn-toggle-producto')) {
- this.toggleProducto(e.target.dataset.productoId);
- }
- });
-
- // Formulario de búsqueda
- const searchForm = document.getElementById('form-buscar-productos');
- if (searchForm) {
- searchForm.addEventListener('submit', (e) => {
- e.preventDefault();
- this.buscarProductos();
- });
- }
- }
-
- /**
- * Cargar lista de productos
- */
- async loadProductos(page = 1, filtros = {}) {
- try {
- const params = new URLSearchParams({
- page: page,
- limit: 20,
- ...filtros
- });
-
- const response = await fetch(`${this.apiUrl}?${params}`);
- const data = await response.json();
-
- if (data.success) {
- this.renderProductos(data.data);
- this.renderPaginacion(data.pagination);
- } else {
- this.showAlert('Error al cargar productos: ' + data.message, 'error');
- }
- } catch (error) {
- this.showAlert('Error de conexión: ' + error.message, 'error');
- }
- }
-
- /**
- * Actualizar precio de producto
- */
- async actualizarPrecio(productoId, nuevoPrecio) {
- try {
- const response = await fetch(this.apiUrl, {
- method: 'PATCH',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify({
- id: productoId,
- campo: 'precio',
- valor: nuevoPrecio
- })
- });
-
- const data = await response.json();
-
- if (data.success) {
- this.showAlert(data.message, 'success');
- this.actualizarProductoEnDOM(productoId, 'precio', data.nuevo_valor);
- } else {
- this.showAlert('Error: ' + data.message, 'error');
- }
- } catch (error) {
- this.showAlert('Error de conexión: ' + error.message, 'error');
- }
- }
-
- /**
- * Actualizar stock de producto
- */
- async actualizarStock(productoId, nuevoStock) {
- try {
- const response = await fetch(this.apiUrl, {
- method: 'PATCH',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify({
- id: productoId,
- campo: 'stock',
- valor: nuevoStock
- })
- });
-
- const data = await response.json();
-
- if (data.success) {
- this.showAlert(data.message, 'success');
- this.actualizarProductoEnDOM(productoId, 'stock', data.nuevo_valor);
- } else {
- this.showAlert('Error: ' + data.message, 'error');
- }
- } catch (error) {
- this.showAlert('Error de conexión: ' + error.message, 'error');
- }
- }
-
- /**
- * Toggle estado activo/inactivo del producto
- */
- async toggleProducto(productoId) {
- try {
- const productoElement = document.querySelector(`[data-producto-id="${productoId}"]`);
- const isActive = !productoElement.classList.contains('producto-inactivo');
-
- const response = await fetch(this.apiUrl, {
- method: 'PATCH',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify({
- id: productoId,
- campo: 'activo',
- valor: isActive ? 0 : 1
- })
- });
-
- const data = await response.json();
-
- if (data.success) {
- this.showAlert(data.message, 'success');
- this.actualizarEstadoProductoEnDOM(productoId, data.nuevo_valor);
- } else {
- this.showAlert('Error: ' + data.message, 'error');
- }
- } catch (error) {
- this.showAlert('Error de conexión: ' + error.message, 'error');
- }
- }
-
- /**
- * Crear nuevo producto
- */
- async crearProducto(datosProducto) {
- try {
- const response = await fetch(this.apiUrl, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify(datosProducto)
- });
-
- const data = await response.json();
-
- if (data.success) {
- this.showAlert(data.message, 'success');
- this.loadProductos(); // Recargar lista
- } else {
- this.showAlert('Error: ' + data.message, 'error');
- }
- } catch (error) {
- this.showAlert('Error de conexión: ' + error.message, 'error');
- }
- }
-
- /**
- * Mostrar modal para actualizar precio
- */
- mostrarModalActualizarPrecio(productoId) {
- const modal = this.createModal('Actualizar Precio', `
-
- `);
-
- modal.querySelector('#form-actualizar-precio').addEventListener('submit', (e) => {
- e.preventDefault();
- const nuevoPrecio = parseFloat(e.target.nuevo_precio.value);
- this.actualizarPrecio(productoId, nuevoPrecio);
- modal.remove();
- });
-
- document.body.appendChild(modal);
- modal.querySelector('#nuevo-precio').focus();
- }
-
- /**
- * Mostrar modal para actualizar stock
- */
- mostrarModalActualizarStock(productoId) {
- const modal = this.createModal('Actualizar Stock', `
-
- `);
-
- modal.querySelector('#form-actualizar-stock').addEventListener('submit', (e) => {
- e.preventDefault();
- const nuevoStock = parseInt(e.target.nuevo_stock.value);
- this.actualizarStock(productoId, nuevoStock);
- modal.remove();
- });
-
- document.body.appendChild(modal);
- modal.querySelector('#nuevo-stock').focus();
- }
-
- /**
- * Crear modal genérico
- */
- createModal(title, content) {
- const modal = document.createElement('div');
- modal.className = 'modal';
- modal.style.cssText = `
- position: fixed;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- background: rgba(0,0,0,0.5);
- display: flex;
- align-items: center;
- justify-content: center;
- z-index: 10000;
- `;
-
- modal.innerHTML = `
-
-
${title}
- ${content}
-
- `;
-
- // Cerrar al hacer clic fuera del modal
- modal.addEventListener('click', (e) => {
- if (e.target === modal) {
- modal.remove();
- }
- });
-
- return modal;
- }
-
- /**
- * Actualizar producto en el DOM
- */
- actualizarProductoEnDOM(productoId, campo, valor) {
- const elemento = document.querySelector(`[data-producto-id="${productoId}"]`);
- if (elemento) {
- if (campo === 'precio') {
- const precioElement = elemento.querySelector('.precio');
- if (precioElement) {
- precioElement.textContent = `$${parseFloat(valor).toLocaleString()}`;
- this.highlightElement(precioElement);
- }
- } else if (campo === 'stock') {
- const stockElement = elemento.querySelector('.stock');
- if (stockElement) {
- stockElement.textContent = `Stock: ${valor}`;
- this.highlightElement(stockElement);
- }
- }
- }
- }
-
- /**
- * Actualizar estado del producto en el DOM
- */
- actualizarEstadoProductoEnDOM(productoId, activo) {
- const elemento = document.querySelector(`[data-producto-id="${productoId}"]`);
- if (elemento) {
- if (activo) {
- elemento.classList.remove('producto-inactivo');
- elemento.style.opacity = '1';
- } else {
- elemento.classList.add('producto-inactivo');
- elemento.style.opacity = '0.5';
- }
- }
- }
-
- /**
- * Resaltar elemento
- */
- highlightElement(element) {
- element.style.transition = 'background-color 0.3s ease';
- element.style.backgroundColor = '#28a745';
- element.style.color = 'white';
-
- setTimeout(() => {
- element.style.backgroundColor = '';
- element.style.color = '';
- }, 1500);
- }
-
- /**
- * Renderizar lista de productos
- */
- renderProductos(productos) {
- const container = document.getElementById('productos-container');
- if (!container) return;
-
- container.innerHTML = productos.map(producto => `
-
-
${producto.NOMBRE_PRODUCTO}
-
${producto.categoria_nombre || 'Sin categoría'}
-
$${parseFloat(producto.PRECIO_PRODUCTO).toLocaleString()}
-
Stock: ${producto.PRODUCTO_STOCK_MIN}
-
-
-
-
-
-
- `).join('');
- }
-
- /**
- * Renderizar paginación
- */
- renderPaginacion(pagination) {
- const container = document.getElementById('paginacion-container');
- if (!container) return;
-
- let html = '';
- container.innerHTML = html;
- }
-
- /**
- * Mostrar alerta
- */
- showAlert(message, type = 'info') {
- const alert = document.createElement('div');
- alert.className = `alert alert-${type}`;
- alert.style.cssText = `
- position: fixed;
- top: 20px;
- right: 20px;
- z-index: 10001;
- padding: 12px 16px;
- border-radius: 4px;
- color: white;
- font-weight: bold;
- max-width: 400px;
- background: ${type === 'success' ? '#28a745' : type === 'error' ? '#dc3545' : '#17a2b8'};
- `;
- alert.textContent = message;
-
- document.body.appendChild(alert);
-
- setTimeout(() => {
- alert.remove();
- }, 5000);
- }
-}
-
-// Inicializar cuando el DOM esté listo
-document.addEventListener('DOMContentLoaded', function() {
- if (document.getElementById('productos-container')) {
- window.adminManager = new AdminProductManager();
- }
-});
-
-// CSS básico para las tarjetas de productos
-const style = document.createElement('style');
-style.textContent = `
- .producto-card {
- border: 1px solid #ddd;
- border-radius: 8px;
- padding: 15px;
- margin-bottom: 15px;
- background: white;
- transition: all 0.3s ease;
- }
-
- .producto-card:hover {
- box-shadow: 0 2px 8px rgba(0,0,0,0.1);
- }
-
- .producto-inactivo {
- opacity: 0.5;
- filter: grayscale(50%);
- }
-
- .acciones {
- margin-top: 10px;
- }
-
- .acciones .btn {
- margin-right: 5px;
- margin-bottom: 5px;
- }
-
- .pagination {
- text-align: center;
- margin: 20px 0;
- }
-
- .pagination .btn {
- margin: 0 2px;
- }
-`;
-document.head.appendChild(style);
diff --git a/files/js/menu-updater.js b/files/js/menu-updater.js
deleted file mode 100644
index 410181b..0000000
--- a/files/js/menu-updater.js
+++ /dev/null
@@ -1,403 +0,0 @@
-/**
- * Cliente JavaScript para Server-Sent Events
- * Escucha actualizaciones en tiempo real del menú
- */
-
-class MenuUpdater {
- constructor(options = {}) {
- this.baseUrl = options.baseUrl || '';
- this.eventSource = null;
- this.lastCheck = options.lastCheck || Math.floor(Date.now() / 1000);
- this.reconnectInterval = options.reconnectInterval || 5000;
- this.maxReconnectAttempts = options.maxReconnectAttempts || 10;
- this.reconnectAttempts = 0;
- this.isConnected = false;
-
- // Callbacks
- this.onMenuUpdate = options.onMenuUpdate || this.defaultMenuUpdateHandler;
- this.onConnected = options.onConnected || this.defaultConnectedHandler;
- this.onError = options.onError || this.defaultErrorHandler;
- this.onDisconnected = options.onDisconnected || this.defaultDisconnectedHandler;
-
- // Elementos del DOM
- this.notificationContainer = null;
- this.createNotificationContainer();
-
- this.init();
- }
-
- /**
- * Inicializar la conexión SSE
- */
- init() {
- if (typeof(EventSource) === "undefined") {
- console.error("Tu navegador no soporta Server-Sent Events");
- this.showNotification("Tu navegador no soporta actualizaciones en tiempo real", "warning");
- return;
- }
-
- this.connect();
- }
-
- /**
- * Conectar al servidor SSE
- */
- connect() {
- if (this.eventSource) {
- this.disconnect();
- }
-
- const url = `${this.baseUrl}sse_menu_updates.php?last_check=${this.lastCheck}`;
- console.log("Conectando a SSE:", url);
-
- this.eventSource = new EventSource(url);
-
- // Evento de conexión exitosa
- this.eventSource.addEventListener('connected', (event) => {
- this.isConnected = true;
- this.reconnectAttempts = 0;
- const data = JSON.parse(event.data);
- console.log("Conectado a SSE:", data);
- this.onConnected(data);
- });
-
- // Evento de actualización del menú
- this.eventSource.addEventListener('menu_update', (event) => {
- const data = JSON.parse(event.data);
- console.log("Actualización del menú recibida:", data);
- this.lastCheck = data.timestamp;
- this.onMenuUpdate(data);
- });
-
- // Evento heartbeat
- this.eventSource.addEventListener('heartbeat', (event) => {
- const data = JSON.parse(event.data);
- console.log("Heartbeat recibido:", data.timestamp);
- });
-
- // Evento de desconexión
- this.eventSource.addEventListener('disconnected', (event) => {
- const data = JSON.parse(event.data);
- console.log("Desconectado del SSE:", data);
- this.onDisconnected(data);
- });
-
- // Evento de error
- this.eventSource.addEventListener('error', (event) => {
- let errorData = { message: "Error de conexión" };
- try {
- errorData = JSON.parse(event.data);
- } catch (e) {
- // Si no se puede parsear, usar mensaje por defecto
- }
- console.error("Error en SSE:", errorData);
- this.onError(errorData);
- });
-
- // Manejar errores de conexión
- this.eventSource.onerror = (event) => {
- console.error("Error en EventSource:", event);
- this.isConnected = false;
-
- if (this.eventSource.readyState === EventSource.CLOSED) {
- this.attemptReconnect();
- }
- };
- }
-
- /**
- * Desconectar del servidor SSE
- */
- disconnect() {
- if (this.eventSource) {
- this.eventSource.close();
- this.eventSource = null;
- this.isConnected = false;
- }
- }
-
- /**
- * Intentar reconexión automática
- */
- attemptReconnect() {
- if (this.reconnectAttempts >= this.maxReconnectAttempts) {
- console.error("Máximo número de intentos de reconexión alcanzado");
- this.showNotification("No se pudo conectar para actualizaciones en tiempo real", "error");
- return;
- }
-
- this.reconnectAttempts++;
- console.log(`Intento de reconexión ${this.reconnectAttempts}/${this.maxReconnectAttempts} en ${this.reconnectInterval}ms`);
-
- setTimeout(() => {
- this.connect();
- }, this.reconnectInterval);
- }
-
- /**
- * Handler por defecto para actualizaciones del menú
- */
- defaultMenuUpdateHandler(data) {
- this.showNotification(`Menú actualizado: ${data.total_cambios} cambios detectados`, "info");
-
- // Actualizar productos en el DOM si están presentes
- this.updateProductsInDOM(data.productos);
-
- // Mostrar notificación detallada
- this.showDetailedUpdateNotification(data);
- }
-
- /**
- * Handler por defecto para conexión exitosa
- */
- defaultConnectedHandler(data) {
- this.showNotification("Conectado para actualizaciones en tiempo real", "success");
- }
-
- /**
- * Handler por defecto para errores
- */
- defaultErrorHandler(data) {
- this.showNotification(`Error: ${data.message}`, "error");
- }
-
- /**
- * Handler por defecto para desconexión
- */
- defaultDisconnectedHandler(data) {
- this.showNotification("Desconectado de actualizaciones en tiempo real", "warning");
- }
-
- /**
- * Actualizar productos en el DOM
- */
- updateProductsInDOM(productos) {
- productos.forEach(producto => {
- // Buscar elementos del producto en el DOM por ID
- const precioElement = document.querySelector(`[data-producto-id="${producto.ID_PRODUCTO}"] .precio`);
- const stockElement = document.querySelector(`[data-producto-id="${producto.ID_PRODUCTO}"] .stock`);
- const productoElement = document.querySelector(`[data-producto-id="${producto.ID_PRODUCTO}"]`);
-
- if (precioElement) {
- precioElement.textContent = `$${parseFloat(producto.PRECIO_PRODUCTO).toLocaleString()}`;
- this.highlightElement(precioElement);
- }
-
- if (stockElement) {
- stockElement.textContent = `Stock: ${producto.PRODUCTO_STOCK_MIN}`;
- this.highlightElement(stockElement);
- }
-
- // Manejar productos desactivados
- if (productoElement) {
- if (producto.ACTIVO == 0) {
- productoElement.style.opacity = '0.5';
- productoElement.style.filter = 'grayscale(50%)';
- } else {
- productoElement.style.opacity = '1';
- productoElement.style.filter = 'none';
- }
- }
- });
- }
-
- /**
- * Resaltar elemento actualizado
- */
- highlightElement(element) {
- element.style.transition = 'background-color 0.3s ease';
- element.style.backgroundColor = '#ffeb3b';
-
- setTimeout(() => {
- element.style.backgroundColor = '';
- }, 2000);
- }
-
- /**
- * Mostrar notificación detallada de actualización
- */
- showDetailedUpdateNotification(data) {
- if (data.logs && data.logs.length > 0) {
- const cambios = data.logs.map(log => {
- let mensaje = `${log.NOMBRE_PRODUCTO}: `;
- switch (log.tipo_cambio) {
- case 'precio':
- mensaje += `Precio cambiado de $${log.valor_anterior} a $${log.valor_nuevo}`;
- break;
- case 'stock':
- mensaje += `Stock cambiado de ${log.valor_anterior} a ${log.valor_nuevo}`;
- break;
- case 'activacion':
- mensaje += 'Producto activado';
- break;
- case 'desactivacion':
- mensaje += 'Producto desactivado';
- break;
- default:
- mensaje += `${log.tipo_cambio}: ${log.valor_anterior} → ${log.valor_nuevo}`;
- }
- return mensaje;
- });
-
- this.showNotification(
- `Cambios recientes:\n${cambios.slice(0, 3).join('\n')}${cambios.length > 3 ? '\n...' : ''}`,
- "info",
- 5000
- );
- }
- }
-
- /**
- * Crear contenedor de notificaciones
- */
- createNotificationContainer() {
- if (document.getElementById('sse-notifications')) {
- return;
- }
-
- const container = document.createElement('div');
- container.id = 'sse-notifications';
- container.style.cssText = `
- position: fixed;
- top: 20px;
- right: 20px;
- z-index: 10000;
- max-width: 400px;
- `;
- document.body.appendChild(container);
- this.notificationContainer = container;
- }
-
- /**
- * Mostrar notificación
- */
- showNotification(message, type = 'info', duration = 3000) {
- const notification = document.createElement('div');
- notification.style.cssText = `
- background: ${this.getNotificationColor(type)};
- color: white;
- padding: 12px 16px;
- margin-bottom: 10px;
- border-radius: 4px;
- box-shadow: 0 2px 8px rgba(0,0,0,0.2);
- font-family: Arial, sans-serif;
- font-size: 14px;
- line-height: 1.4;
- white-space: pre-line;
- animation: slideIn 0.3s ease-out;
- cursor: pointer;
- `;
-
- notification.textContent = message;
-
- // Agregar animación CSS
- if (!document.getElementById('sse-notification-styles')) {
- const style = document.createElement('style');
- style.id = 'sse-notification-styles';
- style.textContent = `
- @keyframes slideIn {
- from { transform: translateX(100%); opacity: 0; }
- to { transform: translateX(0); opacity: 1; }
- }
- @keyframes slideOut {
- from { transform: translateX(0); opacity: 1; }
- to { transform: translateX(100%); opacity: 0; }
- }
- `;
- document.head.appendChild(style);
- }
-
- // Hacer clic para cerrar
- notification.addEventListener('click', () => {
- this.removeNotification(notification);
- });
-
- this.notificationContainer.appendChild(notification);
-
- // Auto-remover después del tiempo especificado
- if (duration > 0) {
- setTimeout(() => {
- this.removeNotification(notification);
- }, duration);
- }
- }
-
- /**
- * Remover notificación con animación
- */
- removeNotification(notification) {
- notification.style.animation = 'slideOut 0.3s ease-in';
- setTimeout(() => {
- if (notification.parentNode) {
- notification.parentNode.removeChild(notification);
- }
- }, 300);
- }
-
- /**
- * Obtener color según tipo de notificación
- */
- getNotificationColor(type) {
- const colors = {
- success: '#4caf50',
- error: '#f44336',
- warning: '#ff9800',
- info: '#2196f3'
- };
- return colors[type] || colors.info;
- }
-
- /**
- * Obtener estado de conexión
- */
- isConnectedToSSE() {
- return this.isConnected && this.eventSource && this.eventSource.readyState === EventSource.OPEN;
- }
-
- /**
- * Destructor
- */
- destroy() {
- this.disconnect();
- if (this.notificationContainer && this.notificationContainer.parentNode) {
- this.notificationContainer.parentNode.removeChild(this.notificationContainer);
- }
- }
-}
-
-// Inicializar automáticamente si se está en una página de menú
-document.addEventListener('DOMContentLoaded', function() {
- // Verificar si estamos en una página que necesita actualizaciones de menú
- const menuElements = document.querySelectorAll('[data-producto-id], .producto-card, .menu-item');
-
- if (menuElements.length > 0) {
- console.log("Página de menú detectada, iniciando MenuUpdater...");
-
- window.menuUpdater = new MenuUpdater({
- onMenuUpdate: function(data) {
- console.log("Actualización personalizada del menú:", data);
-
- // Llamar al handler por defecto
- this.defaultMenuUpdateHandler(data);
-
- // Código personalizado adicional aquí
- // Por ejemplo, recargar carrito, actualizar totales, etc.
- if (typeof updateCartTotals === 'function') {
- updateCartTotals();
- }
- }.bind(window.menuUpdater)
- });
-
- // Agregar evento para limpiar al salir de la página
- window.addEventListener('beforeunload', function() {
- if (window.menuUpdater) {
- window.menuUpdater.destroy();
- }
- });
- }
-});
-
-// Exportar para uso manual
-if (typeof module !== 'undefined' && module.exports) {
- module.exports = MenuUpdater;
-}
diff --git a/files/js/navigation-system.js b/files/js/navigation-system.js
deleted file mode 100644
index fde291a..0000000
--- a/files/js/navigation-system.js
+++ /dev/null
@@ -1,170 +0,0 @@
-/**
- * Sistema de Navegación Inteligente para Panadería
- * Maneja la navegación del navegador de manera inteligente, permitiendo
- * navegación normal dentro del sistema mientras protege contra salidas accidentales
- */
-
-(function() {
- 'use strict';
-
- // Configuración del sistema
- const config = {
- maxBackAttempts: 3,
- confirmationDelay: 1000,
- debugMode: false
- };
-
- // Variables de estado
- let isNavigatingWithinSystem = false;
- let backButtonAttempts = 0;
- let lastNavigationTime = 0;
-
- // Función de logging para debug
- function log(message, data = null) {
- if (config.debugMode) {
- console.log('[NavSystem]', message, data);
- }
- }
-
- // Detectar si una URL es interna al sistema
- function isInternalUrl(url) {
- try {
- const urlObj = new URL(url, window.location.origin);
- const currentDomain = window.location.hostname;
- const targetDomain = urlObj.hostname;
-
- return targetDomain === currentDomain;
- } catch (error) {
- // Si hay error parseando la URL, asumir que es interna (URL relativa)
- return true;
- }
- }
-
- // Detectar clics en enlaces para determinar navegación interna
- function setupLinkDetection() {
- document.addEventListener('click', function(e) {
- const link = e.target.closest('a');
- if (link && link.href) {
- if (isInternalUrl(link.href)) {
- isNavigatingWithinSystem = true;
- lastNavigationTime = Date.now();
- log('Navegación interna detectada', link.href);
-
- // Resetear flag después de un tiempo
- setTimeout(() => {
- isNavigatingWithinSystem = false;
- }, config.confirmationDelay);
- }
- }
- });
- }
-
- // Manejar el botón atrás del navegador
- function setupBackButtonHandling() {
- // Solo aplicar si estamos en un dashboard o página protegida
- const isProtectedPage = window.location.pathname.includes('dashboard') ||
- window.location.pathname.includes('perfil') ||
- window.location.pathname.includes('admin') ||
- window.location.pathname.includes('empleado') ||
- window.location.pathname.includes('cliente');
-
- if (!isProtectedPage) {
- log('Página no protegida, navegación libre');
- return;
- }
-
- // Configurar historial inicial
- if (window.history && window.history.replaceState) {
- history.replaceState(null, null, window.location.pathname);
- }
-
- // Manejar popstate
- window.addEventListener('popstate', function(event) {
- backButtonAttempts++;
- const timeSinceLastNavigation = Date.now() - lastNavigationTime;
-
- log('Popstate detectado', {
- attempts: backButtonAttempts,
- isInternal: isNavigatingWithinSystem,
- timeSince: timeSinceLastNavigation
- });
-
- // Si es navegación reciente dentro del sistema, permitirla
- if (isNavigatingWithinSystem || timeSinceLastNavigation < config.confirmationDelay) {
- log('Navegación interna permitida');
- return;
- }
-
- // Solo mostrar confirmación después de múltiples intentos
- if (backButtonAttempts > config.maxBackAttempts) {
- const userType = getUserType();
- const message = `¿Estás seguro de que quieres cerrar la sesión${userType ? ' de ' + userType : ''}?`;
-
- if (confirm(message)) {
- log('Usuario confirmó salida');
- window.location.href = 'logout.php';
- } else {
- log('Usuario canceló salida');
- backButtonAttempts = 0; // Resetear contador
- history.pushState(null, null, window.location.pathname);
- }
- } else {
- // Permitir navegación normal las primeras veces
- log('Navegación permitida, intento:', backButtonAttempts);
- history.pushState(null, null, window.location.pathname);
- }
- });
- }
-
- // Obtener tipo de usuario para personalizar mensajes
- function getUserType() {
- const path = window.location.pathname;
- if (path.includes('admin')) return 'administrador';
- if (path.includes('empleado')) return 'empleado';
- if (path.includes('cliente')) return 'cliente';
- return null;
- }
-
- // Limpiar datos sensibles solo al cerrar completamente
- function setupCleanup() {
- window.addEventListener('beforeunload', function(e) {
- // Solo limpiar si realmente está cerrando la página, no navegando
- if (!isNavigatingWithinSystem) {
- log('Preparando limpieza de datos');
- // No limpiar automáticamente sessionStorage para permitir navegación
- // sessionStorage.clear(); // Comentado para permitir navegación normal
- }
- });
- }
-
- // Inicializar el sistema cuando el DOM esté listo
- function initialize() {
- log('Inicializando sistema de navegación inteligente');
-
- setupLinkDetection();
- setupBackButtonHandling();
- setupCleanup();
-
- log('Sistema inicializado correctamente');
- }
-
- // Inicializar cuando el DOM esté listo
- if (document.readyState === 'loading') {
- document.addEventListener('DOMContentLoaded', initialize);
- } else {
- initialize();
- }
-
- // Exponer configuración para uso externo si es necesario
- window.NavSystem = {
- config: config,
- setDebugMode: function(enabled) {
- config.debugMode = enabled;
- },
- resetAttempts: function() {
- backButtonAttempts = 0;
- log('Intentos de navegación reseteados');
- }
- };
-
-})();
diff --git a/files/limpiar_empleados.php b/files/limpiar_empleados.php
deleted file mode 100644
index dfa5d21..0000000
--- a/files/limpiar_empleados.php
+++ /dev/null
@@ -1,63 +0,0 @@
-🧹 Limpieza de Empleados de Prueba";
-
-// Mostrar empleados actuales
-echo "👥 Empleados Actuales
";
-$query = "SELECT * FROM Empleados ORDER BY ID_EMPLEADO";
-$result = $conexion->query($query);
-
-if ($result->num_rows > 0) {
- echo "";
- echo "| ID | Nombre | Email | Acción |
";
-
- while ($row = $result->fetch_assoc()) {
- echo "";
- echo "| " . $row['ID_EMPLEADO'] . " | ";
- echo "" . ($row['NOMBRE_EMPLEADO'] ?? 'N/A') . " | ";
- echo "" . ($row['EMAIL_EMPLEADO'] ?? 'N/A') . " | ";
- echo "Eliminar | ";
- echo "
";
- }
- echo "
";
-} else {
- echo "No hay empleados registrados
";
-}
-
-// Procesar eliminación
-if (isset($_GET['delete'])) {
- $id_empleado = (int)$_GET['delete'];
-
- $delete_query = "DELETE FROM Empleados WHERE ID_EMPLEADO = ?";
- $stmt = $conexion->prepare($delete_query);
- $stmt->bind_param('i', $id_empleado);
-
- if ($stmt->execute()) {
- echo "✅ Empleado eliminado exitosamente
";
- echo "";
- } else {
- echo "❌ Error al eliminar empleado
";
- }
-
- $stmt->close();
-}
-
-// Opción para eliminar todos los empleados
-if (isset($_GET['deleteall'])) {
- $delete_all_query = "DELETE FROM Empleados";
- if ($conexion->query($delete_all_query)) {
- echo "✅ Todos los empleados eliminados
";
- echo "";
- } else {
- echo "❌ Error al eliminar todos los empleados
";
- }
-}
-
-echo "
";
-echo "🗑️ Eliminar Todos los Empleados
";
-echo "← Volver al Dashboard
";
-
-$conexion->close();
-?>
diff --git a/files/listar_productos.php b/files/listar_productos.php
deleted file mode 100644
index c0c4f6e..0000000
--- a/files/listar_productos.php
+++ /dev/null
@@ -1,9 +0,0 @@
-prepare('SELECT p.NOMBRE_PRODUCTO, cp.NOMBRE_CATEGORIAPRODUCTO FROM Productos p INNER JOIN Categoria_Productos cp ON p.ID_CATEGORIA_PRODUCTO = cp.ID_CATEGORIA_PRODUCTO WHERE p.ACTIVO = 1 ORDER BY cp.NOMBRE_CATEGORIAPRODUCTO, p.NOMBRE_PRODUCTO');
-$stmt->execute();
-$productos = $stmt->fetchAll(PDO::FETCH_ASSOC);
-foreach($productos as $producto) {
- echo $producto['NOMBRE_CATEGORIAPRODUCTO'] . ' - ' . $producto['NOMBRE_PRODUCTO'] . PHP_EOL;
-}
-?>
diff --git a/files/login.php b/files/login.php
deleted file mode 100644
index 56add6f..0000000
--- a/files/login.php
+++ /dev/null
@@ -1,198 +0,0 @@
-
-
-
-
-
-
-
- Iniciar Sesión - Panadería
-
-
-
-
-

-
-
Iniciar Sesión
-
-
-
-
-
- Sesión cerrada correctamente. Gracias por usar nuestro sistema.
-
-
-
-
-
- Registro exitoso. Ya puede iniciar sesión con sus credenciales.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/files/logout.php b/files/logout.php
deleted file mode 100644
index 36e6a96..0000000
--- a/files/logout.php
+++ /dev/null
@@ -1,29 +0,0 @@
-
diff --git a/files/masvendidos.php b/files/masvendidos.php
deleted file mode 100644
index 79ce59b..0000000
--- a/files/masvendidos.php
+++ /dev/null
@@ -1,56 +0,0 @@
-connect_error) {
- die("Error de conexión: " . $conexion->connect_error);
-}
-
-// Establecer charset
-$conexion->set_charset("utf8");
-
-// Opcional: mantener compatibilidad con PDO para otros archivos que lo usen
-try {
- $pdo_conexion = new PDO("mysql:host=$servidor;dbname=$base_datos;charset=utf8", $usuario, $password);
- $pdo_conexion->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
-} catch(PDOException $e) {
- die("Error de conexión PDO: " . $e->getMessage());
-}
-
-// Ordenar por: 'cantidad' o 'ingresos'
-$ordenarPor = isset($_GET['orden']) ? $_GET['orden'] : 'cantidad';
-
-$ordenSQL = $ordenarPor === 'ingresos' ? 'total_ingresos' : 'total_cantidad';
-
-while ($fila = $resultado->fetch_assoc()): ?>
-
- | = htmlspecialchars($fila['producto']) ?> |
- = $fila['total_cantidad'] ?> |
- = number_format($fila['total_ingresos'], 2) ?> |
-
- query($sql);
-?>
-
-close();
-?>
\ No newline at end of file
diff --git a/files/menu.php b/files/menu.php
deleted file mode 100644
index 8f9fea0..0000000
--- a/files/menu.php
+++ /dev/null
@@ -1,498 +0,0 @@
-setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
-
- // Obtener productos activos organizados por categoría
- $stmt = $pdo->prepare("
- SELECT p.*, cp.NOMBRE_CATEGORIAPRODUCTO
- FROM Productos p
- INNER JOIN Categoria_Productos cp ON p.ID_CATEGORIA_PRODUCTO = cp.ID_CATEGORIA_PRODUCTO
- WHERE p.ACTIVO = 1
- ORDER BY cp.NOMBRE_CATEGORIAPRODUCTO, p.NOMBRE_PRODUCTO
- ");
- $stmt->execute();
- $productos_data = $stmt->fetchAll(PDO::FETCH_ASSOC);
-
- // Organizar productos por categoría
- $productos_por_categoria = [];
- foreach ($productos_data as $producto) {
- $categoria = $producto['NOMBRE_CATEGORIAPRODUCTO'];
- $productos_por_categoria[$categoria][] = $producto;
- }
-
- // Mapeo de categorías para mostrar nombres más amigables
- $categorias_display = [
- 'Tortas Tres Leches' => 'Tortas',
- 'Tortas Milyway' => 'Tortas',
- 'Tortas por Encargo' => 'Tortas',
- 'Pan Grande' => 'Pan Grande',
- 'Pan Pequeño' => 'Pan Pequeño',
- 'Postres' => 'Postres',
- 'Galletas' => 'Galletas',
- 'Tamales' => 'Tamales',
- 'Yogures' => 'Productos Lácteos',
- 'Pasteles Pollo' => 'Hojaldres'
- ];
-
-} catch(PDOException $e) {
- $productos_por_categoria = [];
- $error_msg = "Error al conectar con la base de datos: " . $e->getMessage();
-}
-?>
-
-
-
-
-
-
-
- El Castillo del Pan - Menú
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ¿Estás Listo para Disfrutar de tú antojo?
-
-

-
- Descubre nuestros deliciosos productos artesanales, elaborados con los mejores ingredientes y mucho amor
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Busca tu Producto Favorito
-
-
-
-
-
-
-
-
-
-
-
-
-
- 'img/tamal1.jpg',
- 'Empanadas de Carne (unidad)' => 'img/empanadas.png',
- 'Arequipe (Tarro 500g)' => 'img/arequipe-alpina.png',
-
- // Pan Grande (Categoría 4)
- 'Pan Tajado Integral' => 'img/pan-integral.jpg',
- 'Pan Blanco de Molde' => 'img/pan-de-molde.jpg',
- 'Pan de Hamburguesa' => 'img/panhamburguesa.jpg',
-
- // Yogures (Categoría 7)
- 'Yogurt Fresa Litro' => 'img/yogurt1.jpg',
- 'Postre de Tres Leches' => 'img/postreleche.jpg',
- 'Kumiss Natural' => 'img/kumiss.1.png',
-
- // Galletas (Categoría 5)
- 'Galleta de Tres Ojos' => 'img/galletatresojos.png',
- 'Galletas Surtidas de Mantequilla' => 'img/galletasmantequilla.jpg',
- 'Galletas de Avena y Pasas' => 'img/galletas-de-avena-con-pasas-y-nuez.jpg',
-
- // Tortas Tres Leches (Categoría 1)
- 'Pan Campesino Grande' => 'img/pancampesino.png',
- 'Baguette Clásica' => 'img/baguette.jpg',
- 'Pan Trenza Integral' => 'img/pantrenza.jpg',
- 'Pan Artesanal de Masa Madre' => 'img/pan-con-masa-madre-.jpg',
- 'Pan Blandito' => 'img/panblando.jpeg',
-
- // Tortas por Encargo (Categoría 3)
- 'Torta de Chocolate Pequeña' => 'img/tortachocolate.jpg',
- 'Muffin de Arándanos' => 'img/muffins1.jpg',
- 'Brazo de Reina' => 'img/brazoreina1.jpg',
- 'Cheesecake de Frutos Rojos' => 'img/cheesecake-frutos-rojos.jpg',
- 'Milhoja de Arequipe' => 'img/miloha_de_arequipe.jpg',
-
- // Tortas Milyway (Categoría 2)
- 'Croissant de Almendras' => 'img/croissants.jpg',
- 'Pan de Bono Pequeño' => 'img/pandebono.png',
- 'Mogolla Chicharrona' => 'img/chicharrona.png',
- // Pasteles Pollo (Categoría 9)
- 'Ponqué de Naranja (Porción)' => 'img/naranjaponque.jpg',
- 'Brownie con Nuez' => 'img/browni-con-nueces.jpg'
- ];
-
- // Obtener la imagen del producto o usar imagen por defecto
- $image_path = $product_images[$producto['NOMBRE_PRODUCTO']] ?? 'img/pan-rtzqhi1ok4k1bxlo.jpg';
- ?>
-
-
-
-
![<?php echo htmlspecialchars($producto['NOMBRE_PRODUCTO']); ?>](<?php echo $image_path; ?>)
-
- $
-
-
-
-
-
-
-
-
-
-
-
-
- Disponible
-
- Stock:
-
-
-
-
-
-
-
-
-
-
-
-
-
¡No hay productos!
-
Actualmente no tenemos productos disponibles en el menú. Por favor, vuelve a intentarlo más tarde.
-
-
-
-
-
-
-
-
-
-
-
-
-
¿Listo para ordenar?
-
- Contacta con nosotros para realizar tu pedido personalizado o visita nuestra tienda
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/files/migrar_empleados_fecha.php b/files/migrar_empleados_fecha.php
deleted file mode 100644
index c1ea930..0000000
--- a/files/migrar_empleados_fecha.php
+++ /dev/null
@@ -1,82 +0,0 @@
-Migración de Base de Datos - Tabla Empleados";
-echo "Agregando columna FECHA_REGISTRO...
";
-
-require_once 'conexion.php';
-
-try {
- // Verificar conexión
- if (!$conexion) {
- throw new Exception('Error de conexión a la base de datos');
- }
-
- // Verificar si la columna ya existe
- $check_query = "SHOW COLUMNS FROM Empleados LIKE 'FECHA_REGISTRO'";
- $result = $conexion->query($check_query);
-
- if ($result && $result->num_rows > 0) {
- echo "✓ La columna FECHA_REGISTRO ya existe en la tabla Empleados.
";
- } else {
- // Agregar la columna
- $alter_query = "ALTER TABLE Empleados ADD COLUMN FECHA_REGISTRO TIMESTAMP DEFAULT CURRENT_TIMESTAMP";
-
- if ($conexion->query($alter_query)) {
- echo "✓ Columna FECHA_REGISTRO agregada exitosamente a la tabla Empleados.
";
-
- // Actualizar empleados existentes con fecha actual
- $update_query = "UPDATE Empleados SET FECHA_REGISTRO = NOW() WHERE FECHA_REGISTRO IS NULL";
- if ($conexion->query($update_query)) {
- echo "✓ Fechas de registro actualizadas para empleados existentes.
";
- }
- } else {
- throw new Exception('Error al agregar la columna: ' . $conexion->error);
- }
- }
-
- // Verificar la estructura final
- echo "Estructura actual de la tabla Empleados:
";
- $structure_query = "DESCRIBE Empleados";
- $structure_result = $conexion->query($structure_query);
-
- if ($structure_result) {
- echo "";
- echo "| Campo | Tipo | Nulo | Clave | Por defecto | Extra |
";
-
- while ($row = $structure_result->fetch_assoc()) {
- echo "";
- echo "| " . htmlspecialchars($row['Field']) . " | ";
- echo "" . htmlspecialchars($row['Type']) . " | ";
- echo "" . htmlspecialchars($row['Null']) . " | ";
- echo "" . htmlspecialchars($row['Key']) . " | ";
- echo "" . htmlspecialchars($row['Default']) . " | ";
- echo "" . htmlspecialchars($row['Extra']) . " | ";
- echo "
";
- }
- echo "
";
- }
-
- echo "✓ Migración completada exitosamente.
";
- echo "Volver al Dashboard
";
-
-} catch (Exception $e) {
- echo "✗ Error: " . htmlspecialchars($e->getMessage()) . "
";
- echo "Por favor, contacte al administrador del sistema.
";
-}
-
-// Cerrar conexión
-if (isset($conexion)) {
- $conexion->close();
-}
-?>
diff --git a/files/mis_pedidos_cliente.php b/files/mis_pedidos_cliente.php
deleted file mode 100644
index 24cf856..0000000
--- a/files/mis_pedidos_cliente.php
+++ /dev/null
@@ -1,506 +0,0 @@
-prepare("
- SELECT p.ID_PEDIDO, p.FECHA_INGRESO, p.FECHA_ENTREGA, p.TOTAL_PRODUCTO,
- e.NOMBRE_EMPLEADO, ep.NOMBRE_ESTADO, ep.ID_ESTADO_PEDIDO
- FROM Pedidos p
- INNER JOIN Empleados e ON p.ID_EMPLEADO = e.ID_EMPLEADO
- INNER JOIN Estado_Pedidos ep ON p.ID_ESTADO_PEDIDO = ep.ID_ESTADO_PEDIDO
- WHERE p.ID_CLIENTE = ?
- ORDER BY p.FECHA_INGRESO DESC
- ");
- $stmt->bind_param("i", $_SESSION['usuario_id']);
- $stmt->execute();
- $mis_pedidos = $stmt->get_result();
-} catch (Exception $e) {
- error_log("Error obteniendo pedidos del cliente: " . $e->getMessage());
-}
-?>
-
-
-
-
-
-
- Mis Pedidos - Cliente
-
-
-
-
-
-
-
-
-
-
- num_rows > 0): ?>
-
-
-
- Historial de Pedidos (num_rows; ?>)
-
-
-
- Actualizado automáticamente cada 30 segundos
-
-
-
-
- fetch_assoc()): ?>
-
-
-
-
-
-
-
- Fecha de Pedido:
-
-
-
-
-
-
-
- Fecha de Entrega:
-
-
-
-
-
-
-
- Atendido por:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/files/obtener_administradores_ajax.php b/files/obtener_administradores_ajax.php
deleted file mode 100644
index 6248a07..0000000
--- a/files/obtener_administradores_ajax.php
+++ /dev/null
@@ -1,73 +0,0 @@
- false, 'mensaje' => 'Acceso no autorizado']);
- exit();
-}
-
-// Headers de respuesta JSON
-header('Content-Type: application/json');
-
-// Incluir conexión a la base de datos
-require_once 'conexion.php';
-
-try {
- // Verificar conexión
- if (!$conexion) {
- throw new Exception('Error de conexión a la base de datos');
- }
-
- // Consulta para obtener administradores usando prepared statement
- $consulta = "SELECT
- ID_ADMIN as id,
- NOMBRE_ADMIN as nombre,
- EMAIL_ADMIN as email,
- ACTIVO_ADMIN as activo
- FROM Administradores
- ORDER BY NOMBRE_ADMIN ASC";
-
- $stmt = $conexion->prepare($consulta);
-
- if (!$stmt) {
- throw new Exception('Error al preparar la consulta: ' . $conexion->error);
- }
-
- $stmt->execute();
- $resultado = $stmt->get_result();
-
- if ($resultado) {
- $administradores = [];
- while ($fila = $resultado->fetch_assoc()) {
- $administradores[] = [
- 'id' => $fila['id'] ?? 0,
- 'nombre' => htmlspecialchars($fila['nombre'] ?? ''),
- 'email' => htmlspecialchars($fila['email'] ?? ''),
- 'activo' => $fila['activo'] ?? 1
- ];
- }
-
- echo json_encode([
- 'success' => true,
- 'administradores' => $administradores,
- 'total' => count($administradores)
- ]);
- } else {
- throw new Exception('Error al ejecutar la consulta');
- }
-
- $stmt->close();
-
-} catch (Exception $e) {
- echo json_encode([
- 'success' => false,
- 'mensaje' => 'Error del servidor: ' . $e->getMessage()
- ]);
-}
-
-// Cerrar conexión
-if (isset($conexion)) {
- $conexion->close();
-}
-?>
diff --git a/files/obtener_categorias_ingredientes_ajax.php b/files/obtener_categorias_ingredientes_ajax.php
deleted file mode 100644
index bdb160a..0000000
--- a/files/obtener_categorias_ingredientes_ajax.php
+++ /dev/null
@@ -1,64 +0,0 @@
- false,
- 'error' => 'No autorizado'
- ]);
- exit();
-}
-
-require_once 'conexion.php';
-
-try {
- // Consulta para obtener categorías de ingredientes
- $consulta = "SELECT
- ID_CATEGORIA as id,
- NOMBRE_CATEGORIA_INGREDIENTE as nombre
- FROM Categoria_Ingredientes
- ORDER BY NOMBRE_CATEGORIA_INGREDIENTE ASC";
-
- $resultado = $conexion->query($consulta);
-
- if ($resultado) {
- $categorias = [];
- while ($fila = $resultado->fetch_assoc()) {
- $categorias[] = [
- 'id' => $fila['id'],
- 'nombre' => $fila['nombre']
- ];
- }
-
- echo json_encode([
- 'success' => true,
- 'categorias' => $categorias
- ]);
- } else {
- echo json_encode([
- 'success' => false,
- 'mensaje' => 'Error en la consulta: ' . $conexion->error
- ]);
- }
-
-} catch (Exception $e) {
- echo json_encode([
- 'success' => false,
- 'mensaje' => 'Error del servidor: ' . $e->getMessage()
- ]);
-}
-
-$conexion->close();
-?>
diff --git a/files/obtener_clientes_ajax.php b/files/obtener_clientes_ajax.php
deleted file mode 100644
index bd12747..0000000
--- a/files/obtener_clientes_ajax.php
+++ /dev/null
@@ -1,75 +0,0 @@
- false, 'mensaje' => 'Acceso no autorizado']);
- exit();
-}
-
-// Headers de respuesta JSON
-header('Content-Type: application/json');
-
-// Incluir conexión a la base de datos
-require_once 'conexion.php';
-
-try {
- // Verificar conexión
- if (!$conexion) {
- throw new Exception('Error de conexión a la base de datos');
- }
-
- // Consulta para obtener clientes usando prepared statement
- $consulta = "SELECT
- ID_CLIENTE as id,
- NOMBRE_CLI as nombre,
- EMAIL_CLI as email,
- TELEFONO_CLI as telefono,
- COALESCE(ACTIVO_CLI, 1) as activo
- FROM Clientes
- ORDER BY NOMBRE_CLI ASC";
-
- $stmt = $conexion->prepare($consulta);
-
- if (!$stmt) {
- throw new Exception('Error al preparar la consulta: ' . $conexion->error);
- }
-
- $stmt->execute();
- $resultado = $stmt->get_result();
-
- if ($resultado) {
- $clientes = [];
- while ($fila = $resultado->fetch_assoc()) {
- $clientes[] = [
- 'id' => $fila['id'] ?? 0,
- 'nombre' => htmlspecialchars($fila['nombre'] ?? ''),
- 'email' => htmlspecialchars($fila['email'] ?? ''),
- 'telefono' => htmlspecialchars($fila['telefono'] ?? ''),
- 'activo' => (int)($fila['activo'] ?? 1)
- ];
- }
-
- echo json_encode([
- 'success' => true,
- 'clientes' => $clientes,
- 'total' => count($clientes)
- ]);
- } else {
- throw new Exception('Error al ejecutar la consulta');
- }
-
- $stmt->close();
-
-} catch (Exception $e) {
- echo json_encode([
- 'success' => false,
- 'mensaje' => 'Error del servidor: ' . $e->getMessage()
- ]);
-}
-
-// Cerrar conexión
-if (isset($conexion)) {
- $conexion->close();
-}
-?>
diff --git a/files/obtener_detalle_pedido_ajax.php b/files/obtener_detalle_pedido_ajax.php
deleted file mode 100644
index b22dad3..0000000
--- a/files/obtener_detalle_pedido_ajax.php
+++ /dev/null
@@ -1,169 +0,0 @@
- session_id(),
- 'usuario_logueado' => $_SESSION['usuario_logueado'] ?? 'NO_SET',
- 'usuario_tipo' => $_SESSION['usuario_tipo'] ?? 'NO_SET',
- 'all_session' => $_SESSION
- ];
-
- error_log("AJAX Auth Failed Detalle Pedido - Debug: " . json_encode($debug_info));
-
- http_response_code(401);
- echo json_encode([
- 'success' => false,
- 'mensaje' => 'No autorizado para ver detalles de pedidos.'
- ]);
- exit();
-}
-
-require_once 'conexion.php';
-
-try {
- // Verificar conexión
- if (!$conexion) {
- throw new Exception("No se pudo conectar a la base de datos");
- }
-
- // Obtener datos de la petición
- $input = file_get_contents('php://input');
- $data = json_decode($input, true);
-
- if (!$data) {
- throw new Exception("Datos de entrada inválidos");
- }
-
- $pedido_id = isset($data['pedido_id']) ? intval($data['pedido_id']) : 0;
-
- // Validar datos
- if ($pedido_id <= 0) {
- throw new Exception("ID de pedido inválido");
- }
-
- error_log("Obteniendo detalle del pedido: $pedido_id");
-
- // Obtener información básica del pedido
- $stmt = $conexion->prepare("
- SELECT
- p.ID_PEDIDO,
- p.FECHA_INGRESO,
- p.FECHA_ENTREGA,
- p.TOTAL_PRODUCTO,
- COALESCE(c.NOMBRE_CLI, 'Cliente eliminado') as cliente,
- COALESCE(c.EMAIL_CLI, '') as email_cliente,
- COALESCE(c.TELEFONO_CLI, '') as telefono_cliente,
- COALESCE(e.NOMBRE_EMPLEADO, 'No asignado') as empleado,
- COALESCE(ep.NOMBRE_ESTADO, 'Estado desconocido') as estado_nombre,
- p.ID_ESTADO_PEDIDO as estado_id
- FROM Pedidos p
- LEFT JOIN Clientes c ON p.ID_CLIENTE = c.ID_CLIENTE
- LEFT JOIN Empleados e ON p.ID_EMPLEADO = e.ID_EMPLEADO
- LEFT JOIN Estado_Pedidos ep ON p.ID_ESTADO_PEDIDO = ep.ID_ESTADO_PEDIDO
- WHERE p.ID_PEDIDO = ?
- ");
- $stmt->bind_param("i", $pedido_id);
- $stmt->execute();
- $result = $stmt->get_result();
- $pedido = $result->fetch_assoc();
-
- if (!$pedido) {
- throw new Exception("Pedido no encontrado");
- }
-
- // Verificar si la columna DESCRIPCION_PRODUCTO existe
- $check_descripcion = $conexion->query("SHOW COLUMNS FROM Productos LIKE 'DESCRIPCION_PRODUCTO'");
- $has_descripcion = $check_descripcion && $check_descripcion->num_rows > 0;
-
- // Construir consulta según las columnas disponibles
- $descripcion_field = $has_descripcion ?
- "COALESCE(prod.DESCRIPCION_PRODUCTO, prod.TIPO_PRODUCTO_MARCA, '') as producto_descripcion" :
- "COALESCE(prod.TIPO_PRODUCTO_MARCA, '') as producto_descripcion";
-
- // Obtener los productos del pedido con información completa
- $stmt = $conexion->prepare("
- SELECT
- dp.ID_DETALLE,
- dp.CANTIDAD_PRODUCTO,
- dp.PRECIO_UNITARIO,
- dp.SUBTOTAL,
- COALESCE(prod.NOMBRE_PRODUCTO, 'Producto eliminado') as producto_nombre,
- $descripcion_field,
- COALESCE(cat.NOMBRE_CATEGORIAPRODUCTO, 'Sin categoría') as categoria_nombre,
- prod.ID_PRODUCTO as producto_id
- FROM Detalle_Pedidos dp
- LEFT JOIN Productos prod ON dp.ID_PRODUCTO = prod.ID_PRODUCTO
- LEFT JOIN Categoria_Productos cat ON prod.ID_CATEGORIA_PRODUCTO = cat.ID_CATEGORIA_PRODUCTO
- WHERE dp.ID_PEDIDO = ?
- ORDER BY dp.ID_DETALLE
- ");
- $stmt->bind_param("i", $pedido_id);
- $stmt->execute();
- $result = $stmt->get_result();
- $productos = $result->fetch_all(MYSQLI_ASSOC);
-
- // Calcular totales
- $total_items = 0;
- $total_calculado = 0;
- foreach ($productos as $producto) {
- $total_items += $producto['CANTIDAD_PRODUCTO'];
- $total_calculado += $producto['SUBTOTAL'];
- }
-
- error_log("Detalle obtenido - Pedido: $pedido_id, Productos: " . count($productos) . ", Total items: $total_items");
-
- echo json_encode([
- 'success' => true,
- 'pedido' => [
- 'id' => $pedido['ID_PEDIDO'],
- 'fecha_ingreso' => $pedido['FECHA_INGRESO'],
- 'fecha_entrega' => $pedido['FECHA_ENTREGA'],
- 'total' => $pedido['TOTAL_PRODUCTO'],
- 'cantidad_productos' => $total_items,
- 'cliente' => $pedido['cliente'],
- 'email_cliente' => $pedido['email_cliente'],
- 'telefono_cliente' => $pedido['telefono_cliente'],
- 'empleado' => $pedido['empleado'],
- 'estado_nombre' => $pedido['estado_nombre'],
- 'estado_id' => $pedido['estado_id']
- ],
- 'productos' => array_map(function($prod) {
- return [
- 'id_detalle' => $prod['ID_DETALLE'],
- 'producto_id' => $prod['producto_id'],
- 'nombre' => $prod['producto_nombre'],
- 'descripcion' => $prod['producto_descripcion'],
- 'categoria' => $prod['categoria_nombre'],
- 'cantidad' => $prod['CANTIDAD_PRODUCTO'],
- 'precio_unitario' => $prod['PRECIO_UNITARIO'],
- 'subtotal' => $prod['SUBTOTAL']
- ];
- }, $productos),
- 'resumen' => [
- 'total_items' => $total_items,
- 'total_calculado' => $total_calculado,
- 'total_productos_diferentes' => count($productos)
- ]
- ]);
-
-} catch (Exception $e) {
- error_log("Error en obtener_detalle_pedido_ajax.php: " . $e->getMessage());
- echo json_encode([
- 'success' => false,
- 'mensaje' => 'Error: ' . $e->getMessage()
- ]);
-}
-?>
diff --git a/files/obtener_detalles_pedido.php b/files/obtener_detalles_pedido.php
deleted file mode 100644
index 7d22518..0000000
--- a/files/obtener_detalles_pedido.php
+++ /dev/null
@@ -1,177 +0,0 @@
-
-
-
-
-
Información del Cliente
-
-
-
Nombre:
-
Email:
-
-
Teléfono:
-
-
-
-
-
-
Información del Pedido
-
-
-
ID Pedido: #
-
Fecha:
-
Estado:
-
-
-
-
-
-
Total: $
-
-
-
-
-
-
-
Productos Pedidos
-
-
-
-
- | ID |
- Producto |
- Cantidad |
- Precio Unit. |
- Subtotal |
-
-
-
-
-
- |
- #
- |
-
-
- |
- |
- $ |
- $ |
-
-
-
-
-
- | Total del Pedido: |
- $ |
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/files/obtener_empleados_ajax.php b/files/obtener_empleados_ajax.php
deleted file mode 100644
index a02f804..0000000
--- a/files/obtener_empleados_ajax.php
+++ /dev/null
@@ -1,73 +0,0 @@
- false, 'mensaje' => 'Acceso no autorizado']);
- exit();
-}
-
-// Headers de respuesta JSON
-header('Content-Type: application/json');
-
-// Incluir conexión a la base de datos
-require_once 'conexion.php';
-
-try {
- // Verificar conexión
- if (!$conexion) {
- throw new Exception('Error de conexión a la base de datos');
- }
-
- // Consulta para obtener empleados usando prepared statement
- $consulta = "SELECT
- ID_EMPLEADO as id,
- NOMBRE_EMPLEADO as nombre,
- EMAIL_EMPLEADO as email,
- COALESCE(ACTIVO_EMPLEADO, 1) as activo
- FROM Empleados
- ORDER BY NOMBRE_EMPLEADO ASC";
-
- $stmt = $conexion->prepare($consulta);
-
- if (!$stmt) {
- throw new Exception('Error al preparar la consulta: ' . $conexion->error);
- }
-
- $stmt->execute();
- $resultado = $stmt->get_result();
-
- if ($resultado) {
- $empleados = [];
- while ($fila = $resultado->fetch_assoc()) {
- $empleados[] = [
- 'id' => $fila['id'] ?? 0,
- 'nombre' => htmlspecialchars($fila['nombre'] ?? ''),
- 'email' => htmlspecialchars($fila['email'] ?? ''),
- 'activo' => (int)($fila['activo'] ?? 1)
- ];
- }
-
- echo json_encode([
- 'success' => true,
- 'empleados' => $empleados,
- 'total' => count($empleados)
- ]);
- } else {
- throw new Exception('Error al ejecutar la consulta');
- }
-
- $stmt->close();
-
-} catch (Exception $e) {
- echo json_encode([
- 'success' => false,
- 'mensaje' => 'Error del servidor: ' . $e->getMessage()
- ]);
-}
-
-// Cerrar conexión
-if (isset($conexion)) {
- $conexion->close();
-}
-?>
diff --git a/files/obtener_estados_pedidos_cliente.php b/files/obtener_estados_pedidos_cliente.php
deleted file mode 100644
index e684ad7..0000000
--- a/files/obtener_estados_pedidos_cliente.php
+++ /dev/null
@@ -1,59 +0,0 @@
- false, 'message' => 'No autorizado']);
- exit();
-}
-
-require_once 'conexion.php';
-
-// Obtener el cuerpo de la petición
-$input = json_decode(file_get_contents('php://input'), true);
-$cliente_id = $input['cliente_id'] ?? $_SESSION['usuario_id'];
-
-// Verificar que el cliente_id coincida con la sesión
-if ($cliente_id != $_SESSION['usuario_id']) {
- echo json_encode(['success' => false, 'message' => 'Cliente no autorizado']);
- exit();
-}
-
-try {
- // Obtener todos los pedidos del cliente con sus estados actuales
- $stmt = $conexion->prepare("
- SELECT p.ID_PEDIDO, ep.NOMBRE_ESTADO
- FROM Pedidos p
- INNER JOIN Estado_Pedidos ep ON p.ID_ESTADO_PEDIDO = ep.ID_ESTADO_PEDIDO
- WHERE p.ID_CLIENTE = ?
- ORDER BY p.FECHA_INGRESO DESC
- ");
-
- $stmt->bind_param("i", $cliente_id);
- $stmt->execute();
- $result = $stmt->get_result();
-
- $pedidos = [];
- while ($row = $result->fetch_assoc()) {
- $pedidos[] = [
- 'id' => $row['ID_PEDIDO'],
- 'estado' => $row['NOMBRE_ESTADO']
- ];
- }
-
- echo json_encode([
- 'success' => true,
- 'pedidos' => $pedidos,
- 'timestamp' => date('Y-m-d H:i:s')
- ]);
-
-} catch (Exception $e) {
- error_log("Error obteniendo estados de pedidos: " . $e->getMessage());
- echo json_encode([
- 'success' => false,
- 'message' => 'Error del servidor'
- ]);
-}
-?>
diff --git a/files/obtener_ingredientes_ajax.php b/files/obtener_ingredientes_ajax.php
deleted file mode 100644
index b268fb5..0000000
--- a/files/obtener_ingredientes_ajax.php
+++ /dev/null
@@ -1,80 +0,0 @@
- false, 'mensaje' => 'Acceso no autorizado']);
- exit();
-}
-
-header('Content-Type: application/json');
-require_once 'conexion.php';
-
-try {
- // Verificar conexión
- if (!$conexion) {
- throw new Exception('Error de conexión a la base de datos');
- }
-
- // Consulta para obtener ingredientes con información de categoría y proveedor
- $consulta = "SELECT
- i.ID_INGREDIENTE as id,
- i.NOMBRE_INGREDIENTE as nombre,
- i.CANTIDAD_INGREDIENTE as cantidad,
- i.FECHA_VENCIMIENTO as fecha_vencimiento,
- i.REFERENCIA_INGREDIENTE as referencia,
- i.FECHA_ENTREGA_INGREDIENTE as fecha_entrega,
- c.NOMBRE_CATEGORIA_INGREDIENTE as categoria,
- p.NOMBRE_PROV as proveedor
- FROM Ingredientes i
- LEFT JOIN Categoria_Ingredientes c ON i.ID_CATEGORIA = c.ID_CATEGORIA
- LEFT JOIN Proveedores p ON i.ID_PROVEEDOR = p.ID_PROVEEDOR
- ORDER BY i.ID_INGREDIENTE DESC";
-
- $stmt = $conexion->prepare($consulta);
-
- if (!$stmt) {
- throw new Exception('Error al preparar la consulta: ' . $conexion->error);
- }
-
- $stmt->execute();
- $resultado = $stmt->get_result();
-
- if ($resultado) {
- $ingredientes = [];
- while ($fila = $resultado->fetch_assoc()) {
- $ingredientes[] = [
- 'id' => $fila['id'] ?? 0,
- 'nombre' => htmlspecialchars($fila['nombre'] ?? ''),
- 'cantidad' => $fila['cantidad'] ?? 0,
- 'categoria' => htmlspecialchars($fila['categoria'] ?? ''),
- 'proveedor' => htmlspecialchars($fila['proveedor'] ?? ''),
- 'fecha_vencimiento' => !empty($fila['fecha_vencimiento']) ? date('d/m/Y', strtotime($fila['fecha_vencimiento'])) : '',
- 'referencia' => htmlspecialchars($fila['referencia'] ?? ''),
- 'fecha_entrega' => !empty($fila['fecha_entrega']) ? date('d/m/Y', strtotime($fila['fecha_entrega'])) : ''
- ];
- }
-
- echo json_encode([
- 'success' => true,
- 'ingredientes' => $ingredientes,
- 'total' => count($ingredientes)
- ]);
- } else {
- throw new Exception('Error al ejecutar la consulta');
- }
-
- $stmt->close();
-
-} catch (Exception $e) {
- echo json_encode([
- 'success' => false,
- 'mensaje' => 'Error del servidor: ' . $e->getMessage()
- ]);
-}
-
-// Cerrar conexión
-if (isset($conexion)) {
- $conexion->close();
-}
-?>
diff --git a/files/obtener_ingredientes_proveedores_ajax.php b/files/obtener_ingredientes_proveedores_ajax.php
deleted file mode 100644
index b6e80e5..0000000
--- a/files/obtener_ingredientes_proveedores_ajax.php
+++ /dev/null
@@ -1,94 +0,0 @@
- false,
- 'error' => 'No autorizado'
- ]);
- exit();
-}
-
-require_once 'conexion.php';
-
-try {
- if (!$conexion) {
- throw new Exception("Error de conexión a la base de datos");
- }
-
- // Consulta para obtener ingredientes con información del proveedor
- $sql = "SELECT
- i.ID_INGREDIENTE,
- i.NOMBRE_INGREDIENTE,
- i.CANTIDAD_INGREDIENTE as STOCK,
- i.PRECIO_COMPRA,
- i.REFERENCIA_INGREDIENTE,
- i.FECHA_VENCIMIENTO,
- i.FECHA_ENTREGA_INGREDIENTE,
- p.NOMBRE_PROV as PROVEEDOR,
- p.TELEFONO_PROV as TELEFONO_PROVEEDOR,
- p.EMAIL_PROV as EMAIL_PROVEEDOR,
- p.ID_PROVEEDOR,
- c.NOMBRE_CATEGORIA_INGREDIENTE as CATEGORIA,
- c.ID_CATEGORIA
- FROM Ingredientes i
- LEFT JOIN Proveedores p ON i.ID_PROVEEDOR = p.ID_PROVEEDOR
- LEFT JOIN Categoria_Ingredientes c ON i.ID_CATEGORIA = c.ID_CATEGORIA
- ORDER BY i.NOMBRE_INGREDIENTE ASC";
-
- $result = $conexion->query($sql);
-
- if (!$result) {
- throw new Exception("Error en la consulta: " . $conexion->error);
- }
-
- $ingredientes = [];
- while ($row = $result->fetch_assoc()) {
- $ingredientes[] = array(
- 'id' => $row['ID_INGREDIENTE'],
- 'nombre' => $row['NOMBRE_INGREDIENTE'],
- 'stock' => $row['STOCK'],
- 'precio_compra' => $row['PRECIO_COMPRA'],
- 'referencia' => $row['REFERENCIA_INGREDIENTE'],
- 'fecha_vencimiento' => $row['FECHA_VENCIMIENTO'],
- 'fecha_entrega' => $row['FECHA_ENTREGA_INGREDIENTE'],
- 'proveedor' => $row['PROVEEDOR'] ?? 'Sin asignar',
- 'telefono_proveedor' => $row['TELEFONO_PROVEEDOR'] ?? '',
- 'email_proveedor' => $row['EMAIL_PROVEEDOR'] ?? '',
- 'categoria' => $row['CATEGORIA'] ?? 'Sin categoría',
- 'id_categoria' => $row['ID_CATEGORIA'],
- 'id_proveedor' => $row['ID_PROVEEDOR']
- );
- }
-
- $response = array(
- 'success' => true,
- 'data' => $ingredientes,
- 'total' => count($ingredientes)
- );
-
- echo json_encode($response);
-
-} catch (Exception $e) {
- http_response_code(500);
- $response = array(
- 'success' => false,
- 'error' => $e->getMessage()
- );
- echo json_encode($response);
-}
-
-$conexion->close();
-?>
diff --git a/files/obtener_pedidos_ajax.php b/files/obtener_pedidos_ajax.php
deleted file mode 100644
index d1d86e9..0000000
--- a/files/obtener_pedidos_ajax.php
+++ /dev/null
@@ -1,174 +0,0 @@
- session_id(),
- 'usuario_logueado' => $_SESSION['usuario_logueado'] ?? 'NO_SET',
- 'usuario_tipo' => $_SESSION['usuario_tipo'] ?? 'NO_SET',
- 'all_session' => $_SESSION,
- 'cookies' => $_COOKIE
- ];
-
- error_log("AJAX Auth Failed - Debug: " . json_encode($debug_info));
-
- http_response_code(401);
- echo json_encode([
- 'success' => false,
- 'mensaje' => 'No autorizado. Debug info logged.',
- 'debug' => $debug_info
- ]);
- exit();
-}
-
-require_once 'conexion.php';
-
-try {
- // Verificar conexión
- if (!$conexion) {
- throw new Exception("Error de conexión a la base de datos");
- }
-
- // Obtener datos del POST
- $input = json_decode(file_get_contents('php://input'), true);
-
- if (json_last_error() !== JSON_ERROR_NONE) {
- throw new Exception("Error al decodificar JSON: " . json_last_error_msg());
- }
-
- // Para debug, loggear los parámetros
- error_log("Pedidos AJAX - Input: " . print_r($input, true));
- error_log("Pedidos AJAX - Session: " . print_r($_SESSION, true));
-
- $estado = isset($input['estado']) ? $input['estado'] : '';
- $fecha = isset($input['fecha']) ? $input['fecha'] : '';
- $solo_pendientes = isset($input['solo_pendientes']) ? $input['solo_pendientes'] : false;
-
- // Primero, verificar si las tablas existen
- $test_query = "SHOW TABLES LIKE 'Pedidos'";
- $test_result = $conexion->query($test_query);
- if (!$test_result || $test_result->num_rows == 0) {
- throw new Exception("La tabla 'Pedidos' no existe");
- }
-
- // Construir consulta con las tablas correctas
- $query = "
- SELECT
- p.ID_PEDIDO as id,
- COALESCE(c.NOMBRE_CLI, 'Cliente eliminado') as cliente,
- COALESCE(e.NOMBRE_EMPLEADO, 'No asignado') as empleado,
- p.FECHA_INGRESO as fecha_ingreso,
- p.FECHA_ENTREGA as fecha_entrega,
- p.TOTAL_PRODUCTO as total,
- p.ID_ESTADO_PEDIDO as estado,
- COALESCE(ep.NOMBRE_ESTADO, 'Estado desconocido') as estado_nombre
- FROM Pedidos p
- LEFT JOIN Clientes c ON p.ID_CLIENTE = c.ID_CLIENTE
- LEFT JOIN Empleados e ON p.ID_EMPLEADO = e.ID_EMPLEADO
- LEFT JOIN Estado_Pedidos ep ON p.ID_ESTADO_PEDIDO = ep.ID_ESTADO_PEDIDO
- WHERE 1=1
- ";
-
- $params = [];
- $types = '';
-
- // Filtros
- if ($solo_pendientes) {
- $query .= " AND p.ID_ESTADO_PEDIDO IN (1, 2, 3)"; // Pendiente, Preparación, Listo
- }
-
- if (!empty($estado)) {
- $query .= " AND p.ID_ESTADO_PEDIDO = ?";
- $params[] = $estado;
- $types .= 'i';
- }
-
- if (!empty($fecha)) {
- $query .= " AND DATE(p.FECHA_INGRESO) = ?";
- $params[] = $fecha;
- $types .= 's';
- }
-
- $query .= " ORDER BY p.FECHA_INGRESO DESC, p.ID_PEDIDO DESC LIMIT 50";
-
- error_log("Pedidos AJAX - Query: " . $query);
- error_log("Pedidos AJAX - Params: " . print_r($params, true));
-
- $stmt = $conexion->prepare($query);
-
- if (!$stmt) {
- throw new Exception("Error preparando consulta: " . $conexion->error);
- }
-
- if (!empty($params)) {
- $stmt->bind_param($types, ...$params);
- }
-
- if (!$stmt->execute()) {
- throw new Exception("Error ejecutando consulta: " . $stmt->error);
- }
-
- $result = $stmt->get_result();
-
- if (!$result) {
- throw new Exception("Error obteniendo resultados: " . $stmt->error);
- }
-
- $pedidos = [];
- while ($row = $result->fetch_assoc()) {
- $pedidos[] = [
- 'id' => (int)$row['id'],
- 'cliente' => $row['cliente'] ?: 'Cliente eliminado',
- 'empleado' => $row['empleado'] ?: 'No asignado',
- 'fecha_ingreso' => $row['fecha_ingreso'],
- 'fecha_entrega' => $row['fecha_entrega'],
- 'total' => (float)$row['total'],
- 'estado' => (int)$row['estado'],
- 'estado_nombre' => $row['estado_nombre'] ?: 'Estado desconocido'
- ];
- }
-
- error_log("Pedidos AJAX - Resultado: " . count($pedidos) . " pedidos encontrados");
-
- echo json_encode([
- 'success' => true,
- 'pedidos' => $pedidos,
- 'total' => count($pedidos),
- 'debug' => [
- 'query' => $query,
- 'params' => $params,
- 'session_user' => $_SESSION['usuario_id'] ?? 'no_set'
- ]
- ]);
-
-} catch (Exception $e) {
- error_log("Error en obtener_pedidos_ajax.php: " . $e->getMessage());
- error_log("Error stack: " . $e->getTraceAsString());
- http_response_code(500);
- echo json_encode([
- 'success' => false,
- 'mensaje' => $e->getMessage(),
- 'debug' => [
- 'file' => $e->getFile(),
- 'line' => $e->getLine(),
- 'session_info' => [
- 'usuario_logueado' => $_SESSION['usuario_logueado'] ?? 'not_set',
- 'usuario_tipo' => $_SESSION['usuario_tipo'] ?? 'not_set'
- ]
- ]
- ]);
-}
-?>
diff --git a/files/obtener_pedidos_bypass.php b/files/obtener_pedidos_bypass.php
deleted file mode 100644
index 4b056a4..0000000
--- a/files/obtener_pedidos_bypass.php
+++ /dev/null
@@ -1,63 +0,0 @@
-prepare($sql);
- $stmt->execute();
- $pedidos = $stmt->fetchAll(PDO::FETCH_ASSOC);
-
- echo json_encode([
- 'success' => true,
- 'pedidos' => $pedidos,
- 'total' => count($pedidos),
- 'mensaje' => 'Datos cargados con bypass - SOLO PARA TESTING',
- 'session_info' => $_SESSION
- ]);
-
-} catch (Exception $e) {
- error_log("BYPASS Pedidos Error: " . $e->getMessage());
- echo json_encode([
- 'success' => false,
- 'mensaje' => 'Error: ' . $e->getMessage(),
- 'session_info' => $_SESSION
- ]);
-}
-?>
diff --git a/files/obtener_producto_ajax.php b/files/obtener_producto_ajax.php
deleted file mode 100644
index c0f857f..0000000
--- a/files/obtener_producto_ajax.php
+++ /dev/null
@@ -1,89 +0,0 @@
- false,
- 'mensaje' => 'Método no permitido. Solo se acepta POST.'
- ]);
- exit();
-}
-
-// Verificar que se envió el ID
-if (!isset($_POST['id']) || empty($_POST['id'])) {
- echo json_encode([
- 'success' => false,
- 'mensaje' => 'ID de producto requerido.'
- ]);
- exit();
-}
-
-$id_producto = intval($_POST['id']);
-
-try {
- // Obtener información del producto usando PDO
- $consulta_producto = "SELECT
- ID_PRODUCTO,
- NOMBRE_PRODUCTO,
- PRECIO_PRODUCTO,
- PRODUCTO_STOCK_MIN,
- TIPO_PRODUCTO_MARCA,
- FECHA_VENCIMIENTO_PRODUCTO,
- COALESCE(ACTIVO, 1) as ACTIVO
- FROM Productos
- WHERE ID_PRODUCTO = :id";
-
- $stmt_producto = $pdo_conexion->prepare($consulta_producto);
- $stmt_producto->bindParam(':id', $id_producto, PDO::PARAM_INT);
- $stmt_producto->execute();
- $producto = $stmt_producto->fetch(PDO::FETCH_ASSOC);
-
- if (!$producto) {
- echo json_encode([
- 'success' => false,
- 'mensaje' => 'Producto no encontrado.'
- ]);
- exit();
- }
-
- // Verificar referencias en detalle_pedidos
- $consulta_referencias = "SELECT COUNT(*) as total FROM detalle_pedidos WHERE ID_PRODUCTO = :id";
- $stmt_referencias = $pdo_conexion->prepare($consulta_referencias);
- $stmt_referencias->bindParam(':id', $id_producto, PDO::PARAM_INT);
- $stmt_referencias->execute();
- $referencias_result = $stmt_referencias->fetch(PDO::FETCH_ASSOC);
- $referencias = $referencias_result ? $referencias_result['total'] : 0;
-
- // Preparar respuesta
- $response = [
- 'success' => true,
- 'producto' => [
- 'id' => $producto['ID_PRODUCTO'],
- 'nombre' => $producto['NOMBRE_PRODUCTO'],
- 'precio' => $producto['PRECIO_PRODUCTO'],
- 'stock' => $producto['PRODUCTO_STOCK_MIN'],
- 'categoria' => $producto['TIPO_PRODUCTO_MARCA'],
- 'fecha_vencimiento' => date('d/m/Y', strtotime($producto['FECHA_VENCIMIENTO_PRODUCTO'])),
- 'activo' => $producto['ACTIVO']
- ],
- 'referencias' => $referencias
- ];
-
- echo json_encode($response);
-
-} catch (PDOException $e) {
- echo json_encode([
- 'success' => false,
- 'mensaje' => 'Error en la base de datos: ' . $e->getMessage()
- ]);
-} catch (Exception $e) {
- echo json_encode([
- 'success' => false,
- 'mensaje' => 'Error inesperado: ' . $e->getMessage()
- ]);
-}
-?>
diff --git a/files/obtener_productos_ajax.php b/files/obtener_productos_ajax.php
deleted file mode 100644
index 138263f..0000000
--- a/files/obtener_productos_ajax.php
+++ /dev/null
@@ -1,179 +0,0 @@
- session_id(),
- 'usuario_logueado' => $_SESSION['usuario_logueado'] ?? 'NO_SET',
- 'usuario_tipo' => $_SESSION['usuario_tipo'] ?? 'NO_SET',
- 'all_session' => $_SESSION
- ];
-
- error_log("AJAX Auth Failed Productos - Debug: " . json_encode($debug_info));
-
- http_response_code(401);
- echo json_encode([
- 'success' => false,
- 'mensaje' => 'No autorizado para productos. Debug info logged.'
- ]);
- exit();
-}
-
-require_once 'conexion.php';
-
-try {
- // Verificar conexión
- if (!$conexion) {
- throw new Exception("Error de conexión a la base de datos");
- }
-
- // Obtener datos del POST
- $input = json_decode(file_get_contents('php://input'), true);
-
- if (json_last_error() !== JSON_ERROR_NONE) {
- throw new Exception("Error al decodificar JSON: " . json_last_error_msg());
- }
-
- // Para debug, loggear los parámetros
- error_log("Productos AJAX - Input: " . print_r($input, true));
-
- $buscar = isset($input['buscar']) ? trim($input['buscar']) : '';
- $estado = isset($input['estado']) ? $input['estado'] : '';
- $categoria = isset($input['categoria']) ? $input['categoria'] : '';
-
- // Primero, verificar si las tablas existen
- $test_query = "SHOW TABLES LIKE 'Productos'";
- $test_result = $conexion->query($test_query);
- if (!$test_result || $test_result->num_rows == 0) {
- throw new Exception("La tabla 'Productos' no existe");
- }
-
- // Construir consulta base - simplificada inicialmente
- $query = "
- SELECT
- p.ID_PRODUCTO as id,
- p.NOMBRE_PRODUCTO as nombre,
- 'Sin categoría' as categoria,
- p.PRECIO_PRODUCTO as precio,
- p.PRODUCTO_STOCK_MIN as stock_min,
- p.FECHA_VENCIMIENTO_PRODUCTO as vencimiento,
- p.ACTIVO as activo
- FROM Productos p
- WHERE 1=1
- ";
-
- $params = [];
- $types = '';
-
- // Filtros
- if (!empty($buscar)) {
- $query .= " AND p.NOMBRE_PRODUCTO LIKE ?";
- $params[] = '%' . $buscar . '%';
- $types .= 's';
- }
-
- if ($estado !== '') {
- $query .= " AND p.ACTIVO = ?";
- $params[] = (int)$estado;
- $types .= 'i';
- }
-
- $query .= " ORDER BY p.NOMBRE_PRODUCTO ASC LIMIT 100";
-
- error_log("Productos AJAX - Query: " . $query);
- error_log("Productos AJAX - Params: " . print_r($params, true));
-
- $stmt = $conexion->prepare($query);
-
- if (!$stmt) {
- throw new Exception("Error preparando consulta: " . $conexion->error);
- }
-
- if (!empty($params)) {
- $stmt->bind_param($types, ...$params);
- }
-
- if (!$stmt->execute()) {
- throw new Exception("Error ejecutando consulta: " . $stmt->error);
- }
-
- $result = $stmt->get_result();
-
- if (!$result) {
- throw new Exception("Error obteniendo resultados: " . $stmt->error);
- }
-
- $productos = [];
- while ($row = $result->fetch_assoc()) {
- $productos[] = [
- 'id' => (int)$row['id'],
- 'nombre' => $row['nombre'],
- 'categoria' => $row['categoria'] ?: 'Sin categoría',
- 'precio' => (float)$row['precio'],
- 'stock_min' => (int)$row['stock_min'],
- 'vencimiento' => $row['vencimiento'],
- 'activo' => (bool)$row['activo']
- ];
- }
-
- // Obtener categorías (simplificado)
- $categorias = [];
- try {
- $cat_query = "SHOW TABLES LIKE 'Categoria_Productos'";
- $cat_result = $conexion->query($cat_query);
- if ($cat_result && $cat_result->num_rows > 0) {
- $categorias_query = "SELECT ID_CATEGORIA_PRODUCTO as id, NOMBRE_CATEGORIAPRODUCTO as nombre FROM Categoria_Productos ORDER BY NOMBRE_CATEGORIAPRODUCTO LIMIT 20";
- $categorias_result = $conexion->query($categorias_query);
-
- if ($categorias_result) {
- while ($cat = $categorias_result->fetch_assoc()) {
- $categorias[] = [
- 'id' => (int)$cat['id'],
- 'nombre' => $cat['nombre']
- ];
- }
- }
- }
- } catch (Exception $cat_error) {
- error_log("Error cargando categorías: " . $cat_error->getMessage());
- }
-
- error_log("Productos AJAX - Resultado: " . count($productos) . " productos encontrados");
-
- echo json_encode([
- 'success' => true,
- 'productos' => $productos,
- 'categorias' => $categorias,
- 'total' => count($productos),
- 'debug' => [
- 'query' => $query,
- 'params' => $params
- ]
- ]);
-
-} catch (Exception $e) {
- error_log("Error en obtener_productos_ajax.php: " . $e->getMessage());
- error_log("Error stack: " . $e->getTraceAsString());
- http_response_code(500);
- echo json_encode([
- 'success' => false,
- 'mensaje' => $e->getMessage(),
- 'debug' => [
- 'file' => $e->getFile(),
- 'line' => $e->getLine()
- ]
- ]);
-}
-?>
diff --git a/files/obtener_proveedores_ajax.php b/files/obtener_proveedores_ajax.php
deleted file mode 100644
index 6295bbe..0000000
--- a/files/obtener_proveedores_ajax.php
+++ /dev/null
@@ -1,65 +0,0 @@
- false,
- 'error' => 'No autorizado'
- ]);
- exit();
-}
-
-require_once 'conexion.php';
-
-try {
- // Consulta para obtener proveedores activos
- $consulta = "SELECT
- ID_PROVEEDOR as id,
- NOMBRE_PROV as nombre
- FROM Proveedores
- WHERE ACTIVO_PROV = 1
- ORDER BY NOMBRE_PROV ASC";
-
- $resultado = $conexion->query($consulta);
-
- if ($resultado) {
- $proveedores = [];
- while ($fila = $resultado->fetch_assoc()) {
- $proveedores[] = [
- 'id' => $fila['id'],
- 'nombre' => $fila['nombre']
- ];
- }
-
- echo json_encode([
- 'success' => true,
- 'proveedores' => $proveedores
- ]);
- } else {
- echo json_encode([
- 'success' => false,
- 'mensaje' => 'Error en la consulta: ' . $conexion->error
- ]);
- }
-
-} catch (Exception $e) {
- echo json_encode([
- 'success' => false,
- 'mensaje' => 'Error del servidor: ' . $e->getMessage()
- ]);
-}
-
-$conexion->close();
-?>
diff --git a/files/on_off.php b/files/on_off.php
deleted file mode 100644
index ada7a96..0000000
--- a/files/on_off.php
+++ /dev/null
@@ -1,273 +0,0 @@
-alert('Método no permitido. Use POST.'); window.history.back();";
- exit();
-}
-
-// Verificar si se recibió el ID del producto y el estado actual
-if (isset($_POST['id']) && !empty($_POST['id']) && isset($_POST['estado'])) {
- $id_producto = $_POST['id'];
- $estado_actual = $_POST['estado'];
-
- // Determinar el nuevo estado (invertir el actual)
- $nuevo_estado = ($estado_actual == 1) ? 0 : 1;
- $accion_texto = ($nuevo_estado == 1) ? "activado" : "desactivado";
-
- try {
- // Obtener información del producto antes del cambio
- $consulta_producto = "SELECT NOMBRE_PRODUCTO, ACTIVO FROM Productos WHERE ID_PRODUCTO = :id";
- $stmt_producto = $pdo_conexion->prepare($consulta_producto);
- $stmt_producto->bindParam(':id', $id_producto, PDO::PARAM_INT);
- $stmt_producto->execute();
- $producto = $stmt_producto->fetch(PDO::FETCH_ASSOC);
-
- if ($producto) {
- $nombre_producto = $producto['NOMBRE_PRODUCTO'];
-
- // Actualizar el estado del producto
- $consulta_update = "UPDATE Productos SET ACTIVO = :nuevo_estado WHERE ID_PRODUCTO = :id";
- $stmt_update = $pdo_conexion->prepare($consulta_update);
- $stmt_update->bindParam(':nuevo_estado', $nuevo_estado, PDO::PARAM_INT);
- $stmt_update->bindParam(':id', $id_producto, PDO::PARAM_INT);
-
- if ($stmt_update->execute()) {
- $mensaje = "El producto '{$nombre_producto}' ha sido {$accion_texto} exitosamente.";
- $tipo_mensaje = "success";
- } else {
- $mensaje = "Error: No se pudo cambiar el estado del producto.";
- $tipo_mensaje = "error";
- }
- } else {
- $mensaje = "Error: El producto no existe.";
- $tipo_mensaje = "error";
- }
-
- } catch (PDOException $e) {
- $mensaje = "Error en la base de datos: " . $e->getMessage();
- $tipo_mensaje = "error";
- }
-} else {
- $mensaje = "Error: Parámetros no válidos.";
- $tipo_mensaje = "error";
-}
-?>
-
-
-
-
-
-
- Cambiar Estado - Panadería
-
-
-
-
-
-
✓
-
Estado Cambiado
-
-
✗
-
Error al Cambiar Estado
-
-
-
-
-
-
-
-
-
Información del Cambio:
-
Producto:
-
Nuevo Estado:
-
- ✓ Activo
-
- ✗ Inactivo
-
-
-
Fecha del Cambio:
-
-
-
-
💡 Información Importante:
-
-
- - El producto está ahora INACTIVO y no aparecerá en búsquedas normales
- - Los pedidos existentes que contienen este producto NO se ven afectados
- - Puedes reactivarlo en cualquier momento
-
- - El producto está ahora ACTIVO y disponible para nuevos pedidos
- - Aparecerá en todas las búsquedas y listados normales
- - Los clientes pueden volver a pedirlo
-
-
-
-
-
-
-
-
-
-
- ⏱️ Por favor, lee toda la información mostrada arriba antes de continuar.
- El botón se activará en 5 segundos.
-
-
-
-
-
-
diff --git a/files/pedidos.php b/files/pedidos.php
deleted file mode 100644
index 2d39512..0000000
--- a/files/pedidos.php
+++ /dev/null
@@ -1,557 +0,0 @@
-setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
-} catch(PDOException $e) {
- $error_msg = "Error al conectar con la base de datos: " . $e->getMessage();
-}
-
-// Calcular totales
-$subtotal = 0;
-$carrito_items = [];
-
-if (!empty($_SESSION['carrito'])) {
- foreach ($_SESSION['carrito'] as $item) {
- $subtotal += $item['precio'] * $item['cantidad'];
- $carrito_items[] = $item;
- }
-}
-
-$iva = $subtotal * 0.19;
-$total = $subtotal + $iva;
-?>
-
-
-
-
-
-
- Mis Pedidos - El Castillo del Pan
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Mi Carrito de Compras
-
-
-
-
-
-
-
-
-
Productos Seleccionados
-
-
-
-
-
-
![<?php echo htmlspecialchars($item['nombre']); ?>](img/pan-rtzqhi1ok4k1bxlo.jpg)
-
-
-
-
-
-
-
-
-
Stock:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Resumen del Pedido
-
- Subtotal:
- $
-
-
- IVA (19%):
- $
-
-
-
- Total:
- $
-
-
-
-
-
- Continuar Comprando
-
-
-
-
-
-
-
-
-
-
-
Tu carrito está vacío
-
¡Agrega algunos productos deliciosos a tu carrito!
-
- Ver Menú
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/files/pedidos_historial.php b/files/pedidos_historial.php
deleted file mode 100644
index 0345e35..0000000
--- a/files/pedidos_historial.php
+++ /dev/null
@@ -1,407 +0,0 @@
-
-
-
-
-
-
-
- Historial de Pedidos - Admin
-
-
-
-
-
-
-
-
-
-
-
Historial de Pedidos
-
-
-
-
-
-
-
-
-
-
- | ID Pedido |
- Cliente |
- Email |
- Fecha |
- Total |
- Estado |
- Acciones |
-
-
-
- 0): ?>
-
-
- | # |
- |
- |
- |
- $ |
-
-
-
-
-
- |
-
-
- |
-
-
-
-
- |
-
- No hay pedidos registrados
- |
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/files/perfil_admin.php b/files/perfil_admin.php
deleted file mode 100644
index dbbce57..0000000
--- a/files/perfil_admin.php
+++ /dev/null
@@ -1,242 +0,0 @@
-prepare("UPDATE Administradores SET NOMBRE_ADMIN = ?, TELEFONO_ADMIN = ?, EMAIL_ADMIN = ? WHERE ID_ADMIN = ?");
- $stmt->bind_param("sssi", $nuevo_nombre, $nuevo_telefono, $nuevo_email, $_SESSION['usuario_id']);
-
- if ($stmt->execute()) {
- $_SESSION['usuario_nombre'] = $nuevo_nombre;
- $mensaje = "Perfil actualizado correctamente";
- $tipo_mensaje = "success";
- } else {
- $mensaje = "Error al actualizar el perfil";
- $tipo_mensaje = "error";
- }
- } catch (Exception $e) {
- $mensaje = "Error: " . $e->getMessage();
- $tipo_mensaje = "error";
- }
- }
-}
-
-// Obtener datos actuales del administrador
-$admin_data = null;
-try {
- // Verificar que tenemos el ID de usuario
- if (!isset($_SESSION['usuario_id'])) {
- throw new Exception("ID de usuario no encontrado en la sesión");
- }
-
- $stmt = $conexion->prepare("SELECT * FROM Administradores WHERE ID_ADMIN = ?");
- $stmt->bind_param("i", $_SESSION['usuario_id']);
- $stmt->execute();
- $result = $stmt->get_result();
- $admin_data = $result->fetch_assoc();
-
- if (!$admin_data) {
- throw new Exception("No se encontraron datos del administrador");
- }
-} catch (Exception $e) {
- error_log("Error en perfil_admin.php: " . $e->getMessage());
- $mensaje = "Error al cargar datos del perfil: " . $e->getMessage();
- $tipo_mensaje = "error";
-}
-?>
-
-
-
-
-
-
- Mi Perfil - Administrador
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/files/perfil_cliente.php b/files/perfil_cliente.php
deleted file mode 100644
index f7258b7..0000000
--- a/files/perfil_cliente.php
+++ /dev/null
@@ -1,245 +0,0 @@
-prepare("UPDATE Clientes SET NOMBRE_CLI = ?, TELEFONO_CLI = ?, EMAIL_CLI = ? WHERE ID_CLIENTE = ?");
- $stmt->bind_param("sssi", $nuevo_nombre, $nuevo_telefono, $nuevo_email, $_SESSION['usuario_id']);
-
- if ($stmt->execute()) {
- $_SESSION['usuario_nombre'] = $nuevo_nombre;
- $mensaje = "Perfil actualizado correctamente";
- $tipo_mensaje = "success";
- } else {
- $mensaje = "Error al actualizar el perfil";
- $tipo_mensaje = "error";
- }
- } catch (Exception $e) {
- $mensaje = "Error: " . $e->getMessage();
- $tipo_mensaje = "error";
- }
- }
-}
-
-// Obtener datos actuales del cliente
-$cliente_data = null;
-try {
- // Verificar que tenemos el ID de usuario
- if (!isset($_SESSION['usuario_id'])) {
- throw new Exception("ID de usuario no encontrado en la sesión");
- }
-
- $stmt = $conexion->prepare("SELECT * FROM Clientes WHERE ID_CLIENTE = ?");
- $stmt->bind_param("i", $_SESSION['usuario_id']);
- $stmt->execute();
- $result = $stmt->get_result();
- $cliente_data = $result->fetch_assoc();
-
- if (!$cliente_data) {
- throw new Exception("No se encontraron datos del cliente");
- }
-} catch (Exception $e) {
- error_log("Error en perfil_cliente.php: " . $e->getMessage());
- $mensaje = "Error al cargar datos del perfil: " . $e->getMessage();
- $tipo_mensaje = "error";
-}
-?>
-
-
-
-
-
-
- Mi Perfil - Cliente
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/files/perfil_empleado.php b/files/perfil_empleado.php
deleted file mode 100644
index bc5f915..0000000
--- a/files/perfil_empleado.php
+++ /dev/null
@@ -1,241 +0,0 @@
-prepare("UPDATE Empleados SET NOMBRE_EMPLEADO = ?, EMAIL_EMPLEADO = ? WHERE ID_EMPLEADO = ?");
- $stmt->bind_param("ssi", $nuevo_nombre, $nuevo_email, $_SESSION['usuario_id']);
-
- if ($stmt->execute()) {
- $_SESSION['usuario_nombre'] = $nuevo_nombre;
- $mensaje = "Perfil actualizado correctamente";
- $tipo_mensaje = "success";
- } else {
- $mensaje = "Error al actualizar el perfil";
- $tipo_mensaje = "error";
- }
- } catch (Exception $e) {
- $mensaje = "Error: " . $e->getMessage();
- $tipo_mensaje = "error";
- }
- }
-}
-
-// Obtener datos actuales del empleado
-$empleado_data = null;
-try {
- // Verificar que tenemos el ID de usuario
- if (!isset($_SESSION['usuario_id'])) {
- throw new Exception("ID de usuario no encontrado en la sesión");
- }
-
- $stmt = $conexion->prepare("SELECT * FROM Empleados WHERE ID_EMPLEADO = ?");
- $stmt->bind_param("i", $_SESSION['usuario_id']);
- $stmt->execute();
- $result = $stmt->get_result();
- $empleado_data = $result->fetch_assoc();
-
- if (!$empleado_data) {
- throw new Exception("No se encontraron datos del empleado");
- }
-} catch (Exception $e) {
- error_log("Error en perfil_empleado.php: " . $e->getMessage());
- $mensaje = "Error al cargar datos del perfil: " . $e->getMessage();
- $tipo_mensaje = "error";
-}
-?>
-
-
-
-
-
-
- Mi Perfil - Empleado
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/files/procesar.php b/files/procesar.php
deleted file mode 100644
index 9967e14..0000000
--- a/files/procesar.php
+++ /dev/null
@@ -1,42 +0,0 @@
-prepare($sql);
-
- $resultado = $consulta->execute([
- $nombre,
- $telefono,
- $email,
- $contraseña_encriptada,
- $salt
- ]);
-
- if($resultado) {
- echo "✅ Cliente registrado exitosamente
";
- echo "ID del cliente: " . $pdo_conexion->lastInsertId() . "
";
- echo "Nombre: " . htmlspecialchars($nombre) . "
";
- echo "Email: " . htmlspecialchars($email) . "
";
- echo "
Registrar otro cliente";
- }
-
- } catch(PDOException $e) {
- echo "❌ Error al registrar cliente
";
- echo "Error: " . $e->getMessage() . "
";
- echo "
Volver al formulario";
- }
-} else {
- echo "No hay datos para procesar
";
- echo "Ir al formulario";
-}
-?>
\ No newline at end of file
diff --git a/files/procesar_carrito.php b/files/procesar_carrito.php
deleted file mode 100644
index b7afc97..0000000
--- a/files/procesar_carrito.php
+++ /dev/null
@@ -1,269 +0,0 @@
- false, 'message' => 'Usuario no autenticado']);
- exit();
-}
-
-// Configuración de la base de datos
-$host = 'localhost';
-$db_name = 'proyectopanaderia';
-$username = 'root';
-$password = '';
-
-try {
- $pdo = new PDO("mysql:host=$host;dbname=$db_name;charset=utf8", $username, $password);
- $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
-} catch(PDOException $e) {
- echo json_encode(['success' => false, 'message' => 'Error de conexión a la base de datos']);
- exit();
-}
-
-// Verificar el método de la solicitud
-$method = $_SERVER['REQUEST_METHOD'];
-$input = json_decode(file_get_contents('php://input'), true);
-
-// Inicializar carrito si no existe
-if (!isset($_SESSION['carrito'])) {
- $_SESSION['carrito'] = [];
-}
-
-switch ($method) {
- case 'POST':
- if (isset($input['accion'])) {
- switch ($input['accion']) {
- case 'agregar':
- agregarProducto($pdo, $input);
- break;
- case 'actualizar':
- actualizarCantidad($input);
- break;
- case 'eliminar':
- eliminarProducto($input);
- break;
- case 'finalizar':
- finalizarPedido($pdo, $input);
- break;
- case 'obtener_carrito':
- obtenerCarrito($pdo);
- break;
- default:
- echo json_encode(['success' => false, 'message' => 'Acción no válida']);
- }
- } else {
- echo json_encode(['success' => false, 'message' => 'Acción no especificada']);
- }
- break;
- default:
- echo json_encode(['success' => false, 'message' => 'Método no permitido']);
-}
-
-function agregarProducto($pdo, $input) {
- $producto_id = $input['producto_id'] ?? null;
- $cantidad = $input['cantidad'] ?? 1;
-
- if (!$producto_id) {
- echo json_encode(['success' => false, 'message' => 'ID de producto no especificado']);
- return;
- }
-
- // Verificar que el producto existe y está activo
- $stmt = $pdo->prepare("SELECT * FROM Productos WHERE ID_PRODUCTO = ? AND ACTIVO = 1");
- $stmt->execute([$producto_id]);
- $producto = $stmt->fetch(PDO::FETCH_ASSOC);
-
- if (!$producto) {
- echo json_encode(['success' => false, 'message' => 'Producto no encontrado o no disponible']);
- return;
- }
-
- // Verificar stock disponible
- if ($producto['PRODUCTO_STOCK_MIN'] < $cantidad) {
- echo json_encode(['success' => false, 'message' => 'Stock insuficiente']);
- return;
- }
-
- // Agregar o actualizar producto en el carrito
- if (isset($_SESSION['carrito'][$producto_id])) {
- $nueva_cantidad = $_SESSION['carrito'][$producto_id]['cantidad'] + $cantidad;
- if ($nueva_cantidad > $producto['PRODUCTO_STOCK_MIN']) {
- echo json_encode(['success' => false, 'message' => 'Stock insuficiente para la cantidad solicitada']);
- return;
- }
- $_SESSION['carrito'][$producto_id]['cantidad'] = $nueva_cantidad;
- } else {
- $_SESSION['carrito'][$producto_id] = [
- 'id' => $producto_id,
- 'nombre' => $producto['NOMBRE_PRODUCTO'],
- 'precio' => $producto['PRECIO_PRODUCTO'],
- 'cantidad' => $cantidad,
- 'stock_disponible' => $producto['PRODUCTO_STOCK_MIN']
- ];
- }
-
- echo json_encode([
- 'success' => true,
- 'message' => 'Producto agregado al carrito',
- 'carrito_count' => array_sum(array_column($_SESSION['carrito'], 'cantidad'))
- ]);
-}
-
-function actualizarCantidad($input) {
- $producto_id = $input['producto_id'] ?? null;
- $cantidad = $input['cantidad'] ?? 1;
-
- if (!$producto_id || $cantidad < 1) {
- echo json_encode(['success' => false, 'message' => 'Datos inválidos']);
- return;
- }
-
- if (isset($_SESSION['carrito'][$producto_id])) {
- // Verificar stock disponible
- if ($cantidad > $_SESSION['carrito'][$producto_id]['stock_disponible']) {
- echo json_encode(['success' => false, 'message' => 'Stock insuficiente']);
- return;
- }
-
- $_SESSION['carrito'][$producto_id]['cantidad'] = $cantidad;
- echo json_encode([
- 'success' => true,
- 'message' => 'Cantidad actualizada',
- 'carrito_count' => array_sum(array_column($_SESSION['carrito'], 'cantidad'))
- ]);
- } else {
- echo json_encode(['success' => false, 'message' => 'Producto no encontrado en el carrito']);
- }
-}
-
-function eliminarProducto($input) {
- $producto_id = $input['producto_id'] ?? null;
-
- if (!$producto_id) {
- echo json_encode(['success' => false, 'message' => 'ID de producto no especificado']);
- return;
- }
-
- if (isset($_SESSION['carrito'][$producto_id])) {
- unset($_SESSION['carrito'][$producto_id]);
- echo json_encode([
- 'success' => true,
- 'message' => 'Producto eliminado del carrito',
- 'carrito_count' => array_sum(array_column($_SESSION['carrito'], 'cantidad'))
- ]);
- } else {
- echo json_encode(['success' => false, 'message' => 'Producto no encontrado en el carrito']);
- }
-}
-
-function finalizarPedido($pdo, $input) {
- if (empty($_SESSION['carrito'])) {
- echo json_encode(['success' => false, 'message' => 'El carrito está vacío']);
- return;
- }
-
- $user_id = $_SESSION['usuario_id'] ?? null;
-
- if (!$user_id) {
- echo json_encode(['success' => false, 'message' => 'Usuario no identificado']);
- return;
- }
-
- try {
- $pdo->beginTransaction();
-
- // Calcular total del pedido
- $total = 0;
- foreach ($_SESSION['carrito'] as $item) {
- $total += $item['precio'] * $item['cantidad'];
- }
-
- $iva = $total * 0.19;
- $total_con_iva = $total + $iva;
-
- // Insertar pedido en la base de datos
- $stmt = $pdo->prepare("
- INSERT INTO Pedidos (ID_CLIENTE, ID_ESTADO_PEDIDO, FECHA_INGRESO, FECHA_ENTREGA, TOTAL_PRODUCTO)
- VALUES (?, 1, NOW(), DATE_ADD(NOW(), INTERVAL 1 DAY), ?)
- ");
- $stmt->execute([$user_id, $total_con_iva]);
- $pedido_id = $pdo->lastInsertId();
-
- // Insertar detalles del pedido y actualizar stock
- foreach ($_SESSION['carrito'] as $item) {
- // Verificar stock actual
- $stmt = $pdo->prepare("SELECT PRODUCTO_STOCK_MIN FROM Productos WHERE ID_PRODUCTO = ?");
- $stmt->execute([$item['id']]);
- $stock_actual = $stmt->fetchColumn();
-
- if ($stock_actual < $item['cantidad']) {
- throw new Exception("Stock insuficiente para el producto: " . $item['nombre']);
- }
-
- // Calcular subtotal
- $subtotal = $item['precio'] * $item['cantidad'];
-
- // Insertar detalle del pedido
- $stmt = $pdo->prepare("
- INSERT INTO Detalle_Pedidos (ID_PEDIDO, ID_PRODUCTO, CANTIDAD_PRODUCTO, PRECIO_UNITARIO, SUBTOTAL)
- VALUES (?, ?, ?, ?, ?)
- ");
- $stmt->execute([$pedido_id, $item['id'], $item['cantidad'], $item['precio'], $subtotal]);
-
- // Actualizar stock
- $stmt = $pdo->prepare("
- UPDATE Productos
- SET PRODUCTO_STOCK_MIN = PRODUCTO_STOCK_MIN - ?
- WHERE ID_PRODUCTO = ?
- ");
- $stmt->execute([$item['cantidad'], $item['id']]);
- }
-
- $pdo->commit();
-
- // Limpiar carrito
- $_SESSION['carrito'] = [];
-
- echo json_encode([
- 'success' => true,
- 'message' => 'Pedido realizado con éxito',
- 'pedido_id' => $pedido_id,
- 'total' => $total_con_iva
- ]);
-
- } catch (Exception $e) {
- $pdo->rollBack();
- echo json_encode(['success' => false, 'message' => 'Error al procesar el pedido: ' . $e->getMessage()]);
- }
-}
-
-function obtenerCarrito($pdo) {
- $carrito_info = [];
- $total = 0;
-
- foreach ($_SESSION['carrito'] as $item) {
- // Verificar stock actual
- $stmt = $pdo->prepare("SELECT PRODUCTO_STOCK_MIN FROM Productos WHERE ID_PRODUCTO = ?");
- $stmt->execute([$item['id']]);
- $stock_actual = $stmt->fetchColumn();
-
- $item['stock_disponible'] = $stock_actual;
- $carrito_info[] = $item;
- $total += $item['precio'] * $item['cantidad'];
- }
-
- $iva = $total * 0.19;
- $total_con_iva = $total + $iva;
-
- echo json_encode([
- 'success' => true,
- 'carrito' => $carrito_info,
- 'subtotal' => $total,
- 'iva' => $iva,
- 'total' => $total_con_iva,
- 'carrito_count' => array_sum(array_column($_SESSION['carrito'], 'cantidad'))
- ]);
-}
-?>
diff --git a/files/procesar_login.php b/files/procesar_login.php
deleted file mode 100644
index dc56b40..0000000
--- a/files/procesar_login.php
+++ /dev/null
@@ -1,189 +0,0 @@
-prepare($consulta);
- $stmt->bindParam(':usuario', $usuario, PDO::PARAM_STR);
- $stmt->execute();
-
- $user_data = $stmt->fetch(PDO::FETCH_ASSOC);
-
- // Log para debug
- error_log("Login Debug - Tipo: $tipo_usuario, Usuario buscado: $usuario, Usuario encontrado: " . ($user_data ? "SÍ" : "NO"));
-
- if ($user_data) {
- // Usuario encontrado, verificar contraseña
- $password_hash = "";
- $salt = "";
-
- switch ($tipo_usuario) {
- case 'admin':
- $password_hash = $user_data['CONTRASEÑA_ADMIN'];
- $salt = $user_data['SALT_ADMIN'];
- break;
- case 'empleado':
- $password_hash = $user_data['CONTRASEÑA_EMPLEADO'];
- $salt = $user_data['SALT_EMPLEADO'];
- break;
- case 'cliente':
- $password_hash = $user_data['CONTRASEÑA_CLI'];
- $salt = $user_data['SALT_CLI'];
- break;
- }
-
- // Verificar la contraseña
- $password_valid = false;
-
- // Log para debug de verificación de contraseña
- error_log("Verificando contraseña - Salt: " . ($salt ? "SÍ" : "NO") . ", Hash almacenado: " . ($password_hash ? "SÍ" : "NO"));
-
- if (!empty($salt) && !empty($password_hash)) {
- // Verificar con hash SHA256 + salt (sistema actual)
- $hash_to_check = hash('sha256', $password . $salt);
- error_log("Hash generado para verificación: " . substr($hash_to_check, 0, 20) . "...");
- error_log("Hash almacenado en BD: " . substr($password_hash, 0, 20) . "...");
-
- if ($hash_to_check === $password_hash) {
- $password_valid = true;
- error_log("Contraseña válida con hash SHA256");
- }
- } elseif (!empty($password_hash)) {
- // Verificar contraseña en texto plano (compatibilidad)
- if ($password === $password_hash) {
- $password_valid = true;
- error_log("Contraseña válida en texto plano");
- }
- }
-
- error_log("Resultado verificación de contraseña: " . ($password_valid ? "VÁLIDA" : "INVÁLIDA"));
-
- if ($password_valid) {
- // Contraseña correcta, crear sesión
- $_SESSION['usuario_logueado'] = true;
- $_SESSION['usuario_tipo'] = $tipo_usuario;
- $_SESSION['usuario_id'] = $user_data[$id_campo];
- $_SESSION['usuario_nombre'] = $user_data[$nombre_campo];
-
- // Variables adicionales para compatibilidad
- $_SESSION['user_name'] = $user_data[$nombre_campo];
- $_SESSION['role'] = $tipo_usuario;
-
- // Información adicional según el tipo de usuario
- if ($tipo_usuario === 'admin') {
- $_SESSION['usuario_email'] = $user_data['EMAIL_ADMIN'] ?? '';
- $_SESSION['usuario_telefono'] = $user_data['TELEFONO_ADMIN'] ?? '';
- } elseif ($tipo_usuario === 'cliente') {
- $_SESSION['usuario_email'] = $user_data['EMAIL_CLI'];
- $_SESSION['usuario_telefono'] = $user_data['TELEFONO_CLI'] ?? '';
- // Variable específica para el procesamiento de pedidos
- $_SESSION['cliente_id'] = $user_data['ID_CLIENTE'];
- }
-
- // Log del login exitoso
- error_log("Login exitoso - Tipo: $tipo_usuario, Usuario: " . $user_data[$nombre_campo] . ", IP: " . $_SERVER['REMOTE_ADDR']);
-
- // Redirigir según el tipo de usuario
- switch ($tipo_usuario) {
- case 'admin':
- header("Location: dashboard_admin.php");
- break;
- case 'empleado':
- header("Location: dashboard_empleado.php");
- break;
- case 'cliente':
- header("Location: dashboard_cliente.php");
- break;
- }
- exit();
-
- } else {
- // Contraseña incorrecta
- header("Location: login.php?error=invalid_credentials");
- exit();
- }
-
- } else {
- // Usuario no encontrado
- header("Location: login.php?error=invalid_credentials");
- exit();
- }
-
- } catch (PDOException $e) {
- // Error en la base de datos
- error_log("Error de login (PDO): " . $e->getMessage() . " - Usuario: $usuario, Tipo: $tipo_usuario");
- header("Location: login.php?error=database_error&detail=" . urlencode($e->getMessage()));
- exit();
- } catch (Exception $e) {
- // Error general
- error_log("Error de login (General): " . $e->getMessage() . " - Usuario: $usuario, Tipo: $tipo_usuario");
- header("Location: login.php?error=database_error&detail=" . urlencode($e->getMessage()));
- exit();
- }
-
-} else {
- // Acceso directo sin POST
- header("Location: login.php");
- exit();
-}
-?>
diff --git a/files/procesar_pedido.php b/files/procesar_pedido.php
deleted file mode 100644
index eb81bb0..0000000
--- a/files/procesar_pedido.php
+++ /dev/null
@@ -1,190 +0,0 @@
-setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
-
- // Manejar solicitudes OPTIONS para CORS
- if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
- http_response_code(200);
- exit;
- }
-
- // Solo permitir POST para pedidos
- if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
- throw new Exception('Método no permitido');
- }
-
- // Obtener datos del pedido
- $input = json_decode(file_get_contents('php://input'), true);
-
- if (!$input) {
- throw new Exception('Datos de pedido inválidos');
- }
-
- $producto_id = isset($input['producto_id']) ? (int)$input['producto_id'] : 0;
- $cantidad = isset($input['cantidad']) ? (int)$input['cantidad'] : 1;
-
- // Validaciones básicas
- if ($producto_id <= 0) {
- throw new Exception('ID de producto inválido');
- }
-
- if ($cantidad <= 0) {
- throw new Exception('Cantidad inválida');
- }
-
- // Verificar si el usuario está logueado
- if (!validarSesionCliente()) {
- throw new Exception('Debe iniciar sesión para realizar pedidos');
- }
-
- $cliente_id = $_SESSION['cliente_id'];
-
- // Iniciar transacción
- $pdo->beginTransaction();
-
- try {
- // Verificar que el producto existe y está activo
- $stmt = $pdo->prepare("
- SELECT
- ID_PRODUCTO,
- NOMBRE_PRODUCTO,
- PRECIO_PRODUCTO,
- PRODUCTO_STOCK_MIN,
- ACTIVO
- FROM Productos
- WHERE ID_PRODUCTO = ? AND ACTIVO = 1
- FOR UPDATE
- ");
- $stmt->execute([$producto_id]);
- $producto = $stmt->fetch(PDO::FETCH_ASSOC);
-
- if (!$producto) {
- throw new Exception('Producto no encontrado o no disponible');
- }
-
- // Verificar stock disponible
- if ($producto['PRODUCTO_STOCK_MIN'] < $cantidad) {
- throw new Exception('Stock insuficiente. Stock disponible: ' . $producto['PRODUCTO_STOCK_MIN']);
- }
-
- // Verificar que el stock no quede negativo
- if ($producto['PRODUCTO_STOCK_MIN'] - $cantidad < 0) {
- throw new Exception('No se puede procesar el pedido. Stock insuficiente');
- }
-
- // Descontar stock
- $nuevo_stock = $producto['PRODUCTO_STOCK_MIN'] - $cantidad;
- $stmt = $pdo->prepare("
- UPDATE Productos
- SET PRODUCTO_STOCK_MIN = ?,
- FECHA_ULTIMA_MODIFICACION = NOW()
- WHERE ID_PRODUCTO = ?
- ");
- $stmt->execute([$nuevo_stock, $producto_id]);
-
- // Verificar que la actualización fue exitosa
- if ($stmt->rowCount() === 0) {
- throw new Exception('Error al actualizar el stock');
- }
-
- // Registrar el pedido en la tabla de pedidos
- // Primero obtener el ID del estado "Pendiente"
- $stmt = $pdo->prepare("SELECT ID_ESTADO_PEDIDO FROM Estado_Pedidos WHERE NOMBRE_ESTADO = 'Pendiente'");
- $stmt->execute();
- $estado_pendiente = $stmt->fetch(PDO::FETCH_ASSOC);
-
- $pedido_id = null;
- if ($estado_pendiente) {
- // Crear registro de pedido
- $stmt = $pdo->prepare("
- INSERT INTO Pedidos (ID_CLIENTE, ID_ESTADO_PEDIDO, FECHA_INGRESO, FECHA_ENTREGA, TOTAL_PRODUCTO)
- VALUES (?, ?, NOW(), DATE_ADD(NOW(), INTERVAL 1 DAY), ?)
- ");
- $total_pedido = $producto['PRECIO_PRODUCTO'] * $cantidad;
- $stmt->execute([$cliente_id, $estado_pendiente['ID_ESTADO_PEDIDO'], $total_pedido]);
- $pedido_id = $pdo->lastInsertId();
-
- // Registrar detalle del pedido
- $subtotal = $producto['PRECIO_PRODUCTO'] * $cantidad;
- $stmt = $pdo->prepare("
- INSERT INTO Detalle_Pedidos (ID_PEDIDO, ID_PRODUCTO, CANTIDAD_PRODUCTO, PRECIO_UNITARIO, SUBTOTAL)
- VALUES (?, ?, ?, ?, ?)
- ");
- $stmt->execute([$pedido_id, $producto_id, $cantidad, $producto['PRECIO_PRODUCTO'], $subtotal]);
- }
-
- // Confirmar transacción
- $pdo->commit();
-
- // Log de actividad exitosa
- logActividad("Pedido procesado exitosamente - Producto: {$producto['NOMBRE_PRODUCTO']}, Cantidad: $cantidad, Stock restante: $nuevo_stock", $cliente_id);
-
- // Respuesta exitosa
- echo json_encode([
- 'success' => true,
- 'mensaje' => 'Pedido procesado exitosamente',
- 'producto' => [
- 'id' => $producto_id,
- 'nombre' => $producto['NOMBRE_PRODUCTO'],
- 'precio' => $producto['PRECIO_PRODUCTO'],
- 'cantidad_pedida' => $cantidad,
- 'stock_restante' => $nuevo_stock,
- 'total' => $producto['PRECIO_PRODUCTO'] * $cantidad
- ],
- 'pedido_id' => $pedido_id,
- 'timestamp' => time()
- ]);
-
- } catch (Exception $e) {
- // Rollback en caso de error
- $pdo->rollback();
- throw $e;
- }
-
-} catch (PDOException $e) {
- logActividad("Error de base de datos: " . $e->getMessage());
- echo json_encode([
- 'success' => false,
- 'error' => 'Error de base de datos: ' . $e->getMessage()
- ]);
-} catch (Exception $e) {
- logActividad("Error del servidor: " . $e->getMessage());
- echo json_encode([
- 'success' => false,
- 'error' => $e->getMessage()
- ]);
-}
-?>
diff --git a/files/procesar_registro.php b/files/procesar_registro.php
deleted file mode 100644
index ab957c7..0000000
--- a/files/procesar_registro.php
+++ /dev/null
@@ -1,107 +0,0 @@
-prepare("SELECT ID_CLIENTE FROM Clientes WHERE EMAIL_CLI = ?");
- $stmt->bindParam(1, $email, PDO::PARAM_STR);
- $stmt->execute();
-
- if ($stmt->rowCount() > 0) {
- header('Location: registro_cliente.php?error=email_exists');
- exit();
- }
-
- // Verificar si ya existe un cliente con ese nombre
- $stmt = $pdo_conexion->prepare("SELECT ID_CLIENTE FROM Clientes WHERE NOMBRE_CLI = ?");
- $stmt->bindParam(1, $nombre, PDO::PARAM_STR);
- $stmt->execute();
-
- if ($stmt->rowCount() > 0) {
- header('Location: registro_cliente.php?error=name_exists');
- exit();
- }
-
- // Generar salt aleatorio
- $salt = bin2hex(random_bytes(16));
-
- // Hashear la contraseña con salt
- $password_hash = hash('sha256', $password . $salt);
-
- // Insertar el nuevo cliente
- $stmt = $pdo_conexion->prepare("
- INSERT INTO Clientes (NOMBRE_CLI, EMAIL_CLI, TELEFONO_CLI, CONTRASEÑA_CLI, SALT_CLI, ACTIVO_CLI)
- VALUES (?, ?, ?, ?, ?, 1)
- ");
-
- $stmt->bindParam(1, $nombre, PDO::PARAM_STR);
- $stmt->bindParam(2, $email, PDO::PARAM_STR);
- $stmt->bindParam(3, $telefono, PDO::PARAM_STR);
- $stmt->bindParam(4, $password_hash, PDO::PARAM_STR);
- $stmt->bindParam(5, $salt, PDO::PARAM_STR);
-
- if ($stmt->execute()) {
- // Registro exitoso
- $nuevo_id = $conexion->lastInsertId();
-
- // Log del registro exitoso
- error_log("Nuevo cliente registrado - ID: $nuevo_id, Nombre: $nombre, Email: $email, IP: " . $_SERVER['REMOTE_ADDR']);
-
- // Redirigir al login con mensaje de éxito
- header('Location: login.php?success=registered');
- exit();
- } else {
- // Error en la inserción
- error_log("Error al registrar cliente");
- header('Location: registro_cliente.php?error=database_error');
- exit();
- }
-
- } catch (Exception $e) {
- // Error general
- error_log("Error en registro de cliente: " . $e->getMessage());
- header('Location: registro_cliente.php?error=database_error');
- exit();
- }
-} else {
- // Acceso directo no permitido
- header('Location: registro_cliente.php');
- exit();
-}
-?>
diff --git a/files/productostabla.php b/files/productostabla.php
deleted file mode 100644
index c9df091..0000000
--- a/files/productostabla.php
+++ /dev/null
@@ -1,1504 +0,0 @@
-❌ Error de conexión a la base de datos');
-}
-
-// Consultar todos los productos para mostrarlos en la tabla
-$consulta = "SELECT
- ID_PRODUCTO,
- NOMBRE_PRODUCTO,
- PRECIO_PRODUCTO,
- PRODUCTO_STOCK_MIN,
- TIPO_PRODUCTO_MARCA,
- FECHA_VENCIMIENTO_PRODUCTO,
- COALESCE(ACTIVO, 1) as ACTIVO
- FROM Productos
- ORDER BY ID_PRODUCTO DESC";
-
-$resultado = $conexion->query($consulta);
-
-if (!$resultado) {
- die('❌ Error en la consulta: ' . $conexion->error . '
');
-}
-?>
-
-
-
-
-
-
-
- Gestión de Productos - Panadería
-
-
-
-
-
-
- ✅ Producto agregado exitosamente
';
- }
- }
-
- if (isset($_GET['error'])) {
- $error = $_GET['error'];
- $mensaje_error = '';
- switch ($error) {
- case 'datos_incompletos':
- $mensaje_error = 'Por favor complete todos los campos obligatorios.';
- break;
- case 'error_bd':
- $mensaje_error = 'Error en la base de datos. Intente nuevamente.';
- break;
- default:
- $mensaje_error = 'Error desconocido.';
- }
- echo '❌ ' . $mensaje_error . '
';
- }
- ?>
-
-
-
Añadir Nuevo Producto
-
-
-
-
-
-
-
-
-
-
- | ID |
- Nombre |
- Precio |
- Stock |
- Marca/Tipo |
- Fecha Vencimiento |
- Estado |
- Acciones |
-
-
-
- num_rows > 0): ?>
- fetch_assoc()): ?>
-
- |
- |
-
-
-
- $
-
-
-
-
-
-
-
-
- |
-
-
-
-
-
-
-
-
-
-
-
-
- |
- |
- |
-
-
-
- check_circle
- Activo
-
-
-
- cancel
- Inactivo
-
-
- |
-
-
-
-
- |
-
-
-
-
- |
- No hay productos registrados en el inventario.
- |
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
hourglass_empty
-
Cargando información del producto...
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
✓
-
-
-
-
-
- ⏱️ Esta ventana se cerrará automáticamente en 5 segundos.
-
-
-
-
-
-
-
-
diff --git a/files/prueba_modales.php b/files/prueba_modales.php
deleted file mode 100644
index 126403e..0000000
--- a/files/prueba_modales.php
+++ /dev/null
@@ -1,222 +0,0 @@
-
-
-
-
-
- 🧪 Prueba de Modales - Sistema de Panadería
-
-
-
-
-
-
-
Prueba de Funcionalidades AJAX
-
-
-
Prueba de Empleados
-
-
-
-
-
-
-
-
Prueba de Clientes
-
-
-
-
-
-
-
-
Prueba de Agregar Empleado
-
-
-
-
-
-
-
-
-
-
-
diff --git a/files/prueba_sistema_completo.php b/files/prueba_sistema_completo.php
deleted file mode 100644
index e69de29..0000000
diff --git a/files/registro_cliente.php b/files/registro_cliente.php
deleted file mode 100644
index 77047c8..0000000
--- a/files/registro_cliente.php
+++ /dev/null
@@ -1,304 +0,0 @@
- 100) {
- $errores[] = "El nombre no puede tener más de 100 caracteres.";
- }
-
- if (empty($email)) {
- $errores[] = "El email es obligatorio.";
- } elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
- $errores[] = "El formato del email no es válido.";
- } elseif (strlen($email) > 150) {
- $errores[] = "El email no puede tener más de 150 caracteres.";
- }
-
- if (!empty($telefono)) {
- // El teléfono es opcional, pero si se proporciona debe ser válido
- if (!preg_match('/^[0-9+\-\s\(\)]{7,20}$/', $telefono)) {
- $errores[] = "El formato del teléfono no es válido.";
- }
- }
-
- if (empty($password)) {
- $errores[] = "La contraseña es obligatoria.";
- } elseif (strlen($password) < 6) {
- $errores[] = "La contraseña debe tener al menos 6 caracteres.";
- } elseif (strlen($password) > 255) {
- $errores[] = "La contraseña no puede tener más de 255 caracteres.";
- }
-
- if ($password !== $confirm_password) {
- $errores[] = "Las contraseñas no coinciden.";
- }
-
- // Si no hay errores de validación, verificar si ya existe el email o nombre
- if (empty($errores)) {
- try {
- // Verificar si ya existe un cliente con ese email
- $stmt = $pdo_conexion->prepare("SELECT ID_CLIENTE FROM Clientes WHERE EMAIL_CLI = ?");
- $stmt->execute([$email]);
-
- if ($stmt->rowCount() > 0) {
- $errores[] = "Ya existe un cliente registrado con ese email.";
- }
-
- // Verificar si ya existe un cliente con ese nombre
- $stmt = $pdo_conexion->prepare("SELECT ID_CLIENTE FROM Clientes WHERE NOMBRE_CLI = ?");
- $stmt->execute([$nombre]);
-
- if ($stmt->rowCount() > 0) {
- $errores[] = "Ya existe un cliente registrado con ese nombre.";
- }
-
- } catch (PDOException $e) {
- $errores[] = "Error al verificar los datos: " . $e->getMessage();
- }
- }
-
- // Si no hay errores, proceder con el registro
- if (empty($errores)) {
- try {
- // Generar salt aleatorio
- $salt = bin2hex(random_bytes(16));
-
- // Hashear la contraseña con salt
- $password_hash = hash('sha256', $password . $salt);
-
- // Insertar el nuevo cliente
- $stmt = $pdo_conexion->prepare("
- INSERT INTO Clientes (NOMBRE_CLI, EMAIL_CLI, TELEFONO_CLI, CONTRASEÑA_CLI, SALT_CLI, ACTIVO_CLI)
- VALUES (?, ?, ?, ?, ?, 1)
- ");
-
- $resultado = $stmt->execute([
- $nombre,
- $email,
- $telefono,
- $password_hash,
- $salt
- ]);
-
- if ($resultado) {
- $cliente_id = $pdo_conexion->lastInsertId();
- $registro_exitoso = true;
-
- // Mostrar aviso emergente antes de redirigir
- echo "";
- } else {
- $errores[] = "Error al registrar el cliente.";
- }
-
- } catch (PDOException $e) {
- $errores[] = "Error en la base de datos: " . $e->getMessage();
- }
- }
-}
-?>
-
-
-
-
-
-
-
-
- Registro de Cliente - Panadería
-
-
-
-
-
-
-

-
-
Registro Cliente
-
-
-
-
-
-
Por favor corrige los siguientes errores:
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Tu cuenta ha sido creada exitosamente.
-
Ahora puedes iniciar sesión con tus credenciales.
-
-
-
-
-
-
-
-
diff --git a/files/session_check.php b/files/session_check.php
deleted file mode 100644
index a35ef43..0000000
--- a/files/session_check.php
+++ /dev/null
@@ -1,23 +0,0 @@
- session_id(),
- 'session_status' => session_status(),
- 'session_data' => $_SESSION,
- 'cookies' => $_COOKIE,
- 'is_empleado' => (
- isset($_SESSION['usuario_logueado']) &&
- $_SESSION['usuario_logueado'] === true &&
- isset($_SESSION['usuario_tipo']) &&
- $_SESSION['usuario_tipo'] === 'empleado'
- ),
- 'auth_check' => [
- 'usuario_logueado_set' => isset($_SESSION['usuario_logueado']),
- 'usuario_logueado_value' => $_SESSION['usuario_logueado'] ?? 'not_set',
- 'usuario_tipo_set' => isset($_SESSION['usuario_tipo']),
- 'usuario_tipo_value' => $_SESSION['usuario_tipo'] ?? 'not_set'
- ]
-]);
-?>
diff --git a/files/session_debug.php b/files/session_debug.php
deleted file mode 100644
index da0f109..0000000
--- a/files/session_debug.php
+++ /dev/null
@@ -1,46 +0,0 @@
-Información de la Sesión";
-echo "Session ID: " . session_id() . "
";
-echo "Session Status: " . session_status() . "
";
-
-echo "Variables de Sesión:
";
-echo "";
-print_r($_SESSION);
-echo "
";
-
-echo "Cookies:
";
-echo "";
-print_r($_COOKIE);
-echo "
";
-
-echo "Información del Servidor:
";
-echo "PHP Version: " . PHP_VERSION . "
";
-echo "Server IP: " . $_SERVER['SERVER_ADDR'] . "
";
-echo "Client IP: " . $_SERVER['REMOTE_ADDR'] . "
";
-echo "User Agent: " . $_SERVER['HTTP_USER_AGENT'] . "
";
-
-echo "Validación de Empleado:
";
-$is_empleado = isset($_SESSION['usuario_tipo']) && $_SESSION['usuario_tipo'] === 'empleado';
-echo "¿Es empleado?: " . ($is_empleado ? "SÍ" : "NO") . "
";
-
-if (isset($_SESSION['usuario_tipo'])) {
- echo "Tipo actual: " . $_SESSION['usuario_tipo'] . "
";
-} else {
- echo "Tipo actual: NO DEFINIDO
";
-}
-
-// Verificar si hay conflicto de sesiones
-if (isset($_SESSION['usuario_logueado'])) {
- echo "Usuario logueado: " . ($_SESSION['usuario_logueado'] ? "SÍ" : "NO") . "
";
-} else {
- echo "Usuario logueado: NO DEFINIDO
";
-}
-
-echo "Enlaces de Prueba:
";
-echo "Dashboard Empleado
";
-echo "Login
";
-echo "Logout
";
-?>
diff --git a/files/setup_logs.php b/files/setup_logs.php
deleted file mode 100644
index fbcdf7e..0000000
--- a/files/setup_logs.php
+++ /dev/null
@@ -1,87 +0,0 @@
-query("SHOW TABLES LIKE 'productos_logs'");
-
- if ($check_table->num_rows == 0) {
- echo "Tabla productos_logs no encontrada. Creando...
";
-
- // Crear tabla de logs
- $sql_tabla = "
- CREATE TABLE productos_logs (
- id INT PRIMARY KEY AUTO_INCREMENT,
- producto_id INT NOT NULL,
- tipo_cambio ENUM('precio', 'stock', 'activacion', 'desactivacion') NOT NULL,
- valor_anterior VARCHAR(50),
- valor_nuevo VARCHAR(50),
- usuario_id INT,
- usuario_tipo ENUM('admin', 'empleado') DEFAULT 'admin',
- fecha_cambio TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
- ip_usuario VARCHAR(45),
- FOREIGN KEY (producto_id) REFERENCES Productos(ID_PRODUCTO) ON DELETE CASCADE
- )";
-
- if ($conexion->query($sql_tabla)) {
- echo "✅ Tabla productos_logs creada exitosamente
";
- } else {
- echo "❌ Error al crear tabla productos_logs: " . $conexion->error . "
";
- }
-
- // Crear índices
- $indices = [
- "CREATE INDEX idx_producto_logs_fecha ON productos_logs(fecha_cambio)",
- "CREATE INDEX idx_producto_logs_producto ON productos_logs(producto_id)",
- "CREATE INDEX idx_producto_logs_tipo ON productos_logs(tipo_cambio)"
- ];
-
- foreach ($indices as $indice) {
- if ($conexion->query($indice)) {
- echo "✅ Índice creado exitosamente
";
- } else {
- echo "❌ Error al crear índice: " . $conexion->error . "
";
- }
- }
-
- } else {
- echo "✅ Tabla productos_logs ya existe
";
- }
-
- // Verificar si el trigger existe
- $check_trigger = $conexion->query("SHOW TRIGGERS LIKE 'actualizar_fecha_producto'");
-
- if ($check_trigger->num_rows == 0) {
- echo "Trigger actualizar_fecha_producto no encontrado. Creando...
";
-
- $sql_trigger = "
- CREATE TRIGGER actualizar_fecha_producto
- BEFORE UPDATE ON Productos
- FOR EACH ROW
- BEGIN
- SET NEW.FECHA_ULTIMA_MODIFICACION = CURRENT_TIMESTAMP;
- END";
-
- if ($conexion->query($sql_trigger)) {
- echo "✅ Trigger actualizar_fecha_producto creado exitosamente
";
- } else {
- echo "❌ Error al crear trigger: " . $conexion->error . "
";
- }
- } else {
- echo "✅ Trigger actualizar_fecha_producto ya existe
";
- }
-
- echo "
Configuración completada!
";
- echo "Ir a Gestión de Productos";
-
-} catch (Exception $e) {
- echo "❌ Error: " . $e->getMessage();
-}
-
-$conexion->close();
-?>
diff --git a/files/sse_menu_updates.php b/files/sse_menu_updates.php
deleted file mode 100644
index 1ef1bf6..0000000
--- a/files/sse_menu_updates.php
+++ /dev/null
@@ -1,183 +0,0 @@
- ?
- ";
-
- $stmt = $conexion->prepare($query);
- $stmt->bind_param("d", $last_check);
- $stmt->execute();
- $result = $stmt->get_result()->fetch_assoc();
-
- return $result;
-}
-
-/**
- * Función para obtener detalles de productos modificados
- */
-function obtenerProductosModificados($conexion, $last_check, $limit = 10) {
- $query = "
- SELECT
- p.ID_PRODUCTO,
- p.NOMBRE_PRODUCTO,
- p.PRECIO_PRODUCTO,
- p.PRODUCTO_STOCK_MIN,
- p.ACTIVO,
- c.NOMBRE_CATEGORIA_PRODUCTO as categoria,
- UNIX_TIMESTAMP(p.FECHA_ULTIMA_MODIFICACION) as timestamp_modificacion
- FROM Productos p
- LEFT JOIN Categoria_Productos c ON p.ID_CATEGORIA_PRODUCTO = c.ID_CATEGORIA_PRODUCTO
- WHERE UNIX_TIMESTAMP(p.FECHA_ULTIMA_MODIFICACION) > ?
- ORDER BY p.FECHA_ULTIMA_MODIFICACION DESC
- LIMIT ?
- ";
-
- $stmt = $conexion->prepare($query);
- $stmt->bind_param("di", $last_check, $limit);
- $stmt->execute();
- return $stmt->get_result()->fetch_all(MYSQLI_ASSOC);
-}
-
-/**
- * Función para verificar cambios en logs recientes
- */
-function verificarLogsRecientes($conexion, $last_check) {
- $query = "
- SELECT
- pl.*,
- p.NOMBRE_PRODUCTO
- FROM productos_logs pl
- JOIN Productos p ON pl.producto_id = p.ID_PRODUCTO
- WHERE UNIX_TIMESTAMP(pl.fecha_cambio) > ?
- AND p.ACTIVO = 1
- ORDER BY pl.fecha_cambio DESC
- LIMIT 20
- ";
-
- $stmt = $conexion->prepare($query);
- $stmt->bind_param("d", $last_check);
- $stmt->execute();
- return $stmt->get_result()->fetch_all(MYSQLI_ASSOC);
-}
-
-try {
- // Enviar evento inicial de conexión
- sendSSEEvent('connected', [
- 'message' => 'Conectado al sistema de actualizaciones',
- 'timestamp' => time()
- ]);
-
- $iteration = 0;
- $max_iterations = 300; // 5 minutos con intervalos de 1 segundo
-
- while ($iteration < $max_iterations) {
- // Verificar cambios en productos
- $cambios = verificarCambiosProductos($conexion, $last_check);
-
- if ($cambios['total_cambios'] > 0) {
- // Hay cambios, obtener detalles
- $productos_modificados = obtenerProductosModificados($conexion, $last_check);
- $logs_recientes = verificarLogsRecientes($conexion, $last_check);
-
- // Enviar evento de actualización del menú
- sendSSEEvent('menu_update', [
- 'type' => 'productos_actualizados',
- 'total_cambios' => $cambios['total_cambios'],
- 'ultimo_cambio' => $cambios['ultimo_cambio'],
- 'productos' => $productos_modificados,
- 'logs' => $logs_recientes,
- 'timestamp' => time()
- ]);
-
- // Actualizar last_check al timestamp más reciente
- $last_check = $cambios['ultimo_cambio'];
- }
-
- // Verificar si la conexión sigue activa
- if (connection_aborted()) {
- break;
- }
-
- // Enviar heartbeat cada 30 segundos
- if ($iteration % 30 == 0 && $iteration > 0) {
- sendSSEEvent('heartbeat', [
- 'timestamp' => time(),
- 'iteration' => $iteration
- ]);
- }
-
- // Esperar 1 segundo antes de la siguiente verificación
- sleep(1);
- $iteration++;
- }
-
- // Enviar evento de desconexión
- sendSSEEvent('disconnected', [
- 'message' => 'Sesión SSE finalizada',
- 'timestamp' => time()
- ]);
-
-} catch (Exception $e) {
- // Enviar evento de error
- sendSSEEvent('error', [
- 'message' => 'Error en el servidor: ' . $e->getMessage(),
- 'timestamp' => time()
- ]);
-}
-
-// Cerrar la conexión
-if (isset($conexion)) {
- $conexion->close();
-}
-?>
diff --git a/files/styleadmindst.css b/files/styleadmindst.css
deleted file mode 100644
index 13819a4..0000000
--- a/files/styleadmindst.css
+++ /dev/null
@@ -1,675 +0,0 @@
-@import url('https://fonts.googleapis.com/css2?family=Playfair+Display:wght@700&family=Exo+2:wght@300;400;500;600;700&display=swap');
-
-:root {
- --primary-color: #8C5A37;
- --primary-hover: #6E462A;
- --text-dark: #3D2C21;
- --text-light: #6B5B51;
- --border-color: #D3C5BC;
- --container-bg: rgba(255, 255, 255, 0.75);
- --sidebar-width: 320px;
- --header-height: 120px;
- --white: #ffffff;
- --light-gray: #f8f9fa;
- --success-green: #4CAF50;
- --info-blue: #2196F3;
- --warning-orange: #FF9800;
- --danger-red: #F44336;
- --crema: #f5f5dc;
-}
-
-
-
-body {
- font-family: 'Exo 2', sans-serif;
- background: linear-gradient(135deg, #4e3f30 0%, #63554b 100%);
- color: var(--text-dark);
- overflow-x: hidden;
- min-height: 100vh;
- margin: 0;
-}
-
-/* Sidebar */
-.sidebar {
- position: fixed;
- top: 0;
- left: 0;
- width: var(--sidebar-width);
- height: 100vh;
- background: rgba(255, 255, 255, 0.85);
- color: var(--text-dark);
- z-index: 1000;
- box-shadow: 4px 0 25px rgba(0, 0, 0, 0.15);
- border-right: 1px solid rgba(255, 255, 255, 0.4);
- display: flex;
- flex-direction: column;
-}
-.sidebar-header {
- padding: 25px;
- border-bottom: 1px solid rgba(140, 90, 55, 0.3);
- background: rgba(140, 90, 55, 0.9);
-}
-
-.logo-container {
- display: flex;
- align-items: center;
- gap: 20px;
- justify-content: flex-start;
-}
-
-.logo-container h4 {
- margin: 0;
- font-size: 1.4rem;
-}
-
-.logo-img {
- width: 60px;
- height: 60px;
- border-radius: 50%;
- object-fit: cover;
- border: 3px solid var(--white);
- transition: all 0.3s ease;
- cursor: pointer;
-}
-
-.logo-img:hover {
- transform: scale(1.05);
- border-color: rgba(255, 255, 255, 0.8);
- box-shadow: 0 0 15px rgba(255, 255, 255, 0.3);
-}
-
-.logo-text {
- font-family: 'Playfair Display', serif;
- font-size: 1.4rem;
- font-weight: 700;
- color: var(--white);
-}
-
-.sidebar-nav {
- padding: 25px 0;
- flex: 1;
- overflow-y: auto;
-}
-
-.sidebar-nav .nav {
- padding-left: 0;
- margin-bottom: 0;
- list-style: none;
-}
-
-.sidebar-nav .nav-item {
- margin-bottom: 8px;
-}
-
-.sidebar-nav .nav-link {
- display: flex;
- align-items: center;
- gap: 18px;
- padding: 18px 25px;
- color: var(--text-dark);
- text-decoration: none;
- transition: all 0.3s ease;
- border-left: 4px solid transparent;
- border-radius: 0 12px 12px 0;
- margin: 0 15px 0 0;
- font-size: 1rem;
-}
-
-.sidebar-nav .nav-link:hover {
- background: rgba(140, 90, 55, 0.1);
- color: var(--primary-color);
- border-left-color: var(--primary-color);
- transform: translateX(8px);
-}
-
-.sidebar-nav .nav-link.active {
- background: rgba(140, 90, 55, 0.2);
- color: var(--primary-color);
- border-left-color: var(--primary-color);
- font-weight: 600;
-}
-
-.sidebar-nav .nav-link i {
- width: 24px;
- text-align: center;
- font-size: 1.2rem;
-}
-
-/* Footer del Sidebar */
-.sidebar-footer {
- padding: 25px;
- border-top: 1px solid rgba(140, 90, 55, 0.3);
- background: rgba(140, 90, 55, 0.9);
-}
-
-.user-info {
- display: flex;
- align-items: center;
- gap: 18px;
- margin-bottom: 18px;
- padding: 15px;
- background: rgba(255, 255, 255, 0.1);
- border-radius: 12px;
- border: 1px solid rgba(255, 255, 255, 0.2);
-}
-
-.user-avatar i {
- font-size: 2.2rem;
- color: var(--white);
-}
-
-.user-details {
- display: flex;
- flex-direction: column;
-}
-
-.user-name {
- font-weight: 600;
- color: var(--white);
- font-size: 1.1rem;
-}
-
-.user-role {
- font-size: 0.9rem;
- color: rgba(255, 255, 255, 0.8);
-}
-
-.logout-btn {
- display: flex;
- align-items: center;
- gap: 12px;
- padding: 12px 15px;
- color: var(--white);
- text-decoration: none;
- background: var(--danger-red);
- border-radius: 10px;
- transition: all 0.3s ease;
- font-weight: 600;
- font-size: 1rem;
- font-family: 'Exo 2', sans-serif;
-}
-
-.logout-btn:hover {
- background: #d32f2f;
- color: var(--white);
- transform: translateY(-2px);
- box-shadow: 0 5px 15px rgba(244, 67, 54, 0.3);
-}
-
-/* Contenido principal */
-.main-content {
- margin-left: var(--sidebar-width);
- min-height: 100vh;
-}
-
-/* Header Superior */
-.top-header {
- font-family: "IBM Plex Sans", sans-serif;
- background: rgba(140, 90, 55, 0.15);
- border: 1px solid rgba(216, 188, 168, 0.2);
- padding: 0 40px;
- height: var(--header-height);
- display: flex;
- align-items: center;
- justify-content: space-between;
- box-shadow: 0 8px 32px rgba(140, 90, 55, 0.25);
- position: relative;
- overflow: hidden;
-}
-
-.top-header::before {
- content: '';
- position: absolute;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- background: linear-gradient(135deg, rgba(140, 90, 55, 0.1) 0%, rgba(140, 90, 55, 0.05) 100%);
- pointer-events: none;
-}
-
-.bienvenida-admin {
- font-family: "IBM Plex Sans", sans-serif;
- color: var(--crema);
- font-size: 1.1rem;
- font-weight: 500;
- position: relative;
- z-index: 1;
- text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
-}
-
-.page-title {
- font-family: 'Playfair Display', serif;
- font-size: 1.8rem;
- font-weight: 700;
- color: var(--crema);
- margin: 0;
- text-align: center;
- flex: 1;
- position: relative;
- z-index: 1;
- text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
-}
-
-/* Dashboard */
-.dashboard-content {
- padding: 30px;
-}
-
-/* Stats Container */
-.stats-container {
- margin-bottom: 40px;
-}
-
-.stats-grid {
- display: grid;
- grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
- gap: 20px;
- max-width: 1200px;
- margin: 0 auto;
-}
-
-.stat-card {
- background: rgba(255, 255, 255, 0.85);
- padding: 25px;
- border-radius: 15px;
- text-align: center;
- box-shadow: 0 10px 30px rgba(0, 0, 0, 0.15);
- border: 1px solid rgba(255, 255, 255, 0.4);
- transition: all 0.3s ease;
- border-top: 4px solid var(--primary-color);
-}
-
-.stat-card:hover {
- transform: translateY(-5px);
- box-shadow: 0 15px 40px rgba(0, 0, 0, 0.2);
-}
-
-/* Colores específicos para cada tarjeta */
-.stat-card.stat-primary {
- border-top-color: var(--primary-color);
-}
-
-.stat-card.stat-primary .stat-icon {
- background: linear-gradient(135deg, var(--primary-color) 0%, rgba(140, 90, 55, 0.9) 100%);
- color: var(--white);
-}
-
-.stat-card.stat-success {
- border-top-color: var(--success-green);
-}
-
-.stat-card.stat-success .stat-icon {
- background: linear-gradient(135deg, var(--success-green) 0%, rgba(76, 175, 80, 0.9) 100%);
- color: var(--white);
-}
-
-.stat-card.stat-info {
- border-top-color: var(--info-blue);
-}
-
-.stat-card.stat-info .stat-icon {
- background: linear-gradient(135deg, var(--info-blue) 0%, rgba(33, 150, 243, 0.9) 100%);
- color: var(--white);
-}
-
-.stat-card.stat-warning {
- border-top-color: var(--warning-orange);
-}
-
-.stat-card.stat-warning .stat-icon {
- background: linear-gradient(135deg, var(--warning-orange) 0%, rgba(255, 152, 0, 0.9) 100%);
- color: var(--white);
-}
-
-.stat-card.stat-danger {
- border-top-color: var(--danger-red);
-}
-
-.stat-card.stat-danger .stat-icon {
- background: linear-gradient(135deg, var(--danger-red) 0%, rgba(244, 67, 54, 0.9) 100%);
- color: var(--white);
-}
-
-.stat-icon {
- width: 60px;
- height: 60px;
- border-radius: 50%;
- display: flex;
- align-items: center;
- justify-content: center;
- margin: 0 auto 15px;
- font-size: 1.5rem;
- box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
-}
-
-.stat-number {
- font-size: 2.5rem;
- font-weight: 700;
- color: var(--text-dark);
- margin-bottom: 10px;
-}
-
-.stat-label {
- color: var(--text-light);
- font-weight: 600;
- font-size: 0.95rem;
-}
-
-/* Actions Container */
-.actions-container {
- max-width: 1200px;
- margin: 0 auto;
-}
-
-.actions-grid {
- display: grid;
- grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
- gap: 30px;
-}
-
-.action-card {
- background: rgba(255, 255, 255, 0.85);
- border-radius: 15px;
- box-shadow: 0 10px 30px rgba(0, 0, 0, 0.15);
- border: 1px solid rgba(255, 255, 255, 0.4);
- transition: all 0.3s ease;
- overflow: hidden;
-}
-
-.action-card:hover {
- transform: translateY(-3px);
- box-shadow: 0 15px 40px rgba(0, 0, 0, 0.2);
-}
-
-.action-card .card-header {
- background: linear-gradient(135deg, var(--primary-color) 0%, rgba(140, 90, 55, 0.9) 100%);
- color: var(--white);
- padding: 20px;
- border-bottom: none;
-}
-
-.action-card .card-header h3 {
- font-family: 'Playfair Display', serif;
- margin: 0;
- font-size: 1.2rem;
- font-weight: 700;
- color: var(--white);
-}
-
-.action-card .card-body {
- padding: 25px;
- background: transparent;
- display: flex;
- flex-direction: column;
- gap: 12px;
-}
-
-/* Botones de Acción - Estilo Transparente */
-.action-btn {
- display: inline-flex;
- align-items: center;
- justify-content: center;
- padding: 12px 20px;
- border-radius: 10px;
- text-decoration: none;
- font-weight: 600;
- transition: all 0.3s ease;
- border: 2px solid rgba(140, 90, 55, 0.6);
- background: rgba(140, 90, 55, 0.1);
- color: var(--text-dark);
- font-family: 'Exo 2', sans-serif;
- font-size: 0.9rem;
- text-align: center;
-}
-
-.action-btn:hover {
- background: rgba(140, 90, 55, 0.2);
- border-color: var(--primary-color);
- color: var(--text-dark);
- transform: translateY(-2px);
- box-shadow: 0 8px 20px rgba(140, 90, 55, 0.3);
-}
-
-.action-btn i {
- margin-right: 8px;
-}
-
-/* ===== ESTILOS PARA GESTIÓN DE INGREDIENTES ===== */
-
-/* Estilos para elementos editables */
-.stock-editable, .precio-editable {
- cursor: pointer;
- padding: 2px 6px;
- border-radius: 4px;
- transition: all 0.3s ease;
- display: inline-block;
- min-width: 60px;
-}
-
-.stock-editable:hover, .precio-editable:hover {
- background-color: rgba(0, 123, 255, 0.1);
- border: 1px dashed #007bff;
-}
-
-/* Badges para estado de stock */
-.badge-stock-alto {
- background-color: var(--success-green) !important;
- color: white;
-}
-
-.badge-stock-medio {
- background-color: var(--warning-orange) !important;
- color: white;
-}
-
-.badge-stock-bajo {
- background-color: var(--danger-red) !important;
- color: white;
-}
-
-/* Estilos para botones de acción en tabla */
-.btn-group .btn {
- margin: 0 1px;
-}
-
-.btn-sm i {
- font-size: 0.8rem;
-}
-
-/* Modal de ingredientes específico */
-#ingredientesModal .modal-xl {
- max-width: 95%;
-}
-
-#ingredientesModal .table-responsive {
- max-height: 500px;
- overflow-y: auto;
-}
-
-/* Estadísticas de ingredientes */
-.ingredientes-stats {
- background: linear-gradient(135deg, var(--primary-color), var(--primary-hover));
- color: white;
- border-radius: 10px;
- padding: 15px;
- margin-bottom: 20px;
-}
-
-.ingredientes-stats .stat-item {
- text-align: center;
- padding: 10px;
-}
-
-.ingredientes-stats .stat-number {
- font-size: 2rem;
- font-weight: bold;
- display: block;
-}
-
-.ingredientes-stats .stat-label {
- font-size: 0.9rem;
- opacity: 0.9;
-}
-
-/* Form de agregar ingrediente */
-#formAgregarIngrediente .form-label {
- font-weight: 500;
- color: var(--text-dark);
-}
-
-#formAgregarIngrediente .form-control,
-#formAgregarIngrediente .form-select {
- border-radius: 8px;
- border: 2px solid var(--border-color);
- transition: all 0.3s ease;
-}
-
-#formAgregarIngrediente .form-control:focus,
-#formAgregarIngrediente .form-select:focus {
- border-color: var(--primary-color);
- box-shadow: 0 0 0 0.2rem rgba(140, 90, 55, 0.25);
-}
-
-/* Alertas personalizadas para ingredientes */
-.alert-ingrediente {
- border-radius: 10px;
- border: none;
- box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
-}
-
-.alert-ingrediente.alert-success {
- background: linear-gradient(135deg, #d4edda, #c3e6cb);
- color: #155724;
-}
-
-.alert-ingrediente.alert-warning {
- background: linear-gradient(135deg, #fff3cd, #ffeaa7);
- color: #856404;
-}
-
-.alert-ingrediente.alert-danger {
- background: linear-gradient(135deg, #f8d7da, #f5c6cb);
- color: #721c24;
-}
-
-/* Spinner personalizado para carga de ingredientes */
-.ingredientes-loader {
- display: flex;
- align-items: center;
- justify-content: center;
- flex-direction: column;
- padding: 3rem;
-}
-
-.ingredientes-loader .spinner-border {
- width: 3rem;
- height: 3rem;
- border-width: 0.3rem;
- color: var(--primary-color);
-}
-
-/* Tabla de ingredientes */
-#ingredientesTableBody tr:hover {
- background-color: rgba(140, 90, 55, 0.05);
- transition: all 0.3s ease;
-}
-
-/* Botones de exportar */
-.btn-export {
- background: linear-gradient(135deg, var(--success-green), #45a049);
- border: none;
- color: white;
- transition: all 0.3s ease;
-}
-
-.btn-export:hover {
- background: linear-gradient(135deg, #45a049, #3d8b40);
- transform: translateY(-2px);
- box-shadow: 0 4px 12px rgba(76, 175, 80, 0.3);
-}
-
-/* Responsive para tablets */
-@media (max-width: 768px) {
- #ingredientesModal .modal-xl {
- max-width: 98%;
- margin: 10px;
- }
-
- .ingredientes-stats {
- text-align: center;
- }
-
- .ingredientes-stats .stat-number {
- font-size: 1.5rem;
- }
-
- .btn-group {
- flex-direction: column;
- align-items: stretch;
- }
-
- .btn-group .btn {
- margin: 1px 0;
- border-radius: 4px !important;
- }
-}
-
-/* Animaciones para elementos de ingredientes */
-@keyframes fadeInIngrediente {
- from {
- opacity: 0;
- transform: translateY(20px);
- }
- to {
- opacity: 1;
- transform: translateY(0);
- }
-}
-
-.ingrediente-row {
- animation: fadeInIngrediente 0.5s ease-out;
-}
-
-/* Tooltips personalizados */
-.tooltip-ingrediente {
- position: relative;
- cursor: help;
-}
-
-.tooltip-ingrediente::after {
- content: attr(data-tooltip);
- position: absolute;
- bottom: 125%;
- left: 50%;
- transform: translateX(-50%);
- background-color: rgba(0, 0, 0, 0.8);
- color: white;
- padding: 5px 10px;
- border-radius: 4px;
- font-size: 0.8rem;
- white-space: nowrap;
- opacity: 0;
- visibility: hidden;
- transition: all 0.3s ease;
- z-index: 1000;
-}
-
-.tooltip-ingrediente:hover::after {
- opacity: 1;
- visibility: visible;
-}
-
-/* Estilos para campos requeridos */
-.form-label .text-danger {
- font-weight: bold;
-}
-
-.form-control:invalid {
- border-color: var(--danger-red);
-}
-
-.form-control:invalid:focus {
- border-color: var(--danger-red);
- box-shadow: 0 0 0 0.2rem rgba(244, 67, 54, 0.25);
-}
\ No newline at end of file
diff --git a/files/styleclienteds.css b/files/styleclienteds.css
deleted file mode 100644
index 90c52c6..0000000
--- a/files/styleclienteds.css
+++ /dev/null
@@ -1,695 +0,0 @@
-@import url('https://fonts.googleapis.com/css2?family=Playfair+Display:wght@400;700&family=Inter:wght@300;400;500;600;700&display=swap');
-@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@400;500;600;700&display=swap');
-
-:root {
- --primary-color: #8C5A37;
- --primary-hover: #6E442A;
- --secondary-color: #B8733A;
- --accent-color: #A0522D;
- --text-dark: #2C1810;
- --text-light: #5D4037;
- --text-muted: #8D6E63;
- --bg-cream: #FFF8E1;
- --bg-vanilla: #F5F5DC;
- --bg-light: #FEFEF8;
- --white: #FFFFFF;
- --border-color: #E8D5B7;
- --shadow: rgba(60, 64, 67, 0.15);
- --success: #4CAF50;
- --warning: #FF9800;
- --danger: #F44336;
- --info: #2196F3;
- --sidebar-width: 240px;
-}
-
-* {
- margin: 0;
- padding: 0;
- box-sizing: border-box;
-}
-
-body {
- font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
- background: linear-gradient(135deg, var(--bg-cream) 0%, var(--bg-vanilla) 100%);
- color: var(--text-dark);
- line-height: 1.6;
- min-height: 100vh;
-}
-
-/* === SIDEBAR === */
-.sidebar {
- position: fixed;
- top: 0;
- left: 0;
- width: var(--sidebar-width);
- height: 100vh;
- background: var(--white);
- border-right: 1px solid var(--border-color);
- box-shadow: 0 2px 10px var(--shadow);
- z-index: 1000;
- overflow-y: auto;
-}
-
-.sidebar-content {
- padding: 0;
- height: 100%;
- display: flex;
- flex-direction: column;
-}
-
-.sidebar-brand {
- padding: 20px;
- text-align: center;
- background: var(--bg-light);
-}
-
-.sidebar-logo {
- width: 50px;
- height: 50px;
- border-radius: 50%;
- object-fit: cover;
- margin-bottom: 10px;
- border: 2px solid var(--primary-color);
-}
-
-.sidebar-brand h5 {
- font-family: 'Playfair Display', serif;
- font-weight: 700;
- color: var(--primary-color);
- margin: 0;
- font-size: 1.1rem;
-}
-
-.sidebar-divider {
- height: 1px;
- background: var(--border-color);
- margin: 15px 0;
-}
-
-.nav-link {
- color: var(--text-light) !important;
- font-weight: 500;
- padding: 12px 20px;
- border-radius: 0;
- display: flex;
- align-items: center;
- gap: 10px;
- font-size: 0.9rem;
- border: none;
- background: none;
-}
-
-.nav-link:hover {
- background: var(--bg-vanilla);
- color: var(--primary-color) !important;
-}
-
-.nav-link.active {
- background: var(--primary-color);
- color: var(--white) !important;
-}
-
-.nav-link i {
- width: 18px;
- text-align: center;
- font-size: 1.1rem;
-}
-
-.sidebar-user {
- margin-top: auto;
- padding: 20px;
- border-top: 1px solid var(--border-color);
- background: var(--bg-light);
-}
-
-.user-info {
- color: var(--text-light);
- font-weight: 500;
- margin-bottom: 10px;
- display: flex;
- align-items: center;
- gap: 8px;
- font-size: 0.9rem;
-}
-
-.user-info i {
- font-size: 1.2rem;
- color: var(--primary-color);
-}
-
-.logout-btn {
- background: var(--danger);
- color: var(--white) !important;
- text-decoration: none;
- padding: 8px 16px;
- border-radius: 6px;
- font-weight: 500;
- border: none;
- cursor: pointer;
- display: flex;
- align-items: center;
- gap: 8px;
- font-size: 0.9rem;
- width: 100%;
- justify-content: center;
-}
-
-.logout-btn:hover {
- background: #d32f2f;
- color: var(--white) !important;
- text-decoration: none;
-}
-
-/* === BOTÓN EXPLORAR === */
-.btn-explore {
- background: #c05610;
- color: var(--white) !important;
- text-decoration: none;
- padding: 12px 20px;
- border-radius: 8px;
- font-weight: 600;
- border: none;
- cursor: pointer;
- display: flex;
- align-items: center;
- gap: 10px;
- font-size: 0.9rem;
- justify-content: center;
- transition: all 0.3s ease;
- box-shadow: 0 2px 8px rgba(0, 0, 0, 0.726);
-}
-
-.btn-explore:hover {
- background-image: url(../files/img/iconoboton1.jpg);
- background-position: center center;
- background-repeat: no-repeat;
- background-size: cover;
- color: var(--white) !important;
- text-decoration: none;
- transform: translateY(-2px);
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.4);
-}
-
-.btn-explore i {
- font-size: 1.1rem;
-}
-
-/* === MAIN CONTENT === */
-.main-content {
- margin-left: var(--sidebar-width);
- padding: 30px;
- min-height: 100vh;
- padding-bottom: 200px;
-}
-
-.section-content {
- max-width: 1200px;
- margin: 0 auto;
-}
-
-.section-content h3 {
- font-family: 'Playfair Display', serif;
- font-size: 1.8rem;
- font-weight: 700;
- color: var(--primary-color);
- margin-bottom: 30px;
- text-align: center;
-}
-
-/* === WELCOME SECTION === */
-.welcome-section {
- text-align: center;
- margin-bottom: 40px;
- background: var(--white);
- padding: 30px;
- border-radius: 12px;
- box-shadow: 0 2px 10px var(--shadow);
- border: 1px solid var(--border-color);
-}
-
-.welcome-section h2 {
- font-family: 'Playfair Display', serif;
- font-size: 1.8rem;
- font-weight: 700;
- color: var(--primary-color);
- margin-bottom: 10px;
-}
-
-.welcome-section p {
- font-size: 1rem;
- color: var(--text-muted);
- margin: 0;
-}
-
-/* === STATS GRID === */
-.stats-grid {
- display: grid;
- grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
- gap: 20px;
- margin-bottom: 40px;
-}
-
-.stat-card {
- background: var(--white);
- padding: 25px;
- border-radius: 12px;
- border: 1px solid var(--border-color);
- box-shadow: 0 2px 8px var(--shadow);
- display: flex;
- align-items: center;
- gap: 15px;
-}
-
-.card-icon {
- width: 50px;
- height: 50px;
- background: var(--primary-color);
- border-radius: 50%;
- display: flex;
- align-items: center;
- justify-content: center;
- flex-shrink: 0;
-}
-
-.card-icon i {
- font-size: 1.5rem;
- color: var(--white);
-}
-
-.card-content {
- flex: 1;
-}
-
-.stat-number {
- font-size: 2rem;
- font-weight: 700;
- color: var(--primary-color);
- margin-bottom: 5px;
- line-height: 1;
-}
-
-.stat-label {
- color: var(--text-muted);
- font-weight: 500;
- font-size: 0.9rem;
-}
-
-/* === ORDERS SECTION === */
-.orders-section {
- background: var(--white);
- border-radius: 12px;
- border: 1px solid var(--border-color);
- box-shadow: 0 2px 8px var(--shadow);
- margin-bottom: 40px;
-}
-
-.section-header {
- padding: 20px;
- border-bottom: 1px solid var(--border-color);
- background: var(--bg-light);
- border-radius: 12px 12px 0 0;
-}
-
-.section-header h4 {
- font-family: 'Playfair Display', serif;
- font-size: 1.3rem;
- font-weight: 700;
- color: var(--primary-color);
- margin: 0;
- display: flex;
- align-items: center;
- gap: 10px;
-}
-
-.orders-list {
- padding: 20px;
-}
-
-.order-item {
- display: flex;
- justify-content: space-between;
- align-items: center;
- padding: 15px;
- border: 1px solid var(--border-color);
- border-radius: 8px;
- margin-bottom: 15px;
- background: var(--bg-light);
-}
-
-.order-item:last-child {
- margin-bottom: 0;
-}
-
-.order-info h6 {
- font-weight: 600;
- color: var(--primary-color);
- margin-bottom: 8px;
-}
-
-.order-info p {
- color: var(--text-muted);
- font-size: 0.9rem;
-}
-
-.order-status {
- padding: 6px 12px;
- border-radius: 20px;
- font-weight: 500;
- font-size: 0.8rem;
- text-align: center;
- min-width: 100px;
-}
-
-.status-pendiente {
- background: #FFF3E0;
- color: var(--warning);
- border: 1px solid #FFE0B2;
-}
-
-.status-enproceso {
- background: #E3F2FD;
- color: var(--info);
- border: 1px solid #BBDEFB;
-}
-
-.status-listo {
- background: #E8F5E8;
- color: var(--success);
- border: 1px solid #C8E6C9;
-}
-
-.status-entregado {
- background: #F3E5F5;
- color: #9C27B0;
- border: 1px solid #E1BEE7;
-}
-
-.status-cancelado {
- background: #FFEBEE;
- color: var(--danger);
- border: 1px solid #FFCDD2;
-}
-
-/* === ACTION CARDS === */
-.action-cards {
- display: grid;
- grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
- gap: 30px;
- margin-bottom: 40px;
-}
-
-.action-card {
- background: var(--white);
- border-radius: 12px;
- border: 1px solid var(--border-color);
- box-shadow: 0 2px 8px var(--shadow);
- overflow: hidden;
-}
-
-.action-card .card-header {
- background: var(--primary-color);
- color: var(--white);
- padding: 20px;
- display: flex;
- align-items: center;
- gap: 10px;
-}
-
-.action-card .card-header i {
- font-size: 1.3rem;
-}
-
-.action-card .card-header h5 {
- font-family: 'Playfair Display', serif;
- font-weight: 700;
- margin: 0;
- font-size: 1.2rem;
-}
-
-.action-card .card-body {
- padding: 20px;
-}
-
-.action-btn {
- display: block;
- padding: 12px 20px;
- border: none;
- background: var(--bg-light);
- color: var(--text-dark);
- text-decoration: none;
- font-weight: 500;
- border-bottom: 1px solid var(--border-color);
- font-family: 'Inter', sans-serif;
- display: flex;
- align-items: center;
- gap: 10px;
- font-size: 0.9rem;
-}
-
-.action-btn:hover {
- background: var(--bg-vanilla);
- color: var(--primary-color);
- text-decoration: none;
-}
-
-.action-btn:last-child {
- border-bottom: none;
-}
-
-.special-btn {
- background: var(--success) !important;
- color: var(--white) !important;
- font-weight: 600;
-}
-
-.special-btn:hover {
- background: #45a049 !important;
- color: var(--white) !important;
-}
-
-/* === FOOTER === */
-.footer {
- position: fixed;
- bottom: 0;
- left: var(--sidebar-width);
- right: 0;
- background: var(--white);
- border-top: 1px solid var(--border-color);
- box-shadow: 0 -2px 10px var(--shadow);
- z-index: 500;
- padding: 20px 0;
-}
-
-.footer-content {
- text-align: center;
- max-width: 1200px;
- margin: 0 auto;
- padding: 0 30px;
-}
-
-.footer-content h5 {
- font-family: "IBM Plex Sans", sans-serif;
- font-optical-sizing: auto;
- font-weight: 600;
- color: linear-gradient(rgba(255, 0, 0, 0.767),rgba(219, 147, 11, 0.918));
- margin-bottom: 15px;
- font-size: 2rem;
- display: flex;
- align-items: center;
- justify-content: center;
- gap: 8px;
-}
-
-.product-slider {
- overflow: hidden;
- position: relative;
-}
-
-.slider-container {
- display: flex;
- gap: 15px;
- animation: slide 20s infinite linear;
-}
-
-.product-slide {
- flex: 0 0 auto;
- width: 150px;
-}
-
-.product-card {
- background: var(--bg-light);
- border: 1px solid var(--border-color);
- border-radius: 8px;
- padding: 15px;
- text-align: center;
-}
-
-.product-icon {
- width: 40px;
- height: 40px;
- background: var(--primary-color);
- border-radius: 50%;
- display: flex;
- align-items: center;
- justify-content: center;
- margin: 0 auto 10px;
-}
-
-.product-icon i {
- font-size: 1.2rem;
- color: var(--white);
-}
-
-.product-card h6 {
- font-weight: 600;
- color: var(--primary-color);
- margin-bottom: 5px;
- font-size: 0.9rem;
-}
-
-.product-card .price {
- font-weight: 700;
- color: var(--accent-color);
- margin-bottom: 5px;
-}
-
-.product-card small {
- color: var(--text-muted);
- font-size: 0.8rem;
-}
-
-@keyframes slide {
- 0% {
- transform: translateX(0);
- }
- 100% {
- transform: translateX(-100%);
- }
-}
-
-/* === MOBILE STYLES === */
-@media (max-width: 768px) {
- .sidebar {
- transform: translateX(-100%);
- transition: transform 0.3s ease;
- width: 280px;
- }
-
- .sidebar.show {
- transform: translateX(0);
- }
-
- .main-content {
- margin-left: 0;
- padding: 20px;
- padding-bottom: 200px;
- }
-
- .footer {
- left: 0;
- }
-
- #sidebarToggle {
- background: var(--primary-color);
- border: none;
- color: var(--white);
- font-weight: 500;
- }
-
- .stats-grid {
- grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
- gap: 15px;
- }
-
- .stat-card {
- padding: 20px;
- flex-direction: column;
- text-align: center;
- gap: 10px;
- }
-
- .stat-number {
- font-size: 1.8rem;
- }
-
- .welcome-section {
- padding: 20px;
- }
-
- .welcome-section h2 {
- font-size: 1.5rem;
- }
-
- .order-item {
- flex-direction: column;
- gap: 10px;
- text-align: center;
- }
-
- .order-status {
- min-width: auto;
- }
-
- .action-cards {
- grid-template-columns: 1fr;
- }
-
- .slider-container {
- gap: 10px;
- }
-
- .product-slide {
- width: 120px;
- }
-
- .product-card {
- padding: 10px;
- }
-
- .btn-explore {
- padding: 10px 16px;
- font-size: 0.85rem;
- }
-}
-
-@media (max-width: 576px) {
- .stats-grid {
- grid-template-columns: 1fr;
- }
-
- .welcome-section {
- padding: 15px;
- }
-
- .welcome-section h2 {
- font-size: 1.3rem;
- }
-
- .section-content h3 {
- font-size: 1.5rem;
- }
-
- .main-content {
- padding: 15px;
- padding-bottom: 200px;
- }
-
- .footer-content {
- padding: 0 15px;
- }
-
- .product-slide {
- width: 100px;
- }
-}
-
-/* === BOTÓN CAMBIAR CONTRASEÑA (Café-Crema) === */
-.change-pass-btn {
- background: var(--primary-color);
- color: var(--bg-cream) !important;
- text-decoration: none;
-}
-.change-pass-btn:hover {
- background: var(--primary-hover);
- color: var(--bg-cream) !important;
-}
\ No newline at end of file
diff --git a/files/stylehomepage.css b/files/stylehomepage.css
deleted file mode 100644
index 8c83444..0000000
--- a/files/stylehomepage.css
+++ /dev/null
@@ -1,1869 +0,0 @@
-:root {
- --color-crema: #f5f5dc;
- --color-marron: #8b4513;
- --color-gris-oscuro: #2c3e50;
- --color-cafe-claro: #d2b48c;
- --color-cafe-con-leche: #ddbea9;
- --color-blanco-calido: #fffef7;
- --color-dorado: #ffd700;
- --color-overlay: rgba(139, 69, 19, 0.8);
-}
-
-/* Clases de colores de fondo */
-.bg-crema { background-color: var(--color-crema) !important; }
-.bg-blanco-cálido { background-color:#b08d75 !important; }
-
-/* Clases de colores de texto */
-.text-marron { color: var(--color-marron) !important; }
-.text-gris-oscuro { color: var(--color-gris-oscuro) !important; }
-.text-cafe-claro { color: var(--color-cafe-claro) !important; }
-.text-cafe-con-leche { color: var(--color-cafe-con-leche) !important; }
-.text-crema { color: var(--color-crema) !important; }
-
-/* Clases de borde */
-.border-marron { border-color: var(--color-marron) !important; }
-
-/* Estilos generales */
-body {
- font-family: 'Quicksand', sans-serif;
- background-color: #bb9467 !important;
- line-height: 1.6;
- overflow-x: hidden;
-}
-
-/* Navbar personalizada */
-.navbar {
- transition: all 0.3s ease;
- backdrop-filter: blur(10px);
- position: relative;
- z-index: 9999 !important;
-}
-
-.navbar.scrolled {
- background-color: rgba(245, 245, 220, 0.95) !important;
- box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
-}
-
-/* Header con prioridad máxima */
-header {
- position: relative;
- z-index: 9999 !important;
-}
-
-.logo {
- transition: transform 0.3s ease;
-}
-
-.logo:hover {
- transform: scale(1.05);
-}
-
-/* Botón personalizado */
-.btn-primary {
- background: linear-gradient(135deg, var(--color-marron), #a0522d);
- border: none;
- border-radius: 25px;
- padding: 8px 20px;
- transition: all 0.3s ease;
- box-shadow: 0 4px 15px rgba(139, 69, 19, 0.3);
-}
-
-.btn-primary:hover {
- background: linear-gradient(135deg, #a0522d, var(--color-marron));
- transform: translateY(-2px);
- box-shadow: 0 6px 20px rgba(139, 69, 19, 0.4);
-}
-
-.btn-rounded {
- border-radius: 25px;
-}
-
-/* Carrusel de borde a borde */
-.carousel-fullwidth {
- width: 100vw;
- position: relative;
- left: 50%;
- right: 50%;
- margin-left: -50vw;
- margin-right: -50vw;
- overflow: hidden;
- z-index: 1 !important;
-}
-
-.carousel {
- z-index: 1 !important;
-}
-
-.carousel-inner {
- z-index: 1 !important;
-}
-
-.carousel-item {
- z-index: 1 !important;
-}
-
-.carousel-fixed-img {
- height: 350px;
- object-fit: cover;
- object-position: center;
- width: 100%;
- image-rendering: -webkit-optimize-contrast;
- image-rendering: crisp-edges;
- transition: none !important;
- filter: contrast(1.05) brightness(1.02);
- -webkit-backface-visibility: hidden;
- backface-visibility: hidden;
- transform: none !important;
-}
-
-.carousel-item {
- position: relative;
- overflow: hidden;
- transition: transform 0.8s ease-in-out;
-}
-
-/* Suavizar la transición del carrusel */
-.carousel-inner {
- overflow: hidden;
-}
-
-.carousel-item.active,
-.carousel-item-next,
-.carousel-item-prev {
- display: block;
-}
-
-.carousel-link {
- display: block;
- position: relative;
- text-decoration: none;
- color: inherit;
- overflow: hidden;
-}
-
-.carousel-link::before {
- content: '';
- position: absolute;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- background: linear-gradient(45deg, transparent, rgba(139, 69, 19, 0.1));
- opacity: 0;
- transition: opacity 0.3s ease;
- z-index: 1;
-}
-
-.carousel-link:hover::before {
- opacity: 1;
-}
-
-.carousel-link:hover .carousel-fixed-img {
- transform: scale(1.02);
-}
-
-.carousel-caption {
- background: rgba(0, 0, 0, 0.7);
- border-radius: 8px;
- padding: 12px 20px;
- backdrop-filter: blur(8px);
- bottom: 20px;
- left: 20px;
- right: 20px;
- margin: 0 auto;
- max-width: 400px;
-}
-
-.carousel-caption h5 {
- margin-bottom: 5px;
- font-size: 1.25rem;
- text-shadow: 1px 1px 2px rgba(0,0,0,0.5);
-}
-
-.carousel-caption p {
- margin-bottom: 0;
- font-size: 0.9rem;
- text-shadow: 1px 1px 2px rgba(0,0,0,0.5);
-}
-
-.carousel-control-prev,
-.carousel-control-next {
- width: 50px;
- height: 50px;
- top: 50%;
- transform: translateY(-50%);
- background: rgba(139, 69, 19, 0.8);
- border-radius: 50%;
- transition: all 0.3s ease;
-}
-
-.carousel-control-prev {
- left: 15px;
-}
-
-.carousel-control-next {
- right: 15px;
-}
-
-.carousel-control-prev:hover,
-.carousel-control-next:hover {
- background: rgba(139, 69, 19, 0.9);
- transform: translateY(-50%) scale(1.1);
-}
-
-/* Cards con slide overlay */
-.card {
- border: none;
- transition: all 0.3s ease;
- position: relative;
- overflow: hidden;
- cursor: pointer;
-}
-
-.card::before {
- content: '';
- position: absolute;
- top: 0;
- left: -100%;
- width: 100%;
- height: 100%;
- background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.4), transparent);
- transition: left 0.6s ease;
- z-index: 2;
-}
-
-.card:hover::before {
- left: 100%;
-}
-
-.card:hover {
- transform: translateY(-10px);
- box-shadow: 0 15px 35px rgba(0, 0, 0, 0.2);
-}
-
-.card-img-custom {
- height: 250px;
- object-fit: cover;
- object-position: center;
- transition: transform 0.3s ease;
-}
-
-.card:hover .card-img-custom {
- transform: scale(1.05);
-}
-
-/* Overlay de información en cards */
-.card-overlay {
- position: absolute;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- background: var(--color-overlay);
- color: white;
- display: flex;
- flex-direction: column;
- justify-content: center;
- align-items: center;
- opacity: 0;
- transition: opacity 0.3s ease;
- z-index: 3;
-}
-
-.card:hover .card-overlay {
- opacity: 1;
-}
-
-.card-overlay h5 {
- margin-bottom: 10px;
- font-weight: bold;
-}
-
-.card-overlay p {
- text-align: center;
- padding: 0 20px;
-}
-
-/* Estilos para las tarjetas de productos */
-.card-hover {
- transition: all 0.3s ease;
- border-radius: 15px !important;
- overflow: hidden;
-}
-
-.card-hover:hover {
- transform: translateY(-10px);
- box-shadow: 0 20px 40px rgba(0,0,0,0.1) !important;
-}
-
-.product-image {
- height: 250px;
- object-fit: cover;
- transition: transform 0.3s ease;
-}
-
-.card-hover:hover .product-image {
- transform: scale(1.05);
-}
-
-.card-img-container {
- overflow: hidden;
- border-radius: 15px 15px 0 0;
-}
-
-.btn-pedir {
- background: linear-gradient(135deg, var(--color-marron), var(--color-cafe-claro));
- border: none;
- padding: 12px 20px;
- border-radius: 25px;
- font-weight: 600;
- transition: all 0.3s ease;
- position: relative;
- overflow: hidden;
-}
-
-.btn-pedir:hover {
- transform: translateY(-2px);
- box-shadow: 0 8px 25px rgba(139, 69, 19, 0.3);
-}
-
-.btn-pedir::before {
- content: '';
- position: absolute;
- top: 0;
- left: -100%;
- width: 100%;
- height: 100%;
- background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
- transition: left 0.5s;
-}
-
-.btn-pedir:hover::before {
- left: 100%;
-}
-
-/* Animaciones */
-.fade-in {
- opacity: 0;
- transform: translateY(30px);
- transition: all 0.8s ease;
-}
-
-.fade-in.animate-in {
- opacity: 1;
- transform: translateY(0);
-}
-
-.card {
- opacity: 0;
- transform: translateY(50px);
- transition: all 0.6s ease;
-}
-
-.card.animate-in {
- opacity: 1;
- transform: translateY(0);
-}
-
-/* Hero section específica para menu */
-.hero-section {
- background: linear-gradient(135deg, var(--color-crema), var(--color-blanco-calido));
- margin-top: 76px;
- padding: 80px 0;
- position: relative;
- overflow: hidden;
-}
-
-.hero-section::before {
- content: '';
- position: absolute;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- background: url('data:image/svg+xml,') repeat;
- background-size: 50px 50px;
-}
-
-.hero-section .container {
- position: relative;
- z-index: 1;
-}
-
-/* Estilos para la página del menú */
-.hero-section {
- background: linear-gradient(135deg, var(--color-crema), var(--color-blanco-calido));
- padding: 5rem 0 3rem;
- margin-top: 0;
-}
-
-.hero-section h1 {
- color: var(--color-marron);
- font-weight: 700;
- font-size: 3rem;
- margin-bottom: 1.5rem;
-}
-
-.hero-section .lead {
- color: var(--color-gris-oscuro);
- font-size: 1.2rem;
- font-weight: 500;
-}
-
-.fade-in {
- opacity: 0;
- animation: fadeInUp 0.8s ease forwards;
-}
-
-@keyframes fadeInUp {
- to {
- opacity: 1;
- transform: translateY(0);
- }
- from {
- opacity: 0;
- transform: translateY(20px);
- }
-}
-
-.product-image {
- height: 250px;
- object-fit: cover;
- border-radius: 12px 12px 0 0;
- transition: transform 0.3s ease;
-}
-
-.card-hover {
- transition: all 0.3s ease;
- border: none;
- border-radius: 12px;
- overflow: hidden;
-}
-
-.card-hover:hover {
- transform: translateY(-10px);
- box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
-}
-
-.card-hover:hover .product-image {
- transform: scale(1.05);
-}
-
-.card-img-container {
- overflow: hidden;
- border-radius: 12px 12px 0 0;
-}
-
-.product-info {
- border-top: 1px solid var(--color-cafe-claro);
- padding-top: 1rem;
-}
-
-.badge {
- font-size: 0.8rem;
- padding: 0.5rem 0.75rem;
- border-radius: 20px;
-}
-
-.btn-pedir {
- background: linear-gradient(135deg, #a0522d, var(--color-marron));
- border: none;
- color: white;
- padding: 0.75rem 1.5rem;
- font-weight: 600;
- transition: all 0.3s ease;
- border-radius: 25px;
-}
-
-.btn-pedir:hover {
- background: linear-gradient(135deg, var(--color-marron), #a0522d);
- transform: translateY(-2px);
- box-shadow: 0 6px 20px rgba(139, 69, 19, 0.4);
- color: white;
-}
-
-.animate-in {
- animation: slideInUp 0.6s ease forwards;
-}
-
-@keyframes slideInUp {
- from {
- opacity: 0;
- transform: translateY(30px);
- }
- to {
- opacity: 1;
- transform: translateY(0);
- }
-}
-
-.text-dorado {
- color: var(--color-dorado) !important;
-}
-
-.bg-marron {
- background-color: var(--color-marron) !important;
-}
-
-.bg-gris-oscuro {
- background-color: var(--color-gris-oscuro) !important;
-}
-
-/* Estilos responsive */
-@media (max-width: 768px) {
- .hero-section {
- padding: 60px 0;
- }
-
- .display-4 {
- font-size: 2.5rem;
- }
-
- .product-image {
- height: 200px;
- }
-
- .card-hover:hover {
- transform: none;
- }
-}
-
-@media (max-width: 576px) {
- .carousel-fixed-img {
- height: 200px;
- }
-
- .card-img-custom {
- height: 180px;
- }
-
- .carousel-caption {
- padding: 8px 15px;
- bottom: 10px;
- left: 10px;
- right: 10px;
- max-width: 300px;
- }
-
- .carousel-caption h5 {
- font-size: 1rem;
- }
-
- .carousel-caption p {
- font-size: 0.8rem;
- }
-}
-
-/* Badges de estado */
-.badge {
- font-size: 0.75rem;
- padding: 0.5em 0.75em;
- border-radius: 20px;
-}
-
-/* Efectos de loading */
-.loading {
- opacity: 0.6;
- pointer-events: none;
-}
-
-/* Estilos para el precio */
-.product-info .h5 {
- font-size: 1.5rem;
- font-weight: 700;
- text-shadow: 1px 1px 2px rgba(0,0,0,0.1);
-}
-
-/* Efectos de hover para navegación */
-.nav-link {
- position: relative;
- transition: color 0.3s ease;
-}
-
-.nav-link::after {
- content: '';
- position: absolute;
- bottom: -5px;
- left: 0;
- width: 0;
- height: 2px;
- background: var(--color-marron);
- transition: width 0.3s ease;
-}
-
-.nav-link:hover::after {
- width: 100%;
-}
-
-/* Asegurar alineación correcta del navbar */
-.navbar-nav {
- align-items: center;
-}
-
-.navbar-nav .nav-item {
- display: flex;
- align-items: center;
-}
-
-.navbar-nav .nav-link {
- display: flex;
- align-items: center;
- padding: 0.5rem 1rem;
-}
-
-/* Estilos específicos para el enlace Acceder */
-.nav-item a[href="login.php"] {
- background: linear-gradient(135deg, var(--color-marron), #a0522d);
- color: white !important;
- border-radius: 25px;
- padding: 8px 20px !important;
- text-decoration: none;
- font-weight: 600;
- transition: all 0.3s ease;
- box-shadow: 0 4px 15px rgba(139, 69, 19, 0.3);
- margin-left: 8px;
-}
-
-.nav-item a[href="login.php"]:hover {
- background: linear-gradient(135deg, #a0522d, var(--color-marron));
- transform: translateY(-2px);
- box-shadow: 0 6px 20px rgba(139, 69, 19, 0.4);
- color: white !important;
-}
-
-/* Efectos de scroll suave */
-html {
- scroll-behavior: smooth;
-}
-
-/* Sombras personalizadas */
-.shadow-sm {
- box-shadow: 0 2px 15px rgba(0, 0, 0, 0.1) !important;
-}
-
-.shadow {
- box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15) !important;
-}
-
-/* === DROPDOWN DEL USUARIO === */
-.dropdown-toggle {
- border: none !important;
- background: none !important;
- color: var(--color-marron) !important;
- font-weight: 600;
- display: flex;
- gap: 8px;
- padding: 8px 12px;
- border-radius: 8px;
- transition: all 0.3s ease;
-}
-
-.dropdown-toggle:hover {
- background: rgba(139, 69, 19, 0.1) !important;
- color: var(--color-marron) !important;
-}
-
-.dropdown-toggle:focus {
- box-shadow: 0 0 0 3px rgba(139, 69, 19, 0.2);
-}
-
-.dropdown-toggle::after {
- margin-left: 8px;
- color: var(--color-marron);
-}
-
-.dropdown-menu {
- border: 1px solid var(--color-cafe-claro);
- border-radius: 12px;
- box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
- padding: 0.75rem 0;
- min-width: 200px;
- margin-top: 0.5rem;
- background: var(--color-crema);
- z-index: 10001 !important;
- position: absolute !important;
-}
-
-.dropdown-item {
- color: var(--color-gris-oscuro);
- padding: 0.5rem 1.5rem !important;
- font-weight: 600 !important;
- display: flex;
- align-items: center;
- gap: 10px;
- transition: all 0.3s ease;
- border-radius: 8px !important;
- margin: 0.2rem 0.5rem !important;
-}
-
-.dropdown-item:hover {
- background: var(--color-cafe-con-leche) !important;
- color: var(--color-marron) !important;
- transform: translateX(5px);
-}
-
-.dropdown-item:focus {
- background: var(--color-cafe-con-leche) !important;
- color: var(--color-marron) !important;
-}
-
-.dropdown-divider {
- margin: 0.5rem 0;
- border-color: var(--color-cafe-claro);
-}
-
-/* Asegurar que main no interfiera */
-main {
- position: relative;
- z-index: 1;
-}
-
-/* === NAVBAR Y DROPDOWN - VERSIÓN SIMPLIFICADA === */
-/* Navbar con z-index correcto */
-.navbar {
- position: sticky !important;
- top: 0;
- z-index: 1050 !important;
-}
-
-header {
- position: sticky !important;
- top: 0;
- z-index: 1050 !important;
-}
-
-/* Carrusel con z-index menor */
-.carousel-fullwidth,
-.carousel,
-.carousel-inner,
-.carousel-item {
- z-index: 1 !important;
-}
-
-/* Dropdown con z-index Bootstrap estándar */
-.dropdown-menu {
- z-index: 1051 !important;
-}
-
-/* Responsive */
-@media (max-width: 768px) {
- .carousel-fixed-img {
- height: 250px;
- }
-
- .card-img-custom {
- height: 200px;
- }
-
- .carousel-control-prev,
- .carousel-control-next {
- width: 40px;
- height: 40px;
- }
-
- h2::after {
- width: 60px;
- }
-
- h2::after {
- width: 60px;
- }
-
- /* Dropdown responsivo */
- .dropdown-toggle {
- font-size: 0.9rem;
- padding: 6px 10px;
- }
-
- .dropdown-menu {
- min-width: 180px;
- font-size: 0.9rem;
- }
-
- .dropdown-item {
- padding: 8px 12px;
- }
-}
-
-@media (max-width: 576px) {
- .carousel-fixed-img {
- height: 200px;
- }
-
- .card-img-custom {
- height: 180px;
- }
-
- .carousel-caption {
- padding: 8px 15px;
- bottom: 10px;
- left: 10px;
- right: 10px;
- max-width: 300px;
- }
-
- .carousel-caption h5 {
- font-size: 1rem;
- }
-
- .carousel-caption p {
- font-size: 0.8rem;
- }
-}
-
-/* Badges de estado */
-.badge {
- font-size: 0.75rem;
- padding: 0.5em 0.75em;
- border-radius: 20px;
-}
-
-/* Efectos de loading */
-.loading {
- opacity: 0.6;
- pointer-events: none;
-}
-
-/* Estilos para el precio */
-.product-info .h5 {
- font-size: 1.5rem;
- font-weight: 700;
- text-shadow: 1px 1px 2px rgba(0,0,0,0.1);
-}
-
-/* Efectos de hover para navegación */
-.nav-link {
- position: relative;
- transition: color 0.3s ease;
-}
-
-.nav-link::after {
- content: '';
- position: absolute;
- bottom: -5px;
- left: 0;
- width: 0;
- height: 2px;
- background: var(--color-marron);
- transition: width 0.3s ease;
-}
-
-.nav-link:hover::after {
- width: 100%;
-}
-
-/* Asegurar alineación correcta del navbar */
-.navbar-nav {
- align-items: center;
-}
-
-.navbar-nav .nav-item {
- display: flex;
- align-items: center;
-}
-
-.navbar-nav .nav-link {
- display: flex;
- align-items: center;
- padding: 0.5rem 1rem;
-}
-
-/* Estilos específicos para el enlace Acceder */
-.nav-item a[href="login.php"] {
- background: linear-gradient(135deg, var(--color-marron), #a0522d);
- color: white !important;
- border-radius: 25px;
- padding: 8px 20px !important;
- text-decoration: none;
- font-weight: 600;
- transition: all 0.3s ease;
- box-shadow: 0 4px 15px rgba(139, 69, 19, 0.3);
- margin-left: 8px;
-}
-
-.nav-item a[href="login.php"]:hover {
- background: linear-gradient(135deg, #a0522d, var(--color-marron));
- transform: translateY(-2px);
- box-shadow: 0 6px 20px rgba(139, 69, 19, 0.4);
- color: white !important;
-}
-
-/* Efectos de scroll suave */
-html {
- scroll-behavior: smooth;
-}
-
-/* Sombras personalizadas */
-.shadow-sm {
- box-shadow: 0 2px 15px rgba(0, 0, 0, 0.1) !important;
-}
-
-.shadow {
- box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15) !important;
-}
-
-/* === DROPDOWN DEL USUARIO === */
-.dropdown-toggle {
- border: none !important;
- background: none !important;
- color: var(--color-marron) !important;
- font-weight: 600;
- display: flex;
- gap: 8px;
- padding: 8px 12px;
- border-radius: 8px;
- transition: all 0.3s ease;
-}
-
-.dropdown-toggle:hover {
- background: rgba(139, 69, 19, 0.1) !important;
- color: var(--color-marron) !important;
-}
-
-.dropdown-toggle:focus {
- box-shadow: 0 0 0 3px rgba(139, 69, 19, 0.2);
-}
-
-.dropdown-toggle::after {
- margin-left: 8px;
- color: var(--color-marron);
-}
-
-.dropdown-menu {
- border: 1px solid var(--color-cafe-claro);
- border-radius: 12px;
- box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
- padding: 0.75rem 0;
- min-width: 200px;
- margin-top: 0.5rem;
- background: var(--color-crema);
- z-index: 10001 !important;
- position: absolute !important;
-}
-
-.dropdown-item {
- color: var(--color-gris-oscuro);
- padding: 0.5rem 1.5rem !important;
- font-weight: 600 !important;
- display: flex;
- align-items: center;
- gap: 10px;
- transition: all 0.3s ease;
- border-radius: 8px !important;
- margin: 0.2rem 0.5rem !important;
-}
-
-.dropdown-item:hover {
- background: var(--color-cafe-con-leche) !important;
- color: var(--color-marron) !important;
- transform: translateX(5px);
-}
-
-.dropdown-item:focus {
- background: var(--color-cafe-con-leche) !important;
- color: var(--color-marron) !important;
-}
-
-.dropdown-divider {
- margin: 0.5rem 0;
- border-color: var(--color-cafe-claro);
-}
-
-/* Asegurar que main no interfiera */
-main {
- position: relative;
- z-index: 1;
-}
-
-/* === NAVBAR Y DROPDOWN - VERSIÓN SIMPLIFICADA === */
-/* Navbar con z-index correcto */
-.navbar {
- position: sticky !important;
- top: 0;
- z-index: 1050 !important;
-}
-
-header {
- position: sticky !important;
- top: 0;
- z-index: 1050 !important;
-}
-
-/* Carrusel con z-index menor */
-.carousel-fullwidth,
-.carousel,
-.carousel-inner,
-.carousel-item {
- z-index: 1 !important;
-}
-
-/* Dropdown con z-index Bootstrap estándar */
-.dropdown-menu {
- z-index: 1051 !important;
-}
-
-/* Responsive */
-@media (max-width: 768px) {
- .carousel-fixed-img {
- height: 250px;
- }
-
- .card-img-custom {
- height: 200px;
- }
-
- .carousel-control-prev,
- .carousel-control-next {
- width: 40px;
- height: 40px;
- }
-
- h2::after {
- width: 60px;
- }
-
- h2::after {
- width: 60px;
- }
-
- /* Dropdown responsivo */
- .dropdown-toggle {
- font-size: 0.9rem;
- padding: 6px 10px;
- }
-
- .dropdown-menu {
- min-width: 180px;
- font-size: 0.9rem;
- }
-
- .dropdown-item {
- padding: 8px 12px;
- }
-}
-
-@media (max-width: 576px) {
- .carousel-fixed-img {
- height: 200px;
- }
-
- .card-img-custom {
- height: 180px;
- }
-
- .carousel-caption {
- padding: 8px 15px;
- bottom: 10px;
- left: 10px;
- right: 10px;
- max-width: 300px;
- }
-
- .carousel-caption h5 {
- font-size: 1rem;
- }
-
- .carousel-caption p {
- font-size: 0.8rem;
- }
-}
-
-/* Badges de estado */
-.badge {
- font-size: 0.75rem;
- padding: 0.5em 0.75em;
- border-radius: 20px;
-}
-
-/* Efectos de loading */
-.loading {
- opacity: 0.6;
- pointer-events: none;
-}
-
-/* Estilos para el precio */
-.product-info .h5 {
- font-size: 1.5rem;
- font-weight: 700;
- text-shadow: 1px 1px 2px rgba(0,0,0,0.1);
-}
-
-/* Efectos de hover para navegación */
-.nav-link {
- position: relative;
- transition: color 0.3s ease;
-}
-
-.nav-link::after {
- content: '';
- position: absolute;
- bottom: -5px;
- left: 0;
- width: 0;
- height: 2px;
- background: var(--color-marron);
- transition: width 0.3s ease;
-}
-
-.nav-link:hover::after {
- width: 100%;
-}
-
-/* Asegurar alineación correcta del navbar */
-.navbar-nav {
- align-items: center;
-}
-
-.navbar-nav .nav-item {
- display: flex;
- align-items: center;
-}
-
-.navbar-nav .nav-link {
- display: flex;
- align-items: center;
- padding: 0.5rem 1rem;
-}
-
-/* Estilos específicos para el enlace Acceder */
-.nav-item a[href="login.php"] {
- background: linear-gradient(135deg, var(--color-marron), #a0522d);
- color: white !important;
- border-radius: 25px;
- padding: 8px 20px !important;
- text-decoration: none;
- font-weight: 600;
- transition: all 0.3s ease;
- box-shadow: 0 4px 15px rgba(139, 69, 19, 0.3);
- margin-left: 8px;
-}
-
-.nav-item a[href="login.php"]:hover {
- background: linear-gradient(135deg, #a0522d, var(--color-marron));
- transform: translateY(-2px);
- box-shadow: 0 6px 20px rgba(139, 69, 19, 0.4);
- color: white !important;
-}
-
-/* Efectos de scroll suave */
-html {
- scroll-behavior: smooth;
-}
-
-/* Sombras personalizadas */
-.shadow-sm {
- box-shadow: 0 2px 15px rgba(0, 0, 0, 0.1) !important;
-}
-
-.shadow {
- box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15) !important;
-}
-
-/* === DROPDOWN DEL USUARIO === */
-.dropdown-toggle {
- border: none !important;
- background: none !important;
- color: var(--color-marron) !important;
- font-weight: 600;
- display: flex;
- gap: 8px;
- padding: 8px 12px;
- border-radius: 8px;
- transition: all 0.3s ease;
-}
-
-.dropdown-toggle:hover {
- background: rgba(139, 69, 19, 0.1) !important;
- color: var(--color-marron) !important;
-}
-
-.dropdown-toggle:focus {
- box-shadow: 0 0 0 3px rgba(139, 69, 19, 0.2);
-}
-
-.dropdown-toggle::after {
- margin-left: 8px;
- color: var(--color-marron);
-}
-
-.dropdown-menu {
- border: 1px solid var(--color-cafe-claro);
- border-radius: 12px;
- box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
- padding: 0.75rem 0;
- min-width: 200px;
- margin-top: 0.5rem;
- background: var(--color-crema);
- z-index: 10001 !important;
- position: absolute !important;
-}
-
-.dropdown-item {
- color: var(--color-gris-oscuro);
- padding: 0.5rem 1.5rem !important;
- font-weight: 600 !important;
- display: flex;
- align-items: center;
- gap: 10px;
- transition: all 0.3s ease;
- border-radius: 8px !important;
- margin: 0.2rem 0.5rem !important;
-}
-
-.dropdown-item:hover {
- background: var(--color-cafe-con-leche) !important;
- color: var(--color-marron) !important;
- transform: translateX(5px);
-}
-
-.dropdown-item:focus {
- background: var(--color-cafe-con-leche) !important;
- color: var(--color-marron) !important;
-}
-
-.dropdown-divider {
- margin: 0.5rem 0;
- border-color: var(--color-cafe-claro);
-}
-
-/* Asegurar que main no interfiera */
-main {
- position: relative;
- z-index: 1;
-}
-
-/* === NAVBAR Y DROPDOWN - VERSIÓN SIMPLIFICADA === */
-/* Navbar con z-index correcto */
-.navbar {
- position: sticky !important;
- top: 0;
- z-index: 1050 !important;
-}
-
-header {
- position: sticky !important;
- top: 0;
- z-index: 1050 !important;
-}
-
-/* Carrusel con z-index menor */
-.carousel-fullwidth,
-.carousel,
-.carousel-inner,
-.carousel-item {
- z-index: 1 !important;
-}
-
-/* Dropdown con z-index Bootstrap estándar */
-.dropdown-menu {
- z-index: 1051 !important;
-}
-
-/* Responsive */
-@media (max-width: 768px) {
- .carousel-fixed-img {
- height: 250px;
- }
-
- .card-img-custom {
- height: 200px;
- }
-
- .carousel-control-prev,
- .carousel-control-next {
- width: 40px;
- height: 40px;
- }
-
- h2::after {
- width: 60px;
- }
-
- h2::after {
- width: 60px;
- }
-
- /* Dropdown responsivo */
- .dropdown-toggle {
- font-size: 0.9rem;
- padding: 6px 10px;
- }
-
- .dropdown-menu {
- min-width: 180px;
- font-size: 0.9rem;
- }
-
- .dropdown-item {
- padding: 8px 12px;
- }
-}
-
-@media (max-width: 576px) {
- .carousel-fixed-img {
- height: 200px;
- }
-
- .card-img-custom {
- height: 180px;
- }
-
- .carousel-caption {
- padding: 8px 15px;
- bottom: 10px;
- left: 10px;
- right: 10px;
- max-width: 300px;
- }
-
- .carousel-caption h5 {
- font-size: 1rem;
- }
-
- .carousel-caption p {
- font-size: 0.8rem;
- }
-}
-
-/* Badges de estado */
-.badge {
- font-size: 0.75rem;
- padding: 0.5em 0.75em;
- border-radius: 20px;
-}
-
-/* Efectos de loading */
-.loading {
- opacity: 0.6;
- pointer-events: none;
-}
-
-/* Estilos para el precio */
-.product-info .h5 {
- font-size: 1.5rem;
- font-weight: 700;
- text-shadow: 1px 1px 2px rgba(0,0,0,0.1);
-}
-
-/* Efectos de hover para navegación */
-.nav-link {
- position: relative;
- transition: color 0.3s ease;
-}
-
-.nav-link::after {
- content: '';
- position: absolute;
- bottom: -5px;
- left: 0;
- width: 0;
- height: 2px;
- background: var(--color-marron);
- transition: width 0.3s ease;
-}
-
-.nav-link:hover::after {
- width: 100%;
-}
-
-/* Asegurar alineación correcta del navbar */
-.navbar-nav {
- align-items: center;
-}
-
-.navbar-nav .nav-item {
- display: flex;
- align-items: center;
-}
-
-.navbar-nav .nav-link {
- display: flex;
- align-items: center;
- padding: 0.5rem 1rem;
-}
-
-/* Estilos específicos para el enlace Acceder */
-.nav-item a[href="login.php"] {
- background: linear-gradient(135deg, var(--color-marron), #a0522d);
- color: white !important;
- border-radius: 25px;
- padding: 8px 20px !important;
- text-decoration: none;
- font-weight: 600;
- transition: all 0.3s ease;
- box-shadow: 0 4px 15px rgba(139, 69, 19, 0.3);
- margin-left: 8px;
-}
-
-.nav-item a[href="login.php"]:hover {
- background: linear-gradient(135deg, #a0522d, var(--color-marron));
- transform: translateY(-2px);
- box-shadow: 0 6px 20px rgba(139, 69, 19, 0.4);
- color: white !important;
-}
-
-/* Efectos de scroll suave */
-html {
- scroll-behavior: smooth;
-}
-
-/* Sombras personalizadas */
-.shadow-sm {
- box-shadow: 0 2px 15px rgba(0, 0, 0, 0.1) !important;
-}
-
-.shadow {
- box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15) !important;
-}
-
-/* === DROPDOWN DEL USUARIO === */
-.dropdown-toggle {
- border: none !important;
- background: none !important;
- color: var(--color-marron) !important;
- font-weight: 600;
- display: flex;
- gap: 8px;
- padding: 8px 12px;
- border-radius: 8px;
- transition: all 0.3s ease;
-}
-
-.dropdown-toggle:hover {
- background: rgba(139, 69, 19, 0.1) !important;
- color: var(--color-marron) !important;
-}
-
-.dropdown-toggle:focus {
- box-shadow: 0 0 0 3px rgba(139, 69, 19, 0.2);
-}
-
-.dropdown-toggle::after {
- margin-left: 8px;
- color: var(--color-marron);
-}
-
-.dropdown-menu {
- border: 1px solid var(--color-cafe-claro);
- border-radius: 12px;
- box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
- padding: 0.75rem 0;
- min-width: 200px;
- margin-top: 0.5rem;
- background: var(--color-crema);
- z-index: 10001 !important;
- position: absolute !important;
-}
-
-.dropdown-item {
- color: var(--color-gris-oscuro);
- padding: 0.5rem 1.5rem !important;
- font-weight: 600 !important;
- display: flex;
- align-items: center;
- gap: 10px;
- transition: all 0.3s ease;
- border-radius: 8px !important;
- margin: 0.2rem 0.5rem !important;
-}
-
-.dropdown-item:hover {
- background: var(--color-cafe-con-leche) !important;
- color: var(--color-marron) !important;
- transform: translateX(5px);
-}
-
-.dropdown-item:focus {
- background: var(--color-cafe-con-leche) !important;
- color: var(--color-marron) !important;
-}
-
-.dropdown-divider {
- margin: 0.5rem 0;
- border-color: var(--color-cafe-claro);
-}
-
-/* Asegurar que main no interfiera */
-main {
- position: relative;
- z-index: 1;
-}
-
-/* === NAVBAR Y DROPDOWN - VERSIÓN SIMPLIFICADA === */
-/* Navbar con z-index correcto */
-.navbar {
- position: sticky !important;
- top: 0;
- z-index: 1050 !important;
-}
-
-header {
- position: sticky !important;
- top: 0;
- z-index: 1050 !important;
-}
-
-/* Carrusel con z-index menor */
-.carousel-fullwidth,
-.carousel,
-.carousel-inner,
-.carousel-item {
- z-index: 1 !important;
-}
-
-/* Dropdown con z-index Bootstrap estándar */
-.dropdown-menu {
- z-index: 1051 !important;
-}
-
-/* Responsive */
-@media (max-width: 768px) {
- .carousel-fixed-img {
- height: 250px;
- }
-
- .card-img-custom {
- height: 200px;
- }
-
- .carousel-control-prev,
- .carousel-control-next {
- width: 40px;
- height: 40px;
- }
-
- h2::after {
- width: 60px;
- }
-
- h2::after {
- width: 60px;
- }
-
- /* Dropdown responsivo */
- .dropdown-toggle {
- font-size: 0.9rem;
- padding: 6px 10px;
- }
-
- .dropdown-menu {
- min-width: 180px;
- font-size: 0.9rem;
- }
-
- .dropdown-item {
- padding: 8px 12px;
- }
-}
-
-@media (max-width: 576px) {
- .carousel-fixed-img {
- height: 200px;
- }
-
- .card-img-custom {
- height: 180px;
- }
-
- .carousel-caption {
- padding: 8px 15px;
- bottom: 10px;
- left: 10px;
- right: 10px;
- max-width: 300px;
- }
-
- .carousel-caption h5 {
- font-size: 1rem;
- }
-
- .carousel-caption p {
- font-size: 0.8rem;
- }
-}
-
-/* Badges de estado */
-.badge {
- font-size: 0.75rem;
- padding: 0.5em 0.75em;
- border-radius: 20px;
-}
-
-/* Efectos de loading */
-.loading {
- opacity: 0.6;
- pointer-events: none;
-}
-
-/* Estilos para el precio */
-.product-info .h5 {
- font-size: 1.5rem;
- font-weight: 700;
- text-shadow: 1px 1px 2px rgba(0,0,0,0.1);
-}
-
-/* Efectos de hover para navegación */
-.nav-link {
- position: relative;
- transition: color 0.3s ease;
-}
-
-.nav-link::after {
- content: '';
- position: absolute;
- bottom: -5px;
- left: 0;
- width: 0;
- height: 2px;
- background: var(--color-marron);
- transition: width 0.3s ease;
-}
-
-.nav-link:hover::after {
- width: 100%;
-}
-
-/* Asegurar alineación correcta del navbar */
-.navbar-nav {
- align-items: center;
-}
-
-.navbar-nav .nav-item {
- display: flex;
- align-items: center;
-}
-
-.navbar-nav .nav-link {
- display: flex;
- align-items: center;
- padding: 0.5rem 1rem;
-}
-
-/* Estilos específicos para el enlace Acceder */
-.nav-item a[href="login.php"] {
- background: linear-gradient(135deg, var(--color-marron), #a0522d);
- color: white !important;
- border-radius: 25px;
- padding: 8px 20px !important;
- text-decoration: none;
- font-weight: 600;
- transition: all 0.3s ease;
- box-shadow: 0 4px 15px rgba(139, 69, 19, 0.3);
- margin-left: 8px;
-}
-
-.nav-item a[href="login.php"]:hover {
- background: linear-gradient(135deg, #a0522d, var(--color-marron));
- transform: translateY(-2px);
- box-shadow: 0 6px 20px rgba(139, 69, 19, 0.4);
- color: white !important;
-}
-
-/* Efectos de scroll suave */
-html {
- scroll-behavior: smooth;
-}
-
-/* Sombras personalizadas */
-.shadow-sm {
- box-shadow: 0 2px 15px rgba(0, 0, 0, 0.1) !important;
-}
-
-.shadow {
- box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15) !important;
-}
-
-/* === DROPDOWN DEL USUARIO === */
-.dropdown-toggle {
- border: none !important;
- background: none !important;
- color: var(--color-marron) !important;
- font-weight: 600;
- display: flex;
- gap: 8px;
- padding: 8px 12px;
- border-radius: 8px;
- transition: all 0.3s ease;
-}
-
-.dropdown-toggle:hover {
- background: rgba(139, 69, 19, 0.1) !important;
- color: var(--color-marron) !important;
-}
-
-.dropdown-toggle:focus {
- box-shadow: 0 0 0 3px rgba(139, 69, 19, 0.2);
-}
-
-.dropdown-toggle::after {
- margin-left: 8px;
- color: var(--color-marron);
-}
-
-.dropdown-menu {
- border: 1px solid var(--color-cafe-claro);
- border-radius: 12px;
- box-shadow: 0 8px 25px rgba(0, 0, 0, 0.15);
- padding: 0.75rem 0;
- min-width: 200px;
- margin-top: 0.5rem;
- background: var(--color-crema);
- z-index: 10001 !important;
- position: absolute !important;
-}
-
-.dropdown-item {
- color: var(--color-gris-oscuro);
- padding: 0.5rem 1.5rem !important;
- font-weight: 600 !important;
- display: flex;
- align-items: center;
- gap: 10px;
- transition: all 0.3s ease;
- border-radius: 8px !important;
- margin: 0.2rem 0.5rem !important;
-}
-
-.dropdown-item:hover {
- background: var(--color-cafe-con-leche) !important;
- color: var(--color-marron) !important;
- transform: translateX(5px);
-}
-
-.dropdown-item:focus {
- background: var(--color-cafe-con-leche) !important;
- color: var(--color-marron) !important;
-}
-
-.dropdown-divider {
- margin: 0.5rem 0;
- border-color: var(--color-cafe-claro);
-}
-
-/* Asegurar que main no interfiera */
-main {
- position: relative;
- z-index: 1;
-}
-
-/* === NAVBAR Y DROPDOWN - VERSIÓN SIMPLIFICADA === */
-/* Navbar con z-index correcto */
-.navbar {
- position: sticky !important;
- top: 0;
- z-index: 1050 !important;
-}
-
-header {
- position: sticky !important;
- top: 0;
- z-index: 1050 !important;
-}
-
-/* Carrusel con z-index menor */
-.carousel-fullwidth,
-.carousel,
-.carousel-inner,
-.carousel-item {
- z-index: 1 !important;
-}
-
-/* Dropdown con z-index Bootstrap estándar */
-.dropdown-menu {
- z-index: 1051 !important;
-}
-
-/* Responsive */
-@media (max-width: 768px) {
- .carousel-fixed-img {
- height: 250px;
- }
-
- .card-img-custom {
- height: 200px;
- }
-
- .carousel-control-prev,
- .carousel-control-next {
- width: 40px;
- height: 40px;
- }
-
- h2::after {
- width: 60px;
- }
-
- h2::after {
- width: 60px;
- }
-
- /* Dropdown responsivo */
- .dropdown-toggle {
- font-size: 0.9rem;
- padding: 6px 10px;
- }
-
- .dropdown-menu {
- min-width: 180px;
- font-size: 0.9rem;
- }
-
- .dropdown-item {
- padding: 8px 12px;
- }
-}
-
-@media (max-width: 576px) {
- .carousel-fixed-img {
- height: 200px;
- }
-
- .card-img-custom {
- height: 180px;
- }
-
- .carousel-caption {
- padding: 8px 15px;
- bottom: 10px;
- left: 10px;
- right: 10px;
- max-width: 300px;
- }
-
- .carousel-caption h5 {
- font-size: 1rem;
- }
-
- .carousel-caption p {
- font-size: 0.8rem;
- }
-}
-
-/* Stock agotado */
-.out-of-stock {
- opacity: 0.6;
-}
-
-.out-of-stock::before {
- content: 'Agotado';
- position: absolute;
- top: 10px;
- left: 10px;
- background: #dc3545;
- color: white;
- padding: 4px 8px;
- border-radius: 10px;
- font-size: 0.7rem;
- font-weight: 600;
- z-index: 3;
-}
-
-.out-of-stock .btn-pedir {
- background: #6c757d !important;
- cursor: not-allowed !important;
-}
-
-/* Animaciones para botones */
-.btn-pedir.processing {
- animation: pulseButton 1s infinite;
-}
\ No newline at end of file
diff --git a/files/stylemenu.css b/files/stylemenu.css
deleted file mode 100644
index 02da0b9..0000000
--- a/files/stylemenu.css
+++ /dev/null
@@ -1,19 +0,0 @@
-
-.product-card-item {
- display: block; /* Asegura que la tarjeta sea visible por defecto */
-}
-.product-card-item.hidden {
- display: none; /* Oculta la tarjeta */
-}
-.btn-agregar-pedido {
- background-color: #E2725B; /* Tono terracota */
- color: white;
- border: none;
- transition: background-color 0.3s, transform 0.2s;
- font-weight: bold;
-}
-.btn-agregar-pedido:hover {
- background-color: #C66049; /* Tono terracota más oscuro */
- color: white;
- transform: translateY(-2px);
-}
diff --git a/files/stylempleado.css b/files/stylempleado.css
deleted file mode 100644
index e69de29..0000000
diff --git a/files/styleproductostabla.css b/files/styleproductostabla.css
deleted file mode 100644
index 520e9aa..0000000
--- a/files/styleproductostabla.css
+++ /dev/null
@@ -1,842 +0,0 @@
-/* Estilos para la gestión de productos - Panadería */
-@import url('https://fonts.googleapis.com/css2?family=Playfair+Display:wght@700&family=Exo+2:wght@300;400;500;600;700&display=swap');
-
-/* Variables CSS */
-:root {
- --primary-color: #8C5A37;
- --primary-hover: #6E462A;
- --text-dark: #3D2C21;
- --text-light: #6B5B51;
- --border-color: #D3C5BC;
- --container-bg: rgba(255, 255, 255, 0.75);
- --white: #ffffff;
- --light-gray: #f8f9fa;
- --medium-gray: #e9ecef;
- --success-color: #4CAF50;
- --info-color: #2196F3;
- --warning-color: #FF9800;
- --danger-color: #F44336;
- --crema: #f5f5dc;
- --shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
- --border-radius: 10px;
- --transition: all 0.3s ease;
-}
-
-/* Reset y estilos base */
-* {
- margin: 0;
- padding: 0;
- box-sizing: border-box;
-}
-
-body {
- font-family: 'Exo 2', sans-serif;
- background: linear-gradient(135deg, #4e3f30 0%, #63554b 100%);
- color: var(--text-dark);
- line-height: 1.6;
- min-height: 100vh;
-}
-
-/* Contenedor principal */
-.container {
- max-width: 1200px;
- margin: 0 auto;
- padding: 20px;
-}
-
-/* Header section */
-.header-section {
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-bottom: 30px;
- background: var(--container-bg);
- padding: 20px;
- border-radius: var(--border-radius);
- box-shadow: var(--shadow);
- border: 1px solid var(--border-color);
-}
-
-.header-section h1 {
- color: var(--primary-color);
- font-family: 'Playfair Display', serif;
- font-size: 2.5rem;
- font-weight: 700;
- margin: 0;
- text-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
-}
-
-.btn-regresar {
- display: flex;
- align-items: center;
- gap: 8px;
- padding: 12px 20px;
- background: linear-gradient(135deg, var(--primary-color) 0%, var(--primary-hover) 100%);
- color: var(--white);
- text-decoration: none;
- border-radius: 25px;
- font-weight: 600;
- transition: var(--transition);
- box-shadow: var(--shadow);
- border: 1px solid var(--border-color);
-}
-
-.btn-regresar:hover {
- transform: translateY(-2px);
- box-shadow: 0 4px 20px rgba(140, 90, 55, 0.3);
- color: var(--white);
-}
-
-/* Mensajes de éxito y error */
-.mensaje-exito, .mensaje-error {
- padding: 15px 20px;
- margin: 20px 0;
- border-radius: var(--border-radius);
- font-weight: 600;
- text-align: center;
- animation: slideIn 0.3s ease-out;
-}
-
-.mensaje-exito {
- background: linear-gradient(135deg, rgba(76, 175, 80, 0.1) 0%, rgba(76, 175, 80, 0.05) 100%);
- color: var(--success-color);
- border: 1px solid rgba(76, 175, 80, 0.3);
-}
-
-.mensaje-error {
- background: linear-gradient(135deg, rgba(244, 67, 54, 0.1) 0%, rgba(244, 67, 54, 0.05) 100%);
- color: var(--danger-color);
- border: 1px solid rgba(244, 67, 54, 0.3);
-}
-
-/* Formulario container */
-.formulario-container {
- background: var(--container-bg);
- padding: 30px;
- border-radius: var(--border-radius);
- box-shadow: var(--shadow);
- margin-bottom: 30px;
- text-align: center;
- border: 1px solid var(--border-color);
-}
-
-.formulario-container h2 {
- color: var(--primary-color);
- font-family: 'Playfair Display', serif;
- margin-bottom: 20px;
- font-size: 1.8rem;
- font-weight: 700;
-}
-
-.btn-modal-trigger {
- display: inline-flex;
- align-items: center;
- gap: 10px;
- padding: 15px 30px;
- background: linear-gradient(135deg, var(--success-color) 0%, rgba(76, 175, 80, 0.9) 100%);
- color: var(--white);
- border: none;
- border-radius: 25px;
- font-size: 1.1rem;
- font-weight: 600;
- cursor: pointer;
- transition: var(--transition);
- box-shadow: var(--shadow);
-}
-
-.btn-modal-trigger:hover {
- transform: translateY(-2px);
- box-shadow: 0 4px 20px rgba(76, 175, 80, 0.3);
-}
-
-/* Tabla section */
-.tabla-section {
- background: var(--container-bg);
- border-radius: var(--border-radius);
- box-shadow: var(--shadow);
- overflow: hidden;
- border: 1px solid var(--border-color);
-}
-
-.tabla-header {
- display: flex;
- justify-content: space-between;
- align-items: center;
- padding: 25px 30px;
- background: linear-gradient(135deg, var(--primary-color) 0%, var(--primary-hover) 100%);
- color: var(--white);
-}
-
-.tabla-header h2 {
- margin: 0;
- font-size: 1.8rem;
- font-family: 'Playfair Display', serif;
- font-weight: 700;
-}
-
-.filtro-busqueda {
- display: flex;
- align-items: center;
- gap: 10px;
- background: rgba(255, 255, 255, 0.1);
- padding: 10px 15px;
- border-radius: 20px;
- backdrop-filter: blur(10px);
-}
-
-.filtro-busqueda input {
- background: transparent;
- border: none;
- color: var(--white);
- font-size: 1rem;
- outline: none;
- width: 250px;
-}
-
-.filtro-busqueda input::placeholder {
- color: rgba(255, 255, 255, 0.7);
-}
-
-.filtro-busqueda .material-symbols-outlined {
- color: rgba(255, 255, 255, 0.8);
-}
-
-/* Tabla contenedor */
-.tabla-contenedor {
- overflow-x: auto;
- max-height: 600px;
-}
-
-/* Estilos de tabla */
-#tabla-productos {
- width: 100%;
- border-collapse: collapse;
- font-size: 0.95rem;
-}
-
-#tabla-productos thead {
- background: linear-gradient(135deg, var(--text-dark) 0%, var(--text-light) 100%);
- color: var(--white);
- position: sticky;
- top: 0;
- z-index: 10;
-}
-
-#tabla-productos th {
- padding: 15px 12px;
- text-align: left;
- font-weight: 600;
- text-transform: uppercase;
- letter-spacing: 0.5px;
- border-bottom: 2px solid var(--medium-gray);
-}
-
-#tabla-productos tbody tr {
- transition: var(--transition);
- border-bottom: 1px solid var(--medium-gray);
-}
-
-#tabla-productos tbody tr:hover {
- background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
- transform: scale(1.01);
-}
-
-#tabla-productos tbody tr:nth-child(even) {
- background: #f8f9fa;
-}
-
-#tabla-productos tbody tr:nth-child(even):hover {
- background: linear-gradient(135deg, #e9ecef 0%, #dee2e6 100%);
-}
-
-#tabla-productos td {
- padding: 12px;
- vertical-align: middle;
- border-bottom: 1px solid #dee2e6;
-}
-
-/* Precio destacado */
-.precio {
- font-weight: 700;
- color: var(--success-color);
- font-size: 1.1rem;
-}
-
-/* Estados */
-.estado-activo, .estado-inactivo {
- display: inline-flex;
- align-items: center;
- gap: 5px;
- padding: 5px 12px;
- border-radius: 15px;
- font-size: 0.85rem;
- font-weight: 600;
-}
-
-.estado-activo {
- background: linear-gradient(135deg, rgba(76, 175, 80, 0.1) 0%, rgba(76, 175, 80, 0.05) 100%);
- color: var(--success-color);
- border: 1px solid rgba(76, 175, 80, 0.3);
-}
-
-.estado-inactivo {
- background: linear-gradient(135deg, rgba(244, 67, 54, 0.1) 0%, rgba(244, 67, 54, 0.05) 100%);
- color: var(--danger-color);
- border: 1px solid rgba(244, 67, 54, 0.3);
-}
-
-/* Acciones */
-.acciones {
- display: flex;
- gap: 8px;
- justify-content: center;
-}
-
-.btn-action {
- display: inline-flex;
- align-items: center;
- justify-content: center;
- width: 40px;
- height: 40px;
- border: none;
- border-radius: 50%;
- cursor: pointer;
- transition: var(--transition);
- font-size: 1.2rem;
-}
-
-.btn-toggle {
- background: linear-gradient(135deg, var(--warning-color) 0%, rgba(255, 152, 0, 0.9) 100%);
- color: var(--white);
-}
-
-.btn-toggle:hover {
- transform: scale(1.1);
- box-shadow: 0 2px 10px rgba(255, 152, 0, 0.4);
-}
-
-.btn-gestionar {
- background: linear-gradient(135deg, var(--info-color) 0%, rgba(33, 150, 243, 0.9) 100%);
- color: var(--white);
-}
-
-.btn-gestionar:hover {
- transform: scale(1.1);
- box-shadow: 0 2px 10px rgba(33, 150, 243, 0.4);
-}
-
-.btn-eliminar {
- background: linear-gradient(135deg, var(--danger-color) 0%, rgba(244, 67, 54, 0.9) 100%);
- color: var(--white);
-}
-
-.btn-eliminar:hover {
- transform: scale(1.1);
- box-shadow: 0 2px 10px rgba(244, 67, 54, 0.4);
-}
-
-/* Estilos de modal */
-.modal {
- display: none;
- position: fixed;
- z-index: 1000;
- left: 0;
- top: 0;
- width: 100%;
- height: 100%;
- background: rgba(0, 0, 0, 0.5);
- backdrop-filter: blur(5px);
- animation: fadeIn 0.3s ease-out;
-}
-
-.modal-content {
- background: var(--white);
- margin: 5% auto;
- padding: 0;
- border-radius: var(--border-radius);
- max-width: 600px;
- width: 90%;
- max-height: 80vh;
- overflow-y: auto;
- box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
- animation: slideInModal 0.3s ease-out;
-}
-
-.modal-header {
- display: flex;
- justify-content: space-between;
- align-items: center;
- padding: 20px 30px;
- background: linear-gradient(135deg, var(--primary-color) 0%, var(--primary-hover) 100%);
- color: var(--white);
- border-radius: var(--border-radius) var(--border-radius) 0 0;
-}
-
-.modal-header h2 {
- margin: 0;
- font-size: 1.5rem;
- font-family: 'Playfair Display', serif;
- font-weight: 700;
-}
-
-.modal-close {
- background: none;
- border: none;
- color: var(--white);
- font-size: 2rem;
- cursor: pointer;
- padding: 0;
- width: 30px;
- height: 30px;
- display: flex;
- align-items: center;
- justify-content: center;
- border-radius: 50%;
- transition: var(--transition);
-}
-
-.modal-close:hover {
- background: rgba(255, 255, 255, 0.2);
-}
-
-.modal-body {
- padding: 30px;
-}
-
-/* Formulario styles */
-.form-row {
- display: grid;
- grid-template-columns: 1fr 1fr;
- gap: 20px;
- margin-bottom: 20px;
-}
-
-.form-group {
- display: flex;
- flex-direction: column;
-}
-
-.form-group label {
- margin-bottom: 8px;
- font-weight: 600;
- color: var(--text-dark);
-}
-
-.form-group input {
- padding: 12px 15px;
- border: 2px solid var(--border-color);
- border-radius: var(--border-radius);
- font-size: 1rem;
- transition: var(--transition);
- background: var(--white);
-}
-
-.form-group input:focus {
- outline: none;
- border-color: var(--primary-color);
- box-shadow: 0 0 0 3px rgba(140, 90, 55, 0.1);
-}
-
-/* Modal actions */
-.modal-actions {
- display: flex;
- justify-content: center;
- gap: 15px;
- margin-top: 30px;
- padding-top: 20px;
- border-top: 1px solid var(--medium-gray);
-}
-
-.modal-btn {
- display: inline-flex;
- align-items: center;
- gap: 8px;
- padding: 12px 25px;
- border: none;
- border-radius: 25px;
- font-weight: 600;
- cursor: pointer;
- transition: var(--transition);
- text-decoration: none;
- font-size: 1rem;
- font-family: 'Exo 2', sans-serif;
-}
-
-.modal-btn.primary {
- background: linear-gradient(135deg, var(--primary-color) 0%, var(--primary-hover) 100%);
- color: var(--white);
-}
-
-.modal-btn.primary:hover {
- transform: translateY(-2px);
- box-shadow: 0 4px 20px rgba(140, 90, 55, 0.3);
-}
-
-.modal-btn.secondary {
- background: linear-gradient(135deg, var(--text-light) 0%, var(--text-dark) 100%);
- color: var(--white);
-}
-
-.modal-btn.secondary:hover {
- transform: translateY(-2px);
- box-shadow: 0 4px 20px rgba(107, 91, 81, 0.3);
-}
-
-.modal-btn.success {
- background: linear-gradient(135deg, var(--success-color) 0%, rgba(76, 175, 80, 0.9) 100%);
- color: var(--white);
-}
-
-.modal-btn.success:hover {
- transform: translateY(-2px);
- box-shadow: 0 4px 20px rgba(76, 175, 80, 0.3);
-}
-
-.modal-btn.danger {
- background: linear-gradient(135deg, var(--danger-color) 0%, rgba(244, 67, 54, 0.9) 100%);
- color: var(--white);
-}
-
-.modal-btn.danger:hover {
- transform: translateY(-2px);
- box-shadow: 0 4px 20px rgba(244, 67, 54, 0.3);
-}
-
-/* Modal icon */
-.modal-icon {
- text-align: center;
- margin-bottom: 20px;
- font-size: 4rem;
-}
-
-.modal-icon.success {
- color: var(--success-color);
-}
-
-.modal-icon.error {
- color: var(--danger-color);
-}
-
-.modal-icon.warning {
- color: var(--warning-color);
-}
-
-/* Modal message */
-.modal-message {
- text-align: center;
- margin-bottom: 20px;
- font-size: 1.1rem;
- line-height: 1.6;
-}
-
-/* Countdown info */
-.countdown-info {
- text-align: center;
- margin-top: 15px;
- font-size: 0.9rem;
- color: var(--text-light);
- opacity: 0.7;
-}
-
-/* Status badges */
-.status-badge {
- display: inline-flex;
- align-items: center;
- gap: 5px;
- padding: 6px 12px;
- border-radius: 15px;
- font-size: 0.85rem;
- font-weight: 600;
-}
-
-.status-activo {
- background: linear-gradient(135deg, rgba(76, 175, 80, 0.1) 0%, rgba(76, 175, 80, 0.05) 100%);
- color: var(--success-color);
- border: 1px solid rgba(76, 175, 80, 0.3);
-}
-
-.status-inactivo {
- background: linear-gradient(135deg, rgba(244, 67, 54, 0.1) 0%, rgba(244, 67, 54, 0.05) 100%);
- color: var(--danger-color);
- border: 1px solid rgba(244, 67, 54, 0.3);
-}
-
-/* No resultados */
-.no-resultados {
- text-align: center;
- font-style: italic;
- color: var(--text-light);
- opacity: 0.7;
- padding: 40px !important;
-}
-
-/* Animaciones */
-@keyframes fadeIn {
- from {
- opacity: 0;
- }
- to {
- opacity: 1;
- }
-}
-
-@keyframes slideIn {
- from {
- transform: translateY(-20px);
- opacity: 0;
- }
- to {
- transform: translateY(0);
- opacity: 1;
- }
-}
-
-@keyframes slideInModal {
- from {
- transform: translateY(-50px);
- opacity: 0;
- }
- to {
- transform: translateY(0);
- opacity: 1;
- }
-}
-
-/* ===============================================
- ESTILOS PARA EDICIÓN INLINE EN TABLA
- =============================================== */
-
-/* Contenedor de celda editable */
-.editable-cell {
- display: flex;
- align-items: center;
- gap: 8px;
- padding: 4px;
- min-height: 40px;
- position: relative;
-}
-
-/* Display de valor */
-.editable-cell .value-display {
- font-weight: 600;
- padding: 6px 8px;
- border-radius: 4px;
- transition: all 0.3s ease;
- cursor: default;
-}
-
-/* Input de edición */
-.editable-cell .value-input {
- padding: 6px 8px;
- border: 2px solid var(--primary-color);
- border-radius: 4px;
- font-size: 14px;
- font-weight: 600;
- width: 100px;
- background: white;
- color: var(--text-dark);
- transition: all 0.3s ease;
-}
-
-.editable-cell .value-input:focus {
- outline: none;
- border-color: var(--info-color);
- box-shadow: 0 0 0 3px rgba(33, 150, 243, 0.1);
- transform: scale(1.02);
-}
-
-/* Botón de editar */
-.editable-cell .btn-edit {
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
- color: white;
- border: none;
- padding: 6px 8px;
- border-radius: 15px;
- cursor: pointer;
- display: flex;
- align-items: center;
- justify-content: center;
- font-size: 0.8em;
- transition: all 0.3s ease;
- opacity: 0.7;
- min-width: 32px;
- height: 32px;
-}
-
-.editable-cell:hover .btn-edit {
- opacity: 1;
- transform: scale(1.1);
- box-shadow: 0 2px 8px rgba(102, 126, 234, 0.3);
-}
-
-.editable-cell .btn-edit .material-symbols-outlined {
- font-size: 16px;
-}
-
-/* Controles de edición */
-.editable-cell .edit-controls {
- display: flex;
- gap: 4px;
- align-items: center;
-}
-
-.editable-cell .btn-save,
-.editable-cell .btn-cancel {
- border: none;
- padding: 4px 6px;
- border-radius: 12px;
- cursor: pointer;
- display: flex;
- align-items: center;
- justify-content: center;
- font-size: 0.7em;
- transition: all 0.3s ease;
- min-width: 28px;
- height: 28px;
-}
-
-.editable-cell .btn-save {
- background: linear-gradient(135deg, #28a745 0%, #20c997 100%);
- color: white;
-}
-
-.editable-cell .btn-save:hover {
- transform: scale(1.1);
- box-shadow: 0 2px 8px rgba(40, 167, 69, 0.3);
-}
-
-.editable-cell .btn-cancel {
- background: linear-gradient(135deg, #dc3545 0%, #e74c3c 100%);
- color: white;
-}
-
-.editable-cell .btn-cancel:hover {
- transform: scale(1.1);
- box-shadow: 0 2px 8px rgba(220, 53, 69, 0.3);
-}
-
-.editable-cell .btn-save .material-symbols-outlined,
-.editable-cell .btn-cancel .material-symbols-outlined {
- font-size: 14px;
-}
-
-/* Estilos específicos para precio */
-.precio .editable-cell {
- justify-content: flex-start;
-}
-
-.precio .value-display {
- color: #28a745;
- font-size: 1.1em;
- background: rgba(40, 167, 69, 0.1);
- border: 1px solid rgba(40, 167, 69, 0.2);
-}
-
-/* Estilos específicos para stock */
-.stock .editable-cell {
- justify-content: flex-start;
-}
-
-.stock .value-display {
- color: #17a2b8;
- font-size: 1.1em;
- background: rgba(23, 162, 184, 0.1);
- border: 1px solid rgba(23, 162, 184, 0.2);
-}
-
-/* Efecto de carga */
-.editable-cell .loading {
- display: flex;
- align-items: center;
- gap: 8px;
- color: #007bff;
- font-weight: 600;
- padding: 6px 12px;
- background: rgba(0, 123, 255, 0.1);
- border-radius: 4px;
- border: 1px solid rgba(0, 123, 255, 0.2);
-}
-
-.editable-cell .loading .material-symbols-outlined {
- animation: spin 1s linear infinite;
-}
-
-@keyframes spin {
- from { transform: rotate(0deg); }
- to { transform: rotate(360deg); }
-}
-
-/* Efecto de éxito */
-.editable-cell .success-highlight {
- background: rgba(40, 167, 69, 0.2) !important;
- color: #155724 !important;
- border: 1px solid rgba(40, 167, 69, 0.4) !important;
- animation: successPulse 2s ease-in-out;
-}
-
-@keyframes successPulse {
- 0% { transform: scale(1); }
- 50% { transform: scale(1.05); }
- 100% { transform: scale(1); }
-}
-
-/* Responsive para dispositivos móviles */
-@media (max-width: 768px) {
- .editable-cell {
- flex-direction: column;
- align-items: flex-start;
- gap: 4px;
- min-height: auto;
- }
-
- .editable-cell .value-input {
- width: 80px;
- font-size: 12px;
- }
-
- .editable-cell .btn-edit,
- .editable-cell .btn-save,
- .editable-cell .btn-cancel {
- min-width: 24px;
- height: 24px;
- padding: 2px 4px;
- }
-
- .editable-cell .btn-edit .material-symbols-outlined,
- .editable-cell .btn-save .material-symbols-outlined,
- .editable-cell .btn-cancel .material-symbols-outlined {
- font-size: 12px;
- }
-}
-
-/* Tooltip para botones */
-.editable-cell [title] {
- position: relative;
-}
-
-.editable-cell [title]:hover::after {
- content: attr(title);
- position: absolute;
- bottom: 100%;
- left: 50%;
- transform: translateX(-50%);
- background: rgba(0, 0, 0, 0.8);
- color: white;
- padding: 4px 8px;
- border-radius: 4px;
- font-size: 12px;
- white-space: nowrap;
- z-index: 1000;
- margin-bottom: 4px;
-}
-
-.editable-cell [title]:hover::before {
- content: '';
- position: absolute;
- bottom: 100%;
- left: 50%;
- transform: translateX(-50%);
- border: 4px solid transparent;
- border-top-color: rgba(0, 0, 0, 0.8);
- z-index: 1000;
-}
diff --git a/files/styleregister.css b/files/styleregister.css
deleted file mode 100644
index 36eb72d..0000000
--- a/files/styleregister.css
+++ /dev/null
@@ -1,382 +0,0 @@
-@import url('https://fonts.googleapis.com/css2?family=Playfair+Display:wght@700&family=Lato:wght@400;700&family=Dancing+Script:wght@700&display=swap');
-
-:root {
- --primary-color: #8C5A37; /* Un marrón terracota, sofisticado y cálido */
- --primary-hover: #6E462A; /* Una versión más oscura para el hover */
- --text-dark: #3D2C21; /* Un marrón muy oscuro para texto principal */
- --text-light: #6B5B51; /* Un marrón más claro para texto secundario */
- --border-color: #D3C5BC; /* Un color suave para los bordes */
- --container-bg: rgba(255, 255, 255, 0.75); /* Fondo blanco semitransparente */
-}
-
-body {
- background-image: url(../files/img/pan-rtzqhi1ok4k1bxlo.jpg);
- background-repeat: no-repeat;
- background-size: cover;
- height: 100vh;
- margin: 0;
- display: flex;
- justify-content: center;
- align-items: center;
- font-family: 'Lato', sans-serif;
-}
-
-.registro-container {
- background: var(--container-bg);
- backdrop-filter: blur(10px);
- -webkit-backdrop-filter: blur(10px);
- padding: 40px;
- border-radius: 15px;
- box-shadow: 0 10px 30px rgba(0, 0, 0, 0.15);
- border: 1px solid rgba(255, 255, 255, 0.4);
- width: 90%;
- max-width: 900px;
- display: flex;
- align-items: flex-start;
- gap: 40px;
- text-align: left;
-}
-
-.registro-left {
- flex: 1;
- padding-right: 30px;
- border-right: 3px solid #8C5A37;
- min-height: 400px;
- display: flex;
- flex-direction: column;
- justify-content: center;
-}
-
-.registro-right {
- flex: 1.5;
- padding-left: 30px;
-}
-
-.logo-registro {
- margin-bottom: 20px;
- text-align: center;
-}
-
-.logo-img-registro {
- margin-top: 100px !important;
- width: 200px;
- height: 200px;
- object-fit: cover;
- border-radius: 50%;
- box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
- transition: all 0.3s ease;
- cursor: pointer;
- border: 3px solid var(--primary-color);
-}
-
-.logo-img-registro:hover {
- transform: scale(1.05);
- box-shadow: 0 8px 25px rgba(140, 90, 55, 0.4);
-}
-
-.titulo-registro {
- font-family: 'Exo 2';
- color: var(--primary-color);
- font-size: 4rem;
- font-weight: 700;
- text-align: center;
- text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.1);
-}
-
-.form-group-registro {
- margin-bottom: 20px;
- text-align: left;
-}
-
-.label-registro {
- display: block;
- margin-bottom: 8px;
- color: var(--text-light);
- font-weight: bold;
-}
-
-.input-registro {
- width: 100%;
- padding: 12px;
- border: 2px solid var(--border-color);
- background-color: rgba(255, 255, 255, 0.5);
- border-radius: 8px;
- font-size: 16px;
- color: var(--text-dark);
- transition: all 0.3s ease;
- box-sizing: border-box;
-}
-
-.input-registro:focus {
- outline: none;
- border-color: var(--primary-color);
- box-shadow: 0 0 10px rgba(140, 90, 55, 0.2);
-}
-
-.btn-registro {
- width: 100%;
- padding: 12px;
- background-color: var(--primary-color);
- color: white;
- border: none;
- border-radius: 8px;
- font-size: 16px;
- font-weight: bold;
- cursor: pointer;
- transition: all 0.2s ease;
-}
-
-.btn-registro:hover {
- background-color: var(--primary-hover);
- transform: translateY(-3px);
- box-shadow: 0 6px 20px rgba(140, 90, 55, 0.3);
-}
-
-.btn-registro:active {
- transform: translateY(0);
- box-shadow: 0 3px 10px rgba(140, 90, 55, 0.3);
-}
-
-.footer-links-registro {
- margin-top: 20px;
- padding-top: 20px;
- border-top: 1px solid var(--border-color);
-}
-
-.footer-links-registro a {
- color: var(--primary-color);
- text-decoration: none;
- font-size: 14px;
- font-weight: bold;
-}
-
-.footer-links-registro a:hover {
- text-decoration: underline;
- color: var(--text-dark);
-}
-
-.success-message-registro {
- background-color: #d4edda;
- border: 1px solid #c3e6cb;
- color: #155724;
- padding: 12px;
- border-radius: 8px;
- margin-bottom: 20px;
- font-family: 'Lato', sans-serif;
- font-size: 14px;
- text-align: center;
-}
-
-.error-message-registro {
- background-color: #f8d7da;
- border: 1px solid #f5c6cb;
- color: #721c24;
- padding: 12px;
- border-radius: 8px;
- margin-bottom: 20px;
- font-size: 14px;
- display: none;
-}
-
-.error-message-registro ul {
- list-style-type: none;
- padding: 0;
-}
-
-.error-message-registro li {
- margin: 5px 0;
- padding-left: 15px;
- position: relative;
-}
-
-.error-message-registro li:before {
- content: "•";
- color: #721c24;
- font-weight: bold;
- position: absolute;
- left: 0;
-}
-
-.user-type-info-registro {
- background-color: rgba(140, 90, 55, 0.1);
- border-left: 4px solid var(--primary-color);
- padding: 15px;
- margin-bottom: 20px;
- border-radius: 8px;
- text-align: left;
-}
-
-.user-type-info-registro h4 {
- color: var(--primary-color);
- margin-bottom: 10px;
- font-size: 16px;
- font-weight: bold;
-}
-
-.user-type-info-registro p {
- color: var(--text-light);
- font-size: 14px;
- margin: 5px 0;
- line-height: 1.4;
-}
-
-.loading-registro {
- text-align: center;
- padding: 20px 0;
- display: none;
-}
-
-.loading-registro p {
- margin-top: 10px;
- color: var(--text-light);
- font-size: 14px;
-}
-
-.loading-spinner-registro {
- border: 3px solid rgba(140, 90, 55, 0.2);
- border-top-color: var(--primary-color);
- border-radius: 50%;
- width: 30px;
- height: 30px;
- animation: spin-registro 1s linear infinite;
- margin: 0 auto;
-}
-
-/* Modal de registro exitoso */
-.modal-overlay {
- position: fixed;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- background-color: rgba(0, 0, 0, 0.6);
- display: flex;
- justify-content: center;
- align-items: center;
- z-index: 1000;
- backdrop-filter: blur(5px);
-}
-
-.modal-content {
- background: var(--container-bg);
- backdrop-filter: blur(15px);
- -webkit-backdrop-filter: blur(15px);
- border-radius: 20px;
- padding: 40px;
- box-shadow: 0 15px 35px rgba(0, 0, 0, 0.2);
- border: 1px solid rgba(255, 255, 255, 0.4);
- text-align: center;
- max-width: 400px;
- width: 90%;
- animation: modalAppear 0.3s ease-out;
-}
-
-.modal-header {
- margin-bottom: 25px;
-}
-
-.check-icon {
- margin-bottom: 20px;
- animation: bounceIn 0.6s ease-out;
-}
-
-.modal-header h2 {
- font-family: 'Dancing Script', cursive;
- color: var(--primary-color);
- font-size: 2.2rem;
- margin: 0;
- font-weight: 700;
-}
-
-.modal-body {
- margin-bottom: 30px;
-}
-
-.modal-body p {
- color: var(--text-dark);
- font-size: 16px;
- margin: 10px 0;
- line-height: 1.5;
-}
-
-.btn-modal {
- background-color: var(--primary-color);
- color: white;
- border: none;
- padding: 12px 30px;
- border-radius: 8px;
- font-size: 16px;
- font-weight: bold;
- cursor: pointer;
- transition: all 0.3s ease;
-}
-
-.btn-modal:hover {
- background-color: var(--primary-hover);
- transform: translateY(-2px);
- box-shadow: 0 6px 20px rgba(140, 90, 55, 0.3);
-}
-
-@keyframes modalAppear {
- from {
- opacity: 0;
- transform: scale(0.8) translateY(-20px);
- }
- to {
- opacity: 1;
- transform: scale(1) translateY(0);
- }
-}
-
-@keyframes bounceIn {
- 0% {
- transform: scale(0);
- }
- 50% {
- transform: scale(1.2);
- }
- 100% {
- transform: scale(1);
- }
-}
-
-@media (max-width: 768px) {
- .registro-container {
- flex-direction: column;
- padding: 30px 20px;
- margin: 20px;
- max-width: 90%;
- gap: 20px;
- }
-
- .registro-left {
- border-right: none;
- border-bottom: 3px solid #8C5A37;
- padding-right: 0;
- padding-bottom: 20px;
- min-height: auto;
- }
-
- .registro-right {
- padding-left: 0;
- padding-top: 20px;
- }
-
- .titulo-registro {
- font-size: 2rem;
- }
-
- .logo-img-registro {
- margin-top: 50px !important;
- width: 100px;
- height: 100px;
- }
-
- .form-group-registro {
- margin-bottom: 18px;
- }
-
- .user-type-info-registro {
- padding: 12px;
- }
-}
\ No newline at end of file
diff --git a/files/styles-index.css b/files/styles-index.css
deleted file mode 100644
index 4708d3a..0000000
--- a/files/styles-index.css
+++ /dev/null
@@ -1,367 +0,0 @@
-/* Variables de colores personalizadas */
-:root {
- --color-crema: #f5f5dc;
- --color-marron: #8b4513;
- --color-gris-oscuro: #2c3e50;
- --color-cafe-claro: #d2b48c;
- --color-cafe-con-leche: #ddbea9;
- --color-blanco-calido: #fffef7;
- --color-dorado: #ffd700;
- --color-overlay: rgba(139, 69, 19, 0.8);
-}
-
-/* Clases de colores de fondo */
-.bg-crema { background-color: var(--color-crema) !important; }
-.bg-blanco-calido { background-color: var(--color-blanco-calido) !important; }
-
-/* Clases de colores de texto */
-.text-marron { color: var(--color-marron) !important; }
-.text-gris-oscuro { color: var(--color-gris-oscuro) !important; }
-.text-cafe-claro { color: var(--color-cafe-claro) !important; }
-.text-cafe-con-leche { color: var(--color-cafe-con-leche) !important; }
-.text-crema { color: var(--color-crema) !important; }
-
-/* Clases de borde */
-.border-marron { border-color: var(--color-marron) !important; }
-
-/* Estilos generales */
-body {
- font-family: 'Quicksand', sans-serif;
- line-height: 1.6;
- overflow-x: hidden;
-}
-
-/* Navbar personalizada */
-.navbar {
- transition: all 0.3s ease;
- backdrop-filter: blur(10px);
-}
-
-.logo {
- transition: transform 0.3s ease;
-}
-
-.logo:hover {
- transform: scale(1.05);
-}
-
-/* Botón personalizado */
-.btn-primary {
- background: linear-gradient(135deg, var(--color-marron), #a0522d);
- border: none;
- border-radius: 25px;
- padding: 8px 20px;
- transition: all 0.3s ease;
- box-shadow: 0 4px 15px rgba(139, 69, 19, 0.3);
-}
-
-.btn-primary:hover {
- background: linear-gradient(135deg, #a0522d, var(--color-marron));
- transform: translateY(-2px);
- box-shadow: 0 6px 20px rgba(139, 69, 19, 0.4);
-}
-
-.btn-rounded {
- border-radius: 25px;
-}
-
-/* Carrusel de borde a borde */
-.carousel-fullwidth {
- width: 100vw;
- position: relative;
- left: 50%;
- right: 50%;
- margin-left: -50vw;
- margin-right: -50vw;
-}
-
-.carousel-fixed-img {
- height: 450px;
- object-fit: cover;
- object-position: center;
- width: 100%;
-}
-
-.carousel-item {
- position: relative;
- overflow: hidden;
-}
-
-.carousel-link {
- display: block;
- position: relative;
- text-decoration: none;
- color: inherit;
-}
-
-.carousel-link::before {
- content: '';
- position: absolute;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- background: linear-gradient(45deg, transparent, rgba(139, 69, 19, 0.1));
- opacity: 0;
- transition: opacity 0.3s ease;
- z-index: 1;
-}
-
-.carousel-link:hover::before {
- opacity: 1;
-}
-
-.carousel-caption {
- background: rgba(0, 0, 0, 0.6);
- border-radius: 10px;
- padding: 15px;
- backdrop-filter: blur(10px);
- bottom: 20px;
-}
-
-.carousel-control-prev,
-.carousel-control-next {
- width: 50px;
- height: 50px;
- top: 50%;
- transform: translateY(-50%);
- background: rgba(139, 69, 19, 0.8);
- border-radius: 50%;
- transition: all 0.3s ease;
-}
-
-.carousel-control-prev {
- left: 15px;
-}
-
-.carousel-control-next {
- right: 15px;
-}
-
-.carousel-control-prev:hover,
-.carousel-control-next:hover {
- background: rgba(139, 69, 19, 0.9);
- transform: translateY(-50%) scale(1.1);
-}
-
-/* Cards optimizadas */
-.card {
- border: none;
- transition: all 0.3s ease;
- position: relative;
- overflow: hidden;
- cursor: pointer;
- background: white;
-}
-
-.card::before {
- content: '';
- position: absolute;
- top: 0;
- left: -100%;
- width: 100%;
- height: 100%;
- background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.4), transparent);
- transition: left 0.6s ease;
- z-index: 2;
-}
-
-.card:hover::before {
- left: 100%;
-}
-
-.card:hover {
- transform: translateY(-10px);
- box-shadow: 0 15px 35px rgba(0, 0, 0, 0.2);
-}
-
-.card-img-custom {
- height: 250px;
- object-fit: cover;
- object-position: center;
- transition: transform 0.3s ease;
-}
-
-.card:hover .card-img-custom {
- transform: scale(1.05);
-}
-
-/* Overlay de información en cards */
-.card-overlay {
- position: absolute;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- background: var(--color-overlay);
- color: white;
- display: flex;
- flex-direction: column;
- justify-content: center;
- align-items: center;
- opacity: 0;
- transition: opacity 0.3s ease;
- z-index: 3;
- padding: 20px;
- text-align: center;
-}
-
-.card:hover .card-overlay {
- opacity: 1;
-}
-
-.card-overlay h5 {
- margin-bottom: 15px;
- font-weight: bold;
- font-size: 1.4rem;
-}
-
-.card-overlay p {
- font-size: 0.95rem;
- line-height: 1.4;
-}
-
-/* Títulos con efecto */
-h2 {
- position: relative;
-}
-
-h2::after {
- content: '';
- position: absolute;
- bottom: -10px;
- left: 50%;
- transform: translateX(-50%);
- width: 80px;
- height: 3px;
- background: linear-gradient(90deg, var(--color-marron), var(--color-dorado));
- border-radius: 2px;
-}
-
-/* Navegación mejorada */
-.nav-link {
- position: relative;
- transition: color 0.3s ease;
-}
-
-.nav-link::after {
- content: '';
- position: absolute;
- bottom: -5px;
- left: 0;
- width: 0;
- height: 2px;
- background: var(--color-marron);
- transition: width 0.3s ease;
-}
-
-.nav-link:hover::after {
- width: 100%;
-}
-
-/* Footer mejorado */
-footer {
- background: linear-gradient(135deg, #2c3e50, #34495e) !important;
- position: relative;
- overflow: hidden;
-}
-
-footer::before {
- content: '';
- position: absolute;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
- background: url('data:image/svg+xml,');
- background-size: 50px 50px;
- animation: float 20s infinite linear;
-}
-
-/* Iconos sociales */
-.social-icon-hover {
- transition: all 0.3s ease;
- display: inline-block;
-}
-
-.social-icon-hover:hover {
- color: var(--color-dorado) !important;
- transform: translateY(-3px);
-}
-
-/* Sombras optimizadas */
-.shadow-sm {
- box-shadow: 0 2px 15px rgba(0, 0, 0, 0.1) !important;
-}
-
-.shadow {
- box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15) !important;
-}
-
-/* Animaciones */
-@keyframes float {
- 0% { transform: translateY(0px); }
- 100% { transform: translateY(-100px); }
-}
-
-/* Clases de delay optimizadas */
-.animate__delay-1s { animation-delay: 0.2s; }
-.animate__delay-2s { animation-delay: 0.4s; }
-.animate__delay-3s { animation-delay: 0.6s; }
-.animate__delay-4s { animation-delay: 0.8s; }
-.animate__delay-5s { animation-delay: 1s; }
-
-/* Responsive optimizado */
-@media (max-width: 768px) {
- .carousel-fixed-img {
- height: 300px;
- }
-
- .card-img-custom {
- height: 200px;
- }
-
- h2::after {
- width: 60px;
- }
-
- .carousel-control-prev,
- .carousel-control-next {
- width: 40px;
- height: 40px;
- }
-
- .carousel-caption {
- padding: 10px;
- bottom: 10px;
- }
-
- .carousel-caption h5 {
- font-size: 1rem;
- margin-bottom: 5px;
- }
-}
-
-@media (max-width: 576px) {
- .carousel-small-img {
- height: 200px;
- }
-
- .card-img-custom {
- height: 180px;
- }
-
- .carousel-control-prev,
- .carousel-control-next {
- width: 35px;
- height: 35px;
- }
-
- .carousel-control-prev {
- left: 10px;
- }
-
- .carousel-control-next {
- right: 10px;
- }
-}
diff --git a/files/styleslogin.css b/files/styleslogin.css
deleted file mode 100644
index c58c60a..0000000
--- a/files/styleslogin.css
+++ /dev/null
@@ -1,218 +0,0 @@
-@import url('https://fonts.googleapis.com/css2?family=Playfair+Display:wght@700&family=Lato:wght@400;700&display=swap');
-:root {
- --primary-color: #8C5A37; /* Un marrón terracota, sofisticado y cálido */
- --primary-hover: #6E462A; /* Una versión más oscura para el hover */
- --text-dark: #3D2C21; /* Un marrón muy oscuro para texto principal */
- --text-light: #6B5B51; /* Un marrón más claro para texto secundario */
- --border-color: #D3C5BC; /* Un color suave para los bordes */
- --container-bg: rgba(255, 255, 255, 0.75); /* Fondo blanco semitransparente */
-}
-
-body {
- background-image: url(../files/img/pan-rtzqhi1ok4k1bxlo.jpg);
- background-repeat: no-repeat;
- background-size: cover;
- height: 100vh;
- margin: 0;
- display: flex;
- justify-content: center;
- align-items: center;
- font-family: 'Lato', sans-serif;
-}
-.logo-img {
- width: 80px;
- height: 80px;
- border-radius: 50%;
- box-shadow: 0 8px 25px rgba(140, 90, 55, 0.4);
- object-fit: cover;
- border: 3px solid var(--primary-color);
- animation: bounce 2s infinite;
- transition: all 0.3s ease;
-}
-
-.logo-img:hover {
- transform: scale(1.05);
- box-shadow: 0 12px 35px rgba(140, 90, 55, 0.5);
-}
-
-.login-container {
- background: var(--container-bg);
- backdrop-filter: blur(10px);
- -webkit-backdrop-filter: blur(10px);
- padding: 40px;
- border-radius: 50px;
- box-shadow: 0 10px 30px rgba(0, 0, 0, 0.15);
- border: 1px solid rgba(255, 255, 255, 0.4);
- width: 100%;
- max-width: 400px;
- text-align: center;
-}
-.logo {
- font-size: 48px;
- margin-bottom: 10px;
- color: var(--primary-color);
-}
-
-/* Contenedor específico para el logo con imagen */
-.logo.animated-logo {
- display: flex;
- justify-content: center;
- align-items: center;
- margin: 0 auto 20px auto;
- animation: bounce 2s infinite;
- padding: 10px;
- background: rgba(255, 255, 255, 0.2);
- border-radius: 40%;
- backdrop-filter: blur(5px);
- width: 120px;
- height: 120px;
- box-shadow: 0 10px 30px rgba(140, 90, 55, 0.3);
- font-size: initial;
-}
-
-.logo.animated-logo img {
- border: 3px solid var(--primary-color);
- box-shadow: 0 4px 15px rgba(140, 90, 55, 0.3);
- border-radius: 50%;
-}
-
-h1 {
- font-family: 'Playfair Display', serif;
- color: var(--text-dark);
- margin-bottom: 30px;
- font-size: 28px;
-}
-
-.form-group {
- margin-bottom: 20px;
- text-align: left;
-}
-
-label {
- display: block;
- margin-bottom: 8px;
- color: var(--text-light);
- font-weight: bold;
-}
-
-input[type="text"], input[type="password"], input[type="email"], select {
- width: 100%;
- padding: 12px;
- border: 2px solid var(--border-color);
- background-color: rgba(255, 255, 255, 0.5);
- border-radius: 8px;
- font-size: 16px;
- color: var(--text-dark);
- transition: all 0.3s ease;
- box-sizing: border-box;
-}
-
-input[type="text"]:focus, input[type="password"]:focus, input[type="email"]:focus, select:focus {
- outline: none;
- border-color: var(--primary-color);
- box-shadow: 0 0 10px rgba(140, 90, 55, 0.2);
-}
-
-.btn {
- width: 100%;
- padding: 12px;
- background-color: var(--primary-color);
- color: white;
- border: none;
- border-radius: 8px;
- font-size: 16px;
- font-weight: bold;
- cursor: pointer;
- transition: all 0.2s ease;
-}
-
-.btn:hover {
- background-color: var(--primary-hover);
- transform: translateY(-3px);
- box-shadow: 0 6px 20px rgba(140, 90, 55, 0.3);
-}
-
-.btn:active {
- transform: translateY(0);
- box-shadow: 0 3px 10px rgba(140, 90, 55, 0.3);
-}
-
-.footer-links {
- margin-top: 20px;
- padding-top: 20px;
- border-top: 1px solid var(--border-color);
-}
-
-/* Estilo para enlace de registro - más notorio */
-.signup-link {
- text-align: left;
- margin-top: 25px;
- padding: 15px 20px;
- background: rgba(140, 90, 55, 0.2) !important;
- border-radius: 10px;
- border-left: 4px solid var(--primary-color);
- backdrop-filter: blur(5px);
- box-shadow: 0 4px 15px rgba(140, 90, 55, 0.15);
- transition: all 0.3s ease;
-}
-
-.signup-link:hover {
- background: rgba(140, 90, 55, 0.3) !important;
- transform: translateX(5px);
- box-shadow: 0 6px 20px rgba(140, 90, 55, 0.2);
-}
-
-.signup-link a {
- color: var(--primary-color) !important;
- font-size: 15px;
- font-weight: bold;
- text-decoration: none;
- display: block;
-}
-
-.signup-link a:hover {
- text-decoration: underline;
- color: var(--text-dark);
-}
-
-.footer-links a {
- color: var(--primary-color);
- text-decoration: none;
- font-size: 14px;
- font-weight: bold;
-}
-
-.footer-links a:hover {
- text-decoration: underline;
- color: var(--text-dark);
-}
-
-.loading-spinner {
- border: 3px solid rgba(140, 90, 55, 0.2);
- border-top-color: var(--primary-color);
- border-radius: 50%;
- width: 30px;
- height: 30px;
- animation: spin 1s linear infinite;
- margin: 0 auto;
-}
-
-@keyframes spin {
- 0% { transform: rotate(0deg); }
- 100% { transform: rotate(360deg); }
-}
-
-@keyframes bounce {
-0%, 100% {
- transform: translateY(0);
-}
- 50% {
- transform: translateY(-10px);
- }
-}
-.success-message{
- font-family: 'Exo 2', sans-serif;
- color: var(--text-dark);
- margin-bottom: 30px;
- font-size: 16px;
-}
\ No newline at end of file
diff --git a/files/test_database.php b/files/test_database.php
deleted file mode 100644
index d0832fb..0000000
--- a/files/test_database.php
+++ /dev/null
@@ -1,84 +0,0 @@
-query("SHOW TABLES LIKE 'Pedidos'");
- $tests['pedidos_table_exists'] = $result && $result->num_rows > 0;
-
- // Test 2: Check if Estado_Pedidos table exists
- $result = $conexion->query("SHOW TABLES LIKE 'Estado_Pedidos'");
- $tests['estado_pedidos_table_exists'] = $result && $result->num_rows > 0;
-
- // Test 3: Check if Productos table exists
- $result = $conexion->query("SHOW TABLES LIKE 'Productos'");
- $tests['productos_table_exists'] = $result && $result->num_rows > 0;
-
- // Test 4: Check if Usuario table exists
- $result = $conexion->query("SHOW TABLES LIKE 'Usuario'");
- $tests['usuario_table_exists'] = $result && $result->num_rows > 0;
-
- // Test 5: Check Pedidos structure
- if ($tests['pedidos_table_exists']) {
- $result = $conexion->query("DESCRIBE Pedidos");
- $pedidos_columns = [];
- while ($row = $result->fetch_assoc()) {
- $pedidos_columns[] = $row['Field'];
- }
- $tests['pedidos_columns'] = $pedidos_columns;
- }
-
- // Test 6: Check Productos structure
- if ($tests['productos_table_exists']) {
- $result = $conexion->query("DESCRIBE Productos");
- $productos_columns = [];
- while ($row = $result->fetch_assoc()) {
- $productos_columns[] = $row['Field'];
- }
- $tests['productos_columns'] = $productos_columns;
- }
-
- // Test 7: Count records
- if ($tests['pedidos_table_exists']) {
- $result = $conexion->query("SELECT COUNT(*) as count FROM Pedidos");
- $row = $result->fetch_assoc();
- $tests['pedidos_count'] = $row['count'];
- }
-
- if ($tests['productos_table_exists']) {
- $result = $conexion->query("SELECT COUNT(*) as count FROM Productos");
- $row = $result->fetch_assoc();
- $tests['productos_count'] = $row['count'];
- }
-
- echo json_encode([
- 'success' => true,
- 'tests' => $tests,
- 'session_info' => [
- 'usuario_logueado' => $_SESSION['usuario_logueado'] ?? 'not_set',
- 'usuario_tipo' => $_SESSION['usuario_tipo'] ?? 'not_set',
- 'usuario_id' => $_SESSION['usuario_id'] ?? 'not_set'
- ]
- ]);
-
-} catch (Exception $e) {
- echo json_encode([
- 'success' => false,
- 'error' => $e->getMessage(),
- 'file' => $e->getFile(),
- 'line' => $e->getLine()
- ]);
-}
-?>
diff --git a/files/test_detalle_pedido.php b/files/test_detalle_pedido.php
deleted file mode 100644
index 96a299f..0000000
--- a/files/test_detalle_pedido.php
+++ /dev/null
@@ -1,112 +0,0 @@
-Test Detalle de Pedido";
-
-try {
- // Verificar conexión
- if (!$conexion) {
- throw new Exception("No se pudo conectar a la base de datos");
- }
-
- echo "✅ Conexión a BD exitosa
";
-
- // Verificar estructura de tablas
- echo "📋 Estructura de tablas:
";
-
- // Verificar tabla Detalle_Pedidos
- $result = $conexion->query("DESCRIBE Detalle_Pedidos");
- if ($result) {
- echo "Tabla Detalle_Pedidos:
";
- while ($row = $result->fetch_assoc()) {
- echo "- {$row['Field']} ({$row['Type']})
";
- }
- }
-
- echo "
";
-
- // Verificar tabla Productos
- $result = $conexion->query("DESCRIBE Productos");
- if ($result) {
- echo "Tabla Productos:
";
- while ($row = $result->fetch_assoc()) {
- echo "- {$row['Field']} ({$row['Type']})
";
- }
- }
-
- echo "
";
-
- // Buscar un pedido existente
- $pedidos = $conexion->query("SELECT ID_PEDIDO FROM Pedidos LIMIT 5");
- if ($pedidos && $pedidos->num_rows > 0) {
- echo "🔍 Pedidos disponibles:
";
- while ($pedido = $pedidos->fetch_assoc()) {
- echo "- Pedido ID: {$pedido['ID_PEDIDO']}
";
- }
-
- // Tomar el primer pedido para test
- $pedidos->data_seek(0);
- $primer_pedido = $pedidos->fetch_assoc();
- $test_pedido_id = $primer_pedido['ID_PEDIDO'];
-
- echo "
🧪 Probando detalle del pedido #{$test_pedido_id}:
";
-
- // Simular la llamada AJAX
- $_POST['pedido_id'] = $test_pedido_id;
- $input_data = json_encode(['pedido_id' => $test_pedido_id]);
-
- // Incluir el archivo AJAX directamente
- ob_start();
-
- // Simulamos la entrada JSON
- file_put_contents('php://temp', $input_data);
-
- // Llamamos al endpoint
- include 'obtener_detalle_pedido_ajax.php';
-
- $output = ob_get_clean();
-
- echo "Respuesta del endpoint:
";
- echo "" . htmlspecialchars($output) . "
";
-
- // Intentar parsear como JSON
- $data = json_decode($output, true);
- if ($data) {
- echo "Datos parseados:
";
- echo "- Success: " . ($data['success'] ? 'true' : 'false') . "
";
- if ($data['success']) {
- echo "- Pedido ID: " . $data['pedido']['id'] . "
";
- echo "- Cliente: " . $data['pedido']['cliente'] . "
";
- echo "- Total: $" . number_format($data['pedido']['total']) . "
";
- echo "- Productos: " . count($data['productos']) . "
";
-
- if (!empty($data['productos'])) {
- echo "
Productos del pedido:
";
- foreach ($data['productos'] as $producto) {
- echo " - {$producto['nombre']} (Cantidad: {$producto['cantidad']}, Precio: $" . number_format($producto['precio_unitario']) . ")
";
- }
- }
- } else {
- echo "- Error: " . ($data['mensaje'] ?? 'No especificado') . "
";
- }
- }
-
- } else {
- echo "❌ No se encontraron pedidos en la base de datos
";
- }
-
-} catch (Exception $e) {
- echo "❌ Error: " . htmlspecialchars($e->getMessage()) . "
";
-}
-
-echo "
";
-echo "← Volver al Dashboard";
-?>
diff --git a/files/test_detalle_pedido_correccion.php b/files/test_detalle_pedido_correccion.php
deleted file mode 100644
index cdcffe8..0000000
--- a/files/test_detalle_pedido_correccion.php
+++ /dev/null
@@ -1,134 +0,0 @@
-🔧 Test de Corrección - Detalle de Pedidos";
-echo "Verificando que las consultas funcionen correctamente después de las correcciones.
";
-
-try {
- // Verificar la estructura de la tabla Detalle_Pedidos
- echo "📋 Estructura de Detalle_Pedidos:
";
- $result = $conexion->query("SHOW COLUMNS FROM Detalle_Pedidos");
- if ($result) {
- echo "";
- while ($row = $result->fetch_assoc()) {
- echo "- {$row['Field']} - {$row['Type']}
";
- }
- echo "
";
- }
-
- // Probar la consulta corregida para el dashboard de empleado
- echo "🔍 Test Query Dashboard Empleado (AJAX):
";
- $pedido_id = 1; // Usar el primer pedido como prueba
-
- // Verificar si la columna DESCRIPCION_PRODUCTO existe
- $check_descripcion = $conexion->query("SHOW COLUMNS FROM Productos LIKE 'DESCRIPCION_PRODUCTO'");
- $has_descripcion = $check_descripcion && $check_descripcion->num_rows > 0;
-
- $descripcion_field = $has_descripcion ?
- "COALESCE(prod.DESCRIPCION_PRODUCTO, prod.TIPO_PRODUCTO_MARCA, '') as producto_descripcion" :
- "COALESCE(prod.TIPO_PRODUCTO_MARCA, '') as producto_descripcion";
-
- $stmt = $conexion->prepare("
- SELECT
- dp.ID_DETALLE,
- dp.CANTIDAD_PRODUCTO,
- dp.PRECIO_UNITARIO,
- dp.SUBTOTAL,
- COALESCE(prod.NOMBRE_PRODUCTO, 'Producto eliminado') as producto_nombre,
- $descripcion_field,
- COALESCE(cat.NOMBRE_CATEGORIAPRODUCTO, 'Sin categoría') as categoria_nombre,
- prod.ID_PRODUCTO as producto_id
- FROM Detalle_Pedidos dp
- LEFT JOIN Productos prod ON dp.ID_PRODUCTO = prod.ID_PRODUCTO
- LEFT JOIN Categoria_Productos cat ON prod.ID_CATEGORIA_PRODUCTO = cat.ID_CATEGORIA_PRODUCTO
- WHERE dp.ID_PEDIDO = ?
- ORDER BY dp.ID_DETALLE
- ");
-
- if ($stmt) {
- $stmt->bind_param("i", $pedido_id);
- $stmt->execute();
- $result = $stmt->get_result();
-
- echo "✅ Query ejecutada exitosamente para pedido #$pedido_id
";
- echo "";
- echo "| ID_DETALLE | PRODUCTO_ID | NOMBRE | CANTIDAD | PRECIO | SUBTOTAL |
";
-
- while ($row = $result->fetch_assoc()) {
- echo "";
- echo "| {$row['ID_DETALLE']} | ";
- echo "#{$row['producto_id']} | ";
- echo "{$row['producto_nombre']} | ";
- echo "{$row['CANTIDAD_PRODUCTO']} | ";
- echo "\${$row['PRECIO_UNITARIO']} | ";
- echo "\${$row['SUBTOTAL']} | ";
- echo "
";
- }
- echo "
";
- } else {
- echo "❌ Error preparando query: " . $conexion->error . "
";
- }
-
- // Probar la consulta corregida para el dashboard de admin
- echo "🔍 Test Query Dashboard Admin:
";
- $query_detalles = "SELECT dp.*, pr.ID_PRODUCTO as producto_id, pr.NOMBRE_PRODUCTO as producto_nombre,
- COALESCE(pr.DESCRIPCION_PRODUCTO, pr.TIPO_PRODUCTO_MARCA, '') as producto_descripcion,
- cp.NOMBRE_CATEGORIAPRODUCTO as categoria_nombre
- FROM Detalle_Pedidos dp
- JOIN Productos pr ON dp.ID_PRODUCTO = pr.ID_PRODUCTO
- LEFT JOIN Categoria_Productos cp ON pr.ID_CATEGORIA_PRODUCTO = cp.ID_CATEGORIA_PRODUCTO
- WHERE dp.ID_PEDIDO = ?
- ORDER BY dp.ID_DETALLE";
-
- $stmt_admin = $conexion->prepare($query_detalles);
- if ($stmt_admin) {
- $stmt_admin->bind_param("i", $pedido_id);
- $stmt_admin->execute();
- $result_admin = $stmt_admin->get_result();
-
- echo "✅ Query de admin ejecutada exitosamente para pedido #$pedido_id
";
- echo "";
- echo "| ID_DETALLE | PRODUCTO_ID | NOMBRE | DESCRIPCIÓN | CATEGORÍA | CANTIDAD |
";
-
- while ($row = $result_admin->fetch_assoc()) {
- echo "";
- echo "| {$row['ID_DETALLE']} | ";
- echo "#{$row['producto_id']} | ";
- echo "{$row['producto_nombre']} | ";
- echo "" . substr($row['producto_descripcion'], 0, 50) . "... | ";
- echo "{$row['categoria_nombre']} | ";
- echo "{$row['CANTIDAD_PRODUCTO']} | ";
- echo "
";
- }
- echo "
";
- } else {
- echo "❌ Error preparando query de admin: " . $conexion->error . "
";
- }
-
- echo "🎯 Resumen de Correcciones:
";
- echo "";
- echo "- ✅ Corregido error 'dp.ID_DETALLE_PEDIDO' → 'dp.ID_DETALLE'
";
- echo "- ✅ Agregada columna de ID de producto en ambos dashboards
";
- echo "- ✅ Eliminada columna de imagen en dashboard admin
";
- echo "- ✅ Agregado soporte para descripción de productos
";
- echo "- ✅ Agregada columna de categoría
";
- echo "- ✅ Estructura consistente entre empleado y admin
";
- echo "
";
-
-} catch (Exception $e) {
- echo "❌ Error en el test: " . $e->getMessage() . "
";
-}
-?>
-
-
diff --git a/files/test_endpoints.php b/files/test_endpoints.php
deleted file mode 100644
index c5af2b3..0000000
--- a/files/test_endpoints.php
+++ /dev/null
@@ -1,69 +0,0 @@
-Prueba de Endpoints de Ingredientes\n";
-echo "1. Prueba de Categorías de Ingredientes:
\n";
-
-// Probar endpoint de categorías
-$url_categorias = 'http://localhost/proyectopanaderia/files/obtener_categorias_ingredientes_ajax.php';
-$context = stream_context_create([
- 'http' => [
- 'method' => 'GET',
- 'header' => [
- 'Content-Type: application/json',
- 'X-Requested-With: XMLHttpRequest',
- 'Cookie: ' . session_name() . '=' . session_id()
- ]
- ]
-]);
-
-$response_categorias = file_get_contents($url_categorias, false, $context);
-echo "" . htmlspecialchars($response_categorias) . "
\n";
-
-echo "2. Prueba de Proveedores:
\n";
-
-// Probar endpoint de proveedores
-$url_proveedores = 'http://localhost/proyectopanaderia/files/obtener_proveedores_ajax.php';
-$response_proveedores = file_get_contents($url_proveedores, false, $context);
-echo "" . htmlspecialchars($response_proveedores) . "
\n";
-
-// Verificar datos en base de datos directamente
-echo "3. Verificación directa en Base de Datos:
\n";
-
-require_once 'conexion.php';
-
-echo "Categorías en BD:
\n";
-$consulta_cat = "SELECT * FROM Categoria_Ingredientes ORDER BY NOMBRE_CATEGORIA_INGREDIENTE";
-$resultado_cat = $conexion->query($consulta_cat);
-if ($resultado_cat) {
- echo "\n";
- while ($fila = $resultado_cat->fetch_assoc()) {
- echo "- ID: {$fila['ID_CATEGORIA']} - {$fila['NOMBRE_CATEGORIA_INGREDIENTE']}
\n";
- }
- echo "
\n";
-} else {
- echo "Error: " . $conexion->error . "\n";
-}
-
-echo "Proveedores en BD:
\n";
-$consulta_prov = "SELECT * FROM Proveedores ORDER BY NOMBRE_PROV";
-$resultado_prov = $conexion->query($consulta_prov);
-if ($resultado_prov) {
- echo "\n";
- while ($fila = $resultado_prov->fetch_assoc()) {
- $activo = $fila['ACTIVO_PROV'] ? 'Activo' : 'Inactivo';
- echo "- ID: {$fila['ID_PROVEEDOR']} - {$fila['NOMBRE_PROV']} ({$activo})
\n";
- }
- echo "
\n";
-} else {
- echo "Error: " . $conexion->error . "\n";
-}
-
-$conexion->close();
-?>
diff --git a/files/test_ingredientes_funcionalidad.php b/files/test_ingredientes_funcionalidad.php
deleted file mode 100644
index e69de29..0000000
diff --git a/files/test_pedidos_simple.php b/files/test_pedidos_simple.php
deleted file mode 100644
index dccc60b..0000000
--- a/files/test_pedidos_simple.php
+++ /dev/null
@@ -1,63 +0,0 @@
-query($query);
-
- if ($result) {
- $count = $result->fetch_assoc()['count'];
-
- // Get a few sample records
- $sample_query = "
- SELECT
- ID_PEDIDO as id,
- FECHA_INGRESO as fecha_ingreso,
- FECHA_ENTREGA as fecha_entrega,
- TOTAL_PRODUCTO as total,
- ID_ESTADO_PEDIDO as estado
- FROM Pedidos
- ORDER BY ID_PEDIDO DESC
- LIMIT 5
- ";
-
- $sample_result = $conexion->query($sample_query);
- $samples = [];
-
- if ($sample_result) {
- while ($row = $sample_result->fetch_assoc()) {
- $samples[] = [
- 'id' => (int)$row['id'],
- 'cliente' => 'Cliente Test',
- 'empleado' => 'Empleado Test',
- 'fecha_ingreso' => $row['fecha_ingreso'],
- 'fecha_entrega' => $row['fecha_entrega'],
- 'total' => (float)$row['total'],
- 'estado' => (int)$row['estado'],
- 'estado_nombre' => 'Estado ' . $row['estado']
- ];
- }
- }
-
- echo json_encode([
- 'success' => true,
- 'total_pedidos' => $count,
- 'pedidos' => $samples,
- 'total' => count($samples)
- ]);
- } else {
- throw new Exception("Error en consulta: " . $conexion->error);
- }
-
-} catch (Exception $e) {
- echo json_encode([
- 'success' => false,
- 'mensaje' => $e->getMessage()
- ]);
-}
-?>
diff --git a/files/toggle_estado_cliente.php b/files/toggle_estado_cliente.php
deleted file mode 100644
index 554c83d..0000000
--- a/files/toggle_estado_cliente.php
+++ /dev/null
@@ -1,119 +0,0 @@
- false, 'mensaje' => 'Acceso no autorizado']);
- exit();
-}
-
-// Headers de respuesta JSON
-header('Content-Type: application/json');
-
-// Verificar método POST
-if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
- echo json_encode(['success' => false, 'mensaje' => 'Método no permitido']);
- exit();
-}
-
-try {
- // Conexión PDO
- $dsn = "mysql:host=localhost;dbname=proyectopanaderia;charset=utf8";
- $username = "root";
- $password = "";
-
- $pdo_conexion = new PDO($dsn, $username, $password);
- $pdo_conexion->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
-
- // Obtener datos JSON del cuerpo de la petición
- $raw_input = file_get_contents('php://input');
- error_log("Raw input recibido para cliente: " . $raw_input);
-
- $input = json_decode($raw_input, true);
-
- if (json_last_error() !== JSON_ERROR_NONE) {
- throw new Exception('Error al decodificar JSON: ' . json_last_error_msg());
- }
-
- if (!$input) {
- throw new Exception('Datos JSON inválidos o vacíos');
- }
-
- // Debug: Log de los datos recibidos
- error_log("Datos decodificados para cliente: " . print_r($input, true));
-
- // Validar que se recibieron los campos necesarios
- if (!isset($input['id'])) {
- throw new Exception('Campo "id" faltante en los datos JSON');
- }
-
- if (!isset($input['estado'])) {
- throw new Exception('Campo "estado" faltante en los datos JSON');
- }
-
- // Convertir y validar los datos
- $cliente_id = filter_var($input['id'], FILTER_VALIDATE_INT);
- $nuevo_estado = filter_var($input['estado'], FILTER_VALIDATE_INT);
-
- // Validaciones estrictas
- if ($cliente_id === false || $cliente_id <= 0) {
- throw new Exception('ID de cliente inválido: ' . json_encode($input['id']));
- }
-
- if ($nuevo_estado === false || !in_array($nuevo_estado, [0, 1], true)) {
- throw new Exception('Estado inválido: ' . json_encode($input['estado']));
- }
-
- error_log("Validaciones pasadas para cliente - ID: $cliente_id, Estado: $nuevo_estado");
-
- // Verificar que el cliente existe
- $consulta_verificar = "SELECT ID_CLIENTE, NOMBRE_CLI, ACTIVO_CLI FROM Clientes WHERE ID_CLIENTE = :cliente_id";
- $stmt_verificar = $pdo_conexion->prepare($consulta_verificar);
- $stmt_verificar->bindParam(':cliente_id', $cliente_id, PDO::PARAM_INT);
- $stmt_verificar->execute();
-
- $cliente = $stmt_verificar->fetch(PDO::FETCH_ASSOC);
-
- if (!$cliente) {
- throw new Exception("Cliente con ID $cliente_id no encontrado en la base de datos");
- }
-
- error_log("Cliente encontrado: " . print_r($cliente, true));
-
- // Actualizar el estado del cliente
- $consulta_actualizar = "UPDATE Clientes SET ACTIVO_CLI = :nuevo_estado WHERE ID_CLIENTE = :cliente_id";
- $stmt_actualizar = $pdo_conexion->prepare($consulta_actualizar);
- $stmt_actualizar->bindParam(':nuevo_estado', $nuevo_estado, PDO::PARAM_INT);
- $stmt_actualizar->bindParam(':cliente_id', $cliente_id, PDO::PARAM_INT);
-
- $update_result = $stmt_actualizar->execute();
- $affected_rows = $stmt_actualizar->rowCount();
-
- error_log("Resultado de la actualización de cliente - Éxito: " . ($update_result ? 'Sí' : 'No') . ", Filas afectadas: $affected_rows");
-
- if ($update_result && $affected_rows > 0) {
- $estado_texto = $nuevo_estado ? 'activo' : 'inactivo';
- $accion_texto = $nuevo_estado ? 'activado' : 'desactivado';
-
- echo json_encode([
- 'success' => true,
- 'mensaje' => "Cliente {$accion_texto} exitosamente",
- 'cliente' => [
- 'id' => $cliente_id,
- 'nombre' => $cliente['NOMBRE_CLI'],
- 'estado' => $nuevo_estado,
- 'estado_texto' => $estado_texto
- ]
- ]);
- } else {
- throw new Exception('Error al actualizar el estado del cliente. Filas afectadas: ' . $affected_rows);
- }
-
-} catch (Exception $e) {
- error_log("Error en toggle_estado_cliente.php: " . $e->getMessage());
- echo json_encode([
- 'success' => false,
- 'mensaje' => $e->getMessage()
- ]);
-}
-?>
diff --git a/files/toggle_estado_empleado.php b/files/toggle_estado_empleado.php
deleted file mode 100644
index 707c12e..0000000
--- a/files/toggle_estado_empleado.php
+++ /dev/null
@@ -1,119 +0,0 @@
- false, 'mensaje' => 'Acceso no autorizado']);
- exit();
-}
-
-// Headers de respuesta JSON
-header('Content-Type: application/json');
-
-// Verificar método POST
-if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
- echo json_encode(['success' => false, 'mensaje' => 'Método no permitido']);
- exit();
-}
-
-try {
- // Conexión PDO
- $dsn = "mysql:host=localhost;dbname=proyectopanaderia;charset=utf8";
- $username = "root";
- $password = "";
-
- $pdo_conexion = new PDO($dsn, $username, $password);
- $pdo_conexion->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
-
- // Obtener datos JSON del cuerpo de la petición
- $raw_input = file_get_contents('php://input');
- error_log("Raw input recibido: " . $raw_input);
-
- $input = json_decode($raw_input, true);
-
- if (json_last_error() !== JSON_ERROR_NONE) {
- throw new Exception('Error al decodificar JSON: ' . json_last_error_msg());
- }
-
- if (!$input) {
- throw new Exception('Datos JSON inválidos o vacíos');
- }
-
- // Debug: Log de los datos recibidos
- error_log("Datos decodificados: " . print_r($input, true));
-
- // Validar que se recibieron los campos necesarios
- if (!isset($input['id'])) {
- throw new Exception('Campo "id" faltante en los datos JSON');
- }
-
- if (!isset($input['estado'])) {
- throw new Exception('Campo "estado" faltante en los datos JSON');
- }
-
- // Convertir y validar los datos
- $empleado_id = filter_var($input['id'], FILTER_VALIDATE_INT);
- $nuevo_estado = filter_var($input['estado'], FILTER_VALIDATE_INT);
-
- // Validaciones estrictas
- if ($empleado_id === false || $empleado_id <= 0) {
- throw new Exception('ID de empleado inválido: ' . json_encode($input['id']));
- }
-
- if ($nuevo_estado === false || !in_array($nuevo_estado, [0, 1], true)) {
- throw new Exception('Estado inválido: ' . json_encode($input['estado']));
- }
-
- error_log("Validaciones pasadas - ID: $empleado_id, Estado: $nuevo_estado");
-
- // Verificar que el empleado existe
- $consulta_verificar = "SELECT ID_EMPLEADO, NOMBRE_EMPLEADO, ACTIVO_EMPLEADO FROM Empleados WHERE ID_EMPLEADO = :empleado_id";
- $stmt_verificar = $pdo_conexion->prepare($consulta_verificar);
- $stmt_verificar->bindParam(':empleado_id', $empleado_id, PDO::PARAM_INT);
- $stmt_verificar->execute();
-
- $empleado = $stmt_verificar->fetch(PDO::FETCH_ASSOC);
-
- if (!$empleado) {
- throw new Exception("Empleado con ID $empleado_id no encontrado en la base de datos");
- }
-
- error_log("Empleado encontrado: " . print_r($empleado, true));
-
- // Actualizar el estado del empleado
- $consulta_actualizar = "UPDATE Empleados SET ACTIVO_EMPLEADO = :nuevo_estado WHERE ID_EMPLEADO = :empleado_id";
- $stmt_actualizar = $pdo_conexion->prepare($consulta_actualizar);
- $stmt_actualizar->bindParam(':nuevo_estado', $nuevo_estado, PDO::PARAM_INT);
- $stmt_actualizar->bindParam(':empleado_id', $empleado_id, PDO::PARAM_INT);
-
- $update_result = $stmt_actualizar->execute();
- $affected_rows = $stmt_actualizar->rowCount();
-
- error_log("Resultado de la actualización - Éxito: " . ($update_result ? 'Sí' : 'No') . ", Filas afectadas: $affected_rows");
-
- if ($update_result && $affected_rows > 0) {
- $estado_texto = $nuevo_estado ? 'activo' : 'inactivo';
- $accion_texto = $nuevo_estado ? 'activado' : 'desactivado';
-
- echo json_encode([
- 'success' => true,
- 'mensaje' => "Empleado {$accion_texto} exitosamente",
- 'empleado' => [
- 'id' => $empleado_id,
- 'nombre' => $empleado['NOMBRE_EMPLEADO'],
- 'estado' => $nuevo_estado,
- 'estado_texto' => $estado_texto
- ]
- ]);
- } else {
- throw new Exception('Error al actualizar el estado del empleado. Filas afectadas: ' . $affected_rows);
- }
-
-} catch (Exception $e) {
- error_log("Error en toggle_estado_empleado.php: " . $e->getMessage());
- echo json_encode([
- 'success' => false,
- 'mensaje' => $e->getMessage()
- ]);
-}
-?>
diff --git a/files/toggle_producto.php b/files/toggle_producto.php
deleted file mode 100644
index dc40146..0000000
--- a/files/toggle_producto.php
+++ /dev/null
@@ -1,267 +0,0 @@
-prepare($consulta_producto);
- $stmt_producto->bindParam(':id', $id_producto, PDO::PARAM_INT);
- $stmt_producto->execute();
- $producto = $stmt_producto->fetch(PDO::FETCH_ASSOC);
-
- if ($producto) {
- $nombre_producto = $producto['NOMBRE_PRODUCTO'];
-
- // Actualizar el estado del producto
- $consulta_update = "UPDATE Productos SET ACTIVO = :nuevo_estado WHERE ID_PRODUCTO = :id";
- $stmt_update = $pdo_conexion->prepare($consulta_update);
- $stmt_update->bindParam(':nuevo_estado', $nuevo_estado, PDO::PARAM_INT);
- $stmt_update->bindParam(':id', $id_producto, PDO::PARAM_INT);
-
- if ($stmt_update->execute()) {
- $mensaje = "El producto '{$nombre_producto}' ha sido {$accion_texto} exitosamente.";
- $tipo_mensaje = "success";
- } else {
- $mensaje = "Error: No se pudo cambiar el estado del producto.";
- $tipo_mensaje = "error";
- }
- } else {
- $mensaje = "Error: El producto no existe.";
- $tipo_mensaje = "error";
- }
-
- } catch (PDOException $e) {
- $mensaje = "Error en la base de datos: " . $e->getMessage();
- $tipo_mensaje = "error";
- }
-} else {
- $mensaje = "Error: Parámetros no válidos.";
- $tipo_mensaje = "error";
-}
-?>
-
-
-
-
-
-
- Cambiar Estado - Panadería
-
-
-
-
-
-
✓
-
Estado Cambiado
-
-
✗
-
Error al Cambiar Estado
-
-
-
-
-
-
-
-
-
Información del Cambio:
-
Producto:
-
Nuevo Estado:
-
- ✓ Activo
-
- ✗ Inactivo
-
-
-
Fecha del Cambio:
-
-
-
-
💡 Información Importante:
-
-
- - El producto está ahora INACTIVO y no aparecerá en búsquedas normales
- - Los pedidos existentes que contienen este producto NO se ven afectados
- - Puedes reactivarlo en cualquier momento
-
- - El producto está ahora ACTIVO y disponible para nuevos pedidos
- - Aparecerá en todas las búsquedas y listados normales
- - Los clientes pueden volver a pedirlo
-
-
-
-
-
-
-
-
-
-
- ⏱️ Por favor, lee toda la información mostrada arriba antes de continuar.
- El botón se activará en 5 segundos.
-
-
-
-
-
-
diff --git a/files/toggle_producto_ajax.php b/files/toggle_producto_ajax.php
deleted file mode 100644
index 72179c1..0000000
--- a/files/toggle_producto_ajax.php
+++ /dev/null
@@ -1,70 +0,0 @@
- false,
- 'mensaje' => 'Método no permitido. Use POST.'
- ]);
- exit();
-}
-
-// Verificar si se recibió el ID del producto y el estado actual
-if (isset($_POST['id']) && !empty($_POST['id']) && isset($_POST['estado'])) {
- $id_producto = $_POST['id'];
- $estado_actual = $_POST['estado'];
-
- // Determinar el nuevo estado (invertir el actual)
- $nuevo_estado = ($estado_actual == 1) ? 0 : 1;
- $accion_texto = ($nuevo_estado == 1) ? "activado" : "desactivado";
-
- try {
- // Obtener información del producto antes del cambio
- $consulta_producto = "SELECT NOMBRE_PRODUCTO, ACTIVO FROM Productos WHERE ID_PRODUCTO = ?";
- $stmt_producto = $conexion->prepare($consulta_producto);
- $stmt_producto->bind_param("i", $id_producto);
- $stmt_producto->execute();
- $resultado = $stmt_producto->get_result();
- $producto = $resultado->fetch_assoc();
-
- if ($producto) {
- $nombre_producto = $producto['NOMBRE_PRODUCTO'];
-
- // Actualizar el estado del producto
- $consulta_update = "UPDATE Productos SET ACTIVO = ? WHERE ID_PRODUCTO = ?";
- $stmt_update = $conexion->prepare($consulta_update);
- $stmt_update->bind_param("ii", $nuevo_estado, $id_producto);
-
- if ($stmt_update->execute()) {
- echo json_encode([
- 'success' => true,
- 'mensaje' => "El producto '{$nombre_producto}' ha sido {$accion_texto} exitosamente."
- ]);
- } else {
- echo json_encode([
- 'success' => false,
- 'mensaje' => "Error: No se pudo cambiar el estado del producto."
- ]);
- }
- } else {
- echo json_encode([
- 'success' => false,
- 'mensaje' => "Error: El producto no existe."
- ]);
- }
-
- } catch (Exception $e) {
- echo json_encode([
- 'success' => false,
- 'mensaje' => "Error en la base de datos: " . $e->getMessage()
- ]);
- }
-} else {
- echo json_encode([
- 'success' => false,
- 'mensaje' => "Error: Parámetros no válidos."
- ]);
-}
-?>
diff --git a/files/update_productos_table.sql b/files/update_productos_table.sql
deleted file mode 100644
index e69de29..0000000
diff --git a/files/verificacion_sistema_precios.php b/files/verificacion_sistema_precios.php
deleted file mode 100644
index e69de29..0000000
diff --git a/files/verificar_actualizacion.php b/files/verificar_actualizacion.php
deleted file mode 100644
index 1592697..0000000
--- a/files/verificar_actualizacion.php
+++ /dev/null
@@ -1,157 +0,0 @@
-🔧 Verificador y Actualizador de Base de Datos - Panadería";
-echo "";
-
-try {
- echo "
📋 Verificando estado actual de la base de datos...
";
-
- // 1. Verificar si la tabla productos_logs existe
- echo "
1. Verificando tabla productos_logs: ";
- $check_table = $conexion->query("SHOW TABLES LIKE 'productos_logs'");
-
- if ($check_table->num_rows == 0) {
- echo "❌ No existe
";
-
- echo "
🔨 Creando tabla productos_logs...
";
- $sql_tabla = "
- CREATE TABLE productos_logs (
- id INT PRIMARY KEY AUTO_INCREMENT,
- producto_id INT NOT NULL,
- tipo_cambio ENUM('precio', 'stock', 'activacion', 'desactivacion') NOT NULL,
- valor_anterior VARCHAR(50),
- valor_nuevo VARCHAR(50),
- usuario_id INT,
- usuario_tipo ENUM('admin', 'empleado') DEFAULT 'admin',
- fecha_cambio TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
- ip_usuario VARCHAR(45),
- INDEX idx_producto_logs_fecha (fecha_cambio),
- INDEX idx_producto_logs_producto (producto_id),
- INDEX idx_producto_logs_tipo (tipo_cambio),
- CONSTRAINT FK_PRODUCTO_LOG
- FOREIGN KEY (producto_id) REFERENCES Productos(ID_PRODUCTO) ON DELETE CASCADE
- )";
-
- if ($conexion->query($sql_tabla)) {
- echo "
✅ Tabla productos_logs creada exitosamente
";
- } else {
- echo "
❌ Error al crear tabla: " . $conexion->error . "
";
- }
- } else {
- echo "
✅ Existe";
- }
-
- // 2. Verificar tipo de dato de PRECIO_PRODUCTO
- echo "
2. Verificando tipo de dato PRECIO_PRODUCTO: ";
- $check_column = $conexion->query("SELECT DATA_TYPE, COLUMN_TYPE FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = 'ProyectoPanaderia' AND TABLE_NAME = 'Productos' AND COLUMN_NAME = 'PRECIO_PRODUCTO'");
-
- if ($check_column && $row = $check_column->fetch_assoc()) {
- if (strpos($row['DATA_TYPE'], 'decimal') !== false) {
- echo "✅ DECIMAL(10,2)
";
- } else {
- echo "
⚠️ " . $row['COLUMN_TYPE'] . " (necesita actualización)";
-
- echo "
🔨 Actualizando tipo de dato a DECIMAL(10,2)...
";
- if ($conexion->query("ALTER TABLE Productos MODIFY COLUMN PRECIO_PRODUCTO DECIMAL(10,2) NOT NULL")) {
- echo "
✅ Tipo de dato actualizado exitosamente
";
- } else {
- echo "
❌ Error al actualizar: " . $conexion->error . "
";
- }
- }
- } else {
- echo "
❌ No se pudo verificar";
- }
-
- // 3. Verificar trigger
- echo "
3. Verificando trigger tr_actualizar_fecha_producto: ";
- $check_trigger = $conexion->query("SELECT TRIGGER_NAME FROM information_schema.TRIGGERS WHERE TRIGGER_SCHEMA = 'ProyectoPanaderia' AND TRIGGER_NAME = 'tr_actualizar_fecha_producto'");
-
- if ($check_trigger->num_rows == 0) {
- echo "❌ No existe
";
-
- echo "
🔨 Creando trigger...
";
- $sql_trigger = "
- CREATE TRIGGER tr_actualizar_fecha_producto
- BEFORE UPDATE ON Productos
- FOR EACH ROW
- BEGIN
- SET NEW.FECHA_ULTIMA_MODIFICACION = CURRENT_TIMESTAMP;
- END";
-
- if ($conexion->query($sql_trigger)) {
- echo "
✅ Trigger creado exitosamente
";
- } else {
- echo "
❌ Error al crear trigger: " . $conexion->error . "
";
- }
- } else {
- echo "
✅ Existe";
- }
-
- // 4. Verificar índices de productos_logs
- if ($check_table->num_rows > 0) {
- echo "
4. Verificando índices de productos_logs:
";
- $indices = $conexion->query("SHOW INDEX FROM productos_logs");
- $indices_encontrados = [];
-
- while ($indice = $indices->fetch_assoc()) {
- $indices_encontrados[] = $indice['Key_name'];
- }
-
- $indices_requeridos = ['PRIMARY', 'idx_producto_logs_fecha', 'idx_producto_logs_producto', 'idx_producto_logs_tipo', 'FK_PRODUCTO_LOG'];
-
- foreach ($indices_requeridos as $req) {
- if (in_array($req, $indices_encontrados)) {
- echo "
✅ Índice $req: Existe
";
- } else {
- echo "
⚠️ Índice $req: No encontrado
";
- }
- }
- }
-
- // 5. Estadísticas generales
- echo "
📊 Estadísticas actuales:
";
-
- $productos_count = $conexion->query("SELECT COUNT(*) as total FROM Productos")->fetch_assoc()['total'];
- echo "
📦 Total de productos: $productos_count
";
-
- if ($check_table->num_rows > 0) {
- $logs_count = $conexion->query("SELECT COUNT(*) as total FROM productos_logs")->fetch_assoc()['total'];
- echo "
📝 Total de logs: $logs_count
";
-
- if ($logs_count > 0) {
- $ultimo_cambio = $conexion->query("SELECT MAX(fecha_cambio) as ultimo FROM productos_logs")->fetch_assoc()['ultimo'];
- echo "
🕒 Último cambio: $ultimo_cambio
";
- }
- }
-
- echo "
✅ Verificación completada
";
- echo "
Estado del sistema: LISTO PARA USAR
";
-
- echo "
";
- echo "
🚀 Próximos pasos:
";
- echo "
";
- echo "- La funcionalidad de edición inline ya está disponible en productostabla.php
";
- echo "- Los cambios se registrarán automáticamente en la tabla productos_logs
";
- echo "- El sistema SSE funcionará con las actualizaciones en tiempo real
";
- echo "
";
- echo "
";
-
-} catch (Exception $e) {
- echo "
❌ Error: " . $e->getMessage() . "
";
-}
-
-echo "
";
-
-echo "
";
-
-$conexion->close();
-?>
diff --git a/php-api/api-client.php b/php-api/api-client.php
new file mode 100644
index 0000000..4122f48
--- /dev/null
+++ b/php-api/api-client.php
@@ -0,0 +1,77 @@
+ $usuario) {
+ echo "Cliente " . ($recorrido + 1) . ":\n";
+ foreach ($usuario as $atributo => $valor) {
+ echo " $atributo $valor\n";
+ }
+ echo "------------------------\n";
+ }
+ echo "====================================================\n";
+ echo "Total de clientes: " . count($usuarios_clientes) . "\n";
+ echo "====================================================\n";
+ } else if ($opcion == 2) {
+ echo "Vista de clientes omitida.\n";
+ }
+
+} else if ($decision == 2) {
+ echo "Bienvenido Empleado $nombre_user\n";
+ echo "¿Desea ver todos los datos de los administradores?\n";
+ echo "1. Sí\n";
+ echo "2. No\n";
+ $opcion = readline();
+
+ if ($opcion == 1) {
+ foreach ($usuarios_admins as $recorrido => $admin) {
+ echo "Administrador " . ($recorrido + 1) . ":\n";
+ echo " Nombre: " . ($admin['Nombre:'] ?? 'No disponible') . "\n";
+ echo " Telefono: " . ($admin['Telefono:'] ?? 'No disponible') . "\n";
+ echo "------------------------\n";
+ }
+ echo "====================================================\n";
+ echo "Total de administradores: " . count($usuarios_admins) . "\n";
+ echo "====================================================\n";
+ } else if ($opcion == 2) {
+ echo "Saliendo del sistema....\n";
+ }
+
+} else if ($decision == 3) {
+ echo "Cerrando programa...\n";
+ exit;
+} else {
+ echo "Opción inválida.\n";
+}
+?>
diff --git a/php_api_user/actualizarEmpleado.php b/php_api_user/actualizarEmpleado.php
new file mode 100644
index 0000000..5497e64
--- /dev/null
+++ b/php_api_user/actualizarEmpleado.php
@@ -0,0 +1,109 @@
+ endopointActualizacion::empleado($id),
+ default => throw new InvalidArgumentException("Tipo desconocido: $tipo"),
+ };
+ }
+
+ public function actualizarEmpleado(string $tipo): array {
+ echo "\n==============================\n";
+ echo "=== ACTUALIZAR EMPLEADO ===\n";
+ echo "==============================\n";
+
+ echo "Ingrese el ID del empleado a actualizar: ";
+ $id_empleado = (int)readline();
+
+ $url = $this->getActualizacionEndpoint($tipo, $id_empleado);
+
+ echo "\nEmpleado/a a actualizar es: $id_empleado\n";
+ echo "\n¿Qué desea actualizar?\n";
+ echo "1. Nombre\n";
+ echo "2. Email\n";
+ echo "4. Contraseña\n";
+ echo "5. Todos los campos\n";
+ echo "Seleccione una opción (1-5): ";
+
+ $opcion = readline();
+ $datos_nuevos = array();
+
+ switch ($opcion) {
+ case '1':
+ $nombre = readline("Ingrese el nuevo nombre: ");
+ $datos_nuevos["nombre"] = $nombre;
+ break;
+
+ case '2':
+ $email = readline("Ingrese el nuevo email: ");
+ $datos_nuevos["email"] = $email;
+ break;
+
+ case '3':
+ $contrasena = readline("Ingrese la nueva contraseña: ");
+ $datos_nuevos["contrasena"] = $contrasena;
+ break;
+
+ case '4':
+ $nombre = readline("Ingrese el nombre: ");
+ $email = readline("Ingrese el email: ");
+ $telefono = readline("Ingrese el teléfono: ");
+ $contrasena = readline("Ingrese la contraseña: ");
+
+ $datos_nuevos = array(
+ "nombre" => $nombre,
+ "email" => $email,
+ "contrasena" => $contrasena
+ );
+ break;
+ default:
+ throw new InvalidArgumentException("Opción inválida seleccionada");
+ }
+
+ $data_json = json_encode($datos_nuevos);
+
+ $proceso = curl_init($url);
+ curl_setopt($proceso, CURLOPT_CUSTOMREQUEST, "PATCH");
+ curl_setopt($proceso, CURLOPT_POSTFIELDS, $data_json);
+ curl_setopt($proceso, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($proceso, CURLOPT_HTTPHEADER, array(
+ "Content-Type: application/json",
+ "Content-Length: " . strlen($data_json)
+ ));
+
+ $response = curl_exec($proceso);
+ $http_code = curl_getinfo($proceso, CURLINFO_HTTP_CODE);
+ curl_close($proceso);
+
+ return [
+ 'http_code' => $http_code,
+ 'data' => json_decode($response, true)
+ ];
+ }
+
+ public function mostrarActualizacion(string $tipo): void {
+ echo "\n=== ACTUALIZACIÓN DE EMPLEADO ===\n";
+
+ $resultado = $this->actualizarEmpleado($tipo);
+
+ echo "\n HTTP Code: " . $resultado['http_code'] . "\n";
+
+ if ($resultado['http_code'] == 200){
+ echo "Empleado actualizado exitosamente.\n";
+ } else {
+ echo "Error al actualizar el empleado.\n";
+ }
+
+ if ($resultado['data'] !== null && !empty($resultado['data'])) {
+ echo "Respuesta del servidor:\n";
+ echo json_encode($resultado['data'], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) . "\n";
+ }
+ echo "\n";
+ }
+}
+
+$actualizacion = new actualizarEmpleado();
+$actualizacion->mostrarActualizacion('empleado');
+?>
diff --git a/php_api_user/config.php b/php_api_user/config.php
new file mode 100644
index 0000000..a551f0e
--- /dev/null
+++ b/php_api_user/config.php
@@ -0,0 +1,47 @@
+
diff --git a/php_api_user/detalleClientes.php b/php_api_user/detalleClientes.php
new file mode 100644
index 0000000..ce82fcc
--- /dev/null
+++ b/php_api_user/detalleClientes.php
@@ -0,0 +1,47 @@
+ endpointDetalles::API_DETALLE_CLIENTE,
+ default => throw new InvalidArgumentException("Tipo desconocido: $tipo"),
+ };
+ }
+
+ public function obtenerDatos(string $tipo): array {
+ $url = $this->getDetalleEndpoint($tipo);
+
+ $proceso = curl_init();
+ curl_setopt($proceso, CURLOPT_URL, $url);
+ curl_setopt($proceso, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($proceso, CURLOPT_TIMEOUT, 30);
+ curl_setopt($proceso, CURLOPT_HTTPHEADER, [
+ 'Accept: application/json',
+ 'Content-Type: application/json'
+ ]);
+
+ $response = curl_exec($proceso);
+ $http_code = curl_getinfo($proceso, CURLINFO_HTTP_CODE);
+ curl_close($proceso);
+
+ $dato = json_decode($response, true);
+
+ return ['http_code' => $http_code,'data' => $dato];
+ }
+ public function mostrarDatos(string $tipo): void {
+ echo "\n=== DATOS DE CLIENTES ===\n";
+ echo "Endpoint: " . $this->getDetalleEndpoint($tipo) . "\n";
+
+ $resultado = $this->obtenerDatos($tipo);
+
+ echo "HTTP Code: " . $resultado['http_code'] . "\n";
+ echo "Datos obtenidos:\n";
+ echo json_encode($resultado['data'], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) . "\n";
+ echo "\n";
+ echo "El conteo total de clientes es: " . count($resultado['data']) . "\n";
+ }
+}
+$detalles = new DetallesUsusarios();
+$detalles->mostrarDatos('cliente');
+?>
\ No newline at end of file
diff --git a/php_api_user/detalleEmpleados.php b/php_api_user/detalleEmpleados.php
new file mode 100644
index 0000000..6a06dde
--- /dev/null
+++ b/php_api_user/detalleEmpleados.php
@@ -0,0 +1,46 @@
+ endpointDetalles::API_DETALLE_EMPLEADO,
+ default => throw new InvalidArgumentException("Tipo desconocido: $tipo"),
+ };
+ }
+ public function obtenerDatos(string $tipo): array {
+ $url = $this->getDetalleEndpoint($tipo);
+
+ $proceso = curl_init();
+ curl_setopt($proceso, CURLOPT_URL, $url);
+ curl_setopt($proceso, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($proceso, CURLOPT_TIMEOUT, 30);
+ curl_setopt($proceso, CURLOPT_HTTPHEADER, [
+ 'Accept: application/json',
+ 'Content-Type: application/json'
+ ]);
+
+ $response = curl_exec($proceso);
+ $http_code = curl_getinfo($proceso, CURLINFO_HTTP_CODE);
+ curl_close($proceso);
+
+ $dato = json_decode($response, true);
+
+ return ['http_code' => $http_code,'data' => $dato];
+ }
+ public function mostrarDatos(string $tipo): void {
+ echo "\n=== DATOS DE EMPLEADOS ===\n";
+ echo "Endpoint: " . $this->getDetalleEndpoint($tipo) . "\n";
+
+ $resultado = $this->obtenerDatos($tipo);
+
+ echo "HTTP Code: " . $resultado['http_code'] . "\n";
+ echo "Datos obtenidos:\n";
+ echo json_encode($resultado['data'], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) . "\n";
+ echo "\n";
+ echo "El conteo total de empleados es: " . count($resultado['data']) . "\n";
+ }
+}
+$detalles = new DetallesEmpleados();
+$detalles->mostrarDatos('empleados');
+?>
\ No newline at end of file
diff --git a/php_api_user/registroClientes.php b/php_api_user/registroClientes.php
new file mode 100644
index 0000000..456f6e6
--- /dev/null
+++ b/php_api_user/registroClientes.php
@@ -0,0 +1,74 @@
+ endpointCreacion::API_CREAR_CLIENTE,
+ default => throw new InvalidArgumentException("Tipo desconocido: $tipo"),
+ };
+ }
+
+ public function crearCliente(string $tipo): array {
+ $url = $this->getCreacionEndpoint($tipo);
+
+ echo "\n==============================\n";
+ echo "=== REGISTRO DE CLIENTES ===\n";
+ echo "==============================\n";
+
+ $nombre = readline("Ingrese el nombre: ");
+ $telefono = readline("Ingrese el telefono: ");
+ $correo = readline("Ingrese el correo: ");
+ $contrasena = readline("Ingrese la contraseña: ");
+
+ $datos_nuevos = array(
+ "nombre" => $nombre,
+ "email" => $correo,
+ "telefono" => $telefono,
+ "contrasena" => $contrasena
+ );
+
+ $data_json = json_encode($datos_nuevos);
+
+ $proceso = curl_init($url);
+ curl_setopt($proceso, CURLOPT_CUSTOMREQUEST, "POST");
+ curl_setopt($proceso, CURLOPT_POSTFIELDS, $data_json);
+ curl_setopt($proceso, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($proceso, CURLOPT_HTTPHEADER, array(
+ "Content-Type: application/json",
+ "Content-Length: " . strlen($data_json)
+ ));
+
+ $response = curl_exec($proceso);
+ $http_code = curl_getinfo($proceso, CURLINFO_HTTP_CODE);
+ curl_close($proceso);
+
+ return [
+ 'http_code' => $http_code,
+ 'data' => json_decode($response, true)
+ ];
+ }
+
+ public function mostrarRegistro(string $tipo): void {
+ echo "\n=== REGISTRO DE NUEVO CLIENTE ===\n";
+ echo "Endpoint: " . $this->getCreacionEndpoint($tipo) . "\n";
+
+ $resultado = $this->crearCliente($tipo);
+
+ echo "HTTP Code: " . $resultado['http_code'] . "\n";
+ if ($resultado['http_code'] == 200){
+ echo "Cliente registrado exitosamente.\n";
+ } else {
+ echo "Error al registrar el cliente.\n";
+ }
+ if ($resultado['data'] !== null && !empty($resultado['data'])) {
+ echo "Respuesta del servidor:\n";
+ echo json_encode($resultado['data'], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) . "\n";
+ }
+ echo "\n";
+ }
+}
+
+$registro = new RegistroClientes();
+$registro->mostrarRegistro('cliente');
+?>
\ No newline at end of file
diff --git a/php_api_user/registroEmpleados.php b/php_api_user/registroEmpleados.php
new file mode 100644
index 0000000..73d0fe3
--- /dev/null
+++ b/php_api_user/registroEmpleados.php
@@ -0,0 +1,75 @@
+ endpointCreacion::API_CREAR_EMPLEADO,
+ default => throw new InvalidArgumentException("Tipo desconocido: $tipo"),
+ };
+ }
+
+ public function crearEmpleado(string $tipo): array {
+ $url = $this->getCreacionEndpoint($tipo);
+
+ echo "\n==============================\n";
+ echo "=== REGISTRO DE EMPLEADOS ===\n";
+ echo "==============================\n";
+
+ $nombre = readline("Ingrese el nombre: ");
+ $telefono = readline("Ingrese el telefono: ");
+ $correo = readline("Ingrese el correo: ");
+ $contrasena = readline("Ingrese la contraseña: ");
+
+ $datos_nuevos = array(
+ "nombre" => $nombre,
+ "email" => $correo,
+ "telefono" => $telefono,
+ "contrasena" => $contrasena
+ );
+
+ $data_json = json_encode($datos_nuevos);
+
+ $proceso = curl_init($url);
+ curl_setopt($proceso, CURLOPT_CUSTOMREQUEST, "POST");
+ curl_setopt($proceso, CURLOPT_POSTFIELDS, $data_json);
+ curl_setopt($proceso, CURLOPT_RETURNTRANSFER, true);
+ curl_setopt($proceso, CURLOPT_HTTPHEADER, array(
+ "Content-Type: application/json",
+ "Content-Length: " . strlen($data_json)
+ ));
+
+ $response = curl_exec($proceso);
+ $http_code = curl_getinfo($proceso, CURLINFO_HTTP_CODE);
+ curl_close($proceso);
+
+ return [
+ 'http_code' => $http_code,
+ 'data' => json_decode($response, true)
+ ];
+ }
+
+ public function mostrarRegistro(string $tipo): void {
+ echo "\n=== REGISTRO DE NUEVO EMPLEADO ===\n";
+ echo "Endpoint: " . $this->getCreacionEndpoint($tipo) . "\n";
+
+ $resultado = $this->crearEmpleado($tipo);
+
+ echo "HTTP Code: " . $resultado['http_code'] . "\n";
+
+ if ($resultado['http_code'] == 200){
+ echo "Empleado registrado exitosamente.\n";
+ } else {
+ echo "Error al registrar el Empleado.\n";
+ }
+ if ($resultado['data'] !== null && !empty($resultado['data'])) {
+ echo "Respuesta del servidor:\n";
+ echo json_encode($resultado['data'], JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE) . "\n";
+ }
+ echo "\n";
+ }
+}
+
+$registro = new RegistroEmpleados();
+$registro->mostrarRegistro('cliente');
+?>
\ No newline at end of file
diff --git a/target/classes/com/example/Proyecto/Controllers/ConexionController.class b/target/classes/com/example/Proyecto/Controllers/ConexionController.class
deleted file mode 100644
index c9c646f..0000000
Binary files a/target/classes/com/example/Proyecto/Controllers/ConexionController.class and /dev/null differ
diff --git a/target/classes/com/example/Proyecto/Services/Administrador/ConexionAdminService$1.class b/target/classes/com/example/Proyecto/Services/Administrador/ConexionAdminService$1.class
deleted file mode 100644
index 812d5b5..0000000
Binary files a/target/classes/com/example/Proyecto/Services/Administrador/ConexionAdminService$1.class and /dev/null differ
diff --git a/target/classes/com/example/Proyecto/Services/Administrador/ConexionAdminService.class b/target/classes/com/example/Proyecto/Services/Administrador/ConexionAdminService.class
deleted file mode 100644
index fdeaa36..0000000
Binary files a/target/classes/com/example/Proyecto/Services/Administrador/ConexionAdminService.class and /dev/null differ
diff --git a/target/classes/com/example/Proyecto/Services/Administrador/PojoAdmin.class b/target/classes/com/example/Proyecto/Services/Administrador/PojoAdmin.class
deleted file mode 100644
index 855d7ff..0000000
Binary files a/target/classes/com/example/Proyecto/Services/Administrador/PojoAdmin.class and /dev/null differ
diff --git a/target/classes/com/example/Proyecto/Services/Clientes/ConexionClienteService$1.class b/target/classes/com/example/Proyecto/Services/Clientes/ConexionClienteService$1.class
deleted file mode 100644
index 5e9b77f..0000000
Binary files a/target/classes/com/example/Proyecto/Services/Clientes/ConexionClienteService$1.class and /dev/null differ
diff --git a/target/classes/com/example/Proyecto/Services/Clientes/ConexionClienteService.class b/target/classes/com/example/Proyecto/Services/Clientes/ConexionClienteService.class
deleted file mode 100644
index 64684dc..0000000
Binary files a/target/classes/com/example/Proyecto/Services/Clientes/ConexionClienteService.class and /dev/null differ
diff --git a/target/classes/com/example/Proyecto/Services/Clientes/PojoCliente.class b/target/classes/com/example/Proyecto/Services/Clientes/PojoCliente.class
deleted file mode 100644
index 6e8f743..0000000
Binary files a/target/classes/com/example/Proyecto/Services/Clientes/PojoCliente.class and /dev/null differ
diff --git a/target/classes/com/example/Proyecto/Services/Empleados/ConexionEmpleadoService$1.class b/target/classes/com/example/Proyecto/Services/Empleados/ConexionEmpleadoService$1.class
deleted file mode 100644
index e9027b8..0000000
Binary files a/target/classes/com/example/Proyecto/Services/Empleados/ConexionEmpleadoService$1.class and /dev/null differ
diff --git a/target/classes/com/example/Proyecto/Services/Empleados/ConexionEmpleadoService.class b/target/classes/com/example/Proyecto/Services/Empleados/ConexionEmpleadoService.class
deleted file mode 100644
index 1f5d092..0000000
Binary files a/target/classes/com/example/Proyecto/Services/Empleados/ConexionEmpleadoService.class and /dev/null differ
diff --git a/target/classes/com/example/Proyecto/Services/Empleados/PojoDeleteEmpleado.class b/target/classes/com/example/Proyecto/Services/Empleados/PojoDeleteEmpleado.class
deleted file mode 100644
index 9409bee..0000000
Binary files a/target/classes/com/example/Proyecto/Services/Empleados/PojoDeleteEmpleado.class and /dev/null differ
diff --git a/target/classes/com/example/Proyecto/Services/Empleados/PojoEmpleado.class b/target/classes/com/example/Proyecto/Services/Empleados/PojoEmpleado.class
deleted file mode 100644
index 5cd4549..0000000
Binary files a/target/classes/com/example/Proyecto/Services/Empleados/PojoEmpleado.class and /dev/null differ