Files
inven/app/purchase-orders/page.tsx

101 lines
4.7 KiB
TypeScript
Raw Normal View History

2026-03-23 17:12:35 -05:00
import { PurchaseOrderFulfillmentForm } from "@/components/purchase-order-fulfillment-form";
2026-03-23 16:58:55 -05:00
import { PurchaseOrderForm } from "@/components/purchase-order-form";
2026-03-23 16:16:45 -05:00
import { formatCurrency, formatDate } from "@/lib/format";
2026-03-23 17:12:35 -05:00
import { getLowStockParts, getOrderItemOptions, getPurchaseOrderLineDetails, getPurchaseOrders, getVendors } from "@/lib/repository";
2026-03-23 16:16:45 -05:00
export default function PurchaseOrdersPage() {
const vendors = getVendors();
2026-03-23 16:56:23 -05:00
const items = getOrderItemOptions();
2026-03-23 16:16:45 -05:00
const orders = getPurchaseOrders();
2026-03-23 17:12:35 -05:00
const orderLines = getPurchaseOrderLineDetails();
2026-03-23 16:16:45 -05:00
const lowStockParts = getLowStockParts();
return (
<div className="grid">
<section className="two-up">
<article className="panel">
<h2 className="section-title">Create Purchase Order</h2>
2026-03-23 16:56:23 -05:00
<p className="section-copy">Build the PO from real inventory items so receipts, costing, and restocking stay relational.</p>
2026-03-23 16:58:55 -05:00
<PurchaseOrderForm vendors={vendors} items={items} />
2026-03-23 16:16:45 -05:00
</article>
<article className="panel">
2026-03-23 17:23:07 -05:00
<h2 className="section-title">Purchase Orders</h2>
<p className="section-copy">Review vendor demand, total value, and receiving progress without nested scrolling.</p>
2026-03-23 16:16:45 -05:00
<div className="table-wrap">
<table className="table">
2026-03-23 17:23:07 -05:00
<thead><tr><th>Order</th><th>Vendor</th><th>Status</th><th>Total</th><th>Qty Progress</th><th>Created</th></tr></thead>
2026-03-23 16:16:45 -05:00
<tbody>
{orders.length === 0 ? (
2026-03-23 17:23:07 -05:00
<tr><td colSpan={6} className="muted">No purchase orders yet.</td></tr>
2026-03-23 16:16:45 -05:00
) : (
orders.map((order) => (
<tr key={order.id}>
<td>{order.orderNumber}</td>
<td>{order.vendorName}</td>
<td><span className={`pill ${order.status === "received" ? "" : "warning"}`}>{order.status}</span></td>
<td>{formatCurrency(order.totalAmount)}</td>
<td>{order.fulfilledQuantity} / {order.orderedQuantity}</td>
<td>{formatDate(order.createdAt)}</td>
</tr>
))
)}
</tbody>
</table>
</div>
</article>
</section>
2026-03-23 17:23:07 -05:00
<section className="panel">
<h2 className="section-title">Receiving Flow</h2>
<p className="section-copy">Receive relational order lines directly by entering quantities against the remaining balance on each line.</p>
<div className="grid">
{orders.filter((order) => order.status !== "received").length === 0 ? (
<p className="muted">No open or partial purchase orders need receiving right now.</p>
) : (
orders
.filter((order) => order.status !== "received")
.map((order) => (
<article className="panel" key={`receive-${order.id}`}>
<div className="grid" style={{ gap: 10 }}>
<h3 className="section-title">{order.orderNumber}</h3>
<p className="section-copy">
{order.vendorName} {order.fulfilledQuantity} / {order.orderedQuantity} received {formatCurrency(order.totalAmount)}
</p>
<PurchaseOrderFulfillmentForm
orderId={order.id}
lines={orderLines.filter((line) => line.purchaseOrderId === order.id && line.remainingQuantity > 0)}
/>
</div>
</article>
))
)}
</div>
</section>
2026-03-23 16:16:45 -05:00
<section className="panel">
<h2 className="section-title">Restock Recommendations</h2>
<p className="section-copy">Use this list to plan the next purchase order from items already below target.</p>
<div className="table-wrap">
<table className="table">
<thead><tr><th>SKU</th><th>Name</th><th>On Hand</th><th>Reorder Point</th><th>Suggested Qty</th><th>Last Vendor</th></tr></thead>
<tbody>
{lowStockParts.length === 0 ? (
<tr><td colSpan={6} className="muted">No parts currently need restocking.</td></tr>
) : (
lowStockParts.map((part) => (
<tr key={part.id}>
<td>{part.sku}</td>
<td>{part.name}</td>
<td>{part.quantityOnHand} {part.unitOfMeasure}</td>
<td>{part.reorderPoint}</td>
<td>{part.suggestedReorderQuantity}</td>
<td>{part.preferredVendorName || "-"}</td>
</tr>
))
)}
</tbody>
</table>
</div>
</section>
</div>
);
}