revert: compact tracker mode + wider layout, keep S badge + remaining/Done header (batch 0.33.8.7)

- Removed hasBoth, compact prop, 2xl:min-w-[700px], 2xl:hidden Last Month,
  narrowed columns — back to original single-column tracker layout
- Removed 2xl:max-w-[2000px] from Layout/Sidebar/AdminShell/footer/nav
- Kept S badge in all 4 locations and bucket remaining/Done header
- Added mkdocs/ to .gitignore
- Bump v0.33.8.6 -> v0.33.8.7
This commit is contained in:
null 2026-05-29 21:16:13 -05:00
parent 0b58f7961f
commit 6b0c86b73c
7 changed files with 36 additions and 20 deletions

3
.gitignore vendored
View File

@ -21,3 +21,6 @@ backups/
simplefin-bank-sync-issue.md simplefin-bank-sync-issue.md
project-wide-data-input-and-sync-issue.md project-wide-data-input-and-sync-issue.md
docs/SIMPLEFIN_CONSUMER_GUARDRAILS.md docs/SIMPLEFIN_CONSUMER_GUARDRAILS.md
# MkDocs docs site (auto-generated, not part of app source)
mkdocs/

View File

@ -1,5 +1,20 @@
# Bill Tracker — Changelog # Bill Tracker — Changelog
## v0.33.8.7
### 🛠 Reverted
- **Compact tracker mode** — Removed `hasBoth` side-by-side buckets, `compact` prop from Row/Bucket, `2xl:min-w-[700px]` table override, `2xl:hidden` on Last Month, and narrower Notes/Actions/Due column widths. Restored original single-column layout with `min-w-[1120px]`, Due 10%, Actions 10%, Notes 23%.
- **Wider max-width at 2xl+** — Removed `2xl:max-w-[2000px]` from Layout, Sidebar, AdminShell, footer, mobile nav. All back to `max-w-[1500px]`.
### Kept
- **"S" badge** — Subscription badge shortened to "S" in all four locations.
- **Bucket remaining/Done header** — Per-bucket remaining balance and Done label.
- **MkDocs directory** added to `.gitignore`.
---
## v0.33.8.6 ## v0.33.8.6
### 🎨 Design ### 🎨 Design

View File

