feat: notifications API, auto-jobs, calendar housekeeping fixes
Backend: - notifications table (024 migration) — stores per-hotel notifications - GET/PATCH/POST/DELETE /api/hotels/:slug/notifications endpoints - createNotification() helper used by jobs + future hooks - jobs.ts — background tasks every 10min: auto-cancel no-shows and auto-checkout overdue stays based on hotel_settings, broadcasts WS events and creates notifications for each automated action Frontend: - CalendarPage: handle housekeeping_done WS → update room status in calendar in real-time (bug fix) - CalendarPage: when manually setting room to dirty via context menu, auto-create housekeeping task and broadcast via WS (bug fix) - NotificationsContext: replaced mock data with real API integration, polls every 60s, syncs markRead/delete to backend - SettingsPage booking section: auto-cancel no-show toggle + hours selector; auto-checkout toggle + hours selector - api.ts: notifications API methods - useHotelSocket: notification:new WS message type Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -65,6 +65,10 @@ export function CalendarPage() {
|
||||
setBookings(prev => prev.map(b => b.id === msg.booking.id ? msg.booking : b))
|
||||
} else if (msg.type === 'booking:deleted') {
|
||||
setBookings(prev => prev.filter(b => b.id !== msg.bookingId))
|
||||
} else if (msg.type === 'housekeeping_done') {
|
||||
setRooms(prev => prev.map(r =>
|
||||
r.id === msg.roomId ? { ...r, housekeepingStatus: msg.roomStatus as Room['housekeepingStatus'] } : r
|
||||
))
|
||||
}
|
||||
}, [])
|
||||
|
||||
@@ -153,10 +157,21 @@ export function CalendarPage() {
|
||||
try {
|
||||
const updated = await api.rooms.update(slug, roomId, patch)
|
||||
setRooms(prev => prev.map(r => r.id === updated.id ? updated : r))
|
||||
// When manually marking room as dirty → auto-create a housekeeping task
|
||||
if (patch.housekeepingStatus === 'dirty') {
|
||||
const today = new Date().toISOString().slice(0, 10)
|
||||
const task = await api.housekeeping.create(slug, {
|
||||
room_id: roomId,
|
||||
type: 'regular',
|
||||
priority: 'medium',
|
||||
due_date: today,
|
||||
})
|
||||
send({ type: 'housekeeping_task_created', task: task as unknown as Record<string, unknown> })
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Failed to update room:', err)
|
||||
}
|
||||
}, [slug])
|
||||
}, [slug, send])
|
||||
|
||||
const handleRentalBookingCreate = useCallback(async (b: RentalBooking) => {
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user