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>
This commit is contained in:
2026-03-11 15:20:05 +03:00
parent 4e615359eb
commit c233590c4b
29 changed files with 2171 additions and 149 deletions

38
backend/src/server.ts Normal file
View File

@@ -0,0 +1,38 @@
import { db } from './db'
import { redis } from './redis'
import { runMigrations } from './migrate'
import { seedIfEmpty } from './seed'
import { buildApp } from './app'
import { config } from './config'
async function waitForDb(retries = 10, delayMs = 3000) {
for (let i = 1; i <= retries; i++) {
try {
await db.query('SELECT 1')
console.log('[db] Connected')
return
} catch {
console.log(`[db] Not ready, retry ${i}/${retries}...`)
await new Promise(r => setTimeout(r, delayMs))
}
}
throw new Error('Database not available after retries')
}
async function main() {
await waitForDb()
await runMigrations()
await seedIfEmpty()
await redis.connect()
console.log('[redis] Connected')
const app = await buildApp()
await app.listen({ port: config.port, host: '0.0.0.0' })
console.log(`[server] Listening on :${config.port}`)
}
main().catch(err => {
console.error('[server] Fatal error:', err)
process.exit(1)
})