feat: integrate FullCalendar for booking management and add booking dashboard
- Added FullCalendar component to display bookings in a calendar view. - Implemented BookingDashboardTab to show summary statistics including bookings today, revenue, checked-in guests, and outstanding payments. - Created BookingInvoicesTab to manage and display booking payment receipts separately from membership invoices. - Enhanced AdhocBookingTab to allow selection of existing members for guest bookings. - Updated BookingRosterTab to include payment methods and improved UI for guest identification. - Introduced new API endpoints for fetching booking invoices and dashboard summaries. - Updated models to support new features including payment methods and invoice structures.
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
import { apiRequest } from "@/lib/api/core-http"
|
||||
import type { BookingInvoice, GetBookingInvoicesFilters } from "@/lib/models/booking-invoice"
|
||||
|
||||
/** Booking payment receipts — kept separate from the membership-based Customer Payments view. */
|
||||
function getBookingInvoices(filters: GetBookingInvoicesFilters = {}) {
|
||||
return apiRequest<BookingInvoice[]>("client/bookings/invoices", { query: filters })
|
||||
}
|
||||
|
||||
export { getBookingInvoices }
|
||||
+12
-4
@@ -1,10 +1,13 @@
|
||||
import { apiRequest } from "@/lib/api/core-http"
|
||||
import type { BookingDashboardSummary } from "@/lib/models/booking-dashboard"
|
||||
import type {
|
||||
Booking,
|
||||
CompleteBookingInput,
|
||||
CreateAdhocBookingInput,
|
||||
CreateGuestAdhocBookingInput,
|
||||
CreateGuestBookingInput,
|
||||
GetBookingsFilters,
|
||||
MarkGuestBookingPaidInput,
|
||||
ReassignBookingInput,
|
||||
RescheduleBookingInput,
|
||||
} from "@/lib/models/booking"
|
||||
@@ -41,10 +44,10 @@ function checkInBooking(otpCode: string, rfidTagId?: string) {
|
||||
})
|
||||
}
|
||||
|
||||
function markGuestBookingPaid(id: string, amountCharged: number) {
|
||||
function markGuestBookingPaid(id: string, input: MarkGuestBookingPaidInput) {
|
||||
return apiRequest<Booking>(`client/bookings/${id}/mark-paid`, {
|
||||
method: "POST",
|
||||
body: { bookingId: id, amountCharged },
|
||||
body: { bookingId: id, ...input },
|
||||
})
|
||||
}
|
||||
|
||||
@@ -66,8 +69,12 @@ function markNoShow(id: string) {
|
||||
return apiRequest<Booking>(`client/bookings/${id}/no-show`, { method: "POST" })
|
||||
}
|
||||
|
||||
function completeBooking(id: string) {
|
||||
return apiRequest<Booking>(`client/bookings/${id}/complete`, { method: "POST" })
|
||||
function completeBooking(id: string, input: CompleteBookingInput = {}) {
|
||||
return apiRequest<Booking>(`client/bookings/${id}/complete`, { method: "POST", body: input })
|
||||
}
|
||||
|
||||
function getBookingDashboardSummary() {
|
||||
return apiRequest<BookingDashboardSummary>("client/bookings/dashboard-summary")
|
||||
}
|
||||
|
||||
export {
|
||||
@@ -83,4 +90,5 @@ export {
|
||||
rescheduleBooking,
|
||||
markNoShow,
|
||||
completeBooking,
|
||||
getBookingDashboardSummary,
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
/** Mirrors BookingDashboardSummaryDto. */
|
||||
export interface BookingDashboardSummary {
|
||||
bookingsToday: number
|
||||
revenueToday: number
|
||||
checkedInNow: number
|
||||
upcomingConfirmed: number
|
||||
outstandingUnpaid: number
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
import type { PaymentMethod } from "@/lib/models/booking"
|
||||
|
||||
/** Mirrors BookingInvoiceDto. A booking payment receipt — deliberately separate from
|
||||
* membership-based Customer Payments/invoices. */
|
||||
export interface BookingInvoice {
|
||||
bookingInvoiceId: string
|
||||
bookingId: string
|
||||
amount: number
|
||||
paymentMethod: PaymentMethod
|
||||
guestName: string
|
||||
guestPhone?: string | null
|
||||
facilityName: string
|
||||
bookingStartTime: string
|
||||
bookingEndTime: string
|
||||
issuedAt: string
|
||||
/** Public, unauthenticated link to this receipt's printable page. */
|
||||
shareUrl?: string | null
|
||||
}
|
||||
|
||||
export type GetBookingInvoicesFilters = {
|
||||
fromDate?: string
|
||||
toDate?: string
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
export type BookingStatus = "Confirmed" | "CheckedIn" | "Cancelled" | "NoShow" | "Completed"
|
||||
export type PaymentMethod = "Cash" | "Bank"
|
||||
|
||||
/** Mirrors BookingDto. Covers both Scheduled (facilitySessionId set) and AdHoc
|
||||
* (facilitySessionId null, exclusive-unit) bookings. */
|
||||
@@ -30,6 +31,9 @@ export interface Booking {
|
||||
|
||||
paymentStatus: string
|
||||
amountCharged: number
|
||||
/** Set once paymentStatus becomes "Paid". */
|
||||
paymentMethod?: PaymentMethod | null
|
||||
paidAt?: string | null
|
||||
status: BookingStatus
|
||||
bookedAt: string
|
||||
checkedInAt?: string | null
|
||||
@@ -51,6 +55,8 @@ export interface CreateGuestBookingInput {
|
||||
facilitySessionId: string
|
||||
guestName: string
|
||||
guestPhone: string
|
||||
/** Optional link to an existing registered customer — identification/auto-fill only. */
|
||||
customerId?: string
|
||||
}
|
||||
|
||||
export interface CreateAdhocBookingInput {
|
||||
@@ -69,6 +75,8 @@ export interface CreateGuestAdhocBookingInput {
|
||||
partySize?: number
|
||||
/** Overrides the facility's own price per hour for this booking's charge only. */
|
||||
pricePerHour?: number
|
||||
/** Optional link to an existing registered customer — identification/auto-fill only. */
|
||||
customerId?: string
|
||||
}
|
||||
|
||||
export interface ReassignBookingInput {
|
||||
@@ -82,3 +90,16 @@ export interface RescheduleBookingInput {
|
||||
durationMinutes?: number
|
||||
facilitySessionId?: string
|
||||
}
|
||||
|
||||
/** Only required when the target booking is a guest booking still Unpaid — the backend
|
||||
* rejects checkout otherwise. Ignored for a member booking or a guest booking already Paid. */
|
||||
export interface CompleteBookingInput {
|
||||
markPaid?: boolean
|
||||
amountCollected?: number
|
||||
paymentMethod?: PaymentMethod
|
||||
}
|
||||
|
||||
export interface MarkGuestBookingPaidInput {
|
||||
amountCharged: number
|
||||
paymentMethod?: PaymentMethod
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user