Skip to content

Instantly share code, notes, and snippets.

@Jcbertorello
Created December 26, 2025 18:41
Show Gist options
  • Select an option

  • Save Jcbertorello/c6219084d71aa4eedfb3820aabed17d5 to your computer and use it in GitHub Desktop.

Select an option

Save Jcbertorello/c6219084d71aa4eedfb3820aabed17d5 to your computer and use it in GitHub Desktop.
Dashboard Ajonjolí - 2025-12-26 18:41
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Dashboard de Rendimiento de Mozos - Octubre 2025 - RestoMaster</title>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<style>
:root {
--color-primary: #60B99A;
--color-primary-light: #7FCDB2;
--color-primary-dark: #4A9D80;
--color-secondary: #1F3B4D;
--color-secondary-light: #2D5066;
--color-dark: #1F3B4D;
--color-dark-soft: #2D4A5E;
--color-muted: #5A7A8A;
--color-light: #8FA5B2;
--color-bg: #F8FAFB;
--color-bg-alt: #EEF3F6;
--color-card: #FFFFFF;
--color-border: #D4DEE4;
--color-success: #16a34a;
--color-success-bg: #dcfce7;
--color-danger: #dc2626;
--color-danger-bg: #fee2e2;
--color-warning: #f59e0b;
--color-warning-bg: #fef3c7;
--color-neutral: #6b7280;
--color-neutral-bg: #f3f4f6;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
background-color: var(--color-bg);
color: var(--color-dark);
line-height: 1.6;
min-height: 100vh;
}
.dashboard {
max-width: 1200px;
margin: 0 auto;
padding: 32px 24px;
}
.action-buttons {
display: flex;
gap: 12px;
margin-bottom: 24px;
}
.btn {
display: inline-flex;
align-items: center;
gap: 8px;
padding: 12px 24px;
border-radius: 12px;
font-weight: 600;
font-size: 0.95rem;
cursor: pointer;
border: none;
transition: all 0.2s ease;
text-decoration: none;
}
.btn-primary {
background: linear-gradient(135deg, var(--color-primary) 0%, var(--color-primary-dark) 100%);
color: white;
box-shadow: 0 4px 12px -2px rgba(96, 185, 154, 0.4);
}
.btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 6px 16px -2px rgba(96, 185, 154, 0.5);
}
.btn-secondary {
background-color: var(--color-card);
color: var(--color-dark);
border: 1px solid var(--color-border);
}
.btn-secondary:hover {
background-color: var(--color-bg-alt);
border-color: var(--color-primary);
}
.header {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 32px;
flex-wrap: wrap;
gap: 20px;
}
.header-left {
display: flex;
align-items: center;
gap: 16px;
}
.logo {
width: 56px;
height: 56px;
background: linear-gradient(135deg, var(--color-primary) 0%, var(--color-primary-dark) 100%);
border-radius: 16px;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 1.5rem;
font-weight: 800;
box-shadow: 0 8px 20px -4px rgba(96, 185, 154, 0.4);
}
.header-title {
font-size: 1.75rem;
font-weight: 800;
color: var(--color-dark);
margin-bottom: 4px;
letter-spacing: -0.02em;
}
.header-subtitle {
font-size: 0.95rem;
color: var(--color-muted);
}
.header-right {
text-align: right;
}
.header-client {
font-size: 0.85rem;
font-weight: 600;
color: var(--color-primary);
text-transform: uppercase;
letter-spacing: 0.05em;
margin-bottom: 4px;
}
.header-date {
font-size: 0.85rem;
color: var(--color-light);
}
.kpi-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 20px;
margin-bottom: 32px;
}
.kpi-card {
background-color: var(--color-card);
border: 1px solid var(--color-border);
border-radius: 20px;
padding: 24px;
text-align: center;
box-shadow: 0 4px 20px -4px rgba(31, 59, 77, 0.08);
transition: all 0.3s ease;
break-inside: avoid;
page-break-inside: avoid;
position: relative;
overflow: hidden;
}
.kpi-card::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 4px;
background: linear-gradient(90deg, var(--color-primary), var(--color-primary-light));
}
.kpi-card:hover {
transform: translateY(-4px);
box-shadow: 0 12px 30px -4px rgba(31, 59, 77, 0.15);
}
.kpi-label {
font-size: 0.7rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.12em;
color: var(--color-muted);
margin-bottom: 12px;
}
.kpi-value {
font-size: 2.2rem;
font-weight: 800;
color: var(--color-dark);
line-height: 1.1;
margin-bottom: 8px;
}
.kpi-detail {
font-size: 0.85rem;
color: var(--color-muted);
}
.kpi-badge {
display: inline-flex;
align-items: center;
gap: 4px;
padding: 6px 14px;
border-radius: 50px;
font-size: 0.8rem;
font-weight: 700;
margin-top: 12px;
}
.kpi-badge.positive {
background-color: var(--color-success-bg);
color: var(--color-success);
}
.kpi-badge.negative {
background-color: var(--color-danger-bg);
color: var(--color-danger);
}
.kpi-badge.neutral {
background-color: var(--color-neutral-bg);
color: var(--color-neutral);
}
.grid-2 {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 24px;
margin-bottom: 24px;
}
.grid-3 {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 24px;
margin-bottom: 24px;
}
.chart-container {
height: 300px;
position: relative;
}
.table-wrapper {
overflow-x: auto;
}
.data-table {
width: 100%;
border-collapse: collapse;
font-size: 0.9rem;
}
.data-table thead {
background-color: var(--color-bg-alt);
}
.data-table th {
padding: 14px 16px;
text-align: left;
font-weight: 700;
color: var(--color-muted);
text-transform: uppercase;
font-size: 0.7rem;
letter-spacing: 0.08em;
border-bottom: 2px solid var(--color-border);
}
.data-table th.text-right {
text-align: right;
}
.data-table td {
padding: 14px 16px;
border-bottom: 1px solid var(--color-border);
color: var(--color-dark);
vertical-align: middle;
}
.data-table td.text-right {
text-align: right;
}
.data-table td.font-bold {
font-weight: 700;
}
.data-table tr:hover {
background-color: var(--color-bg);
}
.data-table tr:last-child td {
border-bottom: none;
}
.rank-badge {
width: 32px;
height: 32px;
border-radius: 10px;
display: inline-flex;
align-items: center;
justify-content: center;
font-weight: 800;
font-size: 0.85rem;
}
.rank-1 {
background: linear-gradient(135deg, #fbbf24, #f59e0b);
color: white;
}
.rank-2 {
background: linear-gradient(135deg, #9ca3af, #6b7280);
color: white;
}
.rank-3 {
background: linear-gradient(135deg, #f97316, #ea580c);
color: white;
}
.rank-default {
background-color: var(--color-bg-alt);
color: var(--color-muted);
}
.progress-bar {
height: 8px;
background-color: var(--color-neutral-bg);
border-radius: 4px;
overflow: hidden;
margin-top: 6px;
min-width: 100px;
}
.progress-fill {
height: 100%;
background: linear-gradient(90deg, var(--color-primary), var(--color-primary-light));
border-radius: 4px;
transition: width 1s ease-out;
}
.top-item {
display: flex;
align-items: center;
gap: 16px;
padding: 16px 0;
border-bottom: 1px solid var(--color-border);
}
.top-item:last-child {
border-bottom: none;
}
.top-item-rank {
width: 40px;
height: 40px;
border-radius: 12px;
display: flex;
align-items: center;
justify-content: center;
font-weight: 800;
font-size: 1rem;
flex-shrink: 0;
}
.top-item-content {
flex: 1;
min-width: 0;
}
.top-item-name {
font-weight: 600;
color: var(--color-dark);
margin-bottom: 4px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.top-item-meta {
font-size: 0.8rem;
color: var(--color-muted);
}
.top-item-value {
font-weight: 800;
font-size: 1.1rem;
color: var(--color-dark);
text-align: right;
}
.footer {
text-align: center;
padding: 32px 24px;
margin-top: 32px;
border-top: 1px solid var(--color-border);
}
.footer-content {
display: flex;
flex-direction: column;
align-items: center;
gap: 12px;
}
.footer-brand {
display: inline-flex;
align-items: center;
gap: 10px;
color: var(--color-muted);
font-size: 0.9rem;
}
.footer-logo {
width: 28px;
height: 28px;
background: linear-gradient(135deg, var(--color-primary), var(--color-primary-dark));
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-size: 0.75rem;
font-weight: 800;
}
.footer-tagline {
font-size: 0.75rem;
color: var(--color-light);
font-style: italic;
}
.footer-date {
font-size: 0.8rem;
color: var(--color-light);
}
@media (max-width: 900px) {
.grid-2,
.grid-3 {
grid-template-columns: 1fr;
}
.kpi-grid {
grid-template-columns: repeat(2, 1fr);
}
.header {
flex-direction: column;
}
.header-right {
text-align: left;
}
}
@media (max-width: 500px) {
.kpi-grid {
grid-template-columns: 1fr;
}
.dashboard {
padding: 20px 16px;
}
}
@media print {
body {
background-color: white !important;
-webkit-print-color-adjust: exact !important;
print-color-adjust: exact !important;
}
.action-buttons {
display: none !important;
}
.card,
.kpi-card {
break-inside: avoid !important;
page-break-inside: avoid !important;
box-shadow: none !important;
border: 1px solid #e0e0e0 !important;
}
.card:hover,
.kpi-card:hover {
transform: none !important;
}
.dashboard {
padding: 16px !important;
max-width: 100% !important;
}
.kpi-card::before {
background: var(--color-primary) !important;
}
.logo,
.footer-logo {
background: var(--color-primary) !important;
}
.btn-primary {
background: var(--color-primary) !important;
}
}
</style>
</head>
<body>
<div class="dashboard">
<div class="action-buttons">
<button class="btn btn-primary" onclick="downloadPDF()">
<svg width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4M7 10l5 5 5-5M12 15V3"></path>
</svg>
Descargar PDF
</button>
<button class="btn btn-secondary" onclick="window.print()">
<svg width="18" height="18" fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
<path d="M6 9V2h12v7M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2"></path>
<rect x="6" y="14" width="12" height="8"></rect>
</svg>
Imprimir
</button>
</div>
<div class="header">
<div class="header-left">
<div class="logo">R</div>
<div>
<h1 class="header-title">Dashboard de Rendimiento de Mozos - Octubre 2025</h1>
<p class="header-subtitle">Período: del 01/10/2025 al 31/10/2025</p>
</div>
</div>
<div class="header-right">
<div class="header-client">RestoMaster</div>
<div class="header-date">Generado: 26/12/2025 15:40</div>
</div>
</div>
<div class="kpi-grid">
<div class="kpi-card">
<div class="kpi-label">Total de Mozos</div>
<div class="kpi-value">1</div>
<div class="kpi-detail">Mozos activos en octubre</div>
<div class="kpi-badge neutral">-</div>
</div>
<div class="kpi-card">
<div class="kpi-label">Total de Pedidos</div>
<div class="kpi-value">1</div>
<div class="kpi-detail">Cantidad total de pedidos</div>
<div class="kpi-badge neutral">-</div>
</div>
<div class="kpi-card">
<div class="kpi-label">Facturación Total</div>
<div class="kpi-value">$3.000</div>
<div class="kpi-detail">Importe facturado en octubre</div>
<div class="kpi-badge neutral">-</div>
</div>
<div class="kpi-card">
<div class="kpi-label">Ticket Promedio</div>
<div class="kpi-value">$3.000</div>
<div class="kpi-detail">Promedio por pedido</div>
<div class="kpi-badge neutral">-</div>
</div>
<div class="kpi-card">
<div class="kpi-label">Mesas Atendidas</div>
<div class="kpi-value">1</div>
<div class="kpi-detail">Total de mesas atendidas</div>
<div class="kpi-badge neutral">-</div>
</div>
</div>
<div class="card">
<div class="card-title">Detalle por Mozos</div>
<div class="card-subtitle">Indicadores clave para cada mozo en octubre 2025</div>
<div class="table-wrapper">
<table class="data-table" cellspacing="0">
<thead>
<tr>
<th>Pos</th>
<th>Empleado</th>
<th class="text-right">Pedidos</th>
<th class="text-right">Facturación</th>
<th class="text-right">Ticket Promedio</th>
<th class="text-right">Mesas Atendidas</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<span class="rank-badge rank-1">1</span>
</td>
<td class="font-bold">Juan Pérez</td>
<td class="text-right">1</td>
<td class="text-right">$3.000</td>
<td class="text-right">$3.000</td>
<td class="text-right">1</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="footer">
<div class="footer-content">
<div class="footer-brand">
<div class="footer-logo">M</div>
<span>Powered by <strong>MostachIA</strong></span>
</div>
<div class="footer-tagline">"Procesos inteligentes, resultados superiores"</div>
<div class="footer-date">26/12/2025 15:40</div>
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.10.1/html2pdf.bundle.min.js"></script>
<script>
Chart.defaults.font.family = "system-ui, -apple-system, sans-serif";
Chart.defaults.font.size = 12;
Chart.defaults.color = '#5A7A8A';
Chart.defaults.plugins.legend.labels.usePointStyle = true;
Chart.defaults.plugins.legend.labels.padding = 20;
Chart.defaults.plugins.legend.position = 'bottom';
const chartColors = {
primary: '#60B99A',
primaryLight: '#7FCDB2',
primaryDark: '#4A9D80',
secondary: '#1F3B4D',
secondaryLight: '#2D5066',
muted: '#5A7A8A',
light: '#8FA5B2',
palette: [
'#60B99A',
'#1F3B4D',
'#7FCDB2',
'#2D5066',
'#4A9D80',
'#5A7A8A',
'#8FA5B2',
'#A8D5C2'
],
comparison: ['#60B99A', '#1F3B4D'],
gradientStart: 'rgba(96, 185, 154, 0.3)',
gradientEnd: 'rgba(96, 185, 154, 0.05)'
};
function downloadPDF() {
const buttons = document.querySelector('.action-buttons');
buttons.style.display = 'none';
const element = document.querySelector('.dashboard');
const title = document.querySelector('.header-title')?.textContent || 'Dashboard';
const filename = 'restomaster-' +
title
.toLowerCase()
.normalize('NFD')
.replace(/[\u0300-\u036f]/g, '')
.replace(/[^a-z0-9]+/g, '-')
.replace(/-+/g, '-')
.replace(/^-|-$/g, '') +
'.pdf';
const opt = {
margin: [8, 8, 8, 8],
filename: filename,
image: { type: 'jpeg', quality: 0.95 },
html2canvas: {
scale: 2,
useCORS: true,
logging: false,
backgroundColor: '#ffffff',
windowWidth: 1200
},
jsPDF: {
unit: 'mm',
format: 'a4',
orientation: 'landscape'
},
pagebreak: {
mode: ['avoid-all', 'css', 'legacy'],
before: '.page-break-before',
after: '.page-break-after',
avoid: '.card, .kpi-card'
}
};
html2pdf()
.set(opt)
.from(element)
.save()
.then(() => {
buttons.style.display = 'flex';
})
.catch(() => {
buttons.style.display = 'flex';
alert('Error al generar PDF. Intentá con el botón Imprimir.');
});
}
function formatCurrency(value) {
if (value >= 1000000) {
return "$" + (value / 1000000).toFixed(1) + "M";
}
if (value >= 1000) {
return "$" + (value / 1000).toFixed(0) + "K";
}
return "$" + value.toLocaleString("es-AR", { maximumFractionDigits: 0 });
}
function formatNumber(value) {
return value.toLocaleString("es-AR", { maximumFractionDigits: 0 });
}
function formatPercent(value) {
return value.toFixed(1) + "%";
}
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment