178 lines
4.9 KiB
Markdown
178 lines
4.9 KiB
Markdown
|
|
# Book Slot Hook Migration to Shared Package
|
||
|
|
|
||
|
|
**Date:** 2025-11-08
|
||
|
|
**Status:** ✅ Completed
|
||
|
|
|
||
|
|
## Overview
|
||
|
|
|
||
|
|
Moved the `useBookSlot` hook from `apps/main/src/hooks/book.ts` to the `@xtablo/shared` package, making it available to all apps in the monorepo. Updated the `@xtablo/external` app to use this shared hook instead of the non-existent `useCreateTabloWithOwner` hook.
|
||
|
|
|
||
|
|
## Changes Made
|
||
|
|
|
||
|
|
### 1. Created Shared Hook
|
||
|
|
|
||
|
|
Created `/packages/shared/src/hooks/book.ts` with:
|
||
|
|
- Exported `useBookSlot` hook with improved API signature
|
||
|
|
- Added optional `onSuccess` callback parameter for custom success handling
|
||
|
|
- Made hook flexible to work in different contexts (embedded widgets, modal views, default navigation)
|
||
|
|
|
||
|
|
**Hook Signature:**
|
||
|
|
```typescript
|
||
|
|
export const useBookSlot = (
|
||
|
|
api: AxiosInstance,
|
||
|
|
accessToken?: string,
|
||
|
|
onSuccess?: (data: BookSlotResponse) => void
|
||
|
|
) => { /* ... */ }
|
||
|
|
```
|
||
|
|
|
||
|
|
### 2. Updated Main App
|
||
|
|
|
||
|
|
**File: `apps/main/src/hooks/book.ts`**
|
||
|
|
- Replaced entire implementation with re-export from `@xtablo/shared`
|
||
|
|
- Maintains backward compatibility for existing imports
|
||
|
|
|
||
|
|
**File: `apps/main/src/pages/PublicBookingPage.tsx`**
|
||
|
|
- Updated `useBookSlot()` call to pass required arguments: `useBookSlot(api, session?.access_token)`
|
||
|
|
|
||
|
|
### 3. Updated External App
|
||
|
|
|
||
|
|
**Files Modified:**
|
||
|
|
- `apps/external/src/FloatingBookingWidget.tsx`
|
||
|
|
- `apps/external/src/EmbeddedBookingPage.tsx`
|
||
|
|
|
||
|
|
**Changes:**
|
||
|
|
1. Removed non-existent `useCreateTabloWithOwner` import
|
||
|
|
2. Added `useBookSlot` import from `@xtablo/shared/hooks/book`
|
||
|
|
3. Refactored booking logic to use the booking slot API endpoint instead of direct tablo creation
|
||
|
|
4. Updated both logged-in and non-logged-in user flows
|
||
|
|
5. Maintained custom success callbacks for modal/widget closing behavior
|
||
|
|
|
||
|
|
**Before:**
|
||
|
|
```typescript
|
||
|
|
const { mutateAsync: createTabloWithOwner } = useCreateTabloWithOwner(api, () => {
|
||
|
|
handleCloseModal();
|
||
|
|
});
|
||
|
|
|
||
|
|
await createTabloWithOwner({
|
||
|
|
name: eventType?.name || "",
|
||
|
|
status: "todo",
|
||
|
|
owner_short_id: shortUserId || "",
|
||
|
|
event: { /* ... */ },
|
||
|
|
access_token: session?.access_token || "",
|
||
|
|
});
|
||
|
|
```
|
||
|
|
|
||
|
|
**After:**
|
||
|
|
```typescript
|
||
|
|
const { mutateAsync: bookSlot } = useBookSlot(api, session?.access_token, () => {
|
||
|
|
handleCloseModal();
|
||
|
|
});
|
||
|
|
|
||
|
|
await bookSlot({
|
||
|
|
event_type_standard_name: eventTypeStandardName || "",
|
||
|
|
owner_short_id: shortUserId || "",
|
||
|
|
event_details: {
|
||
|
|
start_date: selectedSlot?.slot.date || "",
|
||
|
|
start_time: startTime,
|
||
|
|
end_time: endTime,
|
||
|
|
},
|
||
|
|
user_details: {
|
||
|
|
name: formData.name,
|
||
|
|
email: formData.email,
|
||
|
|
},
|
||
|
|
});
|
||
|
|
```
|
||
|
|
|
||
|
|
### 4. Updated Shared Package Exports
|
||
|
|
|
||
|
|
**File: `packages/shared/src/index.ts`**
|
||
|
|
- Added export for `./hooks/book`
|
||
|
|
- Added export for `./hooks/public` (for `invalidatePublicSlots`)
|
||
|
|
- Added exports for all type files to ensure proper type resolution
|
||
|
|
|
||
|
|
### 5. Fixed Import Dependencies
|
||
|
|
|
||
|
|
**File: `packages/shared/src/hooks/book.ts`**
|
||
|
|
- Fixed import of `queryClient` from `../lib/api` (not from `../lib/supabase`)
|
||
|
|
- Imported `invalidatePublicSlots` from `./public` to avoid duplicate exports
|
||
|
|
|
||
|
|
## Benefits
|
||
|
|
|
||
|
|
1. **Code Reuse** - Single implementation of booking logic shared across all apps
|
||
|
|
2. **Consistency** - All apps use the same booking API and error handling
|
||
|
|
3. **Maintainability** - One place to update booking logic
|
||
|
|
4. **Flexibility** - Custom success callbacks allow different behavior per context
|
||
|
|
5. **Fixed Bug** - Replaced non-existent `useCreateTabloWithOwner` with working implementation
|
||
|
|
|
||
|
|
## Verification
|
||
|
|
|
||
|
|
All packages pass verification:
|
||
|
|
```bash
|
||
|
|
turbo typecheck lint --filter=@xtablo/shared --filter=@xtablo/external --filter=@xtablo/main
|
||
|
|
```
|
||
|
|
|
||
|
|
✅ **Results:**
|
||
|
|
- `@xtablo/shared` - typecheck ✓ lint ✓
|
||
|
|
- `@xtablo/main` - typecheck ✓ lint ✓
|
||
|
|
- `@xtablo/external` - typecheck ✓ lint ✓
|
||
|
|
|
||
|
|
## API Contract
|
||
|
|
|
||
|
|
### Request Payload
|
||
|
|
```typescript
|
||
|
|
{
|
||
|
|
event_type_standard_name: string;
|
||
|
|
owner_short_id: string;
|
||
|
|
event_details: {
|
||
|
|
start_date: string; // YYYY-MM-DD
|
||
|
|
start_time: string; // HH:MM
|
||
|
|
end_time: string; // HH:MM
|
||
|
|
};
|
||
|
|
user_details: {
|
||
|
|
name: string;
|
||
|
|
email: string;
|
||
|
|
};
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Response
|
||
|
|
```typescript
|
||
|
|
{
|
||
|
|
tablo_id: string;
|
||
|
|
hasCreatedAccount: boolean;
|
||
|
|
email: string;
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## Usage Examples
|
||
|
|
|
||
|
|
### Basic Usage (with default navigation)
|
||
|
|
```typescript
|
||
|
|
const { mutateAsync: bookSlot } = useBookSlot(api, session?.access_token);
|
||
|
|
|
||
|
|
await bookSlot({
|
||
|
|
event_type_standard_name: "consultation",
|
||
|
|
owner_short_id: "abc123",
|
||
|
|
event_details: { /* ... */ },
|
||
|
|
user_details: { /* ... */ },
|
||
|
|
});
|
||
|
|
// Default: navigates to /login or /tablos/:id based on hasCreatedAccount
|
||
|
|
```
|
||
|
|
|
||
|
|
### Custom Success Handler (for widgets)
|
||
|
|
```typescript
|
||
|
|
const { mutateAsync: bookSlot } = useBookSlot(api, session?.access_token, (data) => {
|
||
|
|
handleCloseModal();
|
||
|
|
if (view === "modal") {
|
||
|
|
window.parent.postMessage("xtablo:close", "*");
|
||
|
|
}
|
||
|
|
});
|
||
|
|
```
|
||
|
|
|
||
|
|
## Related Documentation
|
||
|
|
|
||
|
|
- [API Shared Types Migration](./API_SHARED_TYPES_MIGRATION.md)
|
||
|
|
- [Shared Types Integration](./SHARED_TYPES_INTEGRATION.md)
|
||
|
|
- [Types Package](./TYPES_PACKAGE.md)
|
||
|
|
|