import { useEffect, useState } from 'react'; import Layout from '../../components/Layout'; import { supabase } from '../../lib/supabase'; import { useAuth } from '../../context/AuthContext'; import { withTimeout } from '../../lib/withTimeout'; const poStatusColor = { draft: 'not_started', sent: 'in_progress', approved: 'client_approved', ready_to_pay: 'in_progress', paid: 'client_approved', cancelled: 'needs_revision', }; const poStatusLabel = { draft: 'Draft', sent: 'Sent', approved: 'Approved', ready_to_pay: 'Ready to Pay', paid: 'Paid', cancelled: 'Cancelled', }; export default function MyPurchaseOrders() { const { currentUser } = useAuth(); const [purchaseOrders, setPurchaseOrders] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(''); const [savingId, setSavingId] = useState(''); useEffect(() => { async function load() { if (!currentUser?.id) { setLoading(false); return; } try { const { data, error: loadError } = await withTimeout( supabase .from('subcontractor_payments') .select('*, project:projects(id, name, company:companies(name)), items:subcontractor_po_items(*, task:tasks(id, title))') .eq('profile_id', currentUser.id) .order('date', { ascending: false }), 12000, 'Purchase orders load' ); if (loadError) { console.error('Failed to load purchase orders:', loadError); setError(loadError.message || 'Failed to load purchase orders.'); setPurchaseOrders([]); } else { setPurchaseOrders(data || []); setError(''); } } catch (error) { console.error('Purchase orders load failed:', error); setError(error.message || 'Failed to load purchase orders.'); setPurchaseOrders([]); } finally { setLoading(false); } } load(); }, [currentUser?.id]); const handleApprove = async (po) => { setSavingId(po.id); const { data, error: approveError } = await supabase .from('subcontractor_payments') .update({ status: 'approved', approved_at: new Date().toISOString() }) .eq('id', po.id) .eq('profile_id', currentUser.id) .select('*, project:projects(id, name, company:companies(name)), items:subcontractor_po_items(*, task:tasks(id, title))') .single(); if (approveError) { alert(`Failed to approve PO: ${approveError.message}`); } else if (data) { setPurchaseOrders(prev => prev.map(row => row.id === po.id ? data : row)); } setSavingId(''); }; return (
Purchase Orders
Review and approve subcontractor work orders assigned to you.
{loading ? (

Loading...

) : error ? (
{error}
) : purchaseOrders.length === 0 ? (

No purchase orders

New POs will appear here when the Fourge team sends them.

) : (
{purchaseOrders.map(po => (
{po.po_number || 'Purchase Order'}
{po.project?.name || 'Subcontractor Work'}
{po.project?.company?.name || 'Fourge Branding'} · {new Date(po.date).toLocaleDateString()} {po.due_date ? ` · Due ${new Date(po.due_date).toLocaleDateString()}` : ''}
{poStatusLabel[po.status] || po.status}
Scope
{po.description}
{po.items?.length > 0 && (
Line Items
{po.items .slice() .sort((a, b) => Number(a.sort_order || 0) - Number(b.sort_order || 0)) .map(item => (
{item.description || item.task?.title}
{item.task?.title && item.description !== item.task.title && (
{item.task.title}
)}
${Number(item.amount).toFixed(2)}
))}
)}
Amount
${Number(po.amount).toFixed(2)}
Terms
{po.terms || 'Net 15'}
Paid
{po.paid_at ? new Date(po.paid_at).toLocaleDateString() : 'Not paid'}
{po.notes && (
{po.notes}
)}
{po.status === 'sent' && (
)}
))}
)}
); }