Skip to content

Commit 55242b3

Browse files
committed
Support preloading a previous-month comparison report
1 parent 256345d commit 55242b3

4 files changed

Lines changed: 36 additions & 1 deletion

File tree

CONTRIBUTING.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ uploaded, replaced, or cleared. If the file is absent the fetch 404s and the app
5353
falls back to the normal upload flow. This keeps the client-only constraint
5454
intact: the CSV is served as a static asset and parsed entirely in the browser.
5555

56+
Optionally drop a second CSV at `public/preloaded-report-previous.csv` to also
57+
preload the previous-month comparison report. It is fetched and locked only when
58+
the primary preloaded report is present.
59+
5660
## Development guidelines
5761

5862
- Keep the **client-only data** constraint inviolable.

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,16 @@ immediately, with uploading/replacing/clearing disabled. Everything still runs
8484
in the browser - the CSV is served as a static asset and parsed client-side.
8585
Remove the file for the normal upload experience.
8686

87+
To also preload a previous month for month-over-month comparison, drop a second
88+
CSV at `public/preloaded-report-previous.csv`. It is loaded (and locked) only
89+
when the primary preloaded report is present:
90+
91+
```bash
92+
cp ./this-month.csv public/preloaded-report.csv
93+
cp ./last-month.csv public/preloaded-report-previous.csv
94+
npm run build
95+
```
96+
8797
> Note: a file in `public/` is publicly downloadable, so only preload reports
8898
> you are comfortable sharing with anyone who can reach the site.
8999

docs/tools.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ decrease in green; plain counts stay neutral. Covered cards include:
3030

3131
Like the main report, the comparison CSV is parsed and held **in memory in your
3232
browser only**; it is never persisted or sent anywhere. Clearing or replacing the main
33-
report also clears the comparison.
33+
report also clears the comparison. A previous-month report can also be preloaded with
34+
the build (see the README's "Preloading a report" section), in which case it is locked
35+
alongside the main report.
3436

3537
- [Usage Forecast](#usage-forecast)_Forecasting_
3638
- [Team Insights](#team-insights)_Breakdowns_

src/components/report-provider.tsx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,15 @@ import { parseUsageCsvText, type ParsedReport } from "@/lib/report";
88
* `public/preloaded-report.csv` and it is fetched on load, parsed, and locked
99
* so users cannot upload, replace, or clear it. Absent the file, the app
1010
* behaves normally. The base path keeps the URL correct under GitHub Pages.
11+
*
12+
* A second optional CSV at `public/preloaded-report-previous.csv` is loaded as
13+
* the previous-month comparison report when (and only when) the primary
14+
* preloaded report is present; it is locked the same way.
1115
*/
1216
const PRELOADED_REPORT_FILE = "preloaded-report.csv";
1317
const PRELOADED_REPORT_URL = `${process.env.NEXT_PUBLIC_BASE_PATH ?? ""}/${PRELOADED_REPORT_FILE}`;
18+
const PRELOADED_COMPARISON_FILE = "preloaded-report-previous.csv";
19+
const PRELOADED_COMPARISON_URL = `${process.env.NEXT_PUBLIC_BASE_PATH ?? ""}/${PRELOADED_COMPARISON_FILE}`;
1420

1521
interface ReportContextValue {
1622
report: ParsedReport | null;
@@ -61,6 +67,19 @@ export function ReportProvider({ children }: { children: React.ReactNode }) {
6167
const parsed = parseUsageCsvText(text, PRELOADED_REPORT_FILE);
6268
setReport(parsed);
6369
setLocked(true);
70+
71+
// Only probe for the optional previous-month report once the primary
72+
// preloaded report is in place; a comparison without a primary report
73+
// has nothing to compare against.
74+
try {
75+
const cmp = await fetch(PRELOADED_COMPARISON_URL, { signal: controller.signal });
76+
if (cmp.ok && !(cmp.headers.get("content-type") ?? "").includes("text/html")) {
77+
const cmpText = await cmp.text();
78+
setComparisonReport(parseUsageCsvText(cmpText, PRELOADED_COMPARISON_FILE));
79+
}
80+
} catch {
81+
// No preloaded comparison, or it could not be parsed: leave it unset.
82+
}
6483
} catch {
6584
// No preloaded report, or it could not be parsed: normal upload mode.
6685
} finally {

0 commit comments

Comments
 (0)