From 37de6f70e03a3c3ad989063339d3f71e504edbe9 Mon Sep 17 00:00:00 2001 From: counterweight Date: Sun, 21 Dec 2025 21:59:26 +0100 Subject: [PATCH] Add Prettier for TypeScript formatting - Install prettier - Configure .prettierrc.json and .prettierignore - Add npm scripts: format, format:check - Add Makefile target: format-frontend - Format all frontend files --- Makefile | 5 +- frontend/.prettierignore | 4 + frontend/.prettierrc.json | 7 + frontend/app/admin/appointments/page.tsx | 39 ++---- frontend/app/admin/availability/page.tsx | 59 ++++---- frontend/app/admin/invites/page.tsx | 70 +++++----- frontend/app/api.ts | 26 ++-- frontend/app/appointments/page.tsx | 66 ++++----- frontend/app/audit/page.test.tsx | 18 +-- frontend/app/audit/page.tsx | 64 +++++---- frontend/app/auth-context.tsx | 20 ++- frontend/app/booking/page.tsx | 66 ++++----- frontend/app/components/Header.tsx | 13 +- frontend/app/config.ts | 1 - frontend/app/hooks/useRequireAuth.ts | 13 +- frontend/app/invites/page.tsx | 34 ++--- frontend/app/login/page.tsx | 8 +- frontend/app/page.test.tsx | 22 ++- frontend/app/page.tsx | 3 +- frontend/app/profile/page.test.tsx | 156 +++++++++++---------- frontend/app/profile/page.tsx | 41 ++---- frontend/app/signup/[code]/page.tsx | 22 +-- frontend/app/signup/page.tsx | 68 +++++---- frontend/app/styles/auth-form.ts | 1 - frontend/app/sum/page.tsx | 14 +- frontend/app/utils/appointment.ts | 9 +- frontend/app/utils/date.ts | 5 +- frontend/e2e/admin-invites.spec.ts | 59 ++++---- frontend/e2e/appointments.spec.ts | 110 +++++++-------- frontend/e2e/auth.spec.ts | 135 +++++++++--------- frontend/e2e/availability.spec.ts | 158 +++++++++++---------- frontend/e2e/booking.spec.ts | 169 +++++++++++++---------- frontend/e2e/counter.spec.ts | 42 +++--- frontend/e2e/helpers/auth.ts | 1 - frontend/e2e/helpers/date.ts | 1 - frontend/e2e/permissions.spec.ts | 79 +++++------ frontend/e2e/profile.spec.ts | 103 +++++++------- frontend/eslint.config.js | 25 ++-- frontend/next.config.ts | 1 - frontend/package-lock.json | 17 +++ frontend/package.json | 5 +- frontend/playwright.config.ts | 1 - frontend/tsconfig.json | 1 - frontend/vitest.config.ts | 1 - 44 files changed, 906 insertions(+), 856 deletions(-) create mode 100644 frontend/.prettierignore create mode 100644 frontend/.prettierrc.json diff --git a/Makefile b/Makefile index 2b0f75c..952131c 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: install-backend install-frontend install setup-hooks backend frontend db db-stop db-ready db-seed dev test test-backend test-frontend test-e2e typecheck generate-types generate-types-standalone check-types-fresh check-constants lint-backend format-backend fix-backend security-backend lint-frontend fix-frontend +.PHONY: install-backend install-frontend install setup-hooks backend frontend db db-stop db-ready db-seed dev test test-backend test-frontend test-e2e typecheck generate-types generate-types-standalone check-types-fresh check-constants lint-backend format-backend fix-backend security-backend lint-frontend fix-frontend format-frontend -include .env export @@ -111,3 +111,6 @@ lint-frontend: fix-frontend: cd frontend && npm run lint:fix + +format-frontend: + cd frontend && npm run format diff --git a/frontend/.prettierignore b/frontend/.prettierignore new file mode 100644 index 0000000..7898f26 --- /dev/null +++ b/frontend/.prettierignore @@ -0,0 +1,4 @@ +.next/ +node_modules/ +app/generated/ + diff --git a/frontend/.prettierrc.json b/frontend/.prettierrc.json new file mode 100644 index 0000000..1a88ab1 --- /dev/null +++ b/frontend/.prettierrc.json @@ -0,0 +1,7 @@ +{ + "semi": true, + "singleQuote": false, + "tabWidth": 2, + "trailingComma": "es5", + "printWidth": 100 +} diff --git a/frontend/app/admin/appointments/page.tsx b/frontend/app/admin/appointments/page.tsx index 616b46b..4af5964 100644 --- a/frontend/app/admin/appointments/page.tsx +++ b/frontend/app/admin/appointments/page.tsx @@ -189,7 +189,7 @@ export default function AdminAppointmentsPage() { const handleCancel = async (appointmentId: number) => { setCancellingId(appointmentId); setError(null); - + try { await api.post(`/api/admin/appointments/${appointmentId}/cancel`, {}); await fetchAppointments(); @@ -225,13 +225,9 @@ export default function AdminAppointmentsPage() {

All Appointments

-

- View and manage all user appointments -

+

View and manage all user appointments

- {error && ( -
{error}
- )} + {error &&
{error}
} {/* Status Filter */}
@@ -269,26 +265,20 @@ export default function AdminAppointmentsPage() { >
-
- {formatDateTime(apt.slot_start)} -
-
- {apt.user_email} -
- {apt.note && ( -
- "{apt.note}" -
- )} - +
{formatDateTime(apt.slot_start)}
+
{apt.user_email}
+ {apt.note &&
"{apt.note}"
} + {status.text}
- + {apt.status === "booked" && (
{confirmCancelId === apt.id ? ( @@ -327,4 +317,3 @@ export default function AdminAppointmentsPage() { ); } - diff --git a/frontend/app/admin/availability/page.tsx b/frontend/app/admin/availability/page.tsx index ba3c889..255b657 100644 --- a/frontend/app/admin/availability/page.tsx +++ b/frontend/app/admin/availability/page.tsx @@ -8,7 +8,13 @@ import { Header } from "../../components/Header"; import { useRequireAuth } from "../../hooks/useRequireAuth"; import { components } from "../../generated/api"; import constants from "../../../../shared/constants.json"; -import { formatDate, formatDisplayDate, getDateRange, formatTimeString, isWeekend } from "../../utils/date"; +import { + formatDate, + formatDisplayDate, + getDateRange, + formatTimeString, + isWeekend, +} from "../../utils/date"; const { slotDurationMinutes, maxAdvanceDays, minAdvanceDays } = constants.booking; @@ -57,14 +63,14 @@ export default function AdminAvailabilityPage() { const fetchAvailability = useCallback(async () => { const dateRange = getDateRange(minAdvanceDays, maxAdvanceDays); if (!dateRange.length) return; - + try { const fromDate = formatDate(dateRange[0]); const toDate = formatDate(dateRange[dateRange.length - 1]); const data = await api.get( `/api/admin/availability?from=${fromDate}&to=${toDate}` ); - + const map = new Map(); for (const day of data.days) { map.set(day.date, day.slots); @@ -118,21 +124,21 @@ export default function AdminAvailabilityPage() { const saveAvailability = async () => { if (!selectedDate) return; - + setIsSaving(true); setError(null); - + try { const slots = editSlots.map((s) => ({ start_time: s.start_time + ":00", end_time: s.end_time + ":00", })); - + await api.put("/api/admin/availability", { date: formatDate(selectedDate), slots, }); - + await fetchAvailability(); closeModal(); } catch (err) { @@ -144,16 +150,16 @@ export default function AdminAvailabilityPage() { const clearAvailability = async () => { if (!selectedDate) return; - + setIsSaving(true); setError(null); - + try { await api.put("/api/admin/availability", { date: formatDate(selectedDate), slots: [], }); - + await fetchAvailability(); closeModal(); } catch (err) { @@ -186,16 +192,16 @@ export default function AdminAvailabilityPage() { const executeCopy = async () => { if (!copySource || copyTargets.size === 0) return; - + setIsCopying(true); setError(null); - + try { await api.post("/api/admin/availability/copy", { source_date: copySource, target_dates: Array.from(copyTargets), }); - + await fetchAvailability(); cancelCopyMode(); } catch (err) { @@ -236,10 +242,12 @@ export default function AdminAvailabilityPage() {
{copySource && (
- - Select days to copy to, then click Copy - -
- {error && !selectedDate && ( -
{error}
- )} + {error && !selectedDate &&
{error}
}
{dates.map((date) => { @@ -318,9 +324,7 @@ export default function AdminAvailabilityPage() { {selectedDate && (
e.stopPropagation()}> -

- Edit Availability - {formatDisplayDate(selectedDate)} -

+

Edit Availability - {formatDisplayDate(selectedDate)}

{error &&
{error}
} @@ -333,7 +337,9 @@ export default function AdminAvailabilityPage() { style={styles.timeSelect} > {TIME_OPTIONS.map((t) => ( - + ))} @@ -343,7 +349,9 @@ export default function AdminAvailabilityPage() { style={styles.timeSelect} > {TIME_OPTIONS.map((t) => ( - + ))}
- +
@@ -206,43 +204,48 @@ export default function AdminInvitesPage() { {error && ( - + )} - {!error && data?.records.map((record) => ( - - - - - - - + + + - - ))} + {record.status} + + + + + + + ))} {!error && (!data || data.records.length === 0) && ( - + )}
{error} + {error} +
{record.identifier}{record.godfather_email} - - {record.status} - - - {record.used_by_email || "-"} - {formatDate(record.created_at)} - {record.status === READY && ( -
{record.identifier}{record.godfather_email} + - Revoke - - )} -
{record.used_by_email || "-"}{formatDate(record.created_at)} + {record.status === READY && ( + + )} +
No invites yet + No invites yet +
- + {data && data.total_pages > 1 && (