feat: auto-focus and scroll to newly created class in Open Day schedule

This commit is contained in:
2026-03-24 23:11:53 +03:00
parent d0fad4aae5
commit 1047b71abe

View File

@@ -1,6 +1,6 @@
"use client"; "use client";
import { useState, useEffect, useMemo, useCallback } from "react"; import { useState, useEffect, useMemo, useCallback, useRef } from "react";
import { import {
Plus, X, Loader2, Calendar, Trash2, Ban, CheckCircle2, RotateCcw, Sparkles, Plus, X, Loader2, Calendar, Trash2, Ban, CheckCircle2, RotateCcw, Sparkles,
} from "lucide-react"; } from "lucide-react";
@@ -186,6 +186,7 @@ function ClassCell({
minBookings, minBookings,
trainers, trainers,
styles, styles,
autoEdit,
onUpdate, onUpdate,
onDelete, onDelete,
onCancel, onCancel,
@@ -194,13 +195,21 @@ function ClassCell({
minBookings: number; minBookings: number;
trainers: string[]; trainers: string[];
styles: string[]; styles: string[];
autoEdit?: boolean;
onUpdate: (id: number, data: Partial<OpenDayClass>) => void; onUpdate: (id: number, data: Partial<OpenDayClass>) => void;
onDelete: (id: number) => void; onDelete: (id: number) => void;
onCancel: (id: number) => void; onCancel: (id: number) => void;
}) { }) {
const [editing, setEditing] = useState(false); const [editing, setEditing] = useState(!!autoEdit);
const [trainer, setTrainer] = useState(cls.trainer); const [trainer, setTrainer] = useState(cls.trainer);
const [style, setStyle] = useState(cls.style); const [style, setStyle] = useState(cls.style);
const cellRef = useRef<HTMLDivElement>(null);
useEffect(() => {
if (autoEdit && cellRef.current) {
cellRef.current.scrollIntoView({ behavior: "smooth", block: "center" });
}
}, [autoEdit]);
const [endTime, setEndTime] = useState(cls.endTime); const [endTime, setEndTime] = useState(cls.endTime);
const atRisk = cls.bookingCount < minBookings && !cls.cancelled; const atRisk = cls.bookingCount < minBookings && !cls.cancelled;
@@ -216,7 +225,7 @@ function ClassCell({
if (editing) { if (editing) {
return ( return (
<div className="p-2 space-y-1.5"> <div ref={cellRef} className="p-2 space-y-1.5 ring-1 ring-gold/30 rounded-lg">
<select value={style} onChange={(e) => setStyle(e.target.value)} className={selectCls}> <select value={style} onChange={(e) => setStyle(e.target.value)} className={selectCls}>
<option value="">Стиль...</option> <option value="">Стиль...</option>
{styles.map((s) => <option key={s} value={s}>{s}</option>)} {styles.map((s) => <option key={s} value={s}>{s}</option>)}
@@ -332,6 +341,8 @@ function ScheduleGrid({
return counts; return counts;
}, [classes, halls]); }, [classes, halls]);
const [newClassTime, setNewClassTime] = useState<string | null>(null);
async function addClass(startTime: string) { async function addClass(startTime: string) {
const endTime = addHour(startTime); const endTime = addHour(startTime);
await adminFetch("/api/admin/open-day/classes", { await adminFetch("/api/admin/open-day/classes", {
@@ -339,6 +350,7 @@ function ScheduleGrid({
headers: { "Content-Type": "application/json" }, headers: { "Content-Type": "application/json" },
body: JSON.stringify({ eventId, hall: selectedHall, startTime, endTime, trainer: "—", style: "—" }), body: JSON.stringify({ eventId, hall: selectedHall, startTime, endTime, trainer: "—", style: "—" }),
}); });
setNewClassTime(startTime);
onClassesChange(); onClassesChange();
} }
@@ -406,7 +418,8 @@ function ScheduleGrid({
minBookings={minBookings} minBookings={minBookings}
trainers={trainers} trainers={trainers}
styles={styles} styles={styles}
onUpdate={updateClass} autoEdit={cls.startTime === newClassTime}
onUpdate={(id, data) => { setNewClassTime(null); updateClass(id, data); }}
onDelete={deleteClass} onDelete={deleteClass}
onCancel={cancelClass} onCancel={cancelClass}
/> />