From 6ebc57dd36d25020cee4edec73b69f1ad07cce71 Mon Sep 17 00:00:00 2001 From: Guillermo Pages Date: Wed, 12 Nov 2025 17:25:14 +0100 Subject: [PATCH] feat: migrate to API v2.0 with facility-based routing (Build 358+) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Complete migration to match backend breaking changes from Build 355+ and Build 358+: **Terminology Migration (Build 355+):** - Rename club → facility (club_id → facility_id, club_name → facility_name) - Rename remote → origin/provider (remote_server_id → origin_id, remote_type → provider) - Update all field references: remote_name → origin_name, remote_logo_url → origin_logo_url **Facility-Based Routing (Build 358+):** - Change routing from provider-based to facility-based - Update URL parameters: remote_slug → facility_slug in all booking/slot endpoints - Update discovery endpoint: /remotes → /facilities - Update slot responses: remote object → facility object with new field structure - Update user settings: default_remote_sport.origin_slug → facility_slug **Files Updated:** - 32 files modified (TypeScript types, API clients, hooks, components) - 150+ field name changes across the codebase - All response interfaces updated to match new API contract **Verification:** - TypeScript compilation: ✓ No errors - ESLint: ✓ No migration-related issues BREAKING CHANGES: Requires backend Build 358+ for facility-based routing --- .../BookingAdminTestComponent.tsx | 2 +- .../[locale]/admin/clubs/AdminClubsList.tsx | 4 +- .../admin/clubs/[club_id]/AdminClubDetail.tsx | 2 +- src/components/CourtSlotCard.tsx | 2 +- src/components/Navigation.tsx | 8 ++-- src/components/PastBookingCard.tsx | 4 +- src/components/PendingScoresList.tsx | 2 +- src/components/PlayerPicker.tsx | 2 +- src/components/RemoteSportInfo.tsx | 22 ++++----- src/components/RemoteSportSelector.tsx | 14 +++--- src/components/UserBookingsTimeline.tsx | 6 +-- src/components/bookings/BookingDrawer.tsx | 2 +- src/components/landing/BookingShowcase.tsx | 48 +++++++++---------- .../profile/ProfileMatchHistory.tsx | 8 ++-- src/components/profile/ProfileView.tsx | 12 ++--- src/components/profile/RecentMatches.tsx | 6 +-- src/contexts/UserSettingsContext.tsx | 2 +- src/hooks/useBookingLink.ts | 8 ++-- src/hooks/useCourtSlots.ts | 20 ++++---- src/hooks/useEnhancedParams.ts | 8 ++-- src/hooks/usePastBookings.ts | 4 +- src/hooks/useUserBookings.ts | 8 ++-- src/lib/api/admin-clubs.ts | 8 ++-- src/lib/api/courts.ts | 2 +- src/lib/types.ts | 18 +++---- src/lib/types_bis.ts | 4 +- src/types/admin-api.ts | 8 ++-- src/types/booking-admin.ts | 4 +- src/types/bookings.ts | 4 +- src/types/courts.ts | 2 +- src/utils/bookingUtils.ts | 8 ++-- src/utils/hasClaimedAnyCredentials.ts | 4 +- 32 files changed, 128 insertions(+), 128 deletions(-) diff --git a/src/app/[locale]/admin/bookings-test/BookingAdminTestComponent.tsx b/src/app/[locale]/admin/bookings-test/BookingAdminTestComponent.tsx index 1867539..1776996 100644 --- a/src/app/[locale]/admin/bookings-test/BookingAdminTestComponent.tsx +++ b/src/app/[locale]/admin/bookings-test/BookingAdminTestComponent.tsx @@ -602,7 +602,7 @@ export default function BookingAdminTestComponent() {
Court
-
{booking.slot.court.name} (Club: {booking.slot.court.club_name})
+
{booking.slot.court.name} (Club: {booking.slot.court.facility_name})
Capacity
diff --git a/src/app/[locale]/admin/clubs/AdminClubsList.tsx b/src/app/[locale]/admin/clubs/AdminClubsList.tsx index 24fce3b..449cc96 100644 --- a/src/app/[locale]/admin/clubs/AdminClubsList.tsx +++ b/src/app/[locale]/admin/clubs/AdminClubsList.tsx @@ -139,8 +139,8 @@ export default function AdminClubsList() {
{clubs.map((club) => (
diff --git a/src/app/[locale]/admin/clubs/[club_id]/AdminClubDetail.tsx b/src/app/[locale]/admin/clubs/[club_id]/AdminClubDetail.tsx index 9e8140f..b30f990 100644 --- a/src/app/[locale]/admin/clubs/[club_id]/AdminClubDetail.tsx +++ b/src/app/[locale]/admin/clubs/[club_id]/AdminClubDetail.tsx @@ -179,7 +179,7 @@ export default function AdminClubDetailComponent({ clubId }: AdminClubDetailProp
{t('Type')}: - {clubDetail.provider.remote_type} + {clubDetail.provider.provider}
{t('Manages Slot Storage')}: diff --git a/src/components/CourtSlotCard.tsx b/src/components/CourtSlotCard.tsx index 90362e9..c760cee 100644 --- a/src/components/CourtSlotCard.tsx +++ b/src/components/CourtSlotCard.tsx @@ -144,7 +144,7 @@ export default function CourtSlotCard({ currentUser, slot, remoteSlug, sportSlug const buildShareMessage = () => { const playerNames = (slot.players || []).map(p => cleanName(p.full_account_str)); if (playerNames.length === 0 && settings && settings.default_remote_member_id.remotes) { - const claimed = settings.default_remote_member_id.remotes.find(r => r.remote_slug === remoteSlug); + const claimed = settings.default_remote_member_id.remotes.find(r => r.origin_slug === remoteSlug); if (claimed) { const member = remoteMembers.find(m => m.remote_member_id === claimed.remote_member_id); if (member) playerNames.push(cleanName(member.full_account_str)); diff --git a/src/components/Navigation.tsx b/src/components/Navigation.tsx index 21a8a0a..9c405e7 100644 --- a/src/components/Navigation.tsx +++ b/src/components/Navigation.tsx @@ -162,8 +162,8 @@ export default function Navigation({ pageTitle }: NavigationProps) { }; const bookingLink = localizedLink( - settings?.default_remote_sport.remote_slug && settings?.default_remote_sport.sport_slug - ? `/booking/${encodeURIComponent(settings.default_remote_sport.remote_slug)}/${encodeURIComponent(settings.default_remote_sport.sport_slug)}/today` + settings?.default_remote_sport.facility_slug && settings?.default_remote_sport.sport_slug + ? `/booking/${encodeURIComponent(settings.default_remote_sport.facility_slug)}/${encodeURIComponent(settings.default_remote_sport.sport_slug)}/today` : '/select-remote' ); @@ -373,7 +373,7 @@ export default function Navigation({ pageTitle }: NavigationProps) { >
{ - const remoteSlug = settings?.default_remote_sport.remote_slug; + const remoteSlug = settings?.default_remote_sport.facility_slug; const sportSlug = settings?.default_remote_sport.sport_slug; const hasCreds = !!getClaimedRemoteMember(settings); closeMenu(); @@ -528,7 +528,7 @@ export default function Navigation({ pageTitle }: NavigationProps) { isOpen={showPartnerModal} onClose={() => setShowPartnerModal(false)} onSelectPartner={() => {}} - remoteSlug={settings?.default_remote_sport.remote_slug || ''} + remoteSlug={settings?.default_remote_sport.facility_slug || ''} sportSlug={settings?.default_remote_sport.sport_slug || ''} selectedPartners={[]} context="lookup" diff --git a/src/components/PastBookingCard.tsx b/src/components/PastBookingCard.tsx index be757d9..07bd513 100644 --- a/src/components/PastBookingCard.tsx +++ b/src/components/PastBookingCard.tsx @@ -45,7 +45,7 @@ export default function PastBookingCard({ booking, currentUserId, index, onRepor {/* Row 3: Remote info - Mobile */}
- {booking.remote_name} • {t('Court {court}', { court: booking.court })} + {booking.origin_name} • {t('Court {court}', { court: booking.court })}
{/* Desktop header - hidden on mobile */} @@ -62,7 +62,7 @@ export default function PastBookingCard({ booking, currentUserId, index, onRepor {dateInfo.day}
- {booking.remote_name} • {t('Court {court}', { court: booking.court })} + {booking.origin_name} • {t('Court {court}', { court: booking.court })}
diff --git a/src/components/PendingScoresList.tsx b/src/components/PendingScoresList.tsx index 884b727..dc9fce4 100644 --- a/src/components/PendingScoresList.tsx +++ b/src/components/PendingScoresList.tsx @@ -62,7 +62,7 @@ export default function PendingScoresList({ onReport }: Props) {
{new Date(b.start).toLocaleDateString()} • {new Date(b.start).toLocaleTimeString([], {hour:'2-digit',minute:'2-digit'})}
-
{b.remote_name}
+
{b.origin_name}
{b.sport_name} • Court {b.court}
{/* Player display */} {b.players && b.players.length > 0 && ( diff --git a/src/components/PlayerPicker.tsx b/src/components/PlayerPicker.tsx index 5816fd9..0392538 100644 --- a/src/components/PlayerPicker.tsx +++ b/src/components/PlayerPicker.tsx @@ -14,7 +14,7 @@ export default function PlayerPicker({ isOpen, onClose, remoteSlug, onSelect }: const { remoteMembers } = useUserSettings() const { t } = useTranslation() if (!isOpen) return null - const members = remoteMembers.filter(m => m.remote_slug === remoteSlug) + const members = remoteMembers.filter(m => m.origin_slug === remoteSlug) return (
diff --git a/src/components/RemoteSportInfo.tsx b/src/components/RemoteSportInfo.tsx index 7d119cf..b09ad9a 100644 --- a/src/components/RemoteSportInfo.tsx +++ b/src/components/RemoteSportInfo.tsx @@ -5,7 +5,7 @@ import useTranslation from '@/src/hooks/useTranslation'; import apiFetch from '@/src/utils/apiFetch'; interface RemoteInfo { - remote_name: string; + origin_name: string; logo_url?: string; sport_name: string; sport_logo_url?: string; @@ -28,12 +28,12 @@ export default function RemoteInfo({ remoteSlug, sportSlug, remotesData, isLoadi // If remotesData is provided, use it instead of fetching if (remotesData) { - const remote = (remotesData.remotes || []).find((r: any) => r.remote_slug === remoteSlug); + const remote = (remotesData.remotes || []).find((r: any) => r.origin_slug === remoteSlug); const sport = remote?.sports?.find((s: any) => s.sport_slug === sportSlug); if (remote && sport) { setRemoteInfo({ - remote_name: remote.remote_name, - logo_url: remote.remote_logo_url || remote.logo_url, + origin_name: remote.origin_name, + logo_url: remote.origin_logo_url || remote.logo_url, sport_name: sport.sport_name, sport_logo_url: sport.sport_logo_url || sport.logo_url || `/images/${sportSlug}-logo.png`, }); @@ -46,15 +46,15 @@ export default function RemoteInfo({ remoteSlug, sportSlug, remotesData, isLoadi // Fallback to fetching if no data provided setLoading(true); - apiFetch(`/remotes`) + apiFetch(`/facilities`) .then(res => res.json()) .then(data => { - const remote = (data.remotes || []).find((r: any) => r.remote_slug === remoteSlug); + const remote = (data.remotes || []).find((r: any) => r.origin_slug === remoteSlug); const sport = remote?.sports?.find((s: any) => s.sport_slug === sportSlug); if (remote && sport) { setRemoteInfo({ - remote_name: remote.remote_name, - logo_url: remote.remote_logo_url || remote.logo_url, + origin_name: remote.origin_name, + logo_url: remote.origin_logo_url || remote.logo_url, sport_name: sport.sport_name, sport_logo_url: sport.sport_logo_url || sport.logo_url || `/images/${sportSlug}-logo.png`, }); @@ -83,17 +83,17 @@ export default function RemoteInfo({ remoteSlug, sportSlug, remotesData, isLoadi
{remoteInfo.remote_name}
)} - + {/* Club name and sport */}

- {remoteInfo.remote_name} + {remoteInfo.origin_name}

|
diff --git a/src/components/RemoteSportSelector.tsx b/src/components/RemoteSportSelector.tsx index 2edf0ee..7499e9d 100644 --- a/src/components/RemoteSportSelector.tsx +++ b/src/components/RemoteSportSelector.tsx @@ -5,8 +5,8 @@ import LoadingSpinner from './LoadingSpinner'; import useTranslation from '../hooks/useTranslation'; interface Remote { - remote_slug: string; - remote_name: string; + origin_slug: string; + origin_name: string; sports: { sport_slug: string; sport_name: string }[]; } @@ -41,7 +41,7 @@ export default function RemoteSportSelector({ // Simulate API call delay for better UX await new Promise(resolve => setTimeout(resolve, 500)); - onSelect(selectedRemote.remote_slug, sportSlug); + onSelect(selectedRemote.origin_slug, sportSlug); setSaving(false); }; @@ -59,7 +59,7 @@ export default function RemoteSportSelector({

{title}

{selectedRemote - ? `What sport do you play at ${selectedRemote.remote_name}?` + ? `What sport do you play at ${selectedRemote.origin_name}?` : subtitle }

@@ -97,7 +97,7 @@ export default function RemoteSportSelector({ // Remote Selection remotes.map((remote, index) => (
handleRemoteSelect(remote)} @@ -107,12 +107,12 @@ export default function RemoteSportSelector({
- {remote.remote_name.charAt(0).toUpperCase()} + {remote.origin_name.charAt(0).toUpperCase()}

- {remote.remote_name} + {remote.origin_name}

diff --git a/src/components/UserBookingsTimeline.tsx b/src/components/UserBookingsTimeline.tsx index 31b5ee7..3a480fb 100644 --- a/src/components/UserBookingsTimeline.tsx +++ b/src/components/UserBookingsTimeline.tsx @@ -51,8 +51,8 @@ export default function UserBookingsTimeline({ currentUser, bookingsData }: Comp for (const slot of sport.slots || []) { slots.push({ ...slot, - remote_slug: remote.remote_slug, - remote_name: remote.remote_name, + origin_slug: remote.origin_slug, + origin_name: remote.origin_name, sport_slug: sport.sport_slug, sport_name: sport.sport_name, src_timezone: remote.src_timezone, @@ -212,7 +212,7 @@ export default function UserBookingsTimeline({ currentUser, bookingsData }: Comp const timeUntil = getTimeUntilMatch(timeSlot.date.toISOString()); // Get unique remotes and courts for this time slot - const uniqueRemotes = Array.from(new Set(timeSlot.bookings.map(b => b.remote_name))); + const uniqueRemotes = Array.from(new Set(timeSlot.bookings.map(b => b.origin_name))); const uniqueCourts = Array.from(new Set(timeSlot.bookings.map(b => b.court).filter(Boolean))); return ( diff --git a/src/components/bookings/BookingDrawer.tsx b/src/components/bookings/BookingDrawer.tsx index 8e1fcd4..8595900 100644 --- a/src/components/bookings/BookingDrawer.tsx +++ b/src/components/bookings/BookingDrawer.tsx @@ -196,7 +196,7 @@ export default function BookingDrawer({ bookingId, onClose, onUpdate }: BookingD

{booking.slot.court.name}

-

{booking.slot.court.club_name}

+

{booking.slot.court.facility_name}

diff --git a/src/components/landing/BookingShowcase.tsx b/src/components/landing/BookingShowcase.tsx index 684f555..bbe4efc 100644 --- a/src/components/landing/BookingShowcase.tsx +++ b/src/components/landing/BookingShowcase.tsx @@ -11,8 +11,8 @@ import { getSlotStatus } from '@/src/utils/slotStatus'; const mockRemotesData = { remotes: [ { - remote_slug: 'tennis-club-zurich', - remote_name: 'Tennis Club Zurich', + origin_slug: 'tennis-club-zurich', + origin_name: 'Tennis Club Zurich', logo_url: '/images/tennis-club-logo.png', sports: [ { @@ -32,7 +32,7 @@ const mockCurrentUser: RemoteMemberWithNameAndRemoteSlug = { self_reported_level: 3.5, full_account_str: 'Demo User', name: 'Demo User', - remote_slug: 'tennis-club-zurich' + origin_slug: 'tennis-club-zurich' }; // Generate mock players @@ -63,9 +63,9 @@ const generateMockSlots = (): CourtSlotWithDurationAndStatus[] => { booked_by: null, i: null, remote: { - remote_slug: 'tennis-club-zurich', - remote_name: 'Tennis Club Zurich', - remote_logo_url: '/images/tennis-club-logo.png', + origin_slug: 'tennis-club-zurich', + origin_name: 'Tennis Club Zurich', + origin_logo_url: '/images/tennis-club-logo.png', src_timezone: 'Europe/Zurich' }, sport: { @@ -87,9 +87,9 @@ const generateMockSlots = (): CourtSlotWithDurationAndStatus[] => { booked_by: null, i: null, remote: { - remote_slug: 'tennis-club-zurich', - remote_name: 'Tennis Club Zurich', - remote_logo_url: '/images/tennis-club-logo.png', + origin_slug: 'tennis-club-zurich', + origin_name: 'Tennis Club Zurich', + origin_logo_url: '/images/tennis-club-logo.png', src_timezone: 'Europe/Zurich' }, sport: { @@ -111,9 +111,9 @@ const generateMockSlots = (): CourtSlotWithDurationAndStatus[] => { booked_by: null, i: null, remote: { - remote_slug: 'tennis-club-zurich', - remote_name: 'Tennis Club Zurich', - remote_logo_url: '/images/tennis-club-logo.png', + origin_slug: 'tennis-club-zurich', + origin_name: 'Tennis Club Zurich', + origin_logo_url: '/images/tennis-club-logo.png', src_timezone: 'Europe/Zurich' }, sport: { @@ -136,9 +136,9 @@ const generateMockSlots = (): CourtSlotWithDurationAndStatus[] => { booked_by: { remote_member_id: 5, app_user_id: 5 }, i: null, remote: { - remote_slug: 'tennis-club-zurich', - remote_name: 'Tennis Club Zurich', - remote_logo_url: '/images/tennis-club-logo.png', + origin_slug: 'tennis-club-zurich', + origin_name: 'Tennis Club Zurich', + origin_logo_url: '/images/tennis-club-logo.png', src_timezone: 'Europe/Zurich' }, sport: { @@ -160,9 +160,9 @@ const generateMockSlots = (): CourtSlotWithDurationAndStatus[] => { booked_by: { remote_member_id: 2, app_user_id: 2 }, i: null, remote: { - remote_slug: 'tennis-club-zurich', - remote_name: 'Tennis Club Zurich', - remote_logo_url: '/images/tennis-club-logo.png', + origin_slug: 'tennis-club-zurich', + origin_name: 'Tennis Club Zurich', + origin_logo_url: '/images/tennis-club-logo.png', src_timezone: 'Europe/Zurich' }, sport: { @@ -185,9 +185,9 @@ const generateMockSlots = (): CourtSlotWithDurationAndStatus[] => { booked_by: null, i: null, remote: { - remote_slug: 'tennis-club-zurich', - remote_name: 'Tennis Club Zurich', - remote_logo_url: '/images/tennis-club-logo.png', + origin_slug: 'tennis-club-zurich', + origin_name: 'Tennis Club Zurich', + origin_logo_url: '/images/tennis-club-logo.png', src_timezone: 'Europe/Zurich' }, sport: { @@ -209,9 +209,9 @@ const generateMockSlots = (): CourtSlotWithDurationAndStatus[] => { booked_by: null, i: null, remote: { - remote_slug: 'tennis-club-zurich', - remote_name: 'Tennis Club Zurich', - remote_logo_url: '/images/tennis-club-logo.png', + origin_slug: 'tennis-club-zurich', + origin_name: 'Tennis Club Zurich', + origin_logo_url: '/images/tennis-club-logo.png', src_timezone: 'Europe/Zurich' }, sport: { diff --git a/src/components/profile/ProfileMatchHistory.tsx b/src/components/profile/ProfileMatchHistory.tsx index 975de8f..055f51f 100644 --- a/src/components/profile/ProfileMatchHistory.tsx +++ b/src/components/profile/ProfileMatchHistory.tsx @@ -11,8 +11,8 @@ interface Match { date: string; venue_id: number; slot_id?: string; - remote_slug?: string; - remote_name?: string; + origin_slug?: string; + origin_name?: string; sport_slug?: string; court?: string; outcome?: { @@ -71,8 +71,8 @@ export default function ProfileMatchHistory({ matches, venues, currentUserId, t, end: endDate.toISOString(), duration: match.duration_minutes || 90, src_timezone: 'UTC', // Default timezone - remote_name: match.remote_name || venue?.name || 'Unknown Venue', - remote_slug: match.remote_slug || '', + origin_name: match.origin_name || venue?.name || 'Unknown Venue', + origin_slug: match.origin_slug || '', sport_name: match.match_type || 'Padel', sport_slug: match.sport_slug || 'padel', court: match.court || 'Court 1', diff --git a/src/components/profile/ProfileView.tsx b/src/components/profile/ProfileView.tsx index fd7ee68..a9dfaf6 100644 --- a/src/components/profile/ProfileView.tsx +++ b/src/components/profile/ProfileView.tsx @@ -92,7 +92,7 @@ export function ProfileView({ type, id, sportSlug, translations, locale }: Profi // Transform venues array to a map for ProfileDisplay const venuesMap: Record = {}; data.venues.forEach(venue => { - venuesMap[venue.remote_server_id] = { + venuesMap[venue.origin_id] = { name: venue.name, address: undefined }; @@ -134,15 +134,15 @@ export function ProfileView({ type, id, sportSlug, translations, locale }: Profi } // Find venue ID from slug - const venue = data.venues.find(v => v.slug === match.remote_slug); - + const venue = data.venues.find(v => v.slug === match.origin_slug); + return { id: parseInt(match.slot_id) || index, date: match.start_time, - venue_id: venue?.remote_server_id || 1, + venue_id: venue?.origin_id || 1, slot_id: match.slot_id, - remote_slug: match.remote_slug, - remote_name: venue?.name, + origin_slug: match.origin_slug, + origin_name: venue?.name, sport_slug: match.sport_slug, court: match.court, outcome, diff --git a/src/components/profile/RecentMatches.tsx b/src/components/profile/RecentMatches.tsx index a9c2949..2d5df5c 100644 --- a/src/components/profile/RecentMatches.tsx +++ b/src/components/profile/RecentMatches.tsx @@ -6,7 +6,7 @@ interface Match { slot_id: string; court: string; start_time: string; - remote_slug: string; + origin_slug: string; sport_slug: string; players: Array; status: string; @@ -23,7 +23,7 @@ interface Match { interface RecentMatchesProps { matches: Match[]; venues: Array<{ - remote_server_id: number; + origin_id: number; slug: string; name: string; logo_url: string; @@ -137,7 +137,7 @@ export function RecentMatches({
- {getVenueName(match.remote_slug)} - {match.court} + {getVenueName(match.origin_slug)} - {match.court}
diff --git a/src/contexts/UserSettingsContext.tsx b/src/contexts/UserSettingsContext.tsx index c511cd9..a1cf352 100644 --- a/src/contexts/UserSettingsContext.tsx +++ b/src/contexts/UserSettingsContext.tsx @@ -23,7 +23,7 @@ interface ContextValue { export const defaultEmptySettings = { onboarding: { dismissed: false }, - default_remote_sport: { remote_slug: null, sport_slug: null }, + default_remote_sport: { facility_slug: null, sport_slug: null }, remote_credentials: null, default_remote_member_id: { remotes: [] } } diff --git a/src/hooks/useBookingLink.ts b/src/hooks/useBookingLink.ts index fbbbfb5..5823b28 100644 --- a/src/hooks/useBookingLink.ts +++ b/src/hooks/useBookingLink.ts @@ -5,10 +5,10 @@ import { useLocalizedLink } from "./useLocalizedLink"; export default function useBookingLink() { const { settings } = useUserSettings(); const { localizedLink } = useLocalizedLink(); - - const path = settings?.default_remote_sport.remote_slug && settings?.default_remote_sport.sport_slug - ? `/booking/${encodeURIComponent(settings.default_remote_sport.remote_slug)}/${encodeURIComponent(settings.default_remote_sport.sport_slug)}/${isLaterThanHour(21) ? 'tomorrow' : 'today'}` + + const path = settings?.default_remote_sport.facility_slug && settings?.default_remote_sport.sport_slug + ? `/booking/${encodeURIComponent(settings.default_remote_sport.facility_slug)}/${encodeURIComponent(settings.default_remote_sport.sport_slug)}/${isLaterThanHour(21) ? 'tomorrow' : 'today'}` : '/select-remote'; - + return localizedLink(path); } \ No newline at end of file diff --git a/src/hooks/useCourtSlots.ts b/src/hooks/useCourtSlots.ts index b1e33fd..e12f99f 100644 --- a/src/hooks/useCourtSlots.ts +++ b/src/hooks/useCourtSlots.ts @@ -27,10 +27,10 @@ export default function useCourtSlots( useEffect(() => { if (remotesData && remoteSlug) { const remote = (remotesData.remotes || []).find( - (r: any) => r.remote_slug === remoteSlug + (r: any) => r.origin_slug === remoteSlug ); if (remote) { - setRemoteName(remote.remote_name); + setRemoteName(remote.origin_name); setRemoteTimezone(remote.src_timezone || 'UTC'); } } @@ -87,14 +87,14 @@ export default function useCourtSlots( setOldestUpdatedAt(data.oldest_updated_at); } - // Extract remote and sport info from the first court - if (courts.length > 0 && courts[0].remote && courts[0].sport) { - const remoteInfo = courts[0].remote; + // Extract facility and sport info from the first court + if (courts.length > 0 && courts[0].facility && courts[0].sport) { + const facilityInfo = courts[0].facility; const sportInfo = courts[0].sport; // Extract values - extractedRemoteName = remoteInfo.remote_name || ''; - extractedTimezone = remoteInfo.src_timezone || 'UTC'; + extractedRemoteName = facilityInfo.facility_name || ''; + extractedTimezone = facilityInfo.facility_timezone || 'UTC'; // Set remote name and timezone if available if (extractedRemoteName) setRemoteName(extractedRemoteName); @@ -103,9 +103,9 @@ export default function useCourtSlots( // Create remotesData format for RemoteSportInfo component newRemotesData = { remotes: [{ - remote_slug: remoteInfo.remote_slug || remoteSlug, - remote_name: extractedRemoteName, - remote_logo_url: remoteInfo.remote_logo_url, + origin_slug: facilityInfo.facility_slug || remoteSlug, + origin_name: extractedRemoteName, + origin_logo_url: facilityInfo.facility_logo_url, src_timezone: extractedTimezone, sports: [{ sport_slug: sportInfo.sport_slug || sportSlug, diff --git a/src/hooks/useEnhancedParams.ts b/src/hooks/useEnhancedParams.ts index 8aee450..36b3559 100644 --- a/src/hooks/useEnhancedParams.ts +++ b/src/hooks/useEnhancedParams.ts @@ -5,15 +5,15 @@ export function useEnhancedParams() { const slot_id = Array.isArray(params.slot_id) ? params.slot_id[0] : params.slot_id; - const remote_slug = Array.isArray(params.remote_slug) - ? params.remote_slug[0] - : params.remote_slug; + const origin_slug = Array.isArray(params.origin_slug) + ? params.origin_slug[0] + : params.origin_slug; const sport_slug = Array.isArray(params.sport_slug) ? params.sport_slug[0] : params.sport_slug; return { slot_id, - remote_slug, + origin_slug, sport_slug, }; } \ No newline at end of file diff --git a/src/hooks/usePastBookings.ts b/src/hooks/usePastBookings.ts index a31ab5a..d5b2022 100644 --- a/src/hooks/usePastBookings.ts +++ b/src/hooks/usePastBookings.ts @@ -21,8 +21,8 @@ export default function usePastBookings(locale: Locale) { for (const slot of sport.slots || []) { slots.push({ ...slot, - remote_slug: remote.remote_slug, - remote_name: remote.remote_name, + origin_slug: remote.origin_slug, + origin_name: remote.origin_name, sport_slug: sport.sport_slug, sport_name: sport.sport_name, src_timezone: remote.src_timezone, diff --git a/src/hooks/useUserBookings.ts b/src/hooks/useUserBookings.ts index 0b9d468..bedc32f 100644 --- a/src/hooks/useUserBookings.ts +++ b/src/hooks/useUserBookings.ts @@ -15,8 +15,8 @@ export interface UserBooking { players: Player[]; booked_by: number; booked_by_app_user?: boolean; - remote_slug: string; - remote_name: string; + origin_slug: string; + origin_name: string; sport_slug: string; sport_name: string; src_timezone: string; @@ -42,8 +42,8 @@ export default function useUserBookings(locale: Locale) { for (const slot of sport.slots || []) { slots.push({ ...slot, - remote_slug: remote.remote_slug, - remote_name: remote.remote_name, + origin_slug: remote.origin_slug, + origin_name: remote.origin_name, sport_slug: sport.sport_slug, sport_name: sport.sport_name, src_timezone: remote.src_timezone, diff --git a/src/lib/api/admin-clubs.ts b/src/lib/api/admin-clubs.ts index abb35fb..6aa04de 100644 --- a/src/lib/api/admin-clubs.ts +++ b/src/lib/api/admin-clubs.ts @@ -171,13 +171,13 @@ export async function getAdminClubDetail( export const MOCK_CLUBS: AdminClubsResponse = [ { - club_id: 1, + facility_id: 1, name: 'Central Padel Geneva', timezone: 'Europe/Zurich', courts: 4, }, { - club_id: 2, + facility_id: 2, name: 'Riverside Tennis Lausanne', timezone: 'Europe/Zurich', courts: 6, @@ -186,7 +186,7 @@ export const MOCK_CLUBS: AdminClubsResponse = [ export const MOCK_CLUB_DETAIL: AdminClubDetail = { club: { - club_id: 1, + facility_id: 1, name: 'Central Padel Geneva', timezone: 'Europe/Zurich', }, @@ -213,7 +213,7 @@ export const MOCK_CLUB_DETAIL: AdminClubDetail = { slot_definitions: [], upcoming_slots: [], provider: { - remote_type: 'local', + provider: 'local', capabilities: { manages_slot_storage: true, supports_payment_verification: false, diff --git a/src/lib/api/courts.ts b/src/lib/api/courts.ts index c32bfca..f551be6 100644 --- a/src/lib/api/courts.ts +++ b/src/lib/api/courts.ts @@ -338,7 +338,7 @@ export function getMockCourts(clubId: number): Court[] { export function getMockClubProfile(clubId: number): ClubProfile { return { - club_id: clubId, + facility_id: clubId, name: 'Central Padel', timezone: 'Europe/London', settings: { diff --git a/src/lib/types.ts b/src/lib/types.ts index 9dd2767..e4084fa 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -1,8 +1,8 @@ export type AOrBProps = (Partial & A) | (Partial & B); export type Remote = { - remote_logo_url: string; - remote_name: string; + origin_logo_url: string; + origin_name: string; src_timezone: string; } & RemoteSlugProp; @@ -20,7 +20,7 @@ export type BaseRemoteMemberData = { self_reported_level: number | null; } & RemoteMemberIdProp; -export type RemoteSlugProp = { remote_slug: string; } +export type RemoteSlugProp = { origin_slug: string; } export type FullAccountStrProp = { full_account_str: string; @@ -294,23 +294,23 @@ export type CourtSlotWithDurationAndStatus = CourtSlot< export type RemoteMemberWithNameAndRemoteSlug = RemoteMember & NameProp - & { remote_slug: string | undefined; } + & { origin_slug: string | undefined; } export type RemoteMemberWithRemoteSlugAndMaybeName = RemoteMember & Partial - & { remote_slug: string | undefined; } + & { origin_slug: string | undefined; } export type BookingResponse = AOrBProps; // ---------- user settings export interface DefaultRemoteSport { - remote_slug: string | null; + facility_slug: string | null; sport_slug: string | null; } export interface DefaultRemoteMemberId { - remotes?: { remote_slug: string; remote_member_id: number }[]; + remotes?: { origin_slug: string; remote_member_id: number }[]; } export interface UserSettings { @@ -437,7 +437,7 @@ export type PublicProfileResponse = PublicProfileSuccessResponse | PublicProfile // ============================================================================ export interface Venue { - remote_server_id: number; + origin_id: number; slug: string; name: string; logo_url: string | null; @@ -519,7 +519,7 @@ export interface RecentMatch { slot_id: string; // Court slot ID as string court: string; // Court name/number start_time: string | null; // ISO 8601 date string - remote_slug: string; // Venue slug + origin_slug: string; // Venue slug sport_slug: string; players: MatchPlayer[]; // Array of 2-4 players depending on sport status: string; // e.g., "booked", "completed" diff --git a/src/lib/types_bis.ts b/src/lib/types_bis.ts index e653400..14b921b 100644 --- a/src/lib/types_bis.ts +++ b/src/lib/types_bis.ts @@ -13,8 +13,8 @@ } interface Remote { - remote_slug: string; - remote_name: string; + origin_slug: string; + origin_name: string; remote_members: RemoteMember[]; } diff --git a/src/types/admin-api.ts b/src/types/admin-api.ts index 80034e8..46f715d 100644 --- a/src/types/admin-api.ts +++ b/src/types/admin-api.ts @@ -16,7 +16,7 @@ * Returns: unwrapped array of clubs */ export interface AdminClub { - club_id: number; + facility_id: number; name: string; timezone: string; courts: number; // Court count @@ -30,7 +30,7 @@ export type AdminClubsResponse = AdminClub[]; */ export interface AdminClubDetail { club: { - club_id: number; + facility_id: number; name: string; timezone: string; }; @@ -61,7 +61,7 @@ export interface AdminSlot { slot_id: number; // slot_instance_id court_id: number; court_name: string; - club_id: number; + facility_id: number; starts_at: string; // ISO 8601 timestamp ends_at: string; // ISO 8601 timestamp booking: AdminSlotBooking; @@ -91,7 +91,7 @@ export interface AdminSlotMeta { } export interface AdminProviderInfo { - remote_type: 'local' | 'fairplay'; + provider: 'local' | 'fairplay'; capabilities: { manages_slot_storage: boolean; supports_payment_verification: boolean; diff --git a/src/types/booking-admin.ts b/src/types/booking-admin.ts index 1ea150a..d50ee3b 100644 --- a/src/types/booking-admin.ts +++ b/src/types/booking-admin.ts @@ -42,8 +42,8 @@ export type SlotStatus = 'open' | 'booked' | 'held' | 'cancelled'; export interface CourtInfo { court_id: number; name: string; - club_id: number; - club_name: string; + facility_id: number; + facility_name: string; } export interface ProviderInfo { diff --git a/src/types/bookings.ts b/src/types/bookings.ts index 02f5429..73dc8ee 100644 --- a/src/types/bookings.ts +++ b/src/types/bookings.ts @@ -39,8 +39,8 @@ export interface BookingSlot { court: { court_id: number; name: string; - club_id: number; - club_name: string; + facility_id: number; + facility_name: string; }; } diff --git a/src/types/courts.ts b/src/types/courts.ts index fde6507..1af5203 100644 --- a/src/types/courts.ts +++ b/src/types/courts.ts @@ -73,7 +73,7 @@ export interface ClubProfileSettings { } export interface ClubProfile { - club_id: number; + facility_id: number; name: string; timezone: string; // IANA timezone settings?: ClubProfileSettings; diff --git a/src/utils/bookingUtils.ts b/src/utils/bookingUtils.ts index 0f2ad5f..2cc87d9 100644 --- a/src/utils/bookingUtils.ts +++ b/src/utils/bookingUtils.ts @@ -142,17 +142,17 @@ export const isCurrentUserGen = ( p: { remote_member_id: number } ) => currentUser && p.remote_member_id === currentUser.remote_member_id; -export const getCurrentUser = (settings: UserSettings | null, remoteMembers: RemoteMemberWithRemoteSlugAndMaybeName[], remote_slug?: string): RemoteMemberWithNameAndRemoteSlug => { +export const getCurrentUser = (settings: UserSettings | null, remoteMembers: RemoteMemberWithRemoteSlugAndMaybeName[], origin_slug?: string): RemoteMemberWithNameAndRemoteSlug => { if (settings && settings.default_remote_member_id.remotes) { - const remoteSlug = remote_slug ?? settings.default_remote_sport.remote_slug; + const remoteSlug = origin_slug ?? settings.default_remote_sport.facility_slug; const entry = settings.default_remote_member_id.remotes.find( - r => r.remote_slug === remoteSlug + r => r.origin_slug === remoteSlug ); const member = remoteMembers.find(m => m.remote_member_id === entry?.remote_member_id); if (member) return { ...member, name: cleanName(member.full_account_str)}; } // Use -Infinity to indicate no user (won't match any real remote_member_id) - return { remote_member_id: -Infinity, full_account_str: 'You', remote_slug, name: 'You', self_reported_level: null, glicko_level: null }; + return { remote_member_id: -Infinity, full_account_str: 'You', origin_slug, name: 'You', self_reported_level: null, glicko_level: null }; } export const getEnhancedPlayerGen = ( diff --git a/src/utils/hasClaimedAnyCredentials.ts b/src/utils/hasClaimedAnyCredentials.ts index 842db56..901bca1 100644 --- a/src/utils/hasClaimedAnyCredentials.ts +++ b/src/utils/hasClaimedAnyCredentials.ts @@ -6,11 +6,11 @@ export function hasClaimedAnyCredentials(settings: UserSettings | null) { export function getClaimedRemoteMember(settings: UserSettings | null) { if (!settings || !settings.default_remote_member_id.remotes) return undefined; - const remoteMembers = settings.default_remote_member_id && settings.default_remote_member_id.remotes.filter(r => r.remote_slug === settings.default_remote_sport.remote_slug); + const remoteMembers = settings.default_remote_member_id && settings.default_remote_member_id.remotes.filter(r => r.origin_slug === settings.default_remote_sport.facility_slug); return remoteMembers && remoteMembers[0]; } export function hasClaimedCredentialsForRemote(settings: UserSettings | null, remoteSlug: string) { if (!settings || !settings.default_remote_member_id.remotes) return false; - return !!settings.default_remote_member_id.remotes.find(r => r.remote_slug === remoteSlug); + return !!settings.default_remote_member_id.remotes.find(r => r.origin_slug === remoteSlug); }