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"; import { Skeleton } from "boneyard-js/react"; import AttendanceAdminFixture from "../fixtures/AttendanceAdminFixture"; 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 ( } >
); } 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" />
); }