diff --git a/src/admin/orders/KanbanBoard.jsx b/src/admin/orders/KanbanBoard.jsx index 6020651..4a8ae1b 100644 --- a/src/admin/orders/KanbanBoard.jsx +++ b/src/admin/orders/KanbanBoard.jsx @@ -18,7 +18,10 @@ const KanbanBoard = () => { const sensors = useSensors(useSensor(PointerSensor, { activationConstraint: { distance: 5 } })); + const [localOverrides, setLocalOverrides] = useState({}); + const findOrderStatus = (orderId) => { + if (localOverrides[orderId]) return localOverrides[orderId]; for (const status of STATUSES) { if (ordersByStatus[status]?.find((o) => o.id === orderId)) return status; } @@ -27,7 +30,8 @@ const KanbanBoard = () => { const handleDragStart = ({ active }) => { const status = findOrderStatus(active.id); - if (status) setActiveOrder(ordersByStatus[status].find((o) => o.id === active.id)); + if (status) setActiveOrder(ordersByStatus[status].find((o) => o.id === active.id) || + Object.values(ordersByStatus).flat().find((o) => o.id === active.id)); }; const handleDragEnd = async ({ active, over }) => { @@ -38,10 +42,38 @@ const KanbanBoard = () => { const sourceStatus = findOrderStatus(active.id); if (targetStatus && sourceStatus !== targetStatus) { - await updateStatus(active.id, targetStatus, session?.user?.email); + setLocalOverrides((prev) => ({ ...prev, [active.id]: targetStatus })); + const { error } = await updateStatus(active.id, targetStatus, session?.user?.email); + if (error) { + console.error('Status update failed:', error); + setLocalOverrides((prev) => { + const next = { ...prev }; + delete next[active.id]; + return next; + }); + } else { + setLocalOverrides((prev) => { + const next = { ...prev }; + delete next[active.id]; + return next; + }); + } } }; + const effectiveOrdersByStatus = STATUSES.reduce((acc, status) => { + acc[status] = (ordersByStatus[status] || []).filter( + (o) => !localOverrides[o.id] || localOverrides[o.id] === status + ); + // Add orders that were moved here optimistically + const overrideOrders = Object.entries(localOverrides) + .filter(([, s]) => s === status) + .map(([id]) => Object.values(ordersByStatus).flat().find((o) => o.id === id)) + .filter(Boolean); + acc[status] = [...acc[status], ...overrideOrders]; + return acc; + }, {}); + if (loading) { return (
@@ -58,7 +90,7 @@ const KanbanBoard = () => { ))} diff --git a/src/admin/orders/OrderModal.jsx b/src/admin/orders/OrderModal.jsx index 47d6185..e11de90 100644 --- a/src/admin/orders/OrderModal.jsx +++ b/src/admin/orders/OrderModal.jsx @@ -57,6 +57,17 @@ const OrderModal = ({ order, onClose, onSaved, mode = 'edit' }) => { } }, [order?.id]); + const modalRef = React.useRef(null); + + useEffect(() => { + const handleKey = (e) => { + if (e.key === 'Escape') onClose(); + }; + document.addEventListener('keydown', handleKey); + modalRef.current?.focus(); + return () => document.removeEventListener('keydown', handleKey); + }, [onClose]); + const set = (e) => setForm((prev) => ({ ...prev, [e.target.name]: e.target.value })); const handleSave = async () => { @@ -76,7 +87,13 @@ const OrderModal = ({ order, onClose, onSaved, mode = 'edit' }) => { } else { const statusChanged = form.status !== order.status; const updates = { ...form }; - if (statusChanged && form.status === 'закрыт') updates.closed_at = new Date().toISOString(); + if (statusChanged) { + if (form.status === 'закрыт') { + updates.closed_at = new Date().toISOString(); + } else if (order.status === 'закрыт') { + updates.closed_at = null; + } + } const { error } = await supabase.from('orders').update(updates).eq('id', order.id); if (error) { setError(error.message); setSaving(false); return; } @@ -110,6 +127,8 @@ const OrderModal = ({ order, onClose, onSaved, mode = 'edit' }) => { onClick={onClose} >
e.stopPropagation()} @@ -157,7 +176,7 @@ const OrderModal = ({ order, onClose, onSaved, mode = 'edit' }) => {
- setForm((prev) => ({ ...prev, film_thickness: Number(e.target.value) }))} style={{ ...inputStyle, cursor: 'pointer' }}> @@ -205,7 +224,7 @@ const OrderModal = ({ order, onClose, onSaved, mode = 'edit' }) => { {events.map((e) => (
- {new Date(e.created_at).toLocaleDateString('ru-RU', { day: '2-digit', month: '2-digit', hour: '2-digit', minute: '2-digit' })} + {new Date(e.created_at).toLocaleString('ru-RU', { day: '2-digit', month: '2-digit', hour: '2-digit', minute: '2-digit' })} {e.description} {e.created_by && (