Skip to content

Commit 47170f9

Browse files
authored
Fix hunt week scoring and admin controls (#237)
1 parent 194f17c commit 47170f9

14 files changed

Lines changed: 711 additions & 353 deletions

File tree

apps/web/app/challenges/[id]/(dashboard)/users/[userId]/ledger/ledger-content.tsx

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -226,9 +226,21 @@ interface LedgerTableProps {
226226
type TableRow =
227227
| { type: "activity"; dayDate: string; showDate: boolean; activity: LedgerDay["activities"][number] }
228228
| { type: "streak"; dayDate: string; showDate: boolean; bonus: number }
229-
| { type: "day_total"; dayDate: string; showDate: boolean; day: LedgerDay }
229+
| { type: "day_total"; dayDate: string; showDate: boolean; day: LedgerDay; runningTotal: number }
230230
| { type: "grand_total"; base: number; bonus: number; activityTotal: number; streak: number; total: number };
231231

232+
function getRunningTotalByDate(days: LedgerDay[]) {
233+
let runningTotal = 0;
234+
const runningTotals = new Map<string, number>();
235+
236+
for (const day of [...days].reverse()) {
237+
runningTotal += day.dayTotal;
238+
runningTotals.set(day.date, runningTotal);
239+
}
240+
241+
return runningTotals;
242+
}
243+
232244
function LedgerTable({
233245
days,
234246
totalActivityBasePoints,
@@ -244,6 +256,7 @@ function LedgerTable({
244256

245257
const rows = useMemo(() => {
246258
const result: TableRow[] = [];
259+
const runningTotalsByDate = getRunningTotalByDate(days);
247260
for (const day of days) {
248261
let showDate = true;
249262
for (const activity of day.activities) {
@@ -254,7 +267,13 @@ function LedgerTable({
254267
result.push({ type: "streak", dayDate: day.date, showDate, bonus: day.streakBonus });
255268
showDate = false;
256269
}
257-
result.push({ type: "day_total", dayDate: day.date, showDate, day });
270+
result.push({
271+
type: "day_total",
272+
dayDate: day.date,
273+
showDate,
274+
day,
275+
runningTotal: runningTotalsByDate.get(day.date) ?? day.dayTotal,
276+
});
258277
}
259278
result.push({
260279
type: "grand_total",
@@ -285,12 +304,14 @@ function LedgerTable({
285304
map.set(`${rowIdx}:4`, d.activityPoints);
286305
map.set(`${rowIdx}:5`, d.streakBonus);
287306
map.set(`${rowIdx}:6`, d.dayTotal);
307+
map.set(`${rowIdx}:7`, row.runningTotal);
288308
} else if (row.type === "grand_total") {
289309
map.set(`${rowIdx}:2`, row.base);
290310
map.set(`${rowIdx}:3`, row.bonus);
291311
map.set(`${rowIdx}:4`, row.activityTotal);
292312
map.set(`${rowIdx}:5`, row.streak);
293313
map.set(`${rowIdx}:6`, row.total);
314+
map.set(`${rowIdx}:7`, row.total);
294315
}
295316
});
296317
return map;
@@ -408,14 +429,14 @@ function LedgerTable({
408429
<div className="overflow-x-auto">
409430
<table
410431
ref={tableRef}
411-
className="w-full min-w-[640px] select-none border-x border-zinc-800 text-[13px]"
432+
className="w-full min-w-[760px] select-none border-x border-zinc-800 text-[13px]"
412433
style={{ borderCollapse: "collapse" }}
413434
onMouseDown={handleCellMouseDown}
414435
onMouseMove={handleTableMouseMove}
415436
>
416437
<tbody>
417438
<tr className="sticky top-0 z-10 bg-zinc-900/95 backdrop-blur">
418-
{["Date", "Activity", "Base", "Bonus", "Total", "Streak", "Day Total"].map(
439+
{["Date", "Activity", "Base", "Bonus", "Total", "Streak", "Day Total", "Running Total"].map(
419440
(header) => (
420441
<td
421442
key={header}
@@ -513,6 +534,7 @@ function LedgerRow({
513534
{numCell(4, a.pointsEarned, a.isNegative ? "text-red-400" : undefined)}
514535
<td className={cn(CELL)} />
515536
<td className={cn(CELL)} />
537+
<td className={cn(CELL)} />
516538
</tr>
517539
);
518540
}
@@ -529,6 +551,7 @@ function LedgerRow({
529551
<td className={cn(CELL)} />
530552
{numCell(5, row.bonus, "text-orange-400")}
531553
<td className={cn(CELL)} />
554+
<td className={cn(CELL)} />
532555
</tr>
533556
);
534557
}
@@ -548,6 +571,7 @@ function LedgerRow({
548571
{numCell(4, d.activityPoints)}
549572
{numCell(5, d.streakBonus, "text-orange-400")}
550573
{numCell(6, d.dayTotal)}
574+
{numCell(7, row.runningTotal)}
551575
</tr>
552576
);
553577
}
@@ -574,6 +598,9 @@ function LedgerRow({
574598
<td data-row={rowIdx} data-col={6} className={cn(NUM_CELL, "cursor-cell", selStyle(6))}>
575599
{fmt(row.total)}
576600
</td>
601+
<td data-row={rowIdx} data-col={7} className={cn(NUM_CELL, "cursor-cell", selStyle(7))}>
602+
{fmt(row.total)}
603+
</td>
577604
</tr>
578605
);
579606
}
@@ -591,6 +618,7 @@ const CSV_COLUMNS = [
591618
"total_points",
592619
"streak_bonus",
593620
"day_total",
621+
"running_total",
594622
"bonus_details",
595623
"notes",
596624
];
@@ -616,6 +644,7 @@ function downloadLedgerCsv({
616644
}) {
617645
const header = [...CSV_COLUMNS];
618646
const body: (string | number)[][] = [];
647+
const runningTotalsByDate = getRunningTotalByDate(days);
619648

620649
for (const day of days) {
621650
for (const a of day.activities) {
@@ -628,6 +657,7 @@ function downloadLedgerCsv({
628657
a.pointsEarned,
629658
"",
630659
"",
660+
"",
631661
a.triggeredBonuses?.map((b) => b.description).join(" | ") ?? "",
632662
a.notes ?? "",
633663
]);
@@ -642,6 +672,7 @@ function downloadLedgerCsv({
642672
"",
643673
day.streakBonus,
644674
"",
675+
"",
645676
`Day ${day.streakBonus} streak`,
646677
"",
647678
]);
@@ -655,6 +686,7 @@ function downloadLedgerCsv({
655686
day.activityPoints,
656687
day.streakBonus,
657688
day.dayTotal,
689+
runningTotalsByDate.get(day.date) ?? day.dayTotal,
658690
"",
659691
"",
660692
]);
@@ -669,6 +701,7 @@ function downloadLedgerCsv({
669701
totalActivityPoints,
670702
totalStreakBonus,
671703
totalPoints,
704+
totalPoints,
672705
"",
673706
"",
674707
]);

0 commit comments

Comments
 (0)