Budget history by month, shared tab navigation, file imported statements into Statements/year/month and stop re-reading them
build-container / build (push) Successful in 40s

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
nmemmertandClaude Sonnet 5.5 committed 2026-10-21 15:52:05 -04:00
1 parent d7808a3925
commit 20317b14c9
7 files changed
+147 -12

No files matched your search

+7 -1
View File
@@ -24,11 +24,15 @@ th{font-size:12px;color:var(--mute);font-weight:600}td.num{text-align:right;font
.row{display:flex;gap:10px;align-items:center;flex-wrap:wrap}.spacer{flex:1}.mute{color:var(--mute)}code{background:var(--none);padding:1px 5px;border-radius:4px}
.legend span{margin-right:14px;font-size:12px;color:var(--mute)}
#help{display:none;margin-top:10px}
.tabs{position:sticky;top:0;z-index:5;display:flex;gap:4px;margin:0 0 16px;padding:10px 0;background:var(--bg)}
.tabs a{flex:1;max-width:170px;text-align:center;padding:8px 14px;border:1px solid var(--line);border-radius:8px;background:var(--card);color:var(--mute);font-weight:600;font-size:14px;text-decoration:none}
.tabs a:hover{color:var(--ink)}.tabs a.on{background:var(--accent);border-color:var(--accent);color:#fff}
</style>
</head>
<body>
<main>
<div class="row"><h1 style="margin:0">Statement Loader</h1><div class="spacer"></div><a href="/budget" style="color:var(--accent);font-weight:600;text-decoration:none;margin-right:14px">Budget</a><a href="/dashboard" style="color:var(--accent);font-weight:600;text-decoration:none">Dashboard →</a></div>
<nav class="tabs"><a href="/" class="on" aria-current="page">Statements</a><a href="/budget">Budget</a><a href="/dashboard">Dashboard</a></nav>
<div class="row"><h1 style="margin:0">Statement Loader</h1></div>
<div class="sub">Runs only on this Mac. Drop in statements, check what’s covered, then add the new transactions to <b>Bills_Tracker.xlsx</b>. A backup is saved first, every time.</div>
<div id="alerts"></div>
@@ -77,6 +81,8 @@ async function refresh(msg){
if(s.setup){$("#catcard").style.display="none";$("#coverage").innerHTML="";$("#preview").innerHTML="";$("#import").disabled=true;
$("#summary").innerHTML="";alertBox("warn",`<b>First-time setup:</b> <code>Bills_Tracker.xlsx</code> isn’t in the data folder (<code>${esc(s.data_dir)}</code>). Drop your existing one into the box above, or <button id="blank" style="margin-left:6px">Create a blank workbook</button>`+(s.rules?"":" Also add <code>loader_rules.json</code> (see loader_rules.example.json: your name, so transfers between your own accounts aren’t counted as spending)."));
const b=$("#blank");if(b)b.onclick=async()=>{try{const j=await post("/api/create_blank","");await refresh(esc(j.message))}catch(e){alertBox("bad",esc(e.message))}};return}
if(s.archivable>0)alertBox("good",`${s.archivable} statement file(s) are already in the workbook. <button id="filebtn" style="margin-left:6px">File them into Statements/year/month</button>`);
const fb=$("#filebtn");if(fb)fb.onclick=async()=>{try{const j=await post("/api/archive","");await refresh(esc(j.message))}catch(e){alertBox("bad",esc(e.message))}};
s.bad.forEach(b=>alertBox("bad",`<b>${esc(b.file)}</b>: the transactions I read add up to ${fmt(b.parsed)} but the statement says ${fmt(b.stated)}. It will <b>not</b> be imported until that matches.`));
s.skipped.forEach(b=>alertBox("warn",`<b>${esc(b.file)}</b>: ${esc(b.why)}`));
s.duplicates.forEach(b=>alertBox("warn",`<b>${esc(b.file)}</b> is a duplicate of ${esc(b.same_as)}; counted once.`));