Files
app/src/admin/components/BulkPlanModal.tsx
2026-06-08 12:11:20 +02:00

192 lines
4.9 KiB
TypeScript

import Box from "@mui/material/Box";
import Typography from "@mui/material/Typography";
import {
Modal,
Field,
DateField,
Select,
TextField,
CheckboxField,
} from "../ui";
import type { PlanUser, PlanCategory } from "../lib/queries/plan";
import type { Project } from "../lib/queries/projects";
export interface BulkPlanForm {
date_from: string;
date_to: string;
is_range: boolean;
user_ids: string[];
include_weekends: boolean;
project_id: string;
category: string;
note: string;
}
interface Props {
isOpen: boolean;
onClose: () => void;
form: BulkPlanForm;
setForm: (form: BulkPlanForm) => void;
users: PlanUser[];
projects: Project[];
categories: PlanCategory[];
onSubmit: () => void;
submitting: boolean;
toggleUser: (userId: number) => void;
toggleAllUsers: () => void;
}
export default function BulkPlanModal({
isOpen,
onClose,
form,
setForm,
users,
projects,
categories,
onSubmit,
submitting,
toggleUser,
toggleAllUsers,
}: Props) {
const activeCategories = categories.filter((c) => c.is_active);
return (
<Modal
isOpen={isOpen}
onClose={onClose}
title="Hromadné přiřazení"
maxWidth="lg"
loading={submitting}
onSubmit={onSubmit}
submitText="Vytvořit"
submitDisabled={form.user_ids.length === 0}
>
<Typography
variant="body2"
color="text.secondary"
sx={{ mt: 0.25, mb: 2 }}
>
Vytvoří záznamy pro vybrané dny u zvolených zaměstnanců. Dny, které
mají 3 záznamy, se přeskočí.
</Typography>
<Field label="Datum od">
<DateField
value={form.date_from}
onChange={(val) => setForm({ ...form, date_from: val })}
/>
</Field>
<Field label="Rozsah dnů">
<CheckboxField
label="Více dní"
checked={form.is_range}
onChange={(checked) => setForm({ ...form, is_range: checked })}
/>
</Field>
{form.is_range && (
<Field label="Datum do">
<DateField
value={form.date_to}
onChange={(val) => setForm({ ...form, date_to: val })}
/>
</Field>
)}
<Field label="Víkendy">
<CheckboxField
label="Zahrnout víkendy"
checked={form.include_weekends}
onChange={(checked) =>
setForm({ ...form, include_weekends: checked })
}
/>
</Field>
<Box sx={{ mb: 2 }}>
<Box sx={{ display: "flex", alignItems: "center", gap: 1.5, mb: 0.5 }}>
<Typography
component="span"
variant="body2"
sx={{ fontWeight: 600, color: "text.secondary" }}
>
Zaměstnanci
</Typography>
<Typography
component="button"
type="button"
onClick={toggleAllUsers}
variant="caption"
sx={{
background: "none",
border: "none",
p: 0,
cursor: "pointer",
fontWeight: 500,
color: "primary.main",
}}
>
{users.length > 0 && form.user_ids.length === users.length
? "Odznačit vše"
: "Vybrat vše"}
</Typography>
</Box>
<Box
sx={{
display: "flex",
flexDirection: "column",
gap: 0.25,
maxHeight: 200,
overflowY: "auto",
p: 1.5,
bgcolor: "action.hover",
borderRadius: 2,
border: 1,
borderColor: "divider",
}}
>
{users.map((u) => (
<CheckboxField
key={u.id}
label={u.full_name}
checked={form.user_ids.includes(String(u.id))}
onChange={() => toggleUser(u.id)}
/>
))}
</Box>
<Typography variant="caption" color="text.secondary">
Vybráno: {form.user_ids.length} z {users.length}
</Typography>
</Box>
<Field label="Projekt">
<Select
value={form.project_id}
onChange={(val) => setForm({ ...form, project_id: val })}
options={[
{ value: "", label: "— bez projektu —" },
...projects.map((p) => ({ value: String(p.id), label: p.name })),
]}
/>
</Field>
<Field label="Kategorie">
<Select
value={form.category}
onChange={(val) => setForm({ ...form, category: val })}
options={activeCategories.map((c) => ({
value: c.key,
label: c.label,
}))}
/>
</Field>
<Field label="Text poznámky (volitelný)">
<TextField
multiline
minRows={2}
value={form.note}
onChange={(e) => setForm({ ...form, note: e.target.value })}
inputProps={{ maxLength: 500 }}
/>
</Field>
</Modal>
);
}