feat: Release version 1.5.0 with major UI improvements and advanced anticipos

- Add sales subtabs: Ventas and Tickets for better organization
- Implement manual anticipos with confirmation checkbox system
- Add automatic "Público General" for sales without specific client
- Reorganize service order: Clean Girl → Elegant → Mystery → Seduction
- Replace gradient with solid black header background
- Improve price alignment with grid layout
- Add sort_order field to products for consistent ordering
- Move movements section from dashboard to Tickets subtab
- Enhanced JavaScript functionality for subtab navigation
- Remove TASKS.md documentation file

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Marco Gallegos
2025-09-08 18:18:48 -06:00
parent 65837e59b1
commit 02f5775223
7 changed files with 2267 additions and 247 deletions

View File

@@ -12,7 +12,7 @@
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@500;600&family=Open+Sans:wght@400;600&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Material+Icons+Outlined" rel="stylesheet">
<!-- Styles -->
<link rel="stylesheet" href="styles.css?v=1757039067" />
<link rel="stylesheet" href="styles.css?v=1757039804" />
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
</head>
<body>
@@ -33,6 +33,9 @@
<button type="button" class="tab-link" data-tab="tab-products">
<span class="material-icons-outlined">inventory_2</span><span>Productos</span>
</button>
<button type="button" class="tab-link" data-tab="tab-cancellation-requests" id="tab-cancellation-requests-btn" style="display: none;">
<span class="material-icons-outlined">cancel_presentation</span><span>Solicitudes</span>
</button>
<button type="button" class="tab-link" data-tab="tab-settings">
<span class="material-icons-outlined">settings</span><span>Configuración</span>
</button>
@@ -77,30 +80,159 @@
<!-- Pestaña de Movimientos/Recibos -->
<div id="tab-movements" class="tab-content">
<div class="section">
<h2>Nuevo Movimiento</h2>
<form id="formMove" class="form-modern">
<!-- Cliente -->
<div class="form-row">
<div class="form-group">
<label>Cliente</label>
<input type="text" id="m-cliente" list="client-list" required autocomplete="off" placeholder="Nombre del cliente" />
<datalist id="client-list"></datalist>
<div class="sub-tabs">
<button type="button" class="sub-tab-link active" data-subtab="sub-tab-ventas">💰 Ventas</button>
<button type="button" class="sub-tab-link" data-subtab="sub-tab-tickets">🎫 Tickets</button>
</div>
<!-- Sub-Pestaña de Ventas -->
<div id="sub-tab-ventas" class="sub-tab-content active">
<div class="sales-container">
<!-- Header -->
<div class="sales-header">
<h2>💰 Nueva Venta</h2>
<div class="sales-summary">
<span class="cart-count" id="cart-count">0 productos</span>
<span class="cart-total" id="cart-total">$0.00</span>
</div>
</div>
<div class="sales-layout">
<!-- Panel de Productos (Izquierda) -->
<div class="products-panel">
<!-- Cliente -->
<div class="client-selector">
<div class="form-group modern-input">
<label>👤 Cliente</label>
<input type="text" id="m-cliente" list="client-list" autocomplete="off" placeholder="Buscar o crear cliente... (opcional)" />
<datalist id="client-list"></datalist>
</div>
</div>
<!-- Categorías de Productos -->
<div class="categories-container">
<h3>Selecciona tus servicios</h3>
<!-- Vanity Lashes -->
<div class="category-section" data-category="Vanity Lashes">
<div class="category-header">
<span class="category-icon">👁️</span>
<h4>Vanity Lashes</h4>
<button class="category-toggle"></button>
</div>
<div class="products-grid" id="pestanas-products">
<!-- Los productos se cargarán dinámicamente aquí -->
</div>
</div>
<!-- PMU Services -->
<div class="category-section" data-category="PMU Services">
<div class="category-header">
<span class="category-icon">✏️</span>
<h4>PMU Services</h4>
<button class="category-toggle"></button>
</div>
<div class="products-grid" id="microblading-products">
<!-- Los productos se cargarán dinámicamente aquí -->
</div>
</div>
<!-- Uñas -->
<div class="category-section" data-category="Uñas">
<div class="category-header">
<span class="category-icon">💅</span>
<h4>Nail Art</h4>
<button class="category-toggle"></button>
</div>
<div class="products-grid" id="unas-products">
<!-- Los productos se cargarán dinámicamente aquí -->
</div>
</div>
<!-- Anticipos -->
<div class="category-section" data-category="Anticipos">
<div class="category-header">
<span class="category-icon">💰</span>
<h4>Anticipos</h4>
<button class="category-toggle"></button>
</div>
<div class="anticipos-grid" id="anticipos-products">
<div class="anticipo-form">
<div class="anticipo-input-group">
<input type="number" id="anticipo-amount" min="1" placeholder="Cantidad" />
<input type="text" id="anticipo-comment" placeholder="Comentario (opcional)" />
<button class="btn-add-anticipo" onclick="addAnticipo()">Agregar</button>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- Cita -->
<div class="form-section" id="appointment-section">
<h3>Datos de la Cita</h3>
<div class="form-row">
<div class="form-group">
<label>Fecha de la Cita</label>
<input type="date" id="m-fecha-cita" class="date-picker" />
<!-- Panel de Carrito y Checkout (Derecha) -->
<div class="checkout-panel">
<!-- Carrito de Productos -->
<div class="cart-section">
<h3>🛒 Carrito de Compras</h3>
<div id="selected-products-container" class="cart-items">
<div class="empty-cart">
<span class="empty-icon">🛒</span>
<p>Selecciona servicios para comenzar</p>
</div>
</div>
<div class="form-group">
<label>Hora</label>
<select id="m-hora-cita" class="time-select">
<option value="">-- Seleccionar hora --</option>
</div>
<!-- Descuentos y Anticipos -->
<div class="discount-section modern-card">
<div class="discount-header">
<input type="checkbox" id="discount-toggle" class="modern-checkbox">
<label for="discount-toggle" class="discount-label">
<span class="discount-icon">🏷️</span>
<span>Descuentos y Anticipos</span>
</label>
</div>
<div class="discount-container" id="discount-container" style="display: none;">
<div class="discount-options">
<select id="discount-type" class="modern-select">
<option value="">Sin descuento</option>
<option value="percentage">💯 Porcentaje (%)</option>
<option value="amount">💰 Cantidad fija ($)</option>
<option value="anticipo">💳 Aplicar Anticipo</option>
<option value="warrior">🎗️ Vanity (100%)</option>
</select>
<div class="discount-input-group">
<input type="number" id="discount-value" min="0" step="0.01" placeholder="0" disabled />
<span class="input-symbol" id="discount-symbol">%</span>
</div>
</div>
<input type="text" id="discount-reason" placeholder="Motivo del descuento (opcional)" disabled class="modern-input" />
<!-- Checkbox de confirmación para anticipo manual -->
<div id="anticipo-manual-confirmation" style="display: none; margin-top: 10px;">
<label class="checkbox-container">
<input type="checkbox" id="confirm-anticipo-manual">
<span class="checkmark"></span>
<span class="checkbox-text">✅ Confirmo que el anticipo existe y fue dado por la cliente</span>
</label>
</div>
</div>
</div>
<!-- Anticipos Disponibles -->
<div id="anticipos-section" class="anticipos-section modern-card" style="display: none;">
<h4>💰 Anticipos Disponibles</h4>
<div id="anticipos-disponibles" class="anticipos-list">
<!-- Se llenan dinámicamente -->
</div>
</div>
<!-- Datos de Cita -->
<div class="appointment-section modern-card">
<h4>📅 Datos de la Cita</h4>
<div class="appointment-inputs">
<input type="date" id="m-fecha-cita" class="modern-input" placeholder="Fecha" />
<select id="m-hora-cita" class="modern-select">
<option value="">Seleccionar hora</option>
<option value="10:00">10:00 AM</option>
<option value="10:30">10:30 AM</option>
<option value="11:00">11:00 AM</option>
@@ -119,157 +251,108 @@
<option value="17:30">5:30 PM</option>
<option value="18:00">6:00 PM</option>
</select>
<div id="time-availability-info" class="time-availability-info" style="display: none;">
<span id="available-slots-count"></span>
</div>
</div>
<!-- Resumen y Totales -->
<div class="totals-section modern-card">
<div class="totals-breakdown">
<div class="total-row">
<span>Subtotal:</span>
<span id="subtotal-display">$0.00</span>
</div>
<div class="total-row discount-row" id="discount-display-row" style="display: none;">
<span>Descuento:</span>
<span id="discount-display" class="discount-amount">-$0.00</span>
</div>
<div class="total-row final-total">
<span><strong>TOTAL:</strong></span>
<span id="total-display" class="final-amount"><strong>$0.00</strong></span>
</div>
</div>
</div>
</div>
<!-- Venta -->
<div class="form-section">
<h3>Venta</h3>
<div class="products-container">
<div class="product-selector">
<select id="m-categoria" required>
<option value="">-- Seleccione tipo --</option>
<option value="service">Servicio</option>
<option value="course">Curso</option>
<option value="anticipo">Anticipo</option>
</select>
<select id="m-articulo" class="product-select">
<option value="">-- Primero seleccione tipo --</option>
</select>
<input type="number" id="product-quantity" min="1" value="1" class="quantity-input" placeholder="Cant." />
<button type="button" id="add-product-btn" class="btn-add">Agregar</button>
</div>
<div id="selected-products" class="selected-products"></div>
</div>
</div>
<!-- Descuentos -->
<div class="form-section discount-section">
<div class="discount-header">
<input type="checkbox" id="discount-toggle" class="discount-checkbox">
<label for="discount-toggle" class="discount-label">
<span class="material-icons-outlined discount-icon">percent</span>
Aplicar descuento
</label>
</div>
<div class="discount-container" id="discount-container" style="display: none;">
<div class="discount-grid">
<div class="form-group">
<label>Tipo de descuento</label>
<select id="discount-type">
<option value="">Sin descuento</option>
<option value="percentage">Porcentaje (%)</option>
<option value="amount">Cantidad fija ($)</option>
<option value="warrior">🎗️ Vanity (100%)</option>
</select>
</div>
<div class="form-group">
<label>Valor del descuento</label>
<div class="input-with-symbol">
<input type="number" id="discount-value" min="0" step="0.01" placeholder="0" disabled />
<span class="input-symbol" id="discount-symbol">%</span>
<!-- Método de Pago -->
<div class="payment-section modern-card">
<h4>💳 Método de Pago</h4>
<div class="payment-grid">
<label class="payment-option">
<input type="radio" name="m-metodo" value="Efectivo" checked />
<div class="payment-card">
<span class="payment-icon">💵</span>
<span>Efectivo</span>
</div>
</div>
<div class="form-group full-width-discount">
<label>Motivo del descuento</label>
<input type="text" id="discount-reason" placeholder="Ej: Cliente frecuente, promoción especial..." disabled />
</div>
</div>
<div class="discount-preview" id="discount-preview" style="display: none;">
<div class="discount-preview-item">
<span>Descuento aplicado:</span>
<span id="discount-preview-amount" class="discount-amount">$0.00</span>
</div>
</label>
<label class="payment-option">
<input type="radio" name="m-metodo" value="Tarjeta" />
<div class="payment-card">
<span class="payment-icon">💳</span>
<span>Tarjeta</span>
</div>
</label>
<label class="payment-option">
<input type="radio" name="m-metodo" value="Transferencia" />
<div class="payment-card">
<span class="payment-icon">🏦</span>
<span>Transferencia</span>
</div>
</label>
</div>
</div>
</div>
<!-- Anticipos Disponibles -->
<div class="form-section anticipos-section" id="anticipos-section" style="display: none;">
<h4>💰 Anticipos Disponibles</h4>
<div id="anticipos-disponibles" class="anticipos-container">
<!-- Los anticipos se cargarán dinámicamente -->
<!-- Notas -->
<div class="notes-section modern-card">
<h4>📝 Notas Adicionales</h4>
<textarea id="m-notas" placeholder="Comentarios especiales sobre la venta..." class="modern-textarea"></textarea>
</div>
<!-- Botones de Acción -->
<form id="formMove" class="checkout-form">
<input type="hidden" id="m-monto" />
<input type="hidden" id="m-concepto" />
<input type="hidden" id="m-staff" />
<input type="hidden" id="m-metodo" value="Efectivo" />
<div class="action-buttons">
<button type="submit" class="btn-checkout">
<span class="btn-icon">🎫</span>
<span>Generar Venta</span>
</button>
<button type="reset" class="btn-clear">
<span class="btn-icon">🗑️</span>
<span>Limpiar</span>
</button>
</div>
</form>
</div> <!-- fin checkout-panel -->
</div> <!-- fin sales-layout -->
</div> <!-- fin sales-container -->
</div> <!-- fin sub-tab-ventas -->
<!-- Sub-Pestaña de Tickets -->
<div id="sub-tab-tickets" class="sub-tab-content">
<div class="section">
<h2>🎫 Historial de Tickets y Movimientos</h2>
<button id="btnExport" class="btn-secondary">Exportar a CSV</button>
<div class="table-wrapper">
<table id="tblMoves">
<thead>
<tr>
<th>Folio</th>
<th>Fecha</th>
<th>Cita</th>
<th>Cliente</th>
<th>Servicio</th>
<th>Monto</th>
<th>Acciones</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
<!-- Método de Pago y Detalles -->
<div class="form-row">
<div class="form-group">
<label>Método de Pago *</label>
<select id="m-metodo" required>
<option value="">-- Seleccione método de pago --</option>
<option value="Efectivo">Efectivo</option>
<option value="Tarjeta">Tarjeta</option>
<option value="Transferencia">Transferencia</option>
<option value="Depósito">Depósito</option>
<option value="Giftcard">Giftcard</option>
<option value="Interno">Interno</option>
<option value="Otros">Otros</option>
</select>
</div>
<div class="form-group">
<label>Atendió</label>
<input type="text" id="m-staff" readonly />
</div>
</div>
<div class="form-group full-width">
<label>Notas</label>
<textarea id="m-notas" rows="2" placeholder="Notas adicionales..."></textarea>
</div>
<!-- Totales -->
<div class="totals-section">
<div class="totals-row">
<span>Subtotal:</span>
<span id="subtotal-display">$0.00</span>
</div>
<div class="totals-row" id="discount-display" style="display: none;">
<span>Descuento:</span>
<span id="discount-amount-display">-$0.00</span>
</div>
<div class="totals-row total-final">
<span>Total:</span>
<span id="total-display">$0.00</span>
</div>
</div>
<!-- Campos ocultos para compatibilidad -->
<input type="hidden" id="m-monto" />
<input type="hidden" id="m-concepto" />
<div class="form-actions-modern">
<button type="submit" class="btn-primary-large">Generar Venta y Ticket</button>
<button type="reset" class="btn-secondary-large">Limpiar Formulario</button>
</div>
</form>
</div>
<div class="section">
<h2>Movimientos Recientes</h2>
<button id="btnExport" class="btn-secondary">Exportar a CSV</button>
<div class="table-wrapper">
<table id="tblMoves">
<thead>
<tr>
<th>Folio</th>
<th>Fecha</th>
<th>Cita</th>
<th>Cliente</th>
<th>Servicio</th>
<th>Monto</th>
<th>Acciones</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
</div> <!-- fin sub-tab-tickets -->
</div>
<!-- Pestaña de Clientes -->
@@ -438,6 +521,9 @@
<div class="form-actions">
<button type="submit">Guardar</button>
<button type="reset" id="btnCancelEditProduct" class="btn-danger">Cancelar</button>
<button type="button" id="btnImportProducts" class="btn-secondary" onclick="importProductsFromJSON()">
📥 Importar Productos JSON
</button>
</div>
</form>
</div>
@@ -528,6 +614,38 @@
</div>
</div>
<!-- Pestaña de Solicitudes de Cancelación (Solo Admins) -->
<div id="tab-cancellation-requests" class="tab-content">
<div class="section">
<h2>Solicitudes de Cancelación</h2>
<p class="section-description">Aquí puedes revisar y gestionar las solicitudes de cancelación de ventas enviadas por los usuarios.</p>
<div class="table-wrapper">
<table id="tblCancellationRequests">
<thead>
<tr>
<th>Folio</th>
<th>Cliente</th>
<th>Monto</th>
<th>Solicitado por</th>
<th>Fecha Solicitud</th>
<th>Motivo</th>
<th>Estado</th>
<th>Acciones</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
<div id="no-cancellation-requests" style="display: none;">
<p style="text-align: center; color: #6c757d; font-style: italic; margin-top: 2rem;">
No hay solicitudes de cancelación pendientes.
</p>
</div>
</div>
</div>
<!-- Pestaña de Configuración -->
<div id="tab-settings" class="tab-content">
<div class="section">
@@ -629,6 +747,6 @@
<div id="printArea" class="no-print"></div>
<script src="https://cdn.jsdelivr.net/npm/qrcode@1/build/qrcode.min.js"></script>
<script type="module" src="app.js?v=1757039801"></script>
<script type="module" src="app.js?v=1757039803"></script>
</body>
</html>