diff --git a/src/app/admin/_components/FormField.tsx b/src/app/admin/_components/FormField.tsx index 4aa7b5d..ea61d5f 100644 --- a/src/app/admin/_components/FormField.tsx +++ b/src/app/admin/_components/FormField.tsx @@ -191,7 +191,7 @@ export function SelectField({ return (
- + {label && } diff --git a/src/app/admin/open-day/page.tsx b/src/app/admin/open-day/page.tsx index 2c62e3b..49662fe 100644 --- a/src/app/admin/open-day/page.tsx +++ b/src/app/admin/open-day/page.tsx @@ -5,7 +5,7 @@ import { Plus, X, Loader2, Calendar, Trash2, Ban, CheckCircle2, RotateCcw, Sparkles, } from "lucide-react"; import { adminFetch } from "@/lib/csrf"; -import { ParticipantLimits } from "../_components/FormField"; +import { ParticipantLimits, SelectField } from "../_components/FormField"; // --- Types --- @@ -179,6 +179,57 @@ function EventSettings({ ); } +// --- New Class Form (create only on save) --- + +function NewClassForm({ + startTime, + trainers, + styles, + onSave, + onCancel, +}: { + startTime: string; + trainers: string[]; + styles: string[]; + onSave: (data: { trainer: string; style: string; endTime: string }) => void; + onCancel: () => void; +}) { + const [style, setStyle] = useState(""); + const [trainer, setTrainer] = useState(""); + const endTime = addHour(startTime); + const formRef = useRef(null); + + useEffect(() => { + formRef.current?.scrollIntoView({ behavior: "smooth", block: "center" }); + }, []); + + // Auto-save on click outside + useEffect(() => { + function handleClickOutside(e: MouseEvent) { + if (formRef.current && !formRef.current.contains(e.target as Node)) { + if (style && trainer) onSave({ trainer, style, endTime }); + else onCancel(); + } + } + document.addEventListener("mousedown", handleClickOutside); + return () => document.removeEventListener("mousedown", handleClickOutside); + }, [style, trainer, endTime, onSave, onCancel]); + + const canSave = style && trainer; + + return ( +
+ ({ value: s, label: s }))} placeholder="Стиль..." /> + ({ value: t, label: t }))} placeholder="Тренер..." /> +
+ + +
+
+ ); +} + // --- Class Grid Cell --- function ClassCell({ @@ -186,7 +237,6 @@ function ClassCell({ minBookings, trainers, styles, - autoEdit, onUpdate, onDelete, onCancel, @@ -195,49 +245,28 @@ function ClassCell({ minBookings: number; trainers: string[]; styles: string[]; - autoEdit?: boolean; onUpdate: (id: number, data: Partial) => void; onDelete: (id: number) => void; onCancel: (id: number) => void; }) { - const [editing, setEditing] = useState(!!autoEdit); + const [editing, setEditing] = useState(false); const [trainer, setTrainer] = useState(cls.trainer); const [style, setStyle] = useState(cls.style); - const cellRef = useRef(null); - - useEffect(() => { - if (autoEdit && cellRef.current) { - cellRef.current.scrollIntoView({ behavior: "smooth", block: "center" }); - } - }, [autoEdit]); - const [endTime, setEndTime] = useState(cls.endTime); const atRisk = cls.bookingCount < minBookings && !cls.cancelled; function save() { if (trainer.trim() && style.trim()) { - onUpdate(cls.id, { trainer: trainer.trim(), style: style.trim(), endTime }); + onUpdate(cls.id, { trainer: trainer.trim(), style: style.trim() }); setEditing(false); } } - const selectCls = "w-full rounded-md border border-white/10 bg-neutral-800 px-2 py-1 text-xs text-white outline-none focus:border-gold [color-scheme:dark]"; - if (editing) { return ( -
- - -
- - setEndTime(e.target.value)} className={selectCls} /> -
+
+ ({ value: s, label: s }))} placeholder="Стиль..." /> + ({ value: t, label: t }))} placeholder="Тренер..." />