Manage every court without leaving the calendar.

Click a court header to rename or recolor it. Block off time for maintenance with one tap. Set up "court closed every Sunday morning" as a recurring pattern. Edit per-location hours inline. The calendar repaints in place — the front desk never sees stale state.

The whole control panel, in one screen

Before today, blocking a court for maintenance meant leaving the calendar, finding the right admin page, filling in a form, and navigating back. Hours meant a separate page. Renaming a court? Yet another page. Now every action is a click away from the timeline view your front desk already lives in.

Inline court editor

Click any court header. Rename, change the display order, pick a color, toggle indoor/outdoor, mark unavailable with a public reason — all in a modal that respects your dark or light theme.

Block Court

One-time blocks for maintenance, events, lessons, tournaments, private rentals, closures. Pick the court, type, time range, public reason for players, and internal notes for staff. Done.

Repeat weekly

Toggle "Repeat" inside the Block modal and the same form becomes a recurring pattern: day-of-week chips, weekly or biweekly, optional end date. We generate the next 365 days of occurrences up front.

Operating hours

Inline modal with a 7-day open/close grid plus 4 quick presets (extended, standard, business, 24/7). Multi-location clubs get a dropdown to switch sites. No more "go to the locations page" detour.

Permission-gated, not all-or-nothing

  • can_manage_courts — opens the court header edit modal. Front desk staff don't see it.
  • can_manage_court_blocks — gates the Block Court button and the cancel-block action.
  • can_manage_locations — gates the Hours button. Most clubs only let managers or owners change operating hours.
  • Lower-tier staff still see the calendar, the courts, the bookings — they just can't mutate. Server-side enforcement, not just UI hiding.

Hardened for production

  • No more stale availability after a cancel. Three pre-existing query sites that were missing the .active scope on CourtBlocks have been fixed — cancelled blocks no longer count toward marketplace availability or coach-slot conflicts.
  • Overlap validation on every edit, not just on create. Shifting an existing block's time range into another block's window now returns a clear 422.
  • Postgres exclusion constraint for race-safe block creation in production — two concurrent admins clicking Save at the same time can't both win.
  • Cross-tenant guards. Mass-assignment attempt to move a court to another club's location is silently stripped.
  • XSS-safe. Day-of-week keys in the hours JSON payload are whitelisted; ERB output is escaped end-to-end.
  • Live repaint. Every mutation triggers Turbo.visit, not a full reload — scroll position preserved, no manual refresh ever.

Ready to try it

Already on Picklebeast? Open the reservation calendar. New here? Start your free club.

Get Started