Add date editing with conflict detection and rental booking editing
- BookingDetailPanel: edit dates/room with inline conflict detection; options to force-save or swap conflicting booking's room - BookingsPage + CalendarPage: pass rooms/allBookings/onBulkUpdate to panel - RentalBookingModal: accept editBooking prop to pre-populate fields for editing - RentalPage: add edit (pencil) button per booking row, unify create/update handler Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -363,11 +363,21 @@ export function BookingsPage() {
|
||||
<BookingDetailPanel
|
||||
booking={selected}
|
||||
room={room(selected.roomId)}
|
||||
rooms={MOCK_ROOMS}
|
||||
allBookings={bookings}
|
||||
onClose={() => setSelected(null)}
|
||||
onUpdate={(id, data) => {
|
||||
setBookings(prev => prev.map(b => b.id === id ? { ...b, ...data } : b))
|
||||
setSelected(null)
|
||||
}}
|
||||
onBulkUpdate={(updates) => {
|
||||
setBookings(prev => {
|
||||
let next = [...prev]
|
||||
updates.forEach(u => { next = next.map(b => b.id === u.id ? { ...b, ...u.data } : b) })
|
||||
return next
|
||||
})
|
||||
setSelected(null)
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
|
||||
@@ -33,6 +33,14 @@ export function CalendarPage() {
|
||||
}
|
||||
}
|
||||
|
||||
const handleBulkUpdate = (updates: Array<{ id: string; data: Partial<Booking> }>) => {
|
||||
setBookings(prev => {
|
||||
let next = [...prev]
|
||||
updates.forEach(u => { next = next.map(b => b.id === u.id ? { ...b, ...u.data } : b) })
|
||||
return next
|
||||
})
|
||||
}
|
||||
|
||||
const handleRentalCreate = (b: RentalBooking) => {
|
||||
setRentalBookings(prev => [...prev, b])
|
||||
}
|
||||
@@ -45,6 +53,7 @@ export function CalendarPage() {
|
||||
bookings={bookings}
|
||||
onBookingCreate={handleCreate}
|
||||
onBookingUpdate={handleUpdate}
|
||||
onBookingBulkUpdate={handleBulkUpdate}
|
||||
fadingBookingIds={fadingBookings}
|
||||
rentalObjects={isRentalActive ? RENTAL_OBJECTS : undefined}
|
||||
rentalBookings={isRentalActive ? rentalBookings : undefined}
|
||||
|
||||
@@ -234,7 +234,7 @@ export function RentalPage() {
|
||||
const [editObj, setEditObj] = useState<RentalObject | null>(null)
|
||||
const [createModal, setCreateModal] = useState(false)
|
||||
const [selectedObj, setSelectedObj] = useState<RentalObject | null>(null)
|
||||
const [rentalModal, setRentalModal] = useState<{ obj: RentalObject; date: string } | null>(null)
|
||||
const [rentalModal, setRentalModal] = useState<{ obj: RentalObject; date: string; editBooking?: RentalBooking } | null>(null)
|
||||
|
||||
const today = format(new Date(), 'yyyy-MM-dd')
|
||||
|
||||
@@ -252,8 +252,11 @@ export function RentalPage() {
|
||||
if (selectedObj?.id === id) setSelectedObj(null)
|
||||
}
|
||||
|
||||
const handleBookingCreate = (b: RentalBooking) => {
|
||||
setBookings(prev => [...prev, b])
|
||||
const handleBookingSave = (b: RentalBooking) => {
|
||||
setBookings(prev => {
|
||||
const exists = prev.find(x => x.id === b.id)
|
||||
return exists ? prev.map(x => x.id === b.id ? b : x) : [...prev, b]
|
||||
})
|
||||
setRentalModal(null)
|
||||
}
|
||||
|
||||
@@ -378,8 +381,8 @@ export function RentalPage() {
|
||||
<table className="w-full text-sm">
|
||||
<thead>
|
||||
<tr className="border-b border-slate-200 dark:border-slate-700 bg-slate-50 dark:bg-slate-700/40">
|
||||
{['Дата', 'Время', 'Гость', 'Телефон', 'Сумма', 'Статус'].map(h => (
|
||||
<th key={h} className="text-left px-4 py-2.5 text-xs font-semibold text-slate-500 dark:text-slate-400 uppercase tracking-wide">{h}</th>
|
||||
{['Дата', 'Время', 'Гость', 'Телефон', 'Сумма', 'Статус', ''].map((h, i) => (
|
||||
<th key={i} className="text-left px-4 py-2.5 text-xs font-semibold text-slate-500 dark:text-slate-400 uppercase tracking-wide">{h}</th>
|
||||
))}
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -408,6 +411,15 @@ export function RentalPage() {
|
||||
{b.status === 'confirmed' ? 'Подтверждено' : 'Отменено'}
|
||||
</Badge>
|
||||
</td>
|
||||
<td className="px-4 py-2.5">
|
||||
<button
|
||||
onClick={e => { e.stopPropagation(); setRentalModal({ obj: selectedObj, date: b.date, editBooking: b }) }}
|
||||
className="p-1.5 rounded-lg hover:bg-slate-100 dark:hover:bg-slate-700 text-slate-400 hover:text-slate-700 dark:hover:text-slate-300 transition-colors"
|
||||
title="Редактировать"
|
||||
>
|
||||
<Pencil size={13} />
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
))}
|
||||
</tbody>
|
||||
@@ -443,8 +455,9 @@ export function RentalPage() {
|
||||
obj={rentalModal.obj}
|
||||
date={rentalModal.date}
|
||||
existingBookings={bookings.filter(b => b.objectId === rentalModal.obj.id && b.date === rentalModal.date)}
|
||||
editBooking={rentalModal.editBooking}
|
||||
onClose={() => setRentalModal(null)}
|
||||
onSave={handleBookingCreate}
|
||||
onSave={handleBookingSave}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user