fix: comprehensive bookings admin UX improvements
- #1 Delete confirmation dialog before removing bookings - #2 Error toasts instead of silent .catch(() => {}) - #3 Optimistic rollback — UI reverts on API failure - #4 Loading indicator on reminder status buttons - #5 Search results are now actionable (status change + delete) - #6 New bookings banner instead of full tab remount - #7 Error states for failed data loads - #8 InlineNotes only saves on blur when value changed - #9 AddBookingModal supports Instagram/Telegram fields - #10 Polling pauses when browser tab is hidden - #11 Enter key submits ConfirmModal
This commit is contained in:
@@ -25,6 +25,8 @@ export function AddBookingModal({
|
||||
const [eventType, setEventType] = useState<EventType>("master-class");
|
||||
const [name, setName] = useState("");
|
||||
const [phone, setPhone] = useState("");
|
||||
const [instagram, setInstagram] = useState("");
|
||||
const [telegram, setTelegram] = useState("");
|
||||
const [mcTitle, setMcTitle] = useState("");
|
||||
const [mcOptions, setMcOptions] = useState<McOption[]>([]);
|
||||
const [odClasses, setOdClasses] = useState<OdClass[]>([]);
|
||||
@@ -34,7 +36,7 @@ export function AddBookingModal({
|
||||
|
||||
useEffect(() => {
|
||||
if (!open) return;
|
||||
setName(""); setPhone(""); setMcTitle(""); setOdClassId("");
|
||||
setName(""); setPhone(""); setInstagram(""); setTelegram(""); setMcTitle(""); setOdClassId("");
|
||||
|
||||
// Fetch upcoming MCs (filter out expired)
|
||||
adminFetch("/api/admin/sections/masterClasses").then((r) => r.json()).then((data: { items?: { title: string; slots: { date: string }[] }[] }) => {
|
||||
@@ -80,7 +82,12 @@ export function AddBookingModal({
|
||||
await adminFetch("/api/admin/group-bookings", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ name: name.trim(), phone: phone.trim() }),
|
||||
body: JSON.stringify({
|
||||
name: name.trim(),
|
||||
phone: phone.trim(),
|
||||
...(instagram.trim() && { instagram: instagram.trim() }),
|
||||
...(telegram.trim() && { telegram: telegram.trim() }),
|
||||
}),
|
||||
});
|
||||
} else if (eventType === "master-class") {
|
||||
const title = mcTitle || mcOptions[0]?.title || "Мастер-класс";
|
||||
@@ -193,6 +200,10 @@ export function AddBookingModal({
|
||||
|
||||
<input type="text" value={name} onChange={(e) => setName(e.target.value)} placeholder="Имя" className={inputClass} />
|
||||
<input type="tel" value={phone} onChange={(e) => setPhone(e.target.value)} placeholder="Телефон" className={inputClass} />
|
||||
<div className="flex gap-2">
|
||||
<input type="text" value={instagram} onChange={(e) => setInstagram(e.target.value)} placeholder="Instagram" className={inputClass} />
|
||||
<input type="text" value={telegram} onChange={(e) => setTelegram(e.target.value)} placeholder="Telegram" className={inputClass} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button
|
||||
|
||||
Reference in New Issue
Block a user