// fichaje.eu — Screen: Control horario (admin — editable time report) const ScreenControl = () => { const [employee, setEmployee] = React.useState(TEAM[2]); // Marc by default const [editing, setEditing] = React.useState(null); return (
{/* Stats row */}
}/> }/> }/> }/>
Semana 20 · 11–17 mayo 2026
}>Filtros }>Exportar CSV
{/* Employee selector + week */}
{TEAM.map(p => { const active = employee.name === p.name; return ( ); })}
{/* Employee header */}
{employee.name}
{employee.role} · {employee.team}
Trabajadas
20h 38m
Previstas
24h
Saldo
+1h 14m
}>Añadir fichaje
{/* Day rows */}
Día
Entrada
Salida
Pausas
Visual
Trabajado
Saldo
Estado
{TIME_REPORT.map((r, i) => { const live = r.status === 'live'; const future = r.status === 'future'; const edited = r.status === 'edited'; const balance = (r.worked - r.expected); return (
{r.day}
{r.in}
{live ? En curso : r.out}
{r.breaks > 0 ? `${r.breaks} min` : '—'}
{!future && (
)}
{future ? '—' : `${Math.floor(r.worked)}h ${Math.round((r.worked - Math.floor(r.worked)) * 60)}m`}
= 0 ? 'var(--success-600)' : 'var(--danger-600)' }}> {future ? '—' : `${balance >= 0 ? '+' : ''}${Math.round(balance * 60)}m`}
{live && Hoy} {edited && Editado} {r.status === 'ok' && } {future && }
); })}
{/* Day detail (editable) */}
Detalle del martes 12 mayo · editado por Núria Castells
}>Añadir entrada
{[ { type: 'in', time: '09:12', label: 'Entrada' }, { type: 'pause', time: '11:30', label: 'Pausa café', duration: 14 }, { type: 'in', time: '11:44', label: 'Reanudación' }, { type: 'pause', time: '14:05', label: 'Comida', duration: 45 }, { type: 'in', time: '14:50', label: 'Reanudación' }, { type: 'out', time: '17:30', label: 'Salida', edited: true }, ].map((p, i, arr) => (
{p.type === 'in' ? : p.type === 'out' ? : }
{p.label} {p.edited && Editado por Núria}
{p.duration ? `${p.duration} min` : '—'}
))}
Descartar }>Guardar cambios
); }; Object.assign(window, { ScreenControl });