From d20e49887de265708daf33d749438d8ee6ce117d Mon Sep 17 00:00:00 2001 From: TSVRN9 <66744142+TSVRN9@users.noreply.github.com> Date: Wed, 19 Aug 2026 08:03:55 -0400 Subject: [PATCH 1/2] WIP: rank page styling (#38) Partial restyle of the pairwise comparison / rankings screen using #35's tokens. Not verified against acceptance criteria - handing off for evaluation/completion by the #38 agent. --- web/src/routes/rank/+page.svelte | 192 ++++++++++++++++++++++++------- 1 file changed, 148 insertions(+), 44 deletions(-) diff --git a/web/src/routes/rank/+page.svelte b/web/src/routes/rank/+page.svelte index ea9031e0..db6350fc 100644 --- a/web/src/routes/rank/+page.svelte +++ b/web/src/routes/rank/+page.svelte @@ -27,6 +27,13 @@ let pair: [Dish, Dish] | null = $state(null); let hallRanking = $derived(rankDiningHalls(rankedDishes)); let lastPair: [Dish, Dish] | null = null; + // With only two logged dishes pickPair() legitimately returns the same pair every time, so + // choosing a winner changes nothing on screen above the fold and the tap reads as a dead click. + // This line is the acknowledgement. + let lastChoice = $state(""); + + // Each comparison bumps comparisonCount on both dishes, so the sum double-counts. + const comparisonsMade = $derived(Math.round(rankedDishes.reduce((sum, d) => sum + d.comparisonCount, 0) / 2)); function hallName(hallTid: number): string { return DINING_HALLS.find((h) => h.tid === hallTid)?.name ?? `Hall ${hallTid}`; @@ -108,63 +115,160 @@ void syncDiningHallRanks(page.data.supabase, session.user.id, snapshot); } + lastChoice = `${winner.dishName} over ${loser.dishName}`; pair = pickPair(); } function skip() { + lastChoice = ""; pair = pickPair(); } -
Compare dishes you've actually logged — ranking is built from what you've eaten, not the full menu.
++ Compare dishes you’ve actually logged — ranking is built from what you’ve eaten, not + the full menu. Every comparison stays on this device. +
+Log a couple of meals first, then come back here to rank them.
+Nothing to compare yet
++ Ranking needs at least two different dishes in your log. You have {loggedDishes.length}. + Log a couple of meals first, then come back here to rank them. +
+ +No comparisons yet.
-{:else} -Your favorite dishes by name, regardless of which hall serves them.
-{#if rankedFoods.length === 0} -No comparisons yet.
-{:else} -+ {#if lastChoice}Recorded: {lastChoice}{/if} +
++ No comparisons yet — pick a winner above and your dishes start ordering themselves. +
+ {:else} ++ The number on the right is a rating, not calories — it starts at 1000 and moves as you + compare. Only the order matters. +
+ {/if} ++ Your favorite dishes by name, regardless of which hall serves them. +
+ {#if rankedFoods.length === 0} +No comparisons yet.
+ {:else} ++ A hall needs at least 2 rated dishes before it can be placed. +
+ {/if} + From e663ccd3db2377438b4f03d93779da6f583bff82 Mon Sep 17 00:00:00 2001 From: TSVRN9 <66744142+TSVRN9@users.noreply.github.com> Date: Wed, 19 Aug 2026 09:57:25 -0400 Subject: [PATCH 2/2] rank e2e: assert ranked/unranked halls carry a real visual treatment #38 AC2 requires ranked vs. unranked dining halls to be visually distinguishable, not just distinguishable by wording ("not enough data yet"). The existing assertions only checked text content, which would stay green even if the .card treatment on ranked rows regressed back to a plain list. Pin it to the actual class the WIP styling applies. Red/green: removing "card" from the ranked