72407fa9b8
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
92 lines
2.8 KiB
JavaScript
92 lines
2.8 KiB
JavaScript
import { useState, useEffect, useCallback } from 'react';
|
|
import { supabase } from '../../lib/supabase';
|
|
|
|
const STATUSES = ['новая', 'замер', 'согласование', 'монтаж', 'закрыт'];
|
|
|
|
export function useOrders() {
|
|
const [orders, setOrders] = useState([]);
|
|
const [loading, setLoading] = useState(true);
|
|
const [error, setError] = useState(null);
|
|
|
|
const fetchOrders = useCallback(async () => {
|
|
const { data, error } = await supabase
|
|
.from('orders')
|
|
.select('*')
|
|
.order('created_at', { ascending: false });
|
|
|
|
if (error) {
|
|
setError(error.message);
|
|
} else {
|
|
setOrders(data || []);
|
|
}
|
|
setLoading(false);
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
fetchOrders();
|
|
|
|
const channel = supabase
|
|
.channel('orders-realtime')
|
|
.on('postgres_changes', { event: '*', schema: 'public', table: 'orders' }, fetchOrders)
|
|
.subscribe();
|
|
|
|
return () => supabase.removeChannel(channel);
|
|
}, [fetchOrders]);
|
|
|
|
const ordersByStatus = STATUSES.reduce((acc, status) => {
|
|
acc[status] = orders.filter((o) => o.status === status);
|
|
return acc;
|
|
}, {});
|
|
|
|
const updateStatus = async (orderId, newStatus, userEmail) => {
|
|
const order = orders.find((o) => o.id === orderId);
|
|
const updates = { status: newStatus };
|
|
if (newStatus === 'закрыт') updates.closed_at = new Date().toISOString();
|
|
|
|
const { error } = await supabase.from('orders').update(updates).eq('id', orderId);
|
|
|
|
if (!error) {
|
|
await supabase.from('order_events').insert({
|
|
order_id: orderId,
|
|
created_by: userEmail,
|
|
event_type: 'status_change',
|
|
description: `Статус изменён: ${order?.status} → ${newStatus}`,
|
|
});
|
|
}
|
|
return { error };
|
|
};
|
|
|
|
const createOrder = async (orderData, userEmail) => {
|
|
const { data, error } = await supabase
|
|
.from('orders')
|
|
.insert({ ...orderData, source: 'manual', status: 'новая' })
|
|
.select()
|
|
.single();
|
|
|
|
if (!error && data) {
|
|
await supabase.from('order_events').insert({
|
|
order_id: data.id,
|
|
created_by: userEmail,
|
|
event_type: 'status_change',
|
|
description: 'Заявка создана вручную',
|
|
});
|
|
}
|
|
return { data, error };
|
|
};
|
|
|
|
const updateOrder = async (orderId, updates, userEmail) => {
|
|
const { error } = await supabase.from('orders').update(updates).eq('id', orderId);
|
|
if (!error) {
|
|
await supabase.from('order_events').insert({
|
|
order_id: orderId,
|
|
created_by: userEmail,
|
|
event_type: 'edit',
|
|
description: 'Данные заказа обновлены',
|
|
});
|
|
}
|
|
return { error };
|
|
};
|
|
|
|
return { orders, ordersByStatus, loading, error, updateStatus, createOrder, updateOrder, refetch: fetchOrders };
|
|
}
|