mirror of
https://github.com/kbenestad/reimburse.git
synced 2026-06-18 08:04:31 +00:00
Warn when expense date falls outside the report period
When a user enters a date outside the selected period, a modal warning appears explaining they can continue but the date will be flagged. The date input gets an amber border/background as a persistent visual cue. The PDF marks out-of-period dates in orange with a trailing (!) marker. https://claude.ai/code/session_01MbwfxnjLA9KdFTrfzB55HM
This commit is contained in:
parent
4cad8ed292
commit
eeed56ca89
1 changed files with 37 additions and 3 deletions
|
|
@ -29,6 +29,7 @@ input:focus, select:focus, textarea:focus { outline: none; border-color: var(--a
|
|||
input[readonly] { background: #f0f1f3; color: var(--muted); }
|
||||
textarea { resize: vertical; min-height: 48px; width: 100%; }
|
||||
.input-err { border-color: var(--err) !important; }
|
||||
.input-warn { border-color: #e65100 !important; background: #fff8f0 !important; }
|
||||
|
||||
/* Divider */
|
||||
.divider { border: none; border-top: 2px solid var(--accent); margin: 20px 0; }
|
||||
|
|
@ -130,7 +131,29 @@ function defaultPeriod() {
|
|||
return { from: fmt(new Date(y, m, 1)), to: fmt(new Date(y, m + 1, 0)) };
|
||||
}
|
||||
|
||||
// ========== DATE FORMATTING ==========
|
||||
// ========== DATE HELPERS ==========
|
||||
function isDateInPeriod(date) {
|
||||
if (!date || !state.periodFrom || !state.periodTo) return true;
|
||||
return date >= state.periodFrom && date <= state.periodTo;
|
||||
}
|
||||
|
||||
function showWarningModal(msg) {
|
||||
return new Promise(resolve => {
|
||||
const overlay = el('div', {style:{position:'fixed',top:'0',right:'0',bottom:'0',left:'0',background:'rgba(0,0,0,.45)',zIndex:'9999',display:'flex',alignItems:'center',justifyContent:'center'}});
|
||||
const box = el('div', {style:{background:'#fff',borderRadius:'8px',padding:'24px 28px',maxWidth:'400px',width:'90%',boxShadow:'0 8px 32px rgba(0,0,0,.25)'}});
|
||||
const hdr = el('div', {style:{display:'flex',alignItems:'center',gap:'10px',marginBottom:'14px'}});
|
||||
hdr.append(el('span', {style:{fontSize:'20px',color:'#e65100'}}, '⚠'), el('strong', {style:{fontSize:'15px',color:'#e65100'}}, 'Warning'));
|
||||
const body = el('p', {style:{fontSize:'13px',lineHeight:'1.6',color:'var(--text)',marginBottom:'20px'}}, msg);
|
||||
const footer = el('div', {style:{display:'flex',justifyContent:'flex-end'}});
|
||||
const okBtn = el('button', {className:'btn btn-gen', style:{width:'auto',padding:'8px 28px',marginTop:'0'}}, 'OK');
|
||||
okBtn.addEventListener('click', () => { overlay.remove(); resolve(); });
|
||||
footer.appendChild(okBtn);
|
||||
box.append(hdr, body, footer);
|
||||
overlay.appendChild(box);
|
||||
document.body.appendChild(overlay);
|
||||
okBtn.focus();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// ========== CONFIG ==========
|
||||
|
|
@ -346,7 +369,16 @@ function renderLine(ln, item) {
|
|||
|
||||
// Row 1: Date, Vendor, Currency, FX Rate
|
||||
const dateIn = el('input', {type:'date', value: ln.date, style:{width:'150px'}});
|
||||
dateIn.addEventListener('change', () => { ln.date = dateIn.value; });
|
||||
if (ln.date && !isDateInPeriod(ln.date)) dateIn.classList.add('input-warn');
|
||||
dateIn.addEventListener('change', async () => {
|
||||
ln.date = dateIn.value;
|
||||
if (ln.date && !isDateInPeriod(ln.date)) {
|
||||
dateIn.classList.add('input-warn');
|
||||
await showWarningModal('The date of the expense is not within the period you have chosen at the top of the form. You can continue with this date, but it will be flagged on the form.');
|
||||
} else {
|
||||
dateIn.classList.remove('input-warn');
|
||||
}
|
||||
});
|
||||
|
||||
const vendIn = el('input', {type:'text', value: ln.vendor, placeholder:'Vendor name'});
|
||||
vendIn.addEventListener('input', () => { ln.vendor = vendIn.value; });
|
||||
|
|
@ -744,7 +776,9 @@ async function generatePDF() {
|
|||
pg.drawText('FX rate', {x:M.left+c4, y, size:szSm-1, font:fontBold, color:gray});
|
||||
y -= lh;
|
||||
// Row 1 values
|
||||
pg.drawText(ln.date || '–', {x:M.left+c1, y, size:sz, font:fontBody, color:black});
|
||||
const dateInPeriod = isDateInPeriod(ln.date);
|
||||
const dateColor = dateInPeriod ? black : rgb(0.9, 0.33, 0);
|
||||
pg.drawText((ln.date || '–') + (dateInPeriod ? '' : ' (!)'), {x:M.left+c1, y, size:sz, font:fontBody, color:dateColor});
|
||||
pg.drawText(truncate(ln.vendor, fontBody, sz, (c3-c2)-8), {x:M.left+c2, y, size:sz, font:fontBody, color:black});
|
||||
pg.drawText(ln.currency, {x:M.left+c3, y, size:sz, font:fontBody, color:black});
|
||||
const fxStr = ln.currency === baseCur ? '–' : parseFloat(ln.fxRate).toFixed(5);
|
||||
|
|
|
|||
Loading…
Reference in a new issue