Commit Graph

16 Commits

Author SHA1 Message Date
b9116c427a 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>
2026-03-23 23:02:30 +03:00
fd50e02be0 feat: right-click context menu for room status + bed type capacity
- Add RoomContextMenu component (portal, Escape/click-outside to close)
  - Change room status: available / maintenance / blocked
  - Change housekeeping status: clean / dirty / cleaning / inspect
  - Open room edit (optional)
- Calendar: right-click on room label → context menu; onRoomUpdate prop
  wired to CalendarPage (calls api.rooms.update); show 🔧/🔒 badge on label
- Rooms page: right-click on any room card → same context menu;
  show orange "ремонт" badge on maintenance rooms
- BedTypesContext: add capacity field (max guests per bed type)
- BedTypes reference UI: add capacity input to add/edit form; show "N чел."

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 14:30:14 +03:00
8c6cdfb1c7 feat: configurable bed types via BedTypesContext
- Add BedTypesContext with default types + add/remove/update operations
- Replace hardcoded BED_ITEM_TYPES array in RoomModal with useBedTypes()
- Add "Справочник спальных мест" section to RoomCategoriesPage
  (expandable, same UX as amenities: add icon+label, rename, delete)
- BedItem.type changed from union to string for dynamic support

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 14:20:09 +03:00
fd804926e4 BookingModal: move guest fields to right column; Theme: auto mode follows system prefers-color-scheme 2026-03-21 00:04:24 +03:00
bc12f8aabc Fix WS offline on first login: sync token between api.ts and AuthContext
Two root causes fixed:
1. api.ts saveToken() updated only localStorage, not React state — WS kept
   reconnecting with the expired token. Now dispatches hotelsync:token-updated
   event; AuthContext listens and updates session state, triggering WS reconnect
   with the fresh token.
2. AuthContext mount effect could race with login(): if refresh failed while
   login() was concurrently setting a new token, catch() called setSession(null)
   and wiped the fresh session. Fixed with functional setSession updater that
   checks current state before clearing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-18 17:37:36 +03:00
1fd12a6dbb Fix null token in session: refresh on mount if token missing
If localStorage session has user but no token (corrupted/migrated session),
attempt a token refresh via httpOnly cookie. If refresh fails, clear session
and force re-login. Prevents WebSocket 'missing token' skip.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 19:19:19 +03:00
42dc4518e2 Switch session storage from sessionStorage to localStorage
sessionStorage is per-tab — new tabs had no session, so WebSocket
didn't connect and real-time lock/booking sync didn't work.
localStorage shares session across tabs in the same browser.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 18:29:14 +03:00
dd9a2a3da9 Add auto theme mode (light/dark/auto by time of day)
- ThemeContext: add 'auto' mode that switches light 7:00-22:00, dark otherwise, re-checks every minute
- Topbar: cycle through 3 modes on click, show Monitor icon for auto mode
- Settings → Внешний вид: 3-button grid with split preview for auto

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 18:22:37 +03:00
728b20417a Connect frontend to real API — rooms, bookings, housekeeping, calendar
- src/lib/api.ts: central API client with JWT auto-refresh, snake_case→camelCase transform
- src/contexts/AuthContext.tsx: real login via POST /api/auth/login
- src/pages/RoomsPage.tsx: load rooms from API, create/update via API
- src/pages/BookingsPage.tsx: load bookings + rooms from API
- src/pages/HousekeepingPage.tsx: load today's tasks from API, update status via API
- src/pages/CalendarPage.tsx: load rooms + bookings from API
- src/types/index.ts: fix HousekeepingTask.priority to match DB (medium/urgent)
- backend/src/routes/rooms.ts: update to use new column names (max_guests, base_rate) + all new fields
- backend/src/routes/bookings.ts: update price_per_night→base_rate, add paid_amount to PATCH
- backend/migrations/003_fix_constraints.sql: fix rooms.status values, add paid_amount, inquiry status, other source
- public/robots.txt + index.html: noindex for SPA inner pages

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 13:49:30 +03:00
c431ea1486 Add maintenance severity levels, notifications context, and widget payment step
- HousekeepingPage: 3-level severity for maintenance reports (Не срочно / Средняя / Экстренно!); Экстренно automatically blocks the room and triggers an urgent notification; severity displayed as colored badge on task card
- NotificationsContext: extract shared notifications state from Topbar into context so any page can push notifications; add 'maintenance' type with wrench icon
- Topbar: migrate to NotificationsContext; add maintenance notification type with red Wrench icon
- BookingWidgetPage: add payment step after guest form when payment provider is connected (card number/expiry/CVV/name form); Без оплаты mode skips payment and shows "pay on site" message; hourly services (unit='ч') show date + time-from/time-to picker in form step

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 16:04:19 +03:00
87455c2710 Add centralized amenities directory and hourly booking example
- AmenitiesContext: shared amenities list with add/edit/delete, available app-wide
- RoomsPage: collapsible Справочник удобств section (add/rename/delete)
- RoomModal + RoomCategoriesPage: use amenities from context, no hardcoded lists
- RoomCategoriesPage: removed custom amenity input (use справочник instead)
- mockData: room 103 now has allowHourly=true, added sample hourly booking (today, 10-13ч)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 15:40:01 +03:00
401825c01e Activate documents module, reorganize sidebar, add cleaning plans to housekeeping
Sidebar restructure:
- Основное: Шахматка, Бронирования, Номера, Категории номеров, Доступность
- Модули: Уборка + all active addon modules (including Documents)
- Управление: План этажей, Каналы, Модули, Настройки
- Разработчикам: API