@ -83,7 +83,7 @@ function AdminShell({ children }) {
return ( return (
<div className="min-h-screen bg-[radial-gradient(circle_at_top_left,oklch(var(--primary)/0.10),transparent_34rem),linear-gradient(180deg,oklch(var(--background)),oklch(var(--muted)/0.28))] text-foreground"> <div className="min-h-screen bg-[radial-gradient(circle_at_top_left,oklch(var(--primary)/0.10),transparent_34rem),linear-gradient(180deg,oklch(var(--background)),oklch(var(--muted)/0.28))] text-foreground">
<AppNavigation adminMode /> <AppNavigation adminMode />
<main className="mx-auto w-full max-w-[1500px] 2xl:max-w-[2000px] px-4 py-6 sm:px-6 lg:px-8 lg:py-8"> <main className="mx-auto w-full max-w-[1500px] px-4 py-6 sm:px-6 lg:px-8 lg:py-8">
{children} {children}
</main> </main>
</div> </div>

View File

@ -31,13 +31,13 @@ export default function Layout({ mainContentId }) {
<AppNavigation mainContentId={mainContentId} /> <AppNavigation mainContentId={mainContentId} />
<main className="w-full"> <main className="w-full">
<div className="mx-auto w-full max-w-[1500px] 2xl:max-w-[2000px] px-4 py-6 sm:px-6 lg:px-8 lg:py-8" <div className="mx-auto w-full max-w-[1500px] px-4 py-6 sm:px-6 lg:px-8 lg:py-8"
id={mainContentId} id={mainContentId}
> >
<Outlet /> <Outlet />
</div> </div>
</main> </main>
<footer className="mx-auto flex w-full max-w-[1500px] 2xl:max-w-[2000px] flex-wrap items-center justify-center gap-x-4 gap-y-2 px-4 pb-6 text-xs text-muted-foreground sm:px-6 lg:px-8" <footer className="mx-auto flex w-full max-w-[1500px] flex-wrap items-center justify-center gap-x-4 gap-y-2 px-4 pb-6 text-xs text-muted-foreground sm:px-6 lg:px-8"
aria-label="Footer" aria-label="Footer"
> >
<Link to="/about" className="underline-offset-4 hover:text-foreground hover:underline">About</Link> <Link to="/about" className="underline-offset-4 hover:text-foreground hover:underline">About</Link>

View File

@ -172,7 +172,7 @@ export default function Sidebar({ adminMode = false }) {
return ( return (
<header className="sticky top-0 z-40 border-b border-border/80 bg-card/95 shadow-sm shadow-foreground/10 backdrop-blur-md supports-[backdrop-filter]:bg-card/90"> <header className="sticky top-0 z-40 border-b border-border/80 bg-card/95 shadow-sm shadow-foreground/10 backdrop-blur-md supports-[backdrop-filter]:bg-card/90">
<div className="mx-auto flex h-16 w-full max-w-[1500px] 2xl:max-w-[2000px] items-center gap-4 px-4 sm:px-6 lg:px-8"> <div className="mx-auto flex h-16 w-full max-w-[1500px] items-center gap-4 px-4 sm:px-6 lg:px-8">
<BrandBlock adminMode={adminMode} /> <BrandBlock adminMode={adminMode} />
<nav className="hidden items-center gap-1 lg:flex"> <nav className="hidden items-center gap-1 lg:flex">
@ -216,7 +216,7 @@ export default function Sidebar({ adminMode = false }) {
{mobileOpen && ( {mobileOpen && (
<div className="max-h-[70vh] overflow-y-auto border-t border-border/70 bg-card/95 px-4 py-3 shadow-lg shadow-foreground/10 lg:hidden"> <div className="max-h-[70vh] overflow-y-auto border-t border-border/70 bg-card/95 px-4 py-3 shadow-lg shadow-foreground/10 lg:hidden">
<nav className="mx-auto grid max-w-[1500px] 2xl:max-w-[2000px] gap-1"> <nav className="mx-auto grid max-w-[1500px] gap-1">
{!adminMode && trackerItems.map(item => ( {!adminMode && trackerItems.map(item => (
<NavPill key={item.to} item={item} onNavigate={() => setMobileOpen(false)} /> <NavPill key={item.to} item={item} onNavigate={() => setMobileOpen(false)} />
))} ))}

View File

@ -789,7 +789,7 @@ function NotesCell({ row, refresh }) {
} }
// Table row // Table row
function Row({ row, year, month, refresh, index, onEditBill, compact = false }) { function Row({ row, year, month, refresh, index, onEditBill }) {
const amountRef = useRef(null); const amountRef = useRef(null);
const [editPayment, setEditPayment] = useState(null); const [editPayment, setEditPayment] = useState(null);
const [paymentLedgerOpen, setPaymentLedgerOpen] = useState(false); const [paymentLedgerOpen, setPaymentLedgerOpen] = useState(false);
@ -1155,7 +1155,7 @@ function Row({ row, year, month, refresh, index, onEditBill, compact = false })
</TableCell> </TableCell>
{/* Previous month paid */} {/* Previous month paid */}
<TableCell className={cn('tracker-number w-[10%] py-3 text-right text-[13px] font-medium text-muted-foreground/80', compact && '2xl:hidden')}> <TableCell className="tracker-number w-[10%] py-3 text-right text-[13px] font-medium text-muted-foreground/80">
{row.previous_month_paid > 0 ? fmt(row.previous_month_paid) : '—'} {row.previous_month_paid > 0 ? fmt(row.previous_month_paid) : '—'}
</TableCell> </TableCell>
@ -1252,7 +1252,7 @@ function Row({ row, year, month, refresh, index, onEditBill, compact = false })
</TableCell> </TableCell>
{/* Notes cell (monthly state notes) */} {/* Notes cell (monthly state notes) */}
<TableCell className={cn(compact ? 'w-[16%]' : 'w-[23%]', 'py-3 border-l border-border pl-4')}> <TableCell className="w-[23%] py-3 border-l border-border pl-4">
<NotesCell row={{ ...row, year, month }} refresh={refresh} /> <NotesCell row={{ ...row, year, month }} refresh={refresh} />
</TableCell> </TableCell>
</TableRow> </TableRow>
@ -1621,7 +1621,7 @@ function MobileTrackerRow({ row, year, month, refresh, index, onEditBill }) {
} }
// Bucket // Bucket
function Bucket({ label, rows, year, month, refresh, onEditBill, loading, compact = false }) { function Bucket({ label, rows, year, month, refresh, onEditBill, loading }) {
// Use actual_amount (if set) as the per-row threshold; exclude skipped rows from totals // Use actual_amount (if set) as the per-row threshold; exclude skipped rows from totals
const activeRows = rows.filter(r => !r.is_skipped); const activeRows = rows.filter(r => !r.is_skipped);
const totalThreshold = activeRows.reduce((s, r) => s + (r.actual_amount ?? r.expected_amount ?? 0), 0); const totalThreshold = activeRows.reduce((s, r) => s + (r.actual_amount ?? r.expected_amount ?? 0), 0);
@ -1732,18 +1732,18 @@ function Bucket({ label, rows, year, month, refresh, onEditBill, loading, compac
<div className="hidden lg:block" aria-busy={loading ? 'true' : 'false'}> <div className="hidden lg:block" aria-busy={loading ? 'true' : 'false'}>
<div className="overflow-x-auto"> <div className="overflow-x-auto">
<Table className={cn('min-w-[1120px]', compact && '2xl:min-w-[700px]')}> <Table className="min-w-[1120px]">
<TableHeader> <TableHeader>
<TableRow className="border-border/80 bg-background/30 hover:bg-background/30"> <TableRow className="border-border/80 bg-background/30 hover:bg-background/30">
<TableHead className="w-[18%] py-2.5 text-[10px] font-semibold uppercase tracking-widest text-muted-foreground/90">Bill</TableHead> <TableHead className="w-[18%] py-2.5 text-[10px] font-semibold uppercase tracking-widest text-muted-foreground/90">Bill</TableHead>
<TableHead className="w-[9%] py-2.5 text-[10px] font-semibold uppercase tracking-widest text-muted-foreground/90">Due</TableHead> <TableHead className="w-[10%] py-2.5 text-[10px] font-semibold uppercase tracking-widest text-muted-foreground/90">Due</TableHead>
<TableHead className="w-[10%] py-2.5 text-[10px] font-semibold uppercase tracking-widest text-muted-foreground/90 text-right">Expected</TableHead> <TableHead className="w-[10%] py-2.5 text-[10px] font-semibold uppercase tracking-widest text-muted-foreground/90 text-right">Expected</TableHead>
<TableHead className={cn('w-[10%] py-2.5 text-[10px] font-semibold uppercase tracking-widest text-muted-foreground/80 text-right', compact && '2xl:hidden')}>Last Month</TableHead> <TableHead className="w-[10%] py-2.5 text-[10px] font-semibold uppercase tracking-widest text-muted-foreground/80 text-right">Last Month</TableHead>
<TableHead className="w-[10%] py-2.5 text-[10px] font-semibold uppercase tracking-widest text-muted-foreground/90 text-right">Paid</TableHead> <TableHead className="w-[10%] py-2.5 text-[10px] font-semibold uppercase tracking-widest text-muted-foreground/90 text-right">Paid</TableHead>
<TableHead className="w-[10%] py-2.5 text-[10px] font-semibold uppercase tracking-widest text-muted-foreground/90">Paid Date</TableHead> <TableHead className="w-[10%] py-2.5 text-[10px] font-semibold uppercase tracking-widest text-muted-foreground/90">Paid Date</TableHead>
<TableHead className="w-[9%] py-2.5 text-[10px] font-semibold uppercase tracking-widest text-muted-foreground/90">Status</TableHead> <TableHead className="w-[9%] py-2.5 text-[10px] font-semibold uppercase tracking-widest text-muted-foreground/90">Status</TableHead>
<TableHead className="w-[8%] py-2.5" /> <TableHead className="w-[10%] py-2.5" />
<TableHead className={cn('py-2.5 text-[10px] font-semibold uppercase tracking-widest text-muted-foreground/90 border-l border-border/80 pl-4', compact ? 'w-[16%]' : 'w-[23%]')}> <TableHead className="w-[23%] py-2.5 text-[10px] font-semibold uppercase tracking-widest text-muted-foreground/90 border-l border-border/80 pl-4">
Notes Notes
</TableHead> </TableHead>
</TableRow> </TableRow>
@ -1791,7 +1791,6 @@ function Bucket({ label, rows, year, month, refresh, onEditBill, loading, compac
refresh={refresh} refresh={refresh}
index={i} index={i}
onEditBill={onEditBill} onEditBill={onEditBill}
compact={compact}
/> />
)) ))
)} )}
@ -1928,7 +1927,6 @@ export default function TrackerPage() {
}, [filters, rows, search]); }, [filters, rows, search]);
const first = filteredRows.filter(r => r.bucket === '1st'); const first = filteredRows.filter(r => r.bucket === '1st');
const second = filteredRows.filter(r => r.bucket === '15th'); const second = filteredRows.filter(r => r.bucket === '15th');
const hasBoth = first.length > 0 && second.length > 0;
return ( return (
<div className="space-y-5"> <div className="space-y-5">
@ -2122,9 +2120,9 @@ export default function TrackerPage() {
</div> </div>
)} )}
{!isError && (first.length > 0 || second.length > 0) && ( {!isError && (first.length > 0 || second.length > 0) && (
<div className={cn('space-y-5', hasBoth && '2xl:space-y-0 2xl:grid 2xl:grid-cols-2 2xl:gap-5')}> <div className="space-y-5">
{first.length > 0 && <Bucket label="1st 14th" rows={first} year={year} month={month} refresh={refetch} onEditBill={handleOpenEditBill} loading={loading} compact={hasBoth} />} {first.length > 0 && <Bucket label="1st 14th" rows={first} year={year} month={month} refresh={refetch} onEditBill={handleOpenEditBill} loading={loading} />}
{second.length > 0 && <Bucket label="15th 31st" rows={second} year={year} month={month} refresh={refetch} onEditBill={handleOpenEditBill} loading={loading} compact={hasBoth} />} {second.length > 0 && <Bucket label="15th 31st" rows={second} year={year} month={month} refresh={refetch} onEditBill={handleOpenEditBill} loading={loading} />}
</div> </div>
)} )}

View File

@ -1,6 +1,6 @@
{ {
"name": "bill-tracker", "name": "bill-tracker",
"version": "0.33.8.6", "version": "0.33.8.7",
"description": "Monthly bill tracking system", "description": "Monthly bill tracking system",
"main": "server.js", "main": "server.js",
"scripts": { "scripts": {