NewBook-connected daily housekeeping planner. Replaces the hotelhubmodule-housekeeping-dailylist WordPress plugin. LXC 120 · 10.10.10.120:3080 · slug: room-planner. - 3-day booking window (yesterday/today/tomorrow) fetched live from NewBook - Task completion ticks back to NewBook; room status patches NewBook directly - 23px border sliver CSS system for adjacent-day booking status - 3-state filter cycling (off→inclusive→exclusive) for categories and flow types - Stat filters for outstanding tasks and clean/dirty status - Rolling 48h activity log with checkout/checkin/status/tasks events - newbook_pings event bus for future NewBook poller integration - Room modal with permission-gated guest/rate/notes, task checkboxes, status buttons - Placeholder sections for future linen-count and routine-tasks modules - Settings page: task type colours, twin/extra-bed detection, category exclusions - Mobile-first layout (sidebar desktop, compact top bar mobile) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
77 lines
2.4 KiB
TypeScript
77 lines
2.4 KiB
TypeScript
import type { RoomsResponse, ActivityEntry, AppConfig, TaskData } from './types'
|
|
|
|
const BASE = '/room-planner/api'
|
|
|
|
async function request<T>(path: string, opts: RequestInit = {}): Promise<T> {
|
|
const res = await fetch(`${BASE}${path}`, {
|
|
credentials: 'include',
|
|
headers: { 'Content-Type': 'application/json', ...opts.headers },
|
|
...opts,
|
|
})
|
|
if (!res.ok) {
|
|
const err = await res.json().catch(() => ({ error: res.statusText }))
|
|
throw new Error(err.error || `Request failed: ${res.status}`)
|
|
}
|
|
return res.json()
|
|
}
|
|
|
|
export function fetchRooms(date: string): Promise<RoomsResponse> {
|
|
return request(`/rooms?date=${date}`)
|
|
}
|
|
|
|
export function completeTask(taskId: string, roomId: string, serviceDate: string, bookingRef?: string) {
|
|
return request<{ ok: boolean; site_status: string | null }>('/tasks/complete', {
|
|
method: 'POST',
|
|
body: JSON.stringify({ task_id: taskId, room_id: roomId, service_date: serviceDate, booking_ref: bookingRef }),
|
|
})
|
|
}
|
|
|
|
export function uncompleteTask(taskId: string) {
|
|
return request<{ ok: boolean }>('/tasks/uncomplete', {
|
|
method: 'POST',
|
|
body: JSON.stringify({ task_id: taskId }),
|
|
})
|
|
}
|
|
|
|
export function updateStatus(roomId: string, status: string, serviceDate: string, bookingRef?: string) {
|
|
return request<{ ok: boolean }>('/status', {
|
|
method: 'POST',
|
|
body: JSON.stringify({ room_id: roomId, status, service_date: serviceDate, booking_ref: bookingRef }),
|
|
})
|
|
}
|
|
|
|
export function fetchConfig(): Promise<AppConfig> {
|
|
return request('/config')
|
|
}
|
|
|
|
export function updateConfig(key: string, value: unknown): Promise<{ ok: boolean }> {
|
|
return request(`/config/${key}`, {
|
|
method: 'PUT',
|
|
body: JSON.stringify({ value }),
|
|
})
|
|
}
|
|
|
|
export function fetchTaskTypes(): Promise<Array<{ id: string; name: string }>> {
|
|
return request('/config/task-types')
|
|
}
|
|
|
|
export function fetchActivity(date: string): Promise<ActivityEntry[]> {
|
|
return request(`/activity?date=${date}`)
|
|
}
|
|
|
|
export function logActivity(entry: {
|
|
room_id: string
|
|
event_type: ActivityEntry['event_type']
|
|
event_data?: Record<string, unknown>
|
|
service_date?: string
|
|
booking_ref?: string
|
|
}): Promise<{ ok: boolean }> {
|
|
return request('/activity', { method: 'POST', body: JSON.stringify(entry) })
|
|
}
|
|
|
|
export function fetchEvents(since: string): Promise<{
|
|
pings: Array<{ id: number; booking_ids: string[]; event_types: string[]; detected_at: string }>
|
|
server_time: string
|
|
}> {
|
|
return request(`/events?since=${encodeURIComponent(since)}`)
|
|
}
|