122 lines
4.3 KiB
React
122 lines
4.3 KiB
React
import PageBar from "../components/PageBar.jsx";
|
|
import SummaryCard from "../components/SummaryCard.jsx";
|
|
import { formatCurrency, formatTime, titleCase } from "../lib/formatters.js";
|
|
|
|
const queueStatuses = ["new", "making", "ready"];
|
|
|
|
export default function QueuePage({
|
|
adminUnlocked,
|
|
logoPressing,
|
|
onLogoPointerDown,
|
|
onLogoPointerUp,
|
|
onLogoPointerLeave,
|
|
onLogoPointerCancel,
|
|
onHideAdmin,
|
|
view,
|
|
setView,
|
|
orders,
|
|
updateOrderStatus,
|
|
deleteOrder,
|
|
setOrders,
|
|
setError
|
|
}) {
|
|
return (
|
|
<section className="queue-screen">
|
|
<PageBar
|
|
adminUnlocked={adminUnlocked}
|
|
logoPressing={logoPressing}
|
|
onLogoPointerDown={onLogoPointerDown}
|
|
onLogoPointerUp={onLogoPointerUp}
|
|
onLogoPointerLeave={onLogoPointerLeave}
|
|
onLogoPointerCancel={onLogoPointerCancel}
|
|
onHideAdmin={onHideAdmin}
|
|
view={view}
|
|
setView={setView}
|
|
/>
|
|
<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>
|
|
);
|
|
}
|