import { useAlert } from '../context/AlertContext' import { useAuth } from '../context/AuthContext' import Forbidden from '../components/Forbidden' import { motion } from 'framer-motion' import ConfirmModal from '../components/ConfirmModal' import AdminDatePicker from '../components/AdminDatePicker' import BulkAttendanceModal from '../components/BulkAttendanceModal' import ShiftFormModal from '../components/ShiftFormModal' import AttendanceShiftTable from '../components/AttendanceShiftTable' import useModalLock from '../hooks/useModalLock' import useAttendanceAdmin from '../hooks/useAttendanceAdmin' import FormField from '../components/FormField' import { formatMinutes } from '../utils/attendanceHelpers' interface UserTotalData { name: string minutes: number working: boolean vacation_hours: number sick_hours: number holiday_hours: number unpaid_hours: number fund: number | null worked_hours: number covered: number missing: number overtime: number } function getFundBarBackground(data: UserTotalData) { if (data.overtime > 0) return 'linear-gradient(135deg, var(--warning), #d97706)' if (data.covered >= (data.fund ?? 0)) return 'linear-gradient(135deg, var(--success), #059669)' return 'var(--gradient)' } export default function AttendanceAdmin() { const alert = useAlert() const { hasPermission } = useAuth() const { loading, month, setMonth, filterUserId, setFilterUserId, data, hasData, showBulkModal, setShowBulkModal, bulkSubmitting, bulkForm, setBulkForm, showCreateModal, setShowCreateModal, createForm, setCreateForm, showEditModal, setShowEditModal, editingRecord, editForm, setEditForm, deleteConfirm, setDeleteConfirm, projectList, createProjectLogs, setCreateProjectLogs, editProjectLogs, setEditProjectLogs, openCreateModal, handleCreateShiftDateChange, handleCreateSubmit, openBulkModal, toggleBulkUser, toggleAllBulkUsers, handleBulkSubmit, openEditModal, handleEditSubmit, handleDelete, handlePrint } = useAttendanceAdmin({ alert }) useModalLock(showBulkModal) useModalLock(showEditModal) useModalLock(showCreateModal) if (!hasPermission('attendance.admin')) return // Show skeleton only on initial load (no data yet), not on filter changes const isInitialLoad = loading && data.records.length === 0 && Object.keys(data.user_totals).length === 0 if (isInitialLoad) { return (
{[0, 1, 2].map(i => (
))}
{[0, 1, 2, 3, 4].map(i => (
))}
) } return (

Správa docházky

{hasData && ( )}
{/* Filters */}
setMonth(val)} />
{/* User Totals */} {Object.keys(data.user_totals).length > 0 && ( {Object.entries(data.user_totals).map(([uid, userData]) => { const ut = userData as UserTotalData return (
{ut.name} {ut.working ? '\u2713' : '\u2717'}
{formatMinutes(ut.minutes)}
odpracováno
{ut.vacation_hours > 0 && ( Dov: {ut.vacation_hours}h )} {ut.sick_hours > 0 && ( Nem: {ut.sick_hours}h )} {ut.holiday_hours > 0 && ( Sv: {ut.holiday_hours}h )} {ut.unpaid_hours > 0 && ( Nep: {ut.unpaid_hours}h )}
{ut.fund !== null && (
Fond: {ut.worked_hours}h / {ut.fund}h {ut.overtime > 0 && ( +{ut.overtime}h )} {ut.overtime <= 0 && ut.missing > 0 && ( -{ut.missing}h )}
)} {data.leave_balances[uid] && (
Zbývá dovolené: {data.leave_balances[uid].vacation_remaining.toFixed(1)}h / {data.leave_balances[uid].vacation_total}h
)}
) })} )} {/* Records Table */}
setDeleteConfirm({ show: true, record })} />
{/* Modals */} setShowBulkModal(false)} form={bulkForm} setForm={setBulkForm} users={data.users} onSubmit={handleBulkSubmit} submitting={bulkSubmitting} toggleUser={toggleBulkUser} toggleAllUsers={toggleAllBulkUsers} /> setShowCreateModal(false)} onSubmit={handleCreateSubmit} form={createForm} setForm={setCreateForm} projectLogs={createProjectLogs} setProjectLogs={setCreateProjectLogs} projectList={projectList} users={data.users} onShiftDateChange={handleCreateShiftDateChange} editingRecord={null} /> setShowEditModal(false)} onSubmit={handleEditSubmit} form={editForm} setForm={setEditForm} projectLogs={editProjectLogs} setProjectLogs={setEditProjectLogs} projectList={projectList} users={data.users} onShiftDateChange={handleCreateShiftDateChange} editingRecord={editingRecord} /> setDeleteConfirm({ show: false, record: null })} onConfirm={handleDelete} title="Smazat záznam" message="Opravdu chcete smazat tento záznam docházky?" confirmText="Smazat" confirmVariant="danger" />
) }