order details: hide the review surface for spine-bridged retail rows
ci / lint-test (push) Successful in 58s
ci / lint-test (push) Successful in 58s
Verdicts are the meal lane's feedback loop (loved/never steers the next restaurant order and the nudge card warns on re-order). Bridge rows (source='order-bridge': Amazon, eBay, Officeworks...) have no such loop, so ItemVerdictToggle and OrderVerdict stay hidden there. The order API now returns 'source'; OrderReceipt.platform widened to string — the bridge writes real platform slugs beyond the meal trio.
This commit is contained in:
@@ -26,7 +26,7 @@ export async function GET(
|
||||
}
|
||||
|
||||
const row = await queryRow(
|
||||
`SELECT platform, order_reference, line_items, route, subtotal, amount,
|
||||
`SELECT source, platform, order_reference, line_items, route, subtotal, amount,
|
||||
currency, card_last4, flags, source_email_subject, transaction_date
|
||||
FROM expense_metadata
|
||||
-- A card-settled order creates no transaction of its own (I5): the
|
||||
|
||||
@@ -81,6 +81,13 @@ export function OrderDetails({
|
||||
|
||||
const mine = review?.reviews.find((r) => r.participant_id === reviewer);
|
||||
|
||||
// Verdicts are the MEAL lane's feedback loop — "loved / never again" exists
|
||||
// to steer the next restaurant order, and the nudge card warns on re-order.
|
||||
// Spine-bridged retail (Amazon boxes, eBay, Officeworks) has no such loop:
|
||||
// rating a roller-shade motor "order again?" is noise, so the whole review
|
||||
// surface stays hidden for bridge rows.
|
||||
const rateable = receipt.source !== "order-bridge";
|
||||
|
||||
return (
|
||||
<div className={bare ? "" : "border-t border-zinc-800 pt-4"}>
|
||||
<div className="flex items-baseline justify-between mb-2">
|
||||
@@ -106,14 +113,16 @@ export function OrderDetails({
|
||||
<span className="block text-zinc-600">{it.options.join(" · ")}</span>
|
||||
)}
|
||||
</span>
|
||||
<ItemVerdictToggle
|
||||
transactionId={transactionId}
|
||||
reviewer={reviewer}
|
||||
item={it.description}
|
||||
current={mine?.item_verdicts ?? []}
|
||||
rating={mine?.rating ?? null}
|
||||
note={mine?.note ?? null}
|
||||
/>
|
||||
{rateable && (
|
||||
<ItemVerdictToggle
|
||||
transactionId={transactionId}
|
||||
reviewer={reviewer}
|
||||
item={it.description}
|
||||
current={mine?.item_verdicts ?? []}
|
||||
rating={mine?.rating ?? null}
|
||||
note={mine?.note ?? null}
|
||||
/>
|
||||
)}
|
||||
{/* Spine-bridged receipts (Amazon shipment notices, eBay) often
|
||||
name the goods without per-item prices — a null here is "the
|
||||
mail didn't say", and printing $0.00 would assert it did. */}
|
||||
@@ -152,11 +161,13 @@ export function OrderDetails({
|
||||
</p>
|
||||
)}
|
||||
|
||||
<OrderVerdict
|
||||
transactionId={transactionId}
|
||||
reviewer={reviewer}
|
||||
onReviewerChange={setReviewer}
|
||||
/>
|
||||
{rateable && (
|
||||
<OrderVerdict
|
||||
transactionId={transactionId}
|
||||
reviewer={reviewer}
|
||||
onReviewerChange={setReviewer}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
+3
-1
@@ -257,7 +257,9 @@ export function useTransactionSplits(transactionId: number) {
|
||||
}
|
||||
|
||||
export interface OrderReceipt {
|
||||
platform: "doordash" | "ubereats" | "uber" | null;
|
||||
/** 'email' | 'receipt-scan' | 'order-bridge' | ... — which lane wrote the row. */
|
||||
source: string | null;
|
||||
platform: string | null;
|
||||
order_reference: string | null;
|
||||
line_items: { qty: number; description: string; amount: number; options?: string[] }[];
|
||||
route: { label: string; time: string | null; address: string }[];
|
||||
|
||||
Reference in New Issue
Block a user