Spaces:
Running
Running
| import React, { useState, useEffect } from 'react'; | |
| import { db } from '../../firebase/config'; | |
| import { ref, onValue, set } from 'firebase/database'; | |
| import { Clock, Save, User as UserIcon } from 'lucide-react'; | |
| export default function EmployeeSchedules() { | |
| const [employees, setEmployees] = useState([]); | |
| const [schedules, setSchedules] = useState({}); | |
| useEffect(() => { | |
| // Fetch Employees (Users with role 'mesero' or 'admin') | |
| onValue(ref(db, 'users'), (snapshot) => { | |
| const data = snapshot.val(); | |
| if (data) { | |
| setEmployees(Object.keys(data).map(k => ({ email: k.replace(',', '.'), ...data[k] }))); | |
| } | |
| }); | |
| // Fetch Schedules | |
| onValue(ref(db, 'schedules'), (snapshot) => { | |
| if (snapshot.exists()) setSchedules(snapshot.val()); | |
| }); | |
| }, []); | |
| const handleUpdateSchedule = async (email, field, value) => { | |
| const safeEmail = email.replace(/\./g, ','); | |
| await set(ref(db, `schedules/${safeEmail}/${field}`), value); | |
| }; | |
| return ( | |
| <div className="animate-fade-in" style={{ padding: '0 1rem' }}> | |
| <header style={{ marginBottom: '2rem' }}> | |
| <h2 className="text-gradient" style={{ fontSize: '2rem', fontWeight: '800', display: 'flex', alignItems: 'center', gap: '0.75rem' }}> | |
| <Clock size={28} /> Control de Horarios | |
| </h2> | |
| <p style={{ color: 'var(--text-muted)' }}>Asignación de turnos y disponibilidad de personal</p> | |
| </header> | |
| <div className="glass-panel" style={{ overflow: 'hidden' }}> | |
| <table style={{ width: '100%', borderCollapse: 'collapse', textAlign: 'left' }}> | |
| <thead> | |
| <tr style={{ borderBottom: '1px solid var(--border-subtle)', background: 'rgba(255,255,255,0.02)' }}> | |
| <th style={{ padding: '1.25rem', color: 'var(--text-muted)', fontWeight: '500' }}>Empleado</th> | |
| <th style={{ padding: '1.25rem', color: 'var(--text-muted)', fontWeight: '500' }}>Rol</th> | |
| <th style={{ padding: '1.25rem', color: 'var(--text-muted)', fontWeight: '500' }}>Entrada</th> | |
| <th style={{ padding: '1.25rem', color: 'var(--text-muted)', fontWeight: '500' }}>Salida</th> | |
| <th style={{ padding: '1.25rem', color: 'var(--text-muted)', fontWeight: '500' }}>Estado</th> | |
| </tr> | |
| </thead> | |
| <tbody> | |
| {employees.map((emp) => { | |
| const safeEmail = emp.email.replace(/\./g, ','); | |
| const sched = schedules[safeEmail] || { start: '09:00', end: '17:00' }; | |
| return ( | |
| <tr key={emp.email} style={{ borderBottom: '1px solid var(--border-subtle)' }} className="table-row-hover"> | |
| <td style={{ padding: '1.25rem' }}> | |
| <div style={{ display: 'flex', alignItems: 'center', gap: '0.75rem' }}> | |
| <div style={{ width: '32px', height: '32px', borderRadius: '50%', background: 'var(--primary)', display: 'flex', alignItems: 'center', justifyContent: 'center' }}> | |
| <UserIcon size={16} color="#fff" /> | |
| </div> | |
| <span style={{ fontWeight: '600' }}>{emp.email}</span> | |
| </div> | |
| </td> | |
| <td style={{ padding: '1.25rem' }}> | |
| <span style={{ fontSize: '0.75rem', textTransform: 'uppercase', background: 'rgba(255,255,255,0.05)', padding: '4px 10px', borderRadius: '12px', color: 'var(--text-muted)' }}> | |
| {emp.role} | |
| </span> | |
| </td> | |
| <td style={{ padding: '1.25rem' }}> | |
| <input | |
| type="time" | |
| value={sched.start} | |
| onChange={(e) => handleUpdateSchedule(emp.email, 'start', e.target.value)} | |
| style={inputStyle} | |
| /> | |
| </td> | |
| <td style={{ padding: '1.25rem' }}> | |
| <input | |
| type="time" | |
| value={sched.end} | |
| onChange={(e) => handleUpdateSchedule(emp.email, 'end', e.target.value)} | |
| style={inputStyle} | |
| /> | |
| </td> | |
| <td style={{ padding: '1.25rem' }}> | |
| <span style={{ color: 'var(--success)', fontSize: '0.8rem', fontWeight: '600' }}>Activo</span> | |
| </td> | |
| </tr> | |
| ); | |
| })} | |
| </tbody> | |
| </table> | |
| </div> | |
| </div> | |
| ); | |
| } | |
| const inputStyle = { | |
| padding: '0.5rem', | |
| borderRadius: '6px', | |
| background: 'rgba(255,255,255,0.05)', | |
| border: '1px solid var(--border-subtle)', | |
| color: '#fff', | |
| outline: 'none', | |
| fontSize: '0.9rem' | |
| }; | |