Bloqueantes POS: modal-pago, ticket-termico, banner-cliente, fkeys-footer, columnas-costo-margen Componentes nuevos: calculadora-cambio, panel-deslizante, badge-cfdi, arbol-colapsable, tarjeta-metrica, grafica-barras, selector-periodo, etiqueta-codigo-barras Estados: estado-vacio, banner-offline, modal-confirmacion Páginas actualizadas: facturación, contabilidad, dashboard, configuración, reportes
415 lines
14 KiB
HTML
415 lines
14 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="es" data-theme="industrial">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Nexus Autoparts — Selector de Período</title>
|
|
<link rel="stylesheet" href="../tokens/tokens.css">
|
|
<style>
|
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
body {
|
|
font-family: var(--font-body); background: var(--color-bg-base);
|
|
color: var(--color-text-primary); padding: var(--space-8);
|
|
transition: var(--transition-normal);
|
|
}
|
|
.theme-switcher {
|
|
position: sticky; top: 0; z-index: calc(var(--z-modal) + 10);
|
|
display: flex; gap: var(--space-2);
|
|
padding: var(--space-3) var(--space-4);
|
|
background: var(--color-bg-elevated);
|
|
border-bottom: 1px solid var(--color-border);
|
|
margin: calc(-1 * var(--space-8)); margin-bottom: var(--space-8);
|
|
}
|
|
.theme-switcher button {
|
|
padding: var(--space-2) var(--space-4);
|
|
border: 1px solid var(--color-border);
|
|
background: var(--color-bg-base); color: var(--color-text-primary);
|
|
border-radius: var(--radius-md); cursor: pointer;
|
|
font-family: var(--font-body); font-size: var(--text-body-sm);
|
|
transition: var(--transition-fast);
|
|
}
|
|
.theme-switcher button.active {
|
|
background: var(--color-primary); color: var(--color-text-inverse);
|
|
border-color: var(--color-primary);
|
|
}
|
|
h1 { font-family: var(--font-heading); font-size: var(--text-h2);
|
|
font-weight: var(--heading-weight-primary); margin-bottom: var(--space-2);
|
|
color: var(--color-text-accent); }
|
|
.subtitle { color: var(--color-text-muted); font-size: var(--text-body); margin-bottom: var(--space-8); }
|
|
section { margin-bottom: var(--space-10); }
|
|
section > h2 {
|
|
font-family: var(--font-heading); font-size: var(--text-h4);
|
|
font-weight: var(--heading-weight-secondary); color: var(--color-text-secondary);
|
|
margin-bottom: var(--space-4); padding-bottom: var(--space-2);
|
|
border-bottom: 1px solid var(--color-border);
|
|
}
|
|
|
|
/* ── Shared form styles ── */
|
|
.form-label {
|
|
display: block;
|
|
font-size: var(--text-label);
|
|
font-weight: var(--font-weight-semibold);
|
|
color: var(--color-text-secondary);
|
|
margin-bottom: var(--space-1);
|
|
text-transform: uppercase;
|
|
letter-spacing: var(--tracking-wider);
|
|
}
|
|
|
|
select, input[type="date"] {
|
|
appearance: none;
|
|
-webkit-appearance: none;
|
|
font-family: var(--font-body);
|
|
font-size: var(--text-body-sm);
|
|
color: var(--color-text-primary);
|
|
background: var(--color-bg-base);
|
|
border: 1px solid var(--color-border);
|
|
border-radius: var(--radius-md);
|
|
padding: var(--space-2) var(--space-3);
|
|
padding-right: var(--space-8);
|
|
transition: var(--transition-fast);
|
|
cursor: pointer;
|
|
min-width: 0;
|
|
}
|
|
select:hover, input[type="date"]:hover {
|
|
border-color: var(--color-border-strong);
|
|
}
|
|
select:focus, input[type="date"]:focus {
|
|
outline: none;
|
|
border-color: var(--color-border-focus);
|
|
box-shadow: var(--shadow-focus);
|
|
}
|
|
input[type="date"] {
|
|
padding-right: var(--space-3);
|
|
}
|
|
|
|
/* Select arrow */
|
|
.select-wrap {
|
|
position: relative;
|
|
display: inline-block;
|
|
}
|
|
.select-wrap::after {
|
|
content: '';
|
|
position: absolute;
|
|
right: 12px; top: 50%;
|
|
transform: translateY(-50%);
|
|
width: 0; height: 0;
|
|
border-left: 5px solid transparent;
|
|
border-right: 5px solid transparent;
|
|
border-top: 5px solid var(--color-text-muted);
|
|
pointer-events: none;
|
|
}
|
|
|
|
/* ── Buttons ── */
|
|
.btn {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: var(--space-2);
|
|
font-family: var(--font-body);
|
|
font-size: var(--text-body-sm);
|
|
font-weight: var(--font-weight-semibold);
|
|
padding: var(--space-2) var(--space-4);
|
|
border-radius: var(--radius-md);
|
|
border: 1px solid transparent;
|
|
cursor: pointer;
|
|
transition: var(--transition-fast);
|
|
white-space: nowrap;
|
|
}
|
|
.btn-primary {
|
|
background: var(--btn-primary-bg);
|
|
color: var(--btn-primary-text);
|
|
border-color: var(--btn-primary-border);
|
|
}
|
|
.btn-primary:hover { background: var(--btn-primary-bg-hover); }
|
|
.btn-primary:active { background: var(--btn-primary-bg-active); }
|
|
|
|
.btn-ghost {
|
|
background: var(--btn-ghost-bg);
|
|
color: var(--btn-ghost-text);
|
|
border-color: var(--btn-ghost-border);
|
|
}
|
|
.btn-ghost:hover {
|
|
background: var(--color-surface-2);
|
|
}
|
|
|
|
/* ── Period Selector: Dropdown variant ── */
|
|
.period-selector {
|
|
display: flex;
|
|
align-items: flex-end;
|
|
gap: var(--space-3);
|
|
flex-wrap: wrap;
|
|
background: var(--color-bg-elevated);
|
|
border: 1px solid var(--color-border);
|
|
border-radius: var(--radius-lg);
|
|
padding: var(--space-4) var(--space-5);
|
|
}
|
|
.period-selector .field {
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
.period-selector select {
|
|
min-width: 140px;
|
|
}
|
|
|
|
/* ── Presets (quick actions) ── */
|
|
.presets {
|
|
display: flex;
|
|
gap: var(--space-2);
|
|
flex-wrap: wrap;
|
|
}
|
|
.preset-btn {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: var(--space-1);
|
|
font-family: var(--font-body);
|
|
font-size: var(--text-caption);
|
|
font-weight: var(--font-weight-semibold);
|
|
padding: var(--space-1) var(--space-3);
|
|
border-radius: var(--radius-full);
|
|
border: 1px solid var(--color-border);
|
|
background: var(--color-bg-base);
|
|
color: var(--color-text-secondary);
|
|
cursor: pointer;
|
|
transition: var(--transition-fast);
|
|
white-space: nowrap;
|
|
}
|
|
.preset-btn:hover {
|
|
border-color: var(--color-primary);
|
|
color: var(--color-primary);
|
|
background: var(--color-primary-muted);
|
|
}
|
|
.preset-btn.active {
|
|
background: var(--color-primary);
|
|
color: var(--color-text-inverse);
|
|
border-color: var(--color-primary);
|
|
}
|
|
|
|
/* ── Date Range variant ── */
|
|
.date-range-selector {
|
|
display: flex;
|
|
align-items: flex-end;
|
|
gap: var(--space-3);
|
|
flex-wrap: wrap;
|
|
background: var(--color-bg-elevated);
|
|
border: 1px solid var(--color-border);
|
|
border-radius: var(--radius-lg);
|
|
padding: var(--space-4) var(--space-5);
|
|
}
|
|
.date-range-selector .field {
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
.separator {
|
|
font-size: var(--text-body);
|
|
color: var(--color-text-muted);
|
|
padding-bottom: var(--space-2);
|
|
font-weight: var(--font-weight-semibold);
|
|
}
|
|
|
|
/* ── Selected period display ── */
|
|
.selected-display {
|
|
margin-top: var(--space-3);
|
|
padding: var(--space-3) var(--space-4);
|
|
background: var(--color-primary-muted);
|
|
border-left: 3px solid var(--color-primary);
|
|
border-radius: 0 var(--radius-md) var(--radius-md) 0;
|
|
font-size: var(--text-body-sm);
|
|
color: var(--color-text-secondary);
|
|
}
|
|
.selected-display strong {
|
|
color: var(--color-text-accent);
|
|
font-family: var(--font-mono);
|
|
}
|
|
|
|
/* ── Compact inline variant ── */
|
|
.period-inline {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: var(--space-2);
|
|
background: var(--color-bg-elevated);
|
|
border: 1px solid var(--color-border);
|
|
border-radius: var(--radius-lg);
|
|
padding: var(--space-2) var(--space-3);
|
|
}
|
|
.period-inline select {
|
|
padding: var(--space-1) var(--space-2);
|
|
padding-right: var(--space-6);
|
|
font-size: var(--text-caption);
|
|
min-width: 100px;
|
|
}
|
|
.period-inline .btn {
|
|
padding: var(--space-1) var(--space-3);
|
|
font-size: var(--text-caption);
|
|
}
|
|
.period-inline .select-wrap::after {
|
|
right: 8px;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="theme-switcher">
|
|
<button class="active" onclick="document.documentElement.dataset.theme='industrial'; this.classList.add('active'); this.nextElementSibling.classList.remove('active')">🔧 Industrial</button>
|
|
<button onclick="document.documentElement.dataset.theme='modern'; this.classList.add('active'); this.previousElementSibling.classList.remove('active')">⚡ Moderno</button>
|
|
</div>
|
|
|
|
<h1>Selector de Período</h1>
|
|
<p class="subtitle">Controles para seleccionar períodos de reporte: mes/año, presets rápidos y rango de fechas.</p>
|
|
|
|
<!-- ── Variant A: Dropdowns + button ── -->
|
|
<section>
|
|
<h2>Selector por Mes y Año</h2>
|
|
<div class="period-selector">
|
|
<div class="field">
|
|
<label class="form-label" for="selYear">Año</label>
|
|
<div class="select-wrap">
|
|
<select id="selYear">
|
|
<option value="2024">2024</option>
|
|
<option value="2025">2025</option>
|
|
<option value="2026" selected>2026</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="field">
|
|
<label class="form-label" for="selMonth">Mes</label>
|
|
<div class="select-wrap">
|
|
<select id="selMonth">
|
|
<option value="1">Enero</option>
|
|
<option value="2">Febrero</option>
|
|
<option value="3">Marzo</option>
|
|
<option value="4" selected>Abril</option>
|
|
<option value="5">Mayo</option>
|
|
<option value="6">Junio</option>
|
|
<option value="7">Julio</option>
|
|
<option value="8">Agosto</option>
|
|
<option value="9">Septiembre</option>
|
|
<option value="10">Octubre</option>
|
|
<option value="11">Noviembre</option>
|
|
<option value="12">Diciembre</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<button class="btn btn-primary" onclick="consultarPeriodo()">Consultar</button>
|
|
</div>
|
|
<div class="selected-display" id="displayPeriod">
|
|
Período seleccionado: <strong>Abril 2026</strong>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- ── Variant B: Quick presets ── -->
|
|
<section>
|
|
<h2>Presets Rápidos</h2>
|
|
<div class="period-selector" style="flex-direction: column; align-items: flex-start; gap: var(--space-3);">
|
|
<div class="presets" id="presetGroup">
|
|
<button class="preset-btn active" onclick="selectPreset(this, 'Este mes')">Este mes</button>
|
|
<button class="preset-btn" onclick="selectPreset(this, 'Mes anterior')">Mes anterior</button>
|
|
<button class="preset-btn" onclick="selectPreset(this, 'Este trimestre')">Este trimestre</button>
|
|
<button class="preset-btn" onclick="selectPreset(this, 'Este año')">Este año</button>
|
|
</div>
|
|
<div class="selected-display" id="displayPreset">
|
|
Período: <strong>Abril 2026</strong> (Este mes)
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- ── Variant C: Date range ── -->
|
|
<section>
|
|
<h2>Rango de Fechas</h2>
|
|
<div class="date-range-selector">
|
|
<div class="field">
|
|
<label class="form-label" for="dateFrom">Desde</label>
|
|
<input type="date" id="dateFrom" value="2026-04-01">
|
|
</div>
|
|
<span class="separator">—</span>
|
|
<div class="field">
|
|
<label class="form-label" for="dateTo">Hasta</label>
|
|
<input type="date" id="dateTo" value="2026-04-30">
|
|
</div>
|
|
<button class="btn btn-primary" onclick="consultarRango()">Consultar</button>
|
|
<button class="btn btn-ghost" onclick="limpiarRango()">Limpiar</button>
|
|
</div>
|
|
<div class="selected-display" id="displayRange">
|
|
Rango: <strong>01/04/2026</strong> — <strong>30/04/2026</strong> (30 días)
|
|
</div>
|
|
</section>
|
|
|
|
<!-- ── Variant D: Compact inline ── -->
|
|
<section>
|
|
<h2>Variante Compacta (Inline)</h2>
|
|
<p style="color: var(--color-text-muted); font-size: var(--text-body-sm); margin-bottom: var(--space-3);">
|
|
Para uso en headers de tablas o secciones con espacio reducido.
|
|
</p>
|
|
<div class="period-inline">
|
|
<div class="select-wrap">
|
|
<select>
|
|
<option>Abril</option>
|
|
<option>Marzo</option>
|
|
<option>Febrero</option>
|
|
</select>
|
|
</div>
|
|
<div class="select-wrap">
|
|
<select>
|
|
<option>2026</option>
|
|
<option>2025</option>
|
|
<option>2024</option>
|
|
</select>
|
|
</div>
|
|
<button class="btn btn-primary">Ir</button>
|
|
</div>
|
|
</section>
|
|
|
|
<script>
|
|
const meses = ['Enero','Febrero','Marzo','Abril','Mayo','Junio',
|
|
'Julio','Agosto','Septiembre','Octubre','Noviembre','Diciembre'];
|
|
|
|
function consultarPeriodo() {
|
|
const year = document.getElementById('selYear').value;
|
|
const monthIdx = document.getElementById('selMonth').value;
|
|
const monthName = meses[monthIdx - 1];
|
|
document.getElementById('displayPeriod').innerHTML =
|
|
'Período seleccionado: <strong>' + monthName + ' ' + year + '</strong>';
|
|
}
|
|
|
|
function selectPreset(btn, label) {
|
|
document.querySelectorAll('#presetGroup .preset-btn').forEach(b => b.classList.remove('active'));
|
|
btn.classList.add('active');
|
|
|
|
const now = new Date(2026, 3, 1); // April 2026
|
|
let text = '';
|
|
switch (label) {
|
|
case 'Este mes':
|
|
text = 'Período: <strong>Abril 2026</strong> (Este mes)';
|
|
break;
|
|
case 'Mes anterior':
|
|
text = 'Período: <strong>Marzo 2026</strong> (Mes anterior)';
|
|
break;
|
|
case 'Este trimestre':
|
|
text = 'Período: <strong>Enero — Marzo 2026</strong> (Q1 2026)';
|
|
break;
|
|
case 'Este año':
|
|
text = 'Período: <strong>Enero — Diciembre 2026</strong> (Año completo)';
|
|
break;
|
|
}
|
|
document.getElementById('displayPreset').innerHTML = text;
|
|
}
|
|
|
|
function consultarRango() {
|
|
const from = document.getElementById('dateFrom').value;
|
|
const to = document.getElementById('dateTo').value;
|
|
if (!from || !to) return;
|
|
const d1 = new Date(from), d2 = new Date(to);
|
|
const days = Math.round((d2 - d1) / (1000 * 60 * 60 * 24)) + 1;
|
|
const fmt = d => d.toLocaleDateString('es-MX', { day: '2-digit', month: '2-digit', year: 'numeric' });
|
|
document.getElementById('displayRange').innerHTML =
|
|
'Rango: <strong>' + fmt(d1) + '</strong> — <strong>' + fmt(d2) + '</strong> (' + days + ' días)';
|
|
}
|
|
|
|
function limpiarRango() {
|
|
document.getElementById('dateFrom').value = '';
|
|
document.getElementById('dateTo').value = '';
|
|
document.getElementById('displayRange').innerHTML =
|
|
'Rango: <strong>—</strong>';
|
|
}
|
|
</script>
|
|
</body>
|
|
</html>
|