belviskhoremk 4ca40bf2b5 fix: address final whole-branch review findings for Phase 2C
Critical: computeAvailableSlots looped forever when slot_minutes was
0 or negative -- reachable in production, since AdminSchedule's
slot-length input has no validation and clearing it yields Number('')
=== 0. Guarded the computation, added min="5"/required to the admin
input as defense in depth, and added a regression test.

Important fixes:
- Removed the one eslint-disable that slipped into the branch
  (InquiryModal.test.tsx), replacing it with the explicit vi.fn<...>
  generic type pattern already used everywhere else. Also cleaned up
  a similar unused-var workaround in useBooking.test.ts for
  consistency.
- Added a submitting/in-flight guard to both booking and inquiry
  submission, so a double-click can no longer produce a false
  "slot already taken" error after a booking actually succeeded (or
  a duplicate inquiry row).
- Added loading states to Home.tsx (services/products) and Book.tsx
  (services list, date/slot step) -- previously only Shop.tsx had
  one, though the spec named all three pages.
- Restored the full date -> slot -> contact -> confirmation ->
  persisted-booking test in Book.test.tsx, which had been replaced
  rather than supplemented by a narrower slot-fetching test.

Deferred to a follow-up (explicit decision, not silently dropped):
duration-aware slot conflicts. The current model only blocks an exact
(date, time) match, so a 4-hour service booked at 9:00 AM doesn't
block 11:00 AM even though they'd physically overlap. Inherited from
the Phase 2A data model; this branch is what makes it reachable by
real customers, so it needs a recorded decision before go-live rather
than silent inheritance.

Claude-Session: https://claude.ai/code/session_01NhxA4npAXAxmCDEJt6kxSH
2026-08-12 23:03:32 +02:00
2026-08-12 12:52:25 +02:00

Braids by Mira

Public marketing site for Braids by Mira — landing page, product showcase, booking flow, and salon policies.

Scripts

  • npm run dev — start the local dev server
  • npm test (or npx vitest run) — run the frontend test suite
  • npm run build — type-check and build for production
  • npm run lint — run ESLint
  • npm run test:functions — run the Deno tests for the Edge Functions' shared email builders (requires Deno installed)
  • npm run seed — seed products, services, and the default schedule into a Supabase project (see below). Re-running it after admin-panel edits will revert those rows to the hardcoded seed defaults — use it for initial setup / disaster recovery, not routine use.

Backend (Supabase)

The backend lives in supabase/ — Postgres schema/RLS migrations, pgTAP tests, and Deno Edge Functions for booking/inquiry email notifications.

  • npx supabase start — start the local Docker-based Supabase dev stack (Postgres, Studio, Auth, Storage, Edge Functions runtime). Requires Docker.
  • npx supabase db reset — replay all migrations from scratch against the local database.
  • npx supabase test db — run the pgTAP test suite in supabase/tests/database/ against the local database.

Environment variables

Copy .env.example to .env.local and fill in:

  • VITE_SUPABASE_URL, VITE_SUPABASE_ANON_KEY — frontend Supabase client config (exposed to the browser).
  • SUPABASE_URL, SUPABASE_SERVICE_ROLE_KEY — used only by scripts/seed.ts (server-side, never expose the service role key to the browser). These are distinct from the VITE_-prefixed frontend variables above.
Description
No description provided
Readme 3.9 MiB
Languages
TypeScript 77.5%
PLpgSQL 14.6%
CSS 7.1%
HTML 0.5%
JavaScript 0.3%