1<!DOCTYPE html>
2<html lang="en" data-theme="dark">
3<head>
4 <meta charset="UTF-8">
5 <meta name="viewport" content="width=device-width, initial-scale=1.0">
6 <title>Ledger — Personal Finance</title>
7 <link rel="stylesheet" href="style.css">
8</head>
9<body>
10 <div class="app">
11 <header class="app-header">
12 <div class="brand">
13 <span class="brand-mark" aria-hidden="true"></span>
14 <h1>Ledger</h1>
15 </div>
16 <div class="header-actions">
17 <button id="btn-import" class="btn-ghost" title="Import CSV (i)">Import CSV</button>
18 <button id="btn-export" class="btn-ghost" title="Export CSV (e)">Export CSV</button>
19 <button id="btn-new" class="btn-primary" title="New transaction (n)">+ New transaction</button>
20 <button id="btn-help" class="btn-ghost btn-icon" title="Keyboard shortcuts (?)" aria-label="Keyboard shortcuts">?</button>
21 </div>
22 </header>
23
24 <section class="stat-row" aria-label="This month at a glance">
25 <div class="stat-tile stat-hero">
26 <span class="stat-label">Spent in <span id="stat-month-label">this month</span></span>
27 <span class="stat-value" id="stat-spent">$0.00</span>
28 </div>
29 <div class="stat-tile">
30 <span class="stat-label">Income</span>
31 <span class="stat-value stat-value-sm" id="stat-income">$0.00</span>
32 </div>
33 <div class="stat-tile">
34 <span class="stat-label">Net</span>
35 <span class="stat-value stat-value-sm" id="stat-net">$0.00</span>
36 </div>
37 </section>
38
39 <section class="grid-2">
40 <div class="card">
41 <div class="card-head">
42 <h2>Spending over time</h2>
43 <span class="card-sub">Monthly spend, last 12 months</span>
44 </div>
45 <div class="chart-wrap">
46 <canvas id="spending-chart" role="img" aria-label="Line chart of monthly spending over the last 12 months"></canvas>
47 <div id="chart-tooltip" class="chart-tooltip" hidden></div>
48 </div>
49 </div>
50
51 <div class="card">
52 <div class="card-head">
53 <h2>Budgets</h2>
54 <div class="month-nav">
55 <button id="budget-prev" class="btn-ghost btn-icon" title="Previous month ([)" aria-label="Previous month">‹</button>
56 <span id="budget-month-label" class="month-nav-label">Month</span>
57 <button id="budget-next" class="btn-ghost btn-icon" title="Next month (])" aria-label="Next month">›</button>
58 </div>
59 </div>
60 <div id="budget-list" class="budget-list"></div>
61 <p class="card-foot">Click a budget to change its monthly limit.</p>
62 </div>
63 </section>
64
65 <section class="card">
66 <div class="card-head">
67 <h2>Transactions</h2>
68 <span id="tx-count" class="card-sub">0 transactions</span>
69 </div>
70 <div class="filter-row">
71 <input type="search" id="filter-search" placeholder="Search descriptions… ( / )" aria-label="Search transactions">
72 <select id="filter-category" aria-label="Filter by category"></select>
73 <select id="filter-month" aria-label="Filter by month"></select>
74 </div>
75 <div class="table-wrap">
76 <table class="tx-table">
77 <thead>
78 <tr>
79 <th scope="col" class="col-date">Date</th>
80 <th scope="col">Description</th>
81 <th scope="col">Category</th>
82 <th scope="col" class="col-amount">Amount</th>
83 <th scope="col" class="col-actions"><span class="visually-hidden">Actions</span></th>
84 </tr>
85 </thead>
86 <tbody id="tx-body"></tbody>
87 </table>
88 </div>
89 </section>
90
91 <footer class="app-footer">
92 <span><kbd>n</kbd> new · <kbd>/</kbd> search · <kbd>e</kbd> export · <kbd>i</kbd> import · <kbd>[</kbd><kbd>]</kbd> budget month · <kbd>?</kbd> all shortcuts</span>
93 <a href="tests.html">Self-tests</a>
94 </footer>
95 </div>
96
97
98 <div id="form-panel" class="overlay" hidden>
99 <form id="tx-form" class="panel-card" autocomplete="off">
100 <h2 id="form-title">New transaction</h2>
101 <p id="form-error" class="form-error" hidden></p>
102 <label>
103 <span>Date</span>
104 <input type="date" id="f-date" required>
105 </label>
106 <label>
107 <span>Description</span>
108 <input type="text" id="f-desc" placeholder="e.g. Fresh Mart" required>
109 </label>
110 <label>
111 <span>Category</span>
112 <select id="f-category"></select>
113 </label>
114 <label>
115 <span>Amount</span>
116 <input type="number" id="f-amount" min="0.01" step="0.01" placeholder="0.00" required>
117 <small>Enter a positive amount — the “Income” category counts as money in; everything else counts as spending.</small>
118 </label>
119 <div class="panel-actions">
120 <button type="button" id="btn-cancel" class="btn-ghost">Cancel</button>
121 <button type="submit" class="btn-primary">Save</button>
122 </div>
123 </form>
124 </div>
125
126
127 <div id="help-overlay" class="overlay" hidden>
128 <div class="panel-card">
129 <h2>Keyboard shortcuts</h2>
130 <dl class="shortcut-list">
131 <div><dt><kbd>n</kbd></dt><dd>New transaction</dd></div>
132 <div><dt><kbd>/</kbd></dt><dd>Focus search</dd></div>
133 <div><dt><kbd>e</kbd></dt><dd>Export CSV</dd></div>
134 <div><dt><kbd>i</kbd></dt><dd>Import CSV</dd></div>
135 <div><dt><kbd>[</kbd> / <kbd>]</kbd></dt><dd>Previous / next budget month</dd></div>
136 <div><dt><kbd>Esc</kbd></dt><dd>Close dialog / leave search</dd></div>
137 <div><dt><kbd>?</kbd></dt><dd>Toggle this help</dd></div>
138 </dl>
139 <div class="panel-actions">
140 <button id="btn-close-help" class="btn-primary">Close</button>
141 </div>
142 </div>
143 </div>
144
145 <div id="toast" class="toast" role="status" aria-live="polite"></div>
146 <input type="file" id="file-input" accept=".csv,text/csv" hidden>
147
148 <script src="data.js"></script>
149 <script src="charts.js"></script>
150 <script src="app.js"></script>
151</body>
152</html>
153
Discussion
1 comment on this trajectory. Recorded by @patrick-toulme.