Refactor frontend into pages and components
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
import SummaryCard from "../components/SummaryCard.jsx";
|
||||
import { formatCurrency, formatTime, titleCase } from "../lib/formatters.js";
|
||||
|
||||
const queueStatuses = ["new", "making", "ready"];
|
||||
|
||||
export default function QueuePage({
|
||||
orders,
|
||||
updateOrderStatus,
|
||||
deleteOrder,
|
||||
setOrders,
|
||||
setError
|
||||
}) {
|
||||
return (
|
||||
<section className="queue-screen">
|
||||
<div className="queue-summary">
|
||||
<SummaryCard label="Open orders" value={orders.filter((order) => order.status !== "completed").length} />
|
||||
<SummaryCard label="New" value={orders.filter((order) => order.status === "new").length} />
|
||||
<SummaryCard label="Making" value={orders.filter((order) => order.status === "making").length} />
|
||||
<SummaryCard label="Ready" value={orders.filter((order) => order.status === "ready").length} />
|
||||
</div>
|
||||
<div className="queue-columns">
|
||||
{queueStatuses.map((status) => (
|
||||
<section key={status} className="queue-column">
|
||||
<div className="column-head">
|
||||
<p className="eyebrow">{titleCase(status)}</p>
|
||||
<h3>{orders.filter((order) => order.status === status).length} orders</h3>
|
||||
</div>
|
||||
{orders.filter((order) => order.status === status).map((order) => (
|
||||
<article key={order._id} className="queue-card">
|
||||
<header>
|
||||
<div>
|
||||
<p className="eyebrow">Order #{order.number}</p>
|
||||
<h3>{order.customerName || "Walk-in"}</h3>
|
||||
</div>
|
||||
<strong>{formatCurrency(order.total)}</strong>
|
||||
</header>
|
||||
<p className="muted">{formatTime(order.createdAt)} • {titleCase(order.paymentMethod)}</p>
|
||||
<div>
|
||||
{order.lines.map((line, index) => (
|
||||
<p key={`${order._id}-${index}`}>• {line.name} ({line.size})</p>
|
||||
))}
|
||||
</div>
|
||||
<div className="status-actions">
|
||||
<NextStatusButton
|
||||
order={order}
|
||||
onAdvance={async (newStatus) => {
|
||||
try {
|
||||
const response = await updateOrderStatus(order._id, newStatus);
|
||||
setOrders((current) => current.map((item) => {
|
||||
return item._id === response.order._id ? response.order : item;
|
||||
}));
|
||||
} catch (requestError) {
|
||||
setError(requestError.message);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<button
|
||||
className="status-btn danger"
|
||||
onClick={async () => {
|
||||
try {
|
||||
await deleteOrder(order._id);
|
||||
setOrders((current) => current.filter((item) => item._id !== order._id));
|
||||
} catch (requestError) {
|
||||
setError(requestError.message);
|
||||
}
|
||||
}}
|
||||
>
|
||||
Delete
|
||||
</button>
|
||||
</div>
|
||||
</article>
|
||||
))}
|
||||
{orders.filter((order) => order.status === status).length === 0 && (
|
||||
<div className="empty-state">No orders in {status}.</div>
|
||||
)}
|
||||
</section>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
function NextStatusButton({ order, onAdvance }) {
|
||||
const map = {
|
||||
new: "making",
|
||||
making: "ready",
|
||||
ready: "completed"
|
||||
};
|
||||
const next = map[order.status];
|
||||
|
||||
if (!next) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<button className="status-btn" onClick={() => onAdvance(next)}>
|
||||
{next === "making" ? "Start making" : next === "ready" ? "Mark ready" : "Complete"}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user