1import { useEffect, useState } from 'react';
2import { useNavigate, useParams } from 'react-router-dom';
3import MainLayout from '../components/Layout/MainLayout';
4import { apiFetch } from '../lib/api';
6export default function PurchaseOrderDetail() {
7 const navigate = useNavigate();
8 const { id } = useParams();
9 const [po, setPo] = useState(null);
10 const [lines, setLines] = useState([]);
11 const [loading, setLoading] = useState(true);
12 const [error, setError] = useState(null);
18 async function fetchPO() {
21 const token = localStorage.getItem('token');
22 const url = `/purchase-orders/${id}`;
23 const res = await apiFetch(url, { headers: { Authorization: `Bearer ${token}` } });
24 if (!res.ok) throw new Error('Failed to load');
25 const data = await res.json();
26 setPo(data.purchase_order);
27 setLines(data.lines || []);
30 setError(err.message || 'Failed to load');
36 const total = lines.reduce((sum, l) => sum + (l.qty_ordered || 0) * (Number(l.unit_price || 0)), 0);
40 <div className="page-content">
41 <div className="page-header">
42 <div className="header-content">
43 <h2>Purchase Order {po?.po_number ? `#${po.po_number}` : `#${po?.purchase_order_id || ''}`}</h2>
44 <div className="header-actions">
45 <button className="btn" onClick={() => navigate(`/purchase-orders/${id}/edit`)}>
46 <span className="material-symbols-outlined">edit</span>
52 {loading ? <div>Loading...</div> : error ? <div className="error-message">{error}</div> : (
53 <div style={{ maxWidth: 1000 }}>
54 <div className="grid" style={{ gridTemplateColumns: '1fr 1fr', gap: 16 }}>
55 <div><strong>Supplier:</strong> {po?.supplier || '-'}</div>
56 <div><strong>Status:</strong> <span className={`status-badge status-${po?.status}`}>{po?.status}</span></div>
57 <div><strong>Related Ticket:</strong> {po?.related_ticket_id || '-'}</div>
58 <div><strong>Related Customer:</strong> {po?.related_customer_id || '-'}</div>
59 <div style={{ gridColumn: '1 / span 2' }}>
60 <strong>Bill To</strong>
61 <pre style={{ whiteSpace: 'pre-wrap' }}>{po?.bill_to || '-'}</pre>
63 <div style={{ gridColumn: '1 / span 2' }}>
64 <strong>Ship To</strong>
65 <pre style={{ whiteSpace: 'pre-wrap' }}>{po?.ship_to || '-'}</pre>
67 <div style={{ gridColumn: '1 / span 2' }}>
68 <strong>Internal Notes</strong>
69 <pre style={{ whiteSpace: 'pre-wrap' }}>{po?.internal_notes || '-'}</pre>
73 <h3 style={{ marginTop: 24 }}>Line Items</h3>
74 <table className="data-table">
86 <tr key={l.po_line_id}>
87 <td>{l.sku || '-'}</td>
88 <td>{l.description || '-'}</td>
89 <td>{l.qty_ordered}</td>
90 <td>${Number(l.unit_price || 0).toFixed(2)}</td>
91 <td>${Number((l.qty_ordered || 0) * (l.unit_price || 0)).toFixed(2)}</td>
97 <div style={{ textAlign: 'right', marginTop: 12 }}>
98 <strong>Total: ${total.toFixed(2)}</strong>