refactor: comprehensive frontend review — consistency, a11y, code quality

- Replace event dispatchers with BookingContext (Hero, Header, FloatingContact)
- Add focus trap hook for modals (SignupModal, NewsModal)
- Extract shared components: CollapsibleSection, ConfirmDialog, PriceField, AdminSkeleton
- Add delete confirmation dialog to ArrayEditor
- Replace hardcoded colors (#050505, #0a0a0a, #c9a96e, #2ecc71) with theme tokens
- Add CSS variables --color-surface-deep/dark for consistent dark surfaces
- Improve contrast: muted text neutral-500 → neutral-400 in dark mode
- Fix modal z-index hierarchy (modals z-60, header z-50, floats z-40)
- Consolidate duplicate formatDate → shared formatting.ts
- Add useMemo to TeamProfile groupMap computation
- Fix typography: responsive price text in Pricing section
- Add ARIA labels/expanded to FAQ, OpenDay, ArrayEditor grip handles
- Hide number input spinners globally
- Reorder admin sidebar: Dashboard → SEO → Bookings → site section order
- Use shared PriceField in Open Day editor
- Fix schedule grid first time slot (09:00) clipped by container
- Fix pre-existing type errors (bookings, hero, db interfaces)
This commit is contained in:
2026-03-26 19:45:37 +03:00
parent ec08f8e8d5
commit 76307e298b
32 changed files with 613 additions and 319 deletions

View File

@@ -0,0 +1,31 @@
"use client";
import { createContext, useContext, useState, useCallback } from "react";
interface BookingContextValue {
bookingOpen: boolean;
openBooking: () => void;
closeBooking: () => void;
}
const BookingContext = createContext<BookingContextValue | null>(null);
export function BookingProvider({ children }: { children: React.ReactNode }) {
const [bookingOpen, setBookingOpen] = useState(false);
const openBooking = useCallback(() => setBookingOpen(true), []);
const closeBooking = useCallback(() => setBookingOpen(false), []);
return (
<BookingContext.Provider value={{ bookingOpen, openBooking, closeBooking }}>
{children}
</BookingContext.Provider>
);
}
const NOOP = () => {};
const FALLBACK: BookingContextValue = { bookingOpen: false, openBooking: NOOP, closeBooking: NOOP };
/** Returns booking context. Safe to use outside BookingProvider (returns inert fallback). */
export function useBooking(): BookingContextValue {
return useContext(BookingContext) ?? FALLBACK;
}