From b9f605d7b34ea81545907d0711d5a96070bd9d1f Mon Sep 17 00:00:00 2001 From: counterweight Date: Sun, 21 Dec 2025 18:01:30 +0100 Subject: [PATCH] Extract common errorBanner style to shared styles - Added errorBanner to sharedStyles for consistent error display - Removed duplicate errorBanner definitions from all pages - Updated appointments, booking, admin/appointments, and admin/availability pages - Reduced code duplication while maintaining component-specific styles --- frontend/app/admin/appointments/page.tsx | 15 ++++--------- frontend/app/admin/availability/page.tsx | 10 --------- frontend/app/appointments/page.tsx | 15 ++++--------- frontend/app/booking/page.tsx | 15 ++++--------- frontend/app/styles/shared.ts | 28 ++++++++++++++++++++++++ 5 files changed, 40 insertions(+), 43 deletions(-) diff --git a/frontend/app/admin/appointments/page.tsx b/frontend/app/admin/appointments/page.tsx index 5ce2390..616b46b 100644 --- a/frontend/app/admin/appointments/page.tsx +++ b/frontend/app/admin/appointments/page.tsx @@ -9,11 +9,12 @@ import { useRequireAuth } from "../../hooks/useRequireAuth"; import { components } from "../../generated/api"; import { formatDateTime } from "../../utils/date"; import { getStatusDisplay } from "../../utils/appointment"; +import { sharedStyles } from "../../styles/shared"; type AppointmentResponse = components["schemas"]["AppointmentResponse"]; type PaginatedAppointments = components["schemas"]["PaginatedResponse_AppointmentResponse_"]; -const styles: Record = { +const pageStyles: Record = { main: { minHeight: "100vh", background: "linear-gradient(135deg, #0f0f23 0%, #1a1a3e 50%, #2d1b4e 100%)", @@ -48,16 +49,6 @@ const styles: Record = { fontSize: "0.9rem", marginBottom: "1.5rem", }, - errorBanner: { - background: "rgba(239, 68, 68, 0.15)", - border: "1px solid rgba(239, 68, 68, 0.3)", - color: "#f87171", - padding: "1rem", - borderRadius: "8px", - marginBottom: "1rem", - fontFamily: "'DM Sans', system-ui, sans-serif", - fontSize: "0.875rem", - }, filterRow: { display: "flex", alignItems: "center", @@ -161,6 +152,8 @@ const styles: Record = { }, }; +const styles = { ...sharedStyles, ...pageStyles }; + export default function AdminAppointmentsPage() { const { user, isLoading, isAuthorized } = useRequireAuth({ requiredPermission: Permission.VIEW_ALL_APPOINTMENTS, diff --git a/frontend/app/admin/availability/page.tsx b/frontend/app/admin/availability/page.tsx index 8137cfc..ffc85fa 100644 --- a/frontend/app/admin/availability/page.tsx +++ b/frontend/app/admin/availability/page.tsx @@ -431,16 +431,6 @@ const pageStyles: Record = { borderRadius: "8px", cursor: "pointer", }, - errorBanner: { - fontFamily: "'DM Sans', system-ui, sans-serif", - fontSize: "0.9rem", - padding: "1rem", - background: "rgba(239, 68, 68, 0.15)", - border: "1px solid rgba(239, 68, 68, 0.3)", - borderRadius: "8px", - color: "#f87171", - marginBottom: "1rem", - }, calendar: { display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(180px, 1fr))", diff --git a/frontend/app/appointments/page.tsx b/frontend/app/appointments/page.tsx index aa2f495..662e096 100644 --- a/frontend/app/appointments/page.tsx +++ b/frontend/app/appointments/page.tsx @@ -9,10 +9,11 @@ import { useRequireAuth } from "../hooks/useRequireAuth"; import { components } from "../generated/api"; import { formatDateTime } from "../utils/date"; import { getStatusDisplay } from "../utils/appointment"; +import { sharedStyles } from "../styles/shared"; type AppointmentResponse = components["schemas"]["AppointmentResponse"]; -const styles: Record = { +const pageStyles: Record = { main: { minHeight: "100vh", background: "linear-gradient(135deg, #0f0f23 0%, #1a1a3e 50%, #2d1b4e 100%)", @@ -47,16 +48,6 @@ const styles: Record = { fontSize: "0.9rem", marginBottom: "1.5rem", }, - errorBanner: { - background: "rgba(239, 68, 68, 0.15)", - border: "1px solid rgba(239, 68, 68, 0.3)", - color: "#f87171", - padding: "1rem", - borderRadius: "8px", - marginBottom: "1rem", - fontFamily: "'DM Sans', system-ui, sans-serif", - fontSize: "0.875rem", - }, section: { marginBottom: "2rem", }, @@ -155,6 +146,8 @@ const styles: Record = { }, }; +const styles = { ...sharedStyles, ...pageStyles }; + export default function AppointmentsPage() { const { user, isLoading, isAuthorized } = useRequireAuth({ requiredPermission: Permission.VIEW_OWN_APPOINTMENTS, diff --git a/frontend/app/booking/page.tsx b/frontend/app/booking/page.tsx index 4bfc129..4d3c9e0 100644 --- a/frontend/app/booking/page.tsx +++ b/frontend/app/booking/page.tsx @@ -9,6 +9,7 @@ import { useRequireAuth } from "../hooks/useRequireAuth"; import { components } from "../generated/api"; import constants from "../../../shared/constants.json"; import { formatDate, formatTime, getDateRange } from "../utils/date"; +import { sharedStyles } from "../styles/shared"; const { slotDurationMinutes, maxAdvanceDays, minAdvanceDays, noteMaxLength } = constants.booking; @@ -16,7 +17,7 @@ type BookableSlot = components["schemas"]["BookableSlot"]; type AvailableSlotsResponse = components["schemas"]["AvailableSlotsResponse"]; type AppointmentResponse = components["schemas"]["AppointmentResponse"]; -const styles: Record = { +const pageStyles: Record = { main: { minHeight: "100vh", background: "linear-gradient(135deg, #0f0f23 0%, #1a1a3e 50%, #2d1b4e 100%)", @@ -61,16 +62,6 @@ const styles: Record = { fontFamily: "'DM Sans', system-ui, sans-serif", fontSize: "0.875rem", }, - errorBanner: { - background: "rgba(239, 68, 68, 0.15)", - border: "1px solid rgba(239, 68, 68, 0.3)", - color: "#f87171", - padding: "1rem", - borderRadius: "8px", - marginBottom: "1rem", - fontFamily: "'DM Sans', system-ui, sans-serif", - fontSize: "0.875rem", - }, section: { marginBottom: "2rem", }, @@ -217,6 +208,8 @@ const styles: Record = { }, }; +const styles = { ...sharedStyles, ...pageStyles }; + export default function BookingPage() { const { user, isLoading, isAuthorized } = useRequireAuth({ requiredPermission: Permission.BOOK_APPOINTMENT, diff --git a/frontend/app/styles/shared.ts b/frontend/app/styles/shared.ts index 86d98b2..09aee12 100644 --- a/frontend/app/styles/shared.ts +++ b/frontend/app/styles/shared.ts @@ -78,4 +78,32 @@ export const sharedStyles: Record = { justifyContent: "center", padding: "2rem", }, + // Common UI component styles + errorBanner: { + fontFamily: "'DM Sans', system-ui, sans-serif", + fontSize: "0.875rem", + padding: "1rem", + background: "rgba(239, 68, 68, 0.15)", + border: "1px solid rgba(239, 68, 68, 0.3)", + borderRadius: "8px", + color: "#f87171", + marginBottom: "1rem", + }, + cancelButton: { + fontFamily: "'DM Sans', system-ui, sans-serif", + fontSize: "0.85rem", + padding: "0.6rem 1rem", + background: "rgba(255, 255, 255, 0.05)", + color: "rgba(255, 255, 255, 0.7)", + border: "1px solid rgba(255, 255, 255, 0.1)", + borderRadius: "8px", + cursor: "pointer", + transition: "all 0.2s", + }, + emptyState: { + fontFamily: "'DM Sans', system-ui, sans-serif", + color: "rgba(255, 255, 255, 0.4)", + textAlign: "center" as const, + padding: "1rem 0", + }, };