BookingModal: move extra beds+tags to right col, payment to full-width bottom; Calendar: fix today booking left edge fill
This commit is contained in:
@@ -533,41 +533,10 @@ export function BookingModal({ open, draft, rooms, bookings = [], onClose, onSav
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* TV Message — только для существующих броней с активным модулем */}
|
|
||||||
{tvEnabled && existing && existing.roomId && (
|
|
||||||
<div className="rounded-xl border border-violet-200 dark:border-violet-800/60 bg-violet-50 dark:bg-violet-900/20 p-3 space-y-2">
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<Tv2 size={14} className="text-violet-600 dark:text-violet-400 shrink-0" />
|
|
||||||
<span className="text-sm font-medium text-violet-700 dark:text-violet-300">
|
|
||||||
Сообщение гостю на TV
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
<textarea
|
|
||||||
rows={2}
|
{/* ── RIGHT COLUMN ── */}
|
||||||
value={tvMsg}
|
<div className="w-56 shrink-0 space-y-4">
|
||||||
onChange={e => setTvMsg(e.target.value)}
|
|
||||||
placeholder="Введите сообщение для гостя..."
|
|
||||||
className="w-full rounded-lg border border-violet-200 dark:border-violet-700 bg-white dark:bg-slate-800 px-3 py-2 text-sm text-slate-900 dark:text-slate-100 placeholder-slate-400 resize-none focus:outline-none focus:ring-2 focus:ring-violet-400"
|
|
||||||
/>
|
|
||||||
<div className="flex items-center gap-2">
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
onClick={handleSendTv}
|
|
||||||
disabled={tvSending || !tvMsg.trim()}
|
|
||||||
className="flex items-center gap-1.5 px-3 py-1.5 rounded-lg bg-violet-600 hover:bg-violet-700 disabled:opacity-50 text-white text-xs font-medium transition-colors"
|
|
||||||
>
|
|
||||||
{tvSending ? <Loader2 size={12} className="animate-spin" /> : <Send size={12} />}
|
|
||||||
Отправить на TV
|
|
||||||
</button>
|
|
||||||
{tvSent && (
|
|
||||||
<span className="flex items-center gap-1 text-xs text-emerald-600 dark:text-emerald-400">
|
|
||||||
<CheckCircle2 size={12} /> Отправлено
|
|
||||||
</span>
|
|
||||||
)}
|
|
||||||
{tvError && <span className="text-xs text-red-500">{tvError}</span>}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Доп. места */}
|
{/* Доп. места */}
|
||||||
<div className="flex items-center justify-between px-3 py-2.5 rounded-xl bg-slate-50 dark:bg-slate-700/40 border border-slate-200 dark:border-slate-600">
|
<div className="flex items-center justify-between px-3 py-2.5 rounded-xl bg-slate-50 dark:bg-slate-700/40 border border-slate-200 dark:border-slate-600">
|
||||||
@@ -575,20 +544,20 @@ export function BookingModal({ open, draft, rooms, bookings = [], onClose, onSav
|
|||||||
<BedDouble size={15} className="text-slate-400 shrink-0" />
|
<BedDouble size={15} className="text-slate-400 shrink-0" />
|
||||||
<div>
|
<div>
|
||||||
<p className="text-sm font-medium text-slate-700 dark:text-slate-300 leading-tight">Доп. места</p>
|
<p className="text-sm font-medium text-slate-700 dark:text-slate-300 leading-tight">Доп. места</p>
|
||||||
<p className="text-[10px] text-slate-400">{EXTRA_BED_PRICE.toLocaleString('ru-RU')} ₽/место{!isHourly && nights > 0 ? '/ночь' : ''}</p>
|
<p className="text-[10px] text-slate-400">{EXTRA_BED_PRICE.toLocaleString('ru-RU')} ₽{!isHourly && nights > 0 ? '/ночь' : ''}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-1.5">
|
||||||
{extraBeds > 0 && (
|
{extraBeds > 0 && (
|
||||||
<span className="text-xs font-medium text-amber-600 dark:text-amber-400 mr-1">
|
<span className="text-[10px] font-medium text-amber-600 dark:text-amber-400">
|
||||||
+{extraBedsTotal.toLocaleString('ru-RU')} ₽
|
+{extraBedsTotal.toLocaleString('ru-RU')}₽
|
||||||
</span>
|
</span>
|
||||||
)}
|
)}
|
||||||
<button type="button" onClick={() => setExtraBeds(e => Math.max(0, e - 1))}
|
<button type="button" onClick={() => setExtraBeds(e => Math.max(0, e - 1))}
|
||||||
className="w-6 h-6 rounded-md bg-slate-200 dark:bg-slate-600 flex items-center justify-center hover:bg-slate-300 dark:hover:bg-slate-500 transition-colors disabled:opacity-40"
|
className="w-6 h-6 rounded-md bg-slate-200 dark:bg-slate-600 flex items-center justify-center hover:bg-slate-300 dark:hover:bg-slate-500 transition-colors disabled:opacity-40"
|
||||||
disabled={extraBeds === 0}
|
disabled={extraBeds === 0}
|
||||||
><Minus size={11} /></button>
|
><Minus size={11} /></button>
|
||||||
<span className="w-5 text-center text-sm font-semibold text-slate-900 dark:text-slate-100">{extraBeds}</span>
|
<span className="w-4 text-center text-sm font-semibold text-slate-900 dark:text-slate-100">{extraBeds}</span>
|
||||||
<button type="button" onClick={() => setExtraBeds(e => Math.min(4, e + 1))}
|
<button type="button" onClick={() => setExtraBeds(e => Math.min(4, e + 1))}
|
||||||
className="w-6 h-6 rounded-md bg-slate-200 dark:bg-slate-600 flex items-center justify-center hover:bg-slate-300 dark:hover:bg-slate-500 transition-colors disabled:opacity-40"
|
className="w-6 h-6 rounded-md bg-slate-200 dark:bg-slate-600 flex items-center justify-center hover:bg-slate-300 dark:hover:bg-slate-500 transition-colors disabled:opacity-40"
|
||||||
disabled={extraBeds >= 4}
|
disabled={extraBeds >= 4}
|
||||||
@@ -611,7 +580,7 @@ export function BookingModal({ open, draft, rooms, bookings = [], onClose, onSav
|
|||||||
type="button"
|
type="button"
|
||||||
onClick={() => toggleTag(tag)}
|
onClick={() => toggleTag(tag)}
|
||||||
className={cn(
|
className={cn(
|
||||||
'flex items-center gap-1 px-2.5 py-1 rounded-lg text-xs font-medium border transition-colors',
|
'flex items-center gap-1 px-2 py-1 rounded-lg text-xs font-medium border transition-colors',
|
||||||
selected
|
selected
|
||||||
? isVip
|
? isVip
|
||||||
? 'bg-amber-500 border-amber-500 text-white'
|
? 'bg-amber-500 border-amber-500 text-white'
|
||||||
@@ -626,19 +595,63 @@ export function BookingModal({ open, draft, rooms, bookings = [], onClose, onSav
|
|||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{/* TV Message */}
|
||||||
|
{tvEnabled && existing && existing.roomId && (
|
||||||
|
<div className="rounded-xl border border-violet-200 dark:border-violet-800/60 bg-violet-50 dark:bg-violet-900/20 p-3 space-y-2">
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<Tv2 size={14} className="text-violet-600 dark:text-violet-400 shrink-0" />
|
||||||
|
<span className="text-sm font-medium text-violet-700 dark:text-violet-300">TV-сообщение</span>
|
||||||
|
</div>
|
||||||
|
<textarea
|
||||||
|
rows={2}
|
||||||
|
value={tvMsg}
|
||||||
|
onChange={e => setTvMsg(e.target.value)}
|
||||||
|
placeholder="Сообщение гостю..."
|
||||||
|
className="w-full rounded-lg border border-violet-200 dark:border-violet-700 bg-white dark:bg-slate-800 px-3 py-2 text-sm text-slate-900 dark:text-slate-100 placeholder-slate-400 resize-none focus:outline-none focus:ring-2 focus:ring-violet-400"
|
||||||
|
/>
|
||||||
|
<div className="flex items-center gap-2">
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={handleSendTv}
|
||||||
|
disabled={tvSending || !tvMsg.trim()}
|
||||||
|
className="flex items-center gap-1.5 px-3 py-1.5 rounded-lg bg-violet-600 hover:bg-violet-700 disabled:opacity-50 text-white text-xs font-medium transition-colors"
|
||||||
|
>
|
||||||
|
{tvSending ? <Loader2 size={12} className="animate-spin" /> : <Send size={12} />}
|
||||||
|
Отправить
|
||||||
|
</button>
|
||||||
|
{tvSent && (
|
||||||
|
<span className="flex items-center gap-1 text-xs text-emerald-600 dark:text-emerald-400">
|
||||||
|
<CheckCircle2 size={12} /> Отправлено
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
{tvError && <span className="text-xs text-red-500">{tvError}</span>}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* ── RIGHT COLUMN ── */}
|
{/* ── BOTTOM: Примечания + Оплата (полная ширина) ── */}
|
||||||
<div className="flex-1 space-y-3 min-w-0">
|
<div className="border-t border-slate-200 dark:border-slate-700 pt-4 space-y-3">
|
||||||
{/* Payment */}
|
{/* Примечания */}
|
||||||
{total > 0 && (
|
|
||||||
<div className="rounded-xl border border-slate-200 dark:border-slate-600 overflow-hidden">
|
|
||||||
<div className="px-4 py-3 bg-slate-50 dark:bg-slate-700/40 border-b border-slate-200 dark:border-slate-600">
|
|
||||||
<p className="text-sm font-semibold text-slate-700 dark:text-slate-300">Оплата</p>
|
|
||||||
</div>
|
|
||||||
<div className="p-4 space-y-3">
|
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-xs text-slate-500 dark:text-slate-400 mb-1.5">Способ оплаты</label>
|
<label className="block text-xs text-slate-500 dark:text-slate-400 mb-1">Примечания</label>
|
||||||
|
<textarea
|
||||||
|
className="input resize-none"
|
||||||
|
rows={2}
|
||||||
|
placeholder="Дополнительные пожелания..."
|
||||||
|
value={form.notes}
|
||||||
|
onChange={e => set('notes', e.target.value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Оплата — горизонтальная полоса */}
|
||||||
|
<div className="rounded-xl border border-slate-200 dark:border-slate-600 bg-slate-50 dark:bg-slate-700/40 px-4 py-3">
|
||||||
|
<div className="flex flex-wrap items-end gap-4">
|
||||||
|
{/* Способ оплаты */}
|
||||||
|
<div className="shrink-0">
|
||||||
|
<p className="text-xs text-slate-500 dark:text-slate-400 mb-1.5">Способ оплаты</p>
|
||||||
<div className="flex gap-2">
|
<div className="flex gap-2">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
@@ -650,8 +663,7 @@ export function BookingModal({ open, draft, rooms, bookings = [], onClose, onSav
|
|||||||
: 'bg-white dark:bg-slate-700 text-slate-700 dark:text-slate-300 border-slate-200 dark:border-slate-600 hover:border-emerald-400',
|
: 'bg-white dark:bg-slate-700 text-slate-700 dark:text-slate-300 border-slate-200 dark:border-slate-600 hover:border-emerald-400',
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Banknote size={14} />
|
<Banknote size={14} /> Наличные
|
||||||
Наличные
|
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
@@ -663,16 +675,14 @@ export function BookingModal({ open, draft, rooms, bookings = [], onClose, onSav
|
|||||||
: 'bg-white dark:bg-slate-700 text-slate-700 dark:text-slate-300 border-slate-200 dark:border-slate-600 hover:border-blue-400',
|
: 'bg-white dark:bg-slate-700 text-slate-700 dark:text-slate-300 border-slate-200 dark:border-slate-600 hover:border-blue-400',
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<CreditCard size={14} />
|
<CreditCard size={14} /> Терминал
|
||||||
Терминал
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/* Discount */}
|
|
||||||
<div>
|
{/* Скидка */}
|
||||||
<label className="block text-xs text-slate-500 dark:text-slate-400 mb-1.5 flex items-center gap-1">
|
<div className="shrink-0 min-w-[160px]">
|
||||||
<Tag size={11} /> Скидка
|
<p className="text-xs text-slate-500 dark:text-slate-400 mb-1.5 flex items-center gap-1"><Tag size={11} /> Скидка</p>
|
||||||
</label>
|
|
||||||
<select
|
<select
|
||||||
className="input text-sm"
|
className="input text-sm"
|
||||||
value={selectedDiscountId}
|
value={selectedDiscountId}
|
||||||
@@ -685,18 +695,12 @@ export function BookingModal({ open, draft, rooms, bookings = [], onClose, onSav
|
|||||||
</option>
|
</option>
|
||||||
))}
|
))}
|
||||||
</select>
|
</select>
|
||||||
{selectedDiscount && (
|
|
||||||
<p className="text-xs text-emerald-600 dark:text-emerald-400 mt-1">
|
|
||||||
−{discountAmount.toLocaleString('ru-RU')} ₽
|
|
||||||
{selectedDiscount.note ? ` · ${selectedDiscount.note}` : ''}
|
|
||||||
</p>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Additional services */}
|
{/* Доп. услуги */}
|
||||||
<div>
|
<div className="shrink-0 min-w-[180px]">
|
||||||
<label className="block text-xs text-slate-500 dark:text-slate-400 mb-1.5">Дополнительные услуги</label>
|
<p className="text-xs text-slate-500 dark:text-slate-400 mb-1.5">Доп. услуги</p>
|
||||||
<div className="flex gap-2 mb-2">
|
<div className="flex gap-2">
|
||||||
<select
|
<select
|
||||||
className="input flex-1 text-sm"
|
className="input flex-1 text-sm"
|
||||||
value={selectedServiceId}
|
value={selectedServiceId}
|
||||||
@@ -706,19 +710,19 @@ export function BookingModal({ open, draft, rooms, bookings = [], onClose, onSav
|
|||||||
<option key={s.id} value={s.id}>{s.label} — {s.price.toLocaleString('ru-RU')} ₽</option>
|
<option key={s.id} value={s.id}>{s.label} — {s.price.toLocaleString('ru-RU')} ₽</option>
|
||||||
))}
|
))}
|
||||||
</select>
|
</select>
|
||||||
<button type="button" onClick={addService} className="btn-secondary px-2">
|
<button type="button" onClick={addService} className="btn-secondary px-2 shrink-0">
|
||||||
<Plus size={14} />
|
<Plus size={14} />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
{addedServices.length > 0 && (
|
{addedServices.length > 0 && (
|
||||||
<div className="space-y-1">
|
<div className="mt-1.5 space-y-1">
|
||||||
{addedServices.map(s => (
|
{addedServices.map(s => (
|
||||||
<div key={s.id} className="flex items-center justify-between text-xs px-2 py-1 rounded bg-slate-100 dark:bg-slate-700">
|
<div key={s.id} className="flex items-center justify-between text-xs px-2 py-0.5 rounded bg-white dark:bg-slate-700">
|
||||||
<span className="text-slate-700 dark:text-slate-300">{s.label} × {s.qty}</span>
|
<span className="text-slate-600 dark:text-slate-300">{s.label} × {s.qty}</span>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-1.5">
|
||||||
<span className="font-medium text-slate-900 dark:text-slate-100">{(s.price * s.qty).toLocaleString('ru-RU')} ₽</span>
|
<span className="font-medium">{(s.price * s.qty).toLocaleString('ru-RU')} ₽</span>
|
||||||
<button type="button" onClick={() => removeService(s.id)} className="text-slate-400 hover:text-red-500">
|
<button type="button" onClick={() => removeService(s.id)} className="text-slate-400 hover:text-red-500">
|
||||||
<Trash2 size={11} />
|
<Trash2 size={10} />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -727,105 +731,49 @@ export function BookingModal({ open, draft, rooms, bookings = [], onClose, onSav
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
{/* Оплачено */}
|
||||||
<label className="block text-xs text-slate-500 dark:text-slate-400 mb-1.5">
|
<div className="shrink-0">
|
||||||
Оплачено (₽)
|
<p className="text-xs text-slate-500 dark:text-slate-400 mb-1.5">Оплачено (₽)</p>
|
||||||
</label>
|
|
||||||
<input
|
<input
|
||||||
type="number"
|
type="number" min={0} max={total}
|
||||||
min={0}
|
className="input w-32"
|
||||||
max={total}
|
|
||||||
className="input w-40"
|
|
||||||
value={paidAmount}
|
value={paidAmount}
|
||||||
onChange={e => setPaidAmount(Math.min(total, Math.max(0, parseInt(e.target.value) || 0)))}
|
onChange={e => setPaidAmount(Math.min(total, Math.max(0, parseInt(e.target.value) || 0)))}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
</div>
|
{/* Итого */}
|
||||||
</div>
|
{room && total > 0 && (
|
||||||
|
<div className="ml-auto text-right shrink-0">
|
||||||
{/* ── BOTTOM ROW: Notes + Summary ── */}
|
{room && (
|
||||||
<div className="flex gap-6">
|
<p className="text-xs text-slate-400 mb-0.5">
|
||||||
<div className="flex-1">
|
{isHourly && room.allowHourly
|
||||||
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1.5">
|
? `${hourlyHours} ч × ${(room.hourlyRate ?? 0).toLocaleString('ru-RU')} ₽`
|
||||||
Примечания
|
: `${nights} ${nights === 1 ? 'ночь' : nights < 5 ? 'ночи' : 'ночей'} × ${room.baseRate.toLocaleString('ru-RU')} ₽`
|
||||||
</label>
|
}
|
||||||
<textarea
|
{discountAmount > 0 && ` − ${discountAmount.toLocaleString('ru-RU')} ₽`}
|
||||||
className="input resize-none"
|
</p>
|
||||||
rows={2}
|
|
||||||
placeholder="Дополнительные пожелания..."
|
|
||||||
value={form.notes}
|
|
||||||
onChange={e => set('notes', e.target.value)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
{(total > 0 || discountAmount > 0) && room && (
|
|
||||||
<div className="flex-1 rounded-xl bg-slate-50 dark:bg-slate-700/50 px-4 py-3 space-y-1.5 self-end">
|
|
||||||
{isHourly && room.allowHourly ? (
|
|
||||||
<div className="flex items-center justify-between">
|
|
||||||
<span className="text-sm text-slate-600 dark:text-slate-300">
|
|
||||||
{hourlyHours} {hourlyHours === 1 ? 'час' : hourlyHours < 5 ? 'часа' : 'часов'} × {(room.hourlyRate ?? 0).toLocaleString('ru-RU')} ₽
|
|
||||||
</span>
|
|
||||||
<span className={cn('font-semibold', discountAmount > 0 ? 'line-through text-slate-400' : 'text-slate-900 dark:text-slate-100')}>
|
|
||||||
{roomBaseTotal.toLocaleString('ru-RU')} ₽
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<div className="flex items-center justify-between">
|
|
||||||
<span className="text-sm text-slate-600 dark:text-slate-300">
|
|
||||||
{nights} {nights === 1 ? 'ночь' : nights < 5 ? 'ночи' : 'ночей'} × {room.baseRate.toLocaleString('ru-RU')} ₽
|
|
||||||
</span>
|
|
||||||
<span className={cn('font-semibold', discountAmount > 0 ? 'line-through text-slate-400' : 'text-slate-900 dark:text-slate-100')}>
|
|
||||||
{roomBaseTotal.toLocaleString('ru-RU')} ₽
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{discountAmount > 0 && selectedDiscount && (
|
|
||||||
<div className="flex items-center justify-between text-sm">
|
|
||||||
<span className="text-emerald-600 dark:text-emerald-400">
|
|
||||||
{selectedDiscount.value === 100 ? 'Бесплатное проживание' : selectedDiscount.name}
|
|
||||||
</span>
|
|
||||||
<span className="font-semibold text-emerald-600 dark:text-emerald-400">
|
|
||||||
−{discountAmount.toLocaleString('ru-RU')} ₽
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{servicesTotal > 0 && (
|
|
||||||
<div className="flex items-center justify-between text-sm">
|
|
||||||
<span className="text-slate-600 dark:text-slate-300">Доп. услуги</span>
|
|
||||||
<span className="font-semibold text-slate-900 dark:text-slate-100">{servicesTotal.toLocaleString('ru-RU')} ₽</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{(servicesTotal > 0 || discountAmount > 0) && (
|
|
||||||
<div className="flex items-center justify-between border-t border-slate-200 dark:border-slate-600 pt-1.5">
|
|
||||||
<span className="text-sm font-medium text-slate-700 dark:text-slate-200">Итого</span>
|
|
||||||
<span className="text-xl font-bold text-slate-900 dark:text-slate-100">{total.toLocaleString('ru-RU')} ₽</span>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{servicesTotal === 0 && discountAmount === 0 && (
|
|
||||||
<div className="text-xl font-bold text-slate-900 dark:text-slate-100 text-right">{total.toLocaleString('ru-RU')} ₽</div>
|
|
||||||
)}
|
)}
|
||||||
|
<p className="text-2xl font-bold text-slate-900 dark:text-slate-100">
|
||||||
|
{total.toLocaleString('ru-RU')} ₽
|
||||||
|
</p>
|
||||||
{paidAmount > 0 && (
|
{paidAmount > 0 && (
|
||||||
<div className="flex items-center justify-between text-sm">
|
<p className="text-xs text-emerald-600 dark:text-emerald-400">
|
||||||
<span className="text-emerald-600 dark:text-emerald-400">Оплачено</span>
|
Оплачено {paidAmount.toLocaleString('ru-RU')} ₽
|
||||||
<span className="font-semibold text-emerald-600 dark:text-emerald-400">
|
</p>
|
||||||
{paidAmount.toLocaleString('ru-RU')} ₽
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
{debt > 0 && (
|
{debt > 0 && (
|
||||||
<div className="flex items-center gap-1.5 text-sm text-red-600 dark:text-red-400">
|
<p className="text-xs text-red-500 flex items-center gap-1 justify-end">
|
||||||
<AlertCircle size={13} />
|
<AlertCircle size={11} />
|
||||||
<span className="flex-1">{isFutureBooking ? 'Задолженность' : 'Долг при заселении'}</span>
|
{isFutureBooking ? 'Задолженность' : 'Долг'} {debt.toLocaleString('ru-RU')} ₽
|
||||||
<span className="font-semibold">{debt.toLocaleString('ru-RU')} ₽</span>
|
</p>
|
||||||
</div>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
|
|||||||
@@ -121,7 +121,7 @@ export function BookingCalendar({ rooms, bookings, slug, onBookingCreate, onBook
|
|||||||
if (rawColStart >= visibleDays || rawColEnd <= 0) return null
|
if (rawColStart >= visibleDays || rawColEnd <= 0) return null
|
||||||
|
|
||||||
const INSET = Math.round(CELL_WIDTH / 3)
|
const INSET = Math.round(CELL_WIDTH / 3)
|
||||||
const isClippedLeft = rawColStart < 0
|
const isClippedLeft = rawColStart <= 0
|
||||||
const isClippedRight = rawColEnd > visibleDays
|
const isClippedRight = rawColEnd > visibleDays
|
||||||
|
|
||||||
const colStart = Math.max(0, rawColStart)
|
const colStart = Math.max(0, rawColStart)
|
||||||
|
|||||||
Reference in New Issue
Block a user