This commit is contained in:
richarjiang
2026-07-15 17:12:04 +08:00
commit f8c8c688a1
26 changed files with 6789 additions and 0 deletions

122
src/shared/contracts.ts Normal file
View File

@@ -0,0 +1,122 @@
export type CourtStatus = 'online' | 'maintenance' | 'login-required'
export interface CourtSummary {
id: string
name: string
shortName: string
district?: string
address?: string
distanceKm?: number
surface?: string
indoor?: boolean
accent: string
status: CourtStatus
}
export type SlotStatus = 'available' | 'limited' | 'booked' | 'blocked'
export interface BookingContact {
name?: string
phone?: string
}
export interface EnrollmentActivity {
id: string
title: string
startTime: string
endTime: string
feeCents: number
enrolledCount: number
capacity: number
participantNames: string[]
enrollmentDeadline?: string
}
export interface BookingSlot {
id: string
courtLabel: string
startTime: string
endTime: string
priceCents: number
status: SlotStatus
unavailableLabel?: string
bookedBy?: BookingContact[]
enrollment?: EnrollmentActivity
providerReference?: {
classroomUid: string
beginDatetime: string
endDatetime: string
}
sourceLabel?: string
}
export interface AvailabilityDay {
courtId: string
date: string
updatedAt: string
slots: BookingSlot[]
}
export interface AvailabilityQuery {
courtId: string
date: string
}
export interface CourtSettings {
courtId: string
visitorId?: string
visitorIdConfigured: boolean
}
export interface UpdateCourtSettingsInput {
courtId: string
visitorId?: string
}
export interface CreateBookingInput {
courtId: string
date: string
slotId: string
expectedPriceCents: number
}
export interface CancelBookingInput {
courtId: string
orderId: string
}
export interface PendingBooking {
courtId: string
orderId: string
venueAppointmentIds: string[]
amountCents: number
courtLabel: string
startTime: string
endTime: string
expiresAt?: string
status:
| 'submitting-uncertain'
| 'pending-payment'
| 'release-uncertain'
| 'release-confirmed'
}
export interface TennisBookApi {
listCourts(): Promise<CourtSummary[]>
getAvailability(query: AvailabilityQuery): Promise<AvailabilityDay>
getCourtSettings(courtId: string): Promise<CourtSettings>
updateCourtSettings(input: UpdateCourtSettingsInput): Promise<CourtSettings>
createBooking(input: CreateBookingInput): Promise<PendingBooking>
cancelBooking(input: CancelBookingInput): Promise<void>
getPendingBooking(courtId: string): Promise<PendingBooking | null>
}
export const IPC_CHANNELS = {
listCourts: 'courts:list',
getAvailability: 'courts:availability',
getCourtSettings: 'court-settings:get',
updateCourtSettings: 'court-settings:update',
createBooking: 'bookings:create',
cancelBooking: 'bookings:cancel',
getPendingBooking: 'bookings:pending'
} as const