ModulesContext: documents module now active by default (version bump to 3)

HousekeepingPage: added «Планы уборки» tab with:
- Уборка при выезде: auto task creation, priority (high/normal), inspection toggle
- Ежедневная уборка: interval (every 1/2/3/7 days), start from day N of stay
- Уборка по запросу: guest-initiated via QR, priority selection
- Генеральная уборка: deep clean every N days toggle
- Проверка после уборки: inspection task after any cleaning
- Автоназначение горничной: assign based on shift schedule

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-11 22:38:00 +03:00
0e0c11785f Wide BookingModal (2-col), RoomModal, RU channels, migration module, all modules active
- BookingModal: 2-column layout (size=2xl/max-w-3xl), no scroll needed; hourly mode toggle for rooms with allowHourly=true
- RoomModal: full add/edit form with hourly rate toggle and amenities checkboxes; RoomsPage wired up
- Channel manager: Яндекс Путешествия, Островок, Суточно.ру, OneTwoTrip added; split into RU/International sections
- Migration module: 3-step wizard (source select → file upload → progress/results)
- All modules set to active by default (version bump to reset localStorage)
- BookingCalendar booking blocks: guest count badge (Xг), unpaid red dot indicator

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-11 19:16:55 +03:00
c233590c4b Major UX improvements across multiple pages
Шахматка:
- Date/period picker dropdown on navigation button (choose start date + days window)
- Cancelled bookings fade out with animation after 1 second

Бронирования:
- Clickable column headers with sort asc/desc (Гость, Заезд, Выезд, Статус, Источник, Сумма)

Страница входа:
- Removed role-based account selector — just email + password
- System auto-detects role/hotel from credentials

Настройки:
- New "Бронирование" section with room assignment strategy (spread/together/sequential/manual)
- Notifications: SMTP email config + SMS provider config (SMSC, SMS.ru, МТС, etc.)

Модули:
- Added Housekeeping and Channel Manager as proper modules
- Channel Manager lists: Booking.com, Airbnb, Яндекс Путешествия, Островок, Суточно.ру, OneTwoTrip
- Housekeeping visible to all roles (including housekeeper) via module status
- Sidebar now uses module status to show/hide Уборка and Каналы

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-11 15:20:05 +03:00
b277e3e38d Add Availability Calendar, Modules system, and route refactoring
- Add AvailabilityPage with price grid (categories × dates), drag-select,
  channel prices, EditPanel, PeriodModal, and rate periods tab
- Add ModulesContext with localStorage persistence and dynamic sidebar items
- Add ModulesPage with WiFi Auth, Payments, TV Welcome, Smart Locks,
  OLAP Reports, Website Builder, Booking Widget modules
- Add ReportsPage (OLAP analytics with KPI cards, charts, tables)
- Add WebsitePage and BookingWidgetPage placeholders
- Remove hotel slug from URL routing; hotel context from JWT
- Add Доступность nav item in Sidebar under Управление
- Fix LoginPage redirects and HotelSync branding

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-11 14:43:18 +03:00
420d55d57e Initial commit: HotelSync PMS v0.1.0
- React 18 + TypeScript + Vite + Tailwind CSS
- Шахматка бронирований (drag-to-book)
- Страницы: Calendar, Bookings, Rooms, Housekeeping, Channels, API Docs, Settings
- Роли: super_admin, hotel_manager, housekeeper
- Светлая/тёмная тема
- Docker + Nginx конфигурация
- Лендинг hotelsync.ru
2026-03-10 20:38:32 +03:00