feat: early check-in / late checkout fees with room-level configuration
- DB migration 016: add early_checkin_fee, late_checkout_fee to rooms table - Backend rooms: support new fee columns in POST/PATCH - Backend hotel-settings GET: also returns check_in_time, check_out_time - Room type + RoomPayload: add earlyCheckinFee, lateCheckoutFee fields - RoomModal: add fee amount inputs in pricing section - SettingsPage: add toggles for early_checkin_enabled / late_checkout_enabled - BookingDetailPanel: on check-in shows fee warning + adds payment record if current time is before checkInTime and fee is set on the room; same logic for check-out after checkOutTime Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -72,6 +72,8 @@ export function RoomModal({ open, room, categories = [], onClose, onSave, onDele
|
||||
hourlyRate: room?.hourlyRate ?? 1000,
|
||||
categoryId: room?.categoryId ?? '',
|
||||
description: room?.description ?? '',
|
||||
earlyCheckinFee: room?.earlyCheckinFee ?? '',
|
||||
lateCheckoutFee: room?.lateCheckoutFee ?? '',
|
||||
})
|
||||
|
||||
const { amenities: allAmenities } = useAmenities()
|
||||
@@ -148,6 +150,8 @@ export function RoomModal({ open, room, categories = [], onClose, onSave, onDele
|
||||
beds: beds.length > 0 ? beds : undefined,
|
||||
extraPlace: extraPlace.enabled ? extraPlace : undefined,
|
||||
childPolicy: childPolicy.enabled ? childPolicy : undefined,
|
||||
earlyCheckinFee: form.earlyCheckinFee !== '' ? Number(form.earlyCheckinFee) : undefined,
|
||||
lateCheckoutFee: form.lateCheckoutFee !== '' ? Number(form.lateCheckoutFee) : undefined,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -303,6 +307,34 @@ export function RoomModal({ open, room, categories = [], onClose, onSave, onDele
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Early check-in / late checkout fees */}
|
||||
<div className="rounded-xl border border-slate-200 dark:border-slate-700 overflow-hidden">
|
||||
<div className="px-4 py-3 bg-slate-50 dark:bg-slate-700/40 border-b border-slate-200 dark:border-slate-700">
|
||||
<p className="text-sm font-medium text-slate-700 dark:text-slate-300">Тарифы за ранний/поздний заезд</p>
|
||||
<p className="text-xs text-slate-500 dark:text-slate-400 mt-0.5">Применяются если включено в настройках отеля</p>
|
||||
</div>
|
||||
<div className="p-4 grid grid-cols-2 gap-3">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1.5">Ранний заезд ₽</label>
|
||||
<input
|
||||
type="number" min={0} className="input"
|
||||
placeholder="0 = бесплатно"
|
||||
value={form.earlyCheckinFee}
|
||||
onChange={e => set('earlyCheckinFee', e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1.5">Поздний выезд ₽</label>
|
||||
<input
|
||||
type="number" min={0} className="input"
|
||||
placeholder="0 = бесплатно"
|
||||
value={form.lateCheckoutFee}
|
||||
onChange={e => set('lateCheckoutFee', e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Amenities */}
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-2">Удобства</label>
|
||||
|
||||
Reference in New Issue
Block a user