Implement reliability improvements across frontend
- api.js: add exponential backoff retry (3 attempts, 500/1000/2000ms) for GET requests on network errors and 5xx responses; mutating methods are not retried since they are not idempotent - api.js: add offline indicator — fixed pill banner appears at bottom of page when navigator goes offline, disappears when back online - style.css: add styles for offline banner and session expiry warning - auth.js: show amber warning banner below nav when session expires within 24 hours (with exact hours remaining); dismissible with X button - auth.js: fix password min-length client-side check from 6 to 10 to match the backend - log.js, flock.js, budget.js: disable submit button during async request and re-enable in finally block to prevent double-submits and make loading state visible - dashboard.js: fix chart date labels to use user's configured timezone instead of the browser's local timezone Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -231,12 +231,14 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
|
||||
feedForm.addEventListener('submit', async (e) => {
|
||||
e.preventDefault();
|
||||
const btn = feedForm.querySelector('[type=submit]');
|
||||
const data = {
|
||||
date: document.getElementById('date').value,
|
||||
bags: parseFloat(bagsInput.value),
|
||||
price_per_bag: parseFloat(priceInput.value),
|
||||
notes: document.getElementById('notes').value.trim() || null,
|
||||
};
|
||||
btn.disabled = true;
|
||||
try {
|
||||
await API.post('/api/feed', data);
|
||||
showMessage(msg, 'Feed purchase saved!');
|
||||
@@ -246,16 +248,20 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
loadBudget();
|
||||
} catch (err) {
|
||||
showMessage(msg, `Error: ${err.message}`, 'error');
|
||||
} finally {
|
||||
btn.disabled = false;
|
||||
}
|
||||
});
|
||||
|
||||
otherForm.addEventListener('submit', async (e) => {
|
||||
e.preventDefault();
|
||||
const btn = otherForm.querySelector('[type=submit]');
|
||||
const data = {
|
||||
date: document.getElementById('other-date').value,
|
||||
total: parseFloat(document.getElementById('other-total').value),
|
||||
notes: document.getElementById('other-notes').value.trim() || null,
|
||||
};
|
||||
btn.disabled = true;
|
||||
try {
|
||||
await API.post('/api/other', data);
|
||||
showMessage(msg, 'Purchase saved!');
|
||||
@@ -264,6 +270,8 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
loadBudget();
|
||||
} catch (err) {
|
||||
showMessage(msg, `Error: ${err.message}`, 'error');
|
||||
} finally {
|
||||
btn.disabled = false;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user