diff --git a/public/index.html b/public/index.html
index 78188f9..d694f8d 100644
--- a/public/index.html
+++ b/public/index.html
@@ -18,10 +18,13 @@
-
+
+
+ –
+
diff --git a/public/js/app.js b/public/js/app.js
index a9cdc72..912c2ef 100644
--- a/public/js/app.js
+++ b/public/js/app.js
@@ -3,7 +3,10 @@
const state = {
checks: [],
account: null,
- filter: '0', // '' = all, '0' = unprinted, '1' = printed
+ filterStatus: '', // '' = all, '0' = unprinted, '1' = printed
+ filterPayee: '',
+ filterDateFrom: '',
+ filterDateTo: '',
sortCol: 'check_no',
sortDir: 'desc',
selected: new Set(),
@@ -37,9 +40,7 @@ async function loadChecks() {
const tbody = document.getElementById('checks-tbody');
tbody.innerHTML = '
| Loading… |
';
try {
- const params = new URLSearchParams();
- if (state.filter !== '') params.set('printed', state.filter);
- state.checks = await apiFetch('GET', `/api/checks?${params}`);
+ state.checks = await apiFetch('GET', '/api/checks');
state.selected.clear();
renderTable();
refreshPdfButton();
@@ -58,7 +59,7 @@ function renderHeader() {
}
function renderTable() {
- const checks = sortedChecks();
+ const checks = filteredAndSortedChecks();
const tbody = document.getElementById('checks-tbody');
if (checks.length === 0) {
@@ -81,9 +82,6 @@ function renderTable() {
tbody.querySelectorAll('.btn-delete').forEach(btn => {
btn.addEventListener('click', () => deleteCheck(parseInt(btn.dataset.id, 10)));
});
- tbody.querySelectorAll('.btn-reprint').forEach(btn => {
- btn.addEventListener('click', () => reprintCheck(parseInt(btn.dataset.id, 10)));
- });
}
function renderRow(c) {
@@ -100,18 +98,14 @@ function renderRow(c) {
})
: '—';
- const checkbox = printed
- ? '
| '
- : `
| `;
+ const checkbox = `
| `;
const statusBadge = printed
? '
Printed'
: '
Unprinted';
- const actions = printed
- ? `
`
- : `
` +
- `
`;
+ const actions = `
` +
+ `
`;
return `
${checkbox}
@@ -125,10 +119,24 @@ function renderRow(c) {
`;
}
-function sortedChecks() {
+function filteredAndSortedChecks() {
+ const payee = state.filterPayee.toLowerCase();
+ const from = state.filterDateFrom;
+ const to = state.filterDateTo;
+ const status = state.filterStatus;
+
+ let list = state.checks.filter(c => {
+ if (payee && !c.payee.toLowerCase().includes(payee)) return false;
+ if (from && c.check_date < from) return false;
+ if (to && c.check_date > to) return false;
+ if (status === '0' && c.printed) return false;
+ if (status === '1' && !c.printed) return false;
+ return true;
+ });
+
const col = state.sortCol;
const dir = state.sortDir === 'asc' ? 1 : -1;
- return [...state.checks].sort((a, b) => {
+ return list.sort((a, b) => {
let av = a[col];
let bv = b[col];
if (col === 'amount') { av = parseFloat(av); bv = parseFloat(bv); }
@@ -318,26 +326,6 @@ async function generatePdf() {
}
}
-async function reprintCheck(id) {
- const check = state.checks.find(c => c.id === id);
- if (!check) return;
- if (!confirm(`Reprint check #${check.check_no} to "${check.payee}"?\n(Will not re-mark as printed)`)) return;
- try {
- const res = await fetch('/api/pdf?mark_printed=false', {
- method: 'POST',
- headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({ checkIds: [id] }),
- });
- if (!res.ok) {
- const err = await res.json().catch(() => ({ error: res.statusText }));
- throw new Error(err.error || res.statusText);
- }
- const blob = await res.blob();
- window.open(URL.createObjectURL(blob), '_blank');
- } catch (err) {
- alert(`Reprint error: ${err.message}`);
- }
-}
// ── Setup wizard ─────────────────────────────────────────────────────────────
@@ -530,10 +518,22 @@ function init() {
});
});
- // Filter dropdown
+ // Filters (client-side; just re-render)
+ document.getElementById('filter-payee').addEventListener('input', e => {
+ state.filterPayee = e.target.value;
+ renderTable();
+ });
+ document.getElementById('filter-date-from').addEventListener('change', e => {
+ state.filterDateFrom = e.target.value;
+ renderTable();
+ });
+ document.getElementById('filter-date-to').addEventListener('change', e => {
+ state.filterDateTo = e.target.value;
+ renderTable();
+ });
document.getElementById('filter-status').addEventListener('change', e => {
- state.filter = e.target.value;
- loadChecks();
+ state.filterStatus = e.target.value;
+ renderTable();
});
// New check
diff --git a/src/routes/checks.js b/src/routes/checks.js
index b98cf1f..865ad05 100644
--- a/src/routes/checks.js
+++ b/src/routes/checks.js
@@ -86,10 +86,6 @@ router.put('/:id', (req, res) => {
const check = db.prepare('SELECT * FROM checks WHERE id = ?').get(req.params.id);
if (!check) return res.status(404).json({ error: 'Check not found' });
- if (check.printed) {
- return res.status(409).json({ error: 'Cannot edit a check that has been printed.' });
- }
-
const { payee, amount, check_date, memo, note1, note2,
payee_address1, payee_address2, payee_address3, payee_address4 } = req.body;
@@ -120,10 +116,6 @@ router.delete('/:id', (req, res) => {
const check = db.prepare('SELECT * FROM checks WHERE id = ?').get(req.params.id);
if (!check) return res.status(404).json({ error: 'Check not found' });
- if (check.printed) {
- return res.status(409).json({ error: 'Cannot delete a check that has been printed.' });
- }
-
db.prepare('DELETE FROM checks WHERE id = ?').run(req.params.id);
res.status(204).send();
});