From 4a0b755f376da3e7b172c7dbdf574f113e21f5c0 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 13 May 2026 10:07:54 +0000 Subject: [PATCH 1/3] Restore native date pickers; keep formatDate for PDF output only https://claude.ai/code/session_014uUwDBtG5y5FuWcy5zqVD1 --- index.html | 28 ++++++---------------------- 1 file changed, 6 insertions(+), 22 deletions(-) diff --git a/index.html b/index.html index eaa5dcd..cedbc0f 100644 --- a/index.html +++ b/index.html @@ -137,21 +137,6 @@ function formatDate(iso) { if (!y || !m || !d) return iso; return (CFG['date-format'] || 'YYYY-MM-DD').replace('YYYY', y).replace('MM', m).replace('DD', d); } -function parseDate(str) { - if (!str) return ''; - const fmt = CFG['date-format'] || 'YYYY-MM-DD'; - const sep = fmt.match(/[^YMD]/)?.[0] || '-'; - const parts = str.split(sep); - const fmtParts = fmt.split(sep); - let y = '', m = '', d = ''; - fmtParts.forEach((f, i) => { - if (f === 'YYYY') y = parts[i] || ''; - else if (f === 'MM') m = (parts[i] || '').padStart(2, '0'); - else if (f === 'DD') d = (parts[i] || '').padStart(2, '0'); - }); - if (!y || !m || !d) return ''; - return `${y}-${m}-${d}`; -} // ========== CONFIG ========== let CFG; @@ -264,11 +249,10 @@ function render() { const staffInput = el('input', {type:'text', value: state.staff, placeholder:'Full name'}); staffInput.addEventListener('input', () => { state.staff = staffInput.value; localStorage.setItem('reimb-staff', staffInput.value); }); - const dateFmt = CFG['date-format'] || 'YYYY-MM-DD'; - const fromInput = el('input', {type:'text', value: formatDate(state.periodFrom), placeholder: dateFmt, style:{width:'120px'}}); - fromInput.addEventListener('change', () => { state.periodFrom = parseDate(fromInput.value); }); - const toInput = el('input', {type:'text', value: formatDate(state.periodTo), placeholder: dateFmt, style:{width:'120px'}}); - toInput.addEventListener('change', () => { state.periodTo = parseDate(toInput.value); }); + const fromInput = el('input', {type:'date', value: state.periodFrom}); + fromInput.addEventListener('change', () => { state.periodFrom = fromInput.value; }); + const toInput = el('input', {type:'date', value: state.periodTo}); + toInput.addEventListener('change', () => { state.periodTo = toInput.value; }); const baseCurDD = makeCDD(CFG.currencies || [], state.baseCurrency, code => { state.baseCurrency = code; @@ -364,8 +348,8 @@ function renderLine(ln, item) { const baseCur = state.baseCurrency; // Row 1: Date, Vendor, Currency, FX Rate - const dateIn = el('input', {type:'text', value: formatDate(ln.date), placeholder: CFG['date-format'] || 'YYYY-MM-DD', style:{width:'120px'}}); - dateIn.addEventListener('change', () => { ln.date = parseDate(dateIn.value); }); + const dateIn = el('input', {type:'date', value: ln.date, style:{width:'150px'}}); + dateIn.addEventListener('change', () => { ln.date = dateIn.value; }); const vendIn = el('input', {type:'text', value: ln.vendor, placeholder:'Vendor name'}); vendIn.addEventListener('input', () => { ln.vendor = vendIn.value; }); From ee2ee6df408981a91e152f540e3a4c645c51d7bc Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 13 May 2026 10:08:41 +0000 Subject: [PATCH 2/3] PDF dates always YYYY-MM-DD; remove formatDate and date-format config https://claude.ai/code/session_014uUwDBtG5y5FuWcy5zqVD1 --- config.yml | 4 ---- index.html | 13 ++++--------- 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/config.yml b/config.yml index a73cb62..c13ce97 100644 --- a/config.yml +++ b/config.yml @@ -28,10 +28,6 @@ footer: "Confidential" # Base currency (ISO code — must appear in currencies list) currency-base: USD -# Date display format (YYYY = year, MM = month, DD = day) -# Examples: DD/MM/YYYY | YYYY-MM-DD | MM/DD/YYYY | DD.MM.YYYY -date-format: DD/MM/YYYY - # Available currencies currencies: - code: USD diff --git a/index.html b/index.html index cedbc0f..51a3da9 100644 --- a/index.html +++ b/index.html @@ -131,12 +131,7 @@ function defaultPeriod() { } // ========== DATE FORMATTING ========== -function formatDate(iso) { - if (!iso) return ''; - const [y, m, d] = iso.split('-'); - if (!y || !m || !d) return iso; - return (CFG['date-format'] || 'YYYY-MM-DD').replace('YYYY', y).replace('MM', m).replace('DD', d); -} + // ========== CONFIG ========== let CFG; @@ -557,7 +552,7 @@ async function generatePDF() { function drawContHeader() { pg.drawText(state.staff, { x: M.left, y, size: sz, font: fontBold, color: black }); - const periodStr = `Period: ${formatDate(state.periodFrom)} to ${formatDate(state.periodTo)}`; + const periodStr = `Period: ${state.periodFrom} to ${state.periodTo}`; const pw = fontBody.widthOfTextAtSize(periodStr, sz); pg.drawText(periodStr, { x: M.left + W - pw, y, size: sz, font: fontBody, color: gray }); y -= lh + 2; @@ -598,7 +593,7 @@ async function generatePDF() { pg.drawText('Currency', {x:M.left+col3, y, size:szSm-1, font:fontBold, color:gray}); y -= lh; pg.drawText(state.staff, {x:M.left, y, size:sz, font:fontBody, color:black}); - pg.drawText(`${formatDate(state.periodFrom)} to ${formatDate(state.periodTo)}`, {x:M.left+col2, y, size:sz, font:fontBody, color:black}); + pg.drawText(`${state.periodFrom} to ${state.periodTo}`, {x:M.left+col2, y, size:sz, font:fontBody, color:black}); pg.drawText(baseCur, {x:M.left+col3, y, size:sz, font:fontBold, color:black}); y -= lh + 6; @@ -636,7 +631,7 @@ 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(formatDate(ln.date) || '–', {x:M.left+c1, y, size:sz, font:fontBody, color:black}); + pg.drawText(ln.date || '–', {x:M.left+c1, y, size:sz, font:fontBody, color:black}); 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); From 7bca92bc0b5eeb32112f7c6f67e6a24c58ffd87f Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 13 May 2026 10:09:34 +0000 Subject: [PATCH 3/3] Stretch base currency dropdown to fill form width Add grow class to base currency fgrp; add CSS rules so .cdd and its trigger button fill 100% width when inside a grow container. https://claude.ai/code/session_014uUwDBtG5y5FuWcy5zqVD1 --- index.html | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/index.html b/index.html index 51a3da9..65d505f 100644 --- a/index.html +++ b/index.html @@ -67,6 +67,8 @@ textarea { resize: vertical; min-height: 48px; width: 100%; } /* Custom currency dropdown */ .cdd { position: relative; display: inline-block; } +.fgrp.grow .cdd { display: block; width: 100%; } +.fgrp.grow .cdd-trigger { width: 100%; } .cdd-trigger { padding: 7px 10px; border: 1px solid var(--border); border-radius: 4px; background: #fff; cursor: pointer; font-size: 14px; font-family: inherit; text-align: left; min-width: 70px; } .cdd-trigger:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 2px rgba(26,58,92,.1); } .cdd-panel { display: none; position: absolute; top: calc(100% + 2px); left: 0; background: #fff; border: 1px solid var(--border); border-radius: 6px; box-shadow: 0 6px 20px rgba(0,0,0,.14); z-index: 100; min-width: 220px; max-height: 260px; overflow-y: auto; } @@ -263,7 +265,7 @@ function render() { el('div', {className:'fgrp grow'}, [el('label', null, 'Staff'), staffInput]), el('div', {className:'fgrp'}, [el('label', null, 'Period from'), fromInput]), el('div', {className:'fgrp'}, [el('label', null, 'to'), toInput]), - el('div', {className:'fgrp'}, [el('label', null, 'Base currency'), baseCurDD]), + el('div', {className:'fgrp grow'}, [el('label', null, 'Base currency'), baseCurDD]), ])); wrap.appendChild(el('hr', {className:'divider'}));