Stu Mason
Stu Mason

Activity

StuMason/cleanconnect
TidyLinker.com
TypeScript
Pull Request Merged

PR #156 merged: fix: gate booking UI by role + open availability to 24 hours

Context

Two real-user reports this weekend:

  • Tony (prospective customer, runs a cleaning company → signed up as a cleaner) tried to book Jamie. Walked through search → cleaner profile → booking dialog → filled the form → hit "Access denied. client role required." as a raw 403. Four interactions invested before the platform tells him the door is closed.
  • Adele's customer needs to book a cleaner Mon-Fri 5am-9am for two weeks. The booking time-picker offers no 5am slot — turns out the cleaner availability editor itself is capped 06:00-22:00, so cleaners can't even express early-morning availability.

Decided with Stu: single-account-per-role stays (users who need both roles register a separate client account at a different email — see commit message for the trade-off). So the fix here is making the booking surface honest about that and widening the availability editor.

Summary

  • Role-aware booking surface. Cleaners can browse other cleaners (still useful), but the "Book Now" / "Request Booking" CTAs are replaced with a clear NotAClientNotice explaining the one-role-per-account model and linking to /register. The 403 middleware stays as the server-side safety net but should never normally fire.
  • 24-hour availability editor. generateTimeOptions widened from 06:00-22:00 to 00:00-23:30. Backend validation already accepts any H:i, so no server change.

Files

ChangeFile
Book Now hidden for logged-in non-clientsresources/js/components/cleaners/cleaner-card.tsx
Request Booking (hero + sidebar) replaced with noticeresources/js/pages/cleaner-profile.tsx
Defence-in-depth — refuse to render form if dialog opens for non-clientresources/js/components/cleaners/booking-dialog.tsx
Availability editor opened to 24 hoursresources/js/pages/Cleaner/Availability/Index.tsx

What this does NOT do

  • Does not change EnsureUserHasRole middleware or DirectBookingRequest::authorize() — those keep working as the server-side guard.
  • Does not change signup copy or onboarding (separate follow-up).
  • Does not address pre-booking messaging or multi-day range bookings (product backlog).
  • Does not address Adele's "edit job doesn't save" report — investigation concluded the save works correctly; she most likely edited a field not shown on the My Jobs listing. Waiting for screen recording before changing anything there.

Test plan

  • php artisan test --compact tests/Feature/DirectBooking — 32 passed
  • Pint clean, Prettier clean, ESLint clean
  • Local Playwright walk-through:
    • Logged-in cleaner-company sees "View Profile" only on /cleaners cards
    • Same user sees the NotAClientNotice (both hero + sidebar) on /cleaners/{uid}
    • Backend /client/cleaners/{uid}/book POST still returns 403 with same payload (safety net intact)
  • After deploy: have Adele's cleaner set 05:00 start in their availability editor → confirm the booking dropdown then offers 5am
+215
additions
-29
deletions
7
files changed