feat: wire up loyalty + chat — register routes, API types, connect LoyaltyPage, add ChatWidget to layout
This commit is contained in:
@@ -287,6 +287,34 @@ export const api = {
|
||||
req<void>('DELETE', `/api/hotels/${slug}/schedule/${userId}/${date}`),
|
||||
},
|
||||
|
||||
// ── Loyalty ───────────────────────────────────────────────────────────────
|
||||
loyalty: {
|
||||
getSettings: (slug: string) =>
|
||||
req<LoyaltySettings>('GET', `/api/hotels/${slug}/loyalty/settings`),
|
||||
saveSettings: (slug: string, data: Partial<LoyaltySettings>) =>
|
||||
req<LoyaltySettings>('PATCH', `/api/hotels/${slug}/loyalty/settings`, data),
|
||||
listGuests: (slug: string, q?: string) =>
|
||||
req<LoyaltyGuestApi[]>('GET', `/api/hotels/${slug}/loyalty/guests${q ? `?q=${encodeURIComponent(q)}` : ''}`),
|
||||
addPoints: (slug: string, guestId: string, data: { amount: number; reason: string; notes?: string }) =>
|
||||
req<LoyaltyGuestApi>('POST', `/api/hotels/${slug}/loyalty/guests/${guestId}/points`, data),
|
||||
listTransactions: (slug: string, limit = 50) =>
|
||||
req<LoyaltyTransaction[]>('GET', `/api/hotels/${slug}/loyalty/transactions?limit=${limit}`),
|
||||
},
|
||||
|
||||
// ── Chat ──────────────────────────────────────────────────────────────────
|
||||
chat: {
|
||||
listRooms: (slug: string) =>
|
||||
req<ChatRoom[]>('GET', `/api/hotels/${slug}/chat/rooms`),
|
||||
getMessages: (slug: string, roomId: string, limit = 50) =>
|
||||
req<ChatMessage[]>('GET', `/api/hotels/${slug}/chat/rooms/${roomId}/messages?limit=${limit}`),
|
||||
sendMessage: (slug: string, roomId: string, text: string) =>
|
||||
req<ChatMessage>('POST', `/api/hotels/${slug}/chat/rooms/${roomId}/messages`, { text }),
|
||||
markRead: (slug: string, roomId: string) =>
|
||||
req<{ ok: boolean }>('PATCH', `/api/hotels/${slug}/chat/rooms/${roomId}/read`),
|
||||
openDirect: (slug: string, otherUserId: string) =>
|
||||
req<{ room_id: string }>('POST', `/api/hotels/${slug}/chat/direct/${otherUserId}`),
|
||||
},
|
||||
|
||||
// ── Hotels ────────────────────────────────────────────────────────────────
|
||||
hotels: {
|
||||
get: (slug: string) =>
|
||||
@@ -867,6 +895,56 @@ export interface RatePeriodPayload {
|
||||
days_of_week?: number[] | null
|
||||
}
|
||||
|
||||
export interface LoyaltySettings {
|
||||
isActive: boolean
|
||||
pointsPerRuble: number
|
||||
pointValue: number
|
||||
expiryMonths: number
|
||||
}
|
||||
|
||||
export interface LoyaltyGuestApi {
|
||||
id: string
|
||||
name: string
|
||||
email: string | null
|
||||
phone: string | null
|
||||
loyaltyPoints: number
|
||||
loyaltyTier: string
|
||||
totalSpent: number
|
||||
}
|
||||
|
||||
export interface LoyaltyTransaction {
|
||||
id: string
|
||||
guestId: string
|
||||
guestName: string
|
||||
amount: number
|
||||
reason: string
|
||||
notes: string | null
|
||||
staffName: string | null
|
||||
createdAt: string
|
||||
}
|
||||
|
||||
export interface ChatRoom {
|
||||
id: string
|
||||
type: 'general' | 'direct'
|
||||
name: string | null
|
||||
unreadCount: number
|
||||
lastMessage: string | null
|
||||
lastMessageAt: string | null
|
||||
lastSender: string | null
|
||||
otherUserName: string | null
|
||||
otherUserId: string | null
|
||||
}
|
||||
|
||||
export interface ChatMessage {
|
||||
id: string
|
||||
roomId: string
|
||||
senderId: string
|
||||
senderName: string
|
||||
senderRole: string
|
||||
text: string
|
||||
createdAt: string
|
||||
}
|
||||
|
||||
function toHotelPayload(h: HotelPayload): Record<string, unknown> {
|
||||
const out: Record<string, unknown> = {}
|
||||
if (h.name !== undefined) out.name = h.name
|
||||
|
||||
Reference in New Issue
Block a user