import Box from "@mui/material/Box";
import Typography from "@mui/material/Typography";
import IconButton from "@mui/material/IconButton";
import {
Modal,
Button,
Select,
TextField,
DateField,
TimeField,
Field,
Alert,
} from "../ui";
import {
calcFormWorkMinutes,
calcProjectMinutesTotal,
formatDate,
} from "../utils/attendanceHelpers";
let _logKeyCounter = 0;
// ---------- Shared types ----------
export interface ShiftFormData {
user_id: string;
shift_date: string;
leave_type: string;
leave_hours: number;
arrival_date: string;
arrival_time: string;
break_start_date: string;
break_start_time: string;
break_end_date: string;
break_end_time: string;
departure_date: string;
departure_time: string;
notes: string;
}
export interface ProjectLog {
_key?: string;
id?: number;
project_id: string | number;
hours: string | number;
minutes: string | number;
}
export interface Project {
id: number | string;
project_number: string;
name: string;
}
export interface User {
id: number | string;
name: string;
}
export interface EditingRecord {
user_name: string;
shift_date: string;
}
// ---------- Sub-component props ----------
interface ProjectTimeStatusProps {
form: ShiftFormData;
projectLogs: ProjectLog[];
}
interface ProjectLogRowProps {
log: ProjectLog;
index: number;
projectList: Project[];
onUpdate: (index: number, field: string, value: string) => void;
onRemove: (index: number) => void;
}
export interface ShiftFormModalProps {
mode: "create" | "edit";
isOpen: boolean;
onClose: () => void;
onSubmit: () => void;
form: ShiftFormData;
setForm: (form: ShiftFormData) => void;
projectLogs: ProjectLog[];
setProjectLogs: (logs: ProjectLog[]) => void;
projectList: Project[];
users: User[];
onShiftDateChange: (value: string) => void;
editingRecord: EditingRecord | null;
}
const RemoveIcon = (
);
// ---------- ProjectTimeStatus ----------
function ProjectTimeStatus({ form, projectLogs }: ProjectTimeStatusProps) {
const totalWork = calcFormWorkMinutes(form);
const totalProject = calcProjectMinutesTotal(
projectLogs.map((l) => ({
...l,
project_id:
l.project_id !== "" && l.project_id != null
? Number(l.project_id)
: undefined,
})),
);
const remaining = totalWork - totalProject;
const hasLogs = projectLogs.some((l) => l.project_id);
if (!hasLogs || totalWork <= 0) return null;
const isMatch = remaining === 0;
return (
Odpracováno: {Math.floor(totalWork / 60)}h {totalWork % 60}m |
Přiřazeno: {Math.floor(totalProject / 60)}h {totalProject % 60}m |
Zbývá: {Math.floor(Math.abs(remaining) / 60)}h{" "}
{Math.abs(remaining) % 60}m {remaining < 0 ? "(překročeno)" : ""}
);
}
// ---------- ProjectLogRow ----------
function ProjectLogRow({
log,
index,
projectList,
onUpdate,
onRemove,
}: ProjectLogRowProps) {
return (
onUpdate(index, "hours", e.target.value)}
placeholder="h"
slotProps={{
htmlInput: { min: 0, max: 24, style: { textAlign: "center" } },
}}
/>
h
onUpdate(index, "minutes", e.target.value)}
placeholder="m"
slotProps={{
htmlInput: { min: 0, max: 59, style: { textAlign: "center" } },
}}
/>
m
onRemove(index)}
aria-label="Odebrat"
title="Odebrat"
sx={{ flexShrink: 0 }}
>
{RemoveIcon}
);
}
// ---------- ShiftFormModal ----------
export default function ShiftFormModal({
mode,
isOpen,
onClose,
onSubmit,
form,
setForm,
projectLogs,
setProjectLogs,
projectList,
users,
onShiftDateChange,
editingRecord,
}: ShiftFormModalProps) {
const isCreate = mode === "create";
const isWorkType = form.leave_type === "work";
const updateField = (field: keyof ShiftFormData, value: string | number) => {
setForm({ ...form, [field]: value });
};
const updateProjectLog = (index: number, field: string, value: string) => {
const updated = [...projectLogs];
updated[index] = { ...updated[index], [field]: value };
setProjectLogs(updated);
};
const removeProjectLog = (index: number) => {
setProjectLogs(projectLogs.filter((_, j) => j !== index));
};
const addProjectLog = () => {
setProjectLogs([
...projectLogs,
{
_key: `log-${++_logKeyCounter}`,
project_id: "",
hours: "",
minutes: "",
},
]);
};
return (
{isCreate ? (
onShiftDateChange(val)}
/>
) : (
updateField("shift_date", val)}
/>
)}
{!isWorkType && (
updateField("leave_hours", parseFloat(e.target.value))
}
slotProps={{ htmlInput: { min: 0.5, max: 24, step: 0.5 } }}
/>
)}
{isWorkType && (
<>
{/* Arrival */}
updateField("arrival_date", val)}
/>
updateField("arrival_time", val)}
/>
{/* Break start */}
updateField("break_start_date", val)}
/>
updateField("break_start_time", val)}
/>
{/* Break end */}
updateField("break_end_date", val)}
/>
updateField("break_end_time", val)}
/>
{/* Departure */}
updateField("departure_date", val)}
/>
updateField("departure_time", val)}
/>
>
)}
{isWorkType && projectList.length > 0 && (
{projectLogs.map((log, i) => (
))}
)}
updateField("notes", e.target.value)}
/>
);
}