Swap Invoice details / Payment positions; bank fields only for Other

- New layout: Sender | Invoice details (top row), Charge to | Payment (bottom row)
- Bank account fields (#bank-section) are hidden by default and only revealed
  when "Other" is selected for charge-to; hidden again for predefined recipients
- gatherData() only collects bank fields when bank-section is visible
- Preview and PDF panels updated to match the new quadrant order

https://claude.ai/code/session_015iyCBgoTXNNqaErR287U1u
This commit is contained in:
Claude 2026-05-19 09:34:43 +00:00
parent 275d3a3b71
commit a63fcc8a42
No known key found for this signature in database

View file

@ -507,27 +507,23 @@ function buildForm() {
<input id="se" type="email" data-ls="se" autocomplete="email"></div>
</div>
<div class="card">
<div class="card-title" id="lbl-pay-sec">${t("payment")}</div>
<div class="pay-terms-row">
<label id="lbl-pterm">${t("payment-terms")}:</label>
<input id="pterm" type="number" min="0" value="7" oninput="calcPayBy()" data-ls="pterm">
<span id="lbl-days">${t("payment-days")}</span>
<div class="card-title" id="sec-invdet">${t("invoice-details-section")}</div>
<div class="fg"><label id="lbl-idate" for="idate">${t("invoice-date")}</label>
<input id="idate" type="date" value="${dateDef}"></div>
<div class="fg"><label id="lbl-icur" for="icur">${t("invoice-currency")}</label>
<select id="icur" data-ls="icur">${curOpts}</select></div>
<div class="fg"><label id="lbl-pcode" for="pcode">${t("project-code")}</label>
<select id="pcode">
<option value="">${t("select")}</option>
${pcOpts}
<option value="__other__">${t("other")}</option>
</select></div>
<div class="fg" id="pcode-other-wrap" style="display:none">
<label id="lbl-pcode-other" for="pcode-other">${t("project-code")} (${t("other")})</label>
<input id="pcode-other" type="text">
</div>
<div class="pay-by-row">
<label id="lbl-paybyl">${t("pay-by")}:</label>
<span id="paybydisp"></span>
</div>
<div class="fg"><label id="lbl-pacct">${t("account-holder")}</label>
<input id="pacct" type="text" data-ls="pacct"></div>
<div class="fg"><label id="lbl-piban">${t("account-no")}</label>
<input id="piban" type="text" data-ls="piban"></div>
<div class="fg"><label id="lbl-pbic">${t("bank-bic")}</label>
<input id="pbic" type="text" data-ls="pbic"></div>
<div class="fg"><label id="lbl-pbadr">${t("bank-address")}</label>
<input id="pbadr1" type="text" data-ls="pbadr1">
<input id="pbadr2" type="text" style="margin-top:6px" data-ls="pbadr2"></div>
<div class="fg"><label id="lbl-pref">${t("payment-ref")}</label>
<input id="pref" type="text" data-ls="pref"></div>
<div class="fg"><label id="lbl-ino" for="ino">${t("invoice-no")}</label>
<input id="ino" type="text" data-ls="ino"></div>
</div>
<div class="card">
<div class="card-title" style="display:flex;align-items:center;gap:8px;flex-wrap:wrap">
@ -562,23 +558,29 @@ function buildForm() {
</div>
</div>
<div class="card">
<div class="card-title" id="sec-invdet">${t("invoice-details-section")}</div>
<div class="fg"><label id="lbl-idate" for="idate">${t("invoice-date")}</label>
<input id="idate" type="date" value="${dateDef}"></div>
<div class="fg"><label id="lbl-icur" for="icur">${t("invoice-currency")}</label>
<select id="icur" data-ls="icur">${curOpts}</select></div>
<div class="fg"><label id="lbl-pcode" for="pcode">${t("project-code")}</label>
<select id="pcode">
<option value="">${t("select")}</option>
${pcOpts}
<option value="__other__">${t("other")}</option>
</select></div>
<div class="fg" id="pcode-other-wrap" style="display:none">
<label id="lbl-pcode-other" for="pcode-other">${t("project-code")} (${t("other")})</label>
<input id="pcode-other" type="text">
<div class="card-title" id="lbl-pay-sec">${t("payment")}</div>
<div class="pay-terms-row">
<label id="lbl-pterm">${t("payment-terms")}:</label>
<input id="pterm" type="number" min="0" value="7" oninput="calcPayBy()" data-ls="pterm">
<span id="lbl-days">${t("payment-days")}</span>
</div>
<div class="pay-by-row">
<label id="lbl-paybyl">${t("pay-by")}:</label>
<span id="paybydisp"></span>
</div>
<div id="bank-section" style="display:none">
<div class="fg"><label id="lbl-pacct">${t("account-holder")}</label>
<input id="pacct" type="text" data-ls="pacct"></div>
<div class="fg"><label id="lbl-piban">${t("account-no")}</label>
<input id="piban" type="text" data-ls="piban"></div>
<div class="fg"><label id="lbl-pbic">${t("bank-bic")}</label>
<input id="pbic" type="text" data-ls="pbic"></div>
<div class="fg"><label id="lbl-pbadr">${t("bank-address")}</label>
<input id="pbadr1" type="text" data-ls="pbadr1">
<input id="pbadr2" type="text" style="margin-top:6px" data-ls="pbadr2"></div>
<div class="fg"><label id="lbl-pref">${t("payment-ref")}</label>
<input id="pref" type="text" data-ls="pref"></div>
</div>
<div class="fg"><label id="lbl-ino" for="ino">${t("invoice-no")}</label>
<input id="ino" type="text" data-ls="ino"></div>
</div>
</div>
@ -645,6 +647,9 @@ function fillChargeTo(v) {
const f = (id, val) => { const el = document.getElementById(id); if (el) el.value = val ?? ""; };
const fields = document.getElementById("ct-fields");
const bsec = document.getElementById("bank-section");
if (bsec) bsec.style.display = v === "__other__" ? "" : "none";
if (v === "" || v === "__other__") {
if (v === "") ["ctn","ca1","ca2","ca3","ca4","cc","cph","cem","cvat","creg"].forEach(id => f(id, ""));
fields?.classList.remove("locked");
@ -1043,12 +1048,14 @@ function gatherData(renderLang) {
const pTerm = parseInt(document.getElementById("pterm")?.value) || 0;
const pPayBy = document.getElementById("paybydisp")?.textContent || "";
const pAcct = g("pacct");
const pIban = g("piban");
const pBic = g("pbic");
const pBadr1 = g("pbadr1");
const pBadr2 = g("pbadr2");
const pRef = g("pref");
const bsecEl = document.getElementById("bank-section");
const bankVis = bsecEl && bsecEl.style.display !== "none";
const pAcct = bankVis ? g("pacct") : "";
const pIban = bankVis ? g("piban") : "";
const pBic = bankVis ? g("pbic") : "";
const pBadr1 = bankVis ? g("pbadr1"): "";
const pBadr2 = bankVis ? g("pbadr2"): "";
const pRef = bankVis ? g("pref") : "";
const hasBank = !!(pAcct || pIban || pBic || pBadr1 || pRef);
const hidePaymentOut = cfg["hide-payment-info"] === true || cfg["hide-payment-info"] === "yes";
@ -1142,16 +1149,14 @@ function buildPreviewHTML() {
${sPh ? `<p>${h(td("sender-phone"))}: ${h(sPh)}</p>` : ""}
${sEm ? `<p>${h(td("sender-email"))}: ${h(sEm)}</p>` : ""}
</div>
<div class="d-tr d-pay-hdr">
<div class="ph-lbl">${h(td("payment"))}</div>
${pTerm > 0 ? `<div class="ph-terms">${h(td("payment-terms"))}: <strong>${pTerm}</strong> ${h(td("payment-days"))}${pPayBy ? ` &mdash; ${h(td("pay-by"))}: <strong>${h(pPayBy)}</strong>` : ""}</div>` : ""}
${showBank ? `<div class="ph-grid">
${pAcct ? `<span class="pl">${h(td("account-holder"))}</span><span class="pv">${h(pAcct)}</span>` : ""}
${pIban ? `<span class="pl">${h(td("account-no"))}</span><span class="pv">${h(pIban)}</span>` : ""}
${pBic ? `<span class="pl">${h(td("bank-bic"))}</span><span class="pv">${h(pBic)}</span>` : ""}
${pBadr1 || pBadr2 ? `<span class="pl">${h(td("bank-address"))}</span><span class="pv">${[pBadr1,pBadr2].filter(Boolean).map(l=>h(l)).join("<br>")}</span>` : ""}
</div>
${pRef ? `<div class="ph-ref">${h(td("payment-ref"))}: <strong>${h(pRef)}</strong></div>` : ""}` : ""}
<div class="d-tr d-inv-meta">
<h1>${h(td("invoice"))}</h1>
<table class="d-meta">
${iNo ? `<tr><td class="ml">${h(td("invoice-no"))}</td><td class="mv">${h(iNo)}</td></tr>` : ""}
${iDate ? `<tr><td class="ml">${h(td("invoice-date"))}</td><td class="mv">${h(fmtDate(iDate))}</td></tr>` : ""}
${pCode ? `<tr><td class="ml">${h(td("project-code"))}</td><td class="mv">${h(pCode)}</td></tr>` : ""}
${iCur ? `<tr><td class="ml">${h(td("invoice-currency"))}</td><td class="mv">${h(iCur)}</td></tr>` : ""}
</table>
</div>
<div class="d-bl d-bill">
<div class="bt-lbl">${h(td("charge-to"))}</div>
@ -1165,14 +1170,16 @@ function buildPreviewHTML() {
${ctReg ? `<span><strong>${h(td("registration-no"))}:</strong> ${h(ctReg)}</span>` : ""}
</div>
</div>
<div class="d-br d-inv-meta">
<h1>${h(td("invoice"))}</h1>
<table class="d-meta">
${iNo ? `<tr><td class="ml">${h(td("invoice-no"))}</td><td class="mv">${h(iNo)}</td></tr>` : ""}
${iDate ? `<tr><td class="ml">${h(td("invoice-date"))}</td><td class="mv">${h(fmtDate(iDate))}</td></tr>` : ""}
${pCode ? `<tr><td class="ml">${h(td("project-code"))}</td><td class="mv">${h(pCode)}</td></tr>` : ""}
${iCur ? `<tr><td class="ml">${h(td("invoice-currency"))}</td><td class="mv">${h(iCur)}</td></tr>` : ""}
</table>
<div class="d-br d-pay-hdr">
<div class="ph-lbl">${h(td("payment"))}</div>
${pTerm > 0 ? `<div class="ph-terms">${h(td("payment-terms"))}: <strong>${pTerm}</strong> ${h(td("payment-days"))}${pPayBy ? ` &mdash; ${h(td("pay-by"))}: <strong>${h(pPayBy)}</strong>` : ""}</div>` : ""}
${showBank ? `<div class="ph-grid">
${pAcct ? `<span class="pl">${h(td("account-holder"))}</span><span class="pv">${h(pAcct)}</span>` : ""}
${pIban ? `<span class="pl">${h(td("account-no"))}</span><span class="pv">${h(pIban)}</span>` : ""}
${pBic ? `<span class="pl">${h(td("bank-bic"))}</span><span class="pv">${h(pBic)}</span>` : ""}
${pBadr1 || pBadr2 ? `<span class="pl">${h(td("bank-address"))}</span><span class="pv">${[pBadr1,pBadr2].filter(Boolean).map(l=>h(l)).join("<br>")}</span>` : ""}
</div>
${pRef ? `<div class="ph-ref">${h(td("payment-ref"))}: <strong>${h(pRef)}</strong></div>` : ""}` : ""}
</div>
</div>
<table class="d-lines">
@ -1253,34 +1260,19 @@ function buildPDF() {
fn(8); tc(107,114,128); tL(parts.join(" "), ML, ly); ly += 5;
}
// ── Row 1 right: Payment ──
if (pTerm > 0 || showBank) {
fb(7); tc(107,114,128); tL(td("payment").toUpperCase(), XM_L, ry); ry += 5;
if (pTerm > 0) {
const ts = `${td("payment-terms")}: ${pTerm} ${td("payment-days")}${pPayBy ? ` ${td("pay-by")}: ${pPayBy}` : ""}`;
fn(8.5); tc(17,24,39); tL(ts, XM_L, ry); ry += 5;
}
if (showBank) {
const LLBL = 46;
const payRows = [
pAcct ? [td("account-holder"), pAcct] : null,
pIban ? [td("account-no"), pIban] : null,
pBic ? [td("bank-bic"), pBic] : null,
(pBadr1||pBadr2) ? [td("bank-address"), [pBadr1,pBadr2].filter(Boolean).join(", ")] : null,
].filter(Boolean);
payRows.forEach(([lbl, val]) => {
fn(8); tc(107,114,128); tL(lbl + ":", XM_L, ry);
fn(8.5); tc(17,24,39);
const wrapped = sp(val, LW - LLBL - 2);
wrapped.forEach((line, i) => tL(line, XM_L + LLBL, ry + i * 4));
ry += Math.max(4.5, wrapped.length * 4);
});
if (pRef) {
fn(8); tc(107,114,128); tL(td("payment-ref") + ":", XM_L, ry);
fb(8.5); tc(17,24,39); tL(pRef, XM_L + LLBL, ry); ry += 5;
}
}
}
// ── Row 1 right: INVOICE + meta ──
fb(24); tc(30,45,69); tR(td("invoice"), XR, ry); ry += 10;
const metaRows = [
iNo ? [td("invoice-no"), iNo] : null,
iDate ? [td("invoice-date"), fmtDate(iDate)] : null,
pCode ? [td("project-code"), pCode] : null,
iCur ? [td("invoice-currency"), iCur] : null,
].filter(Boolean);
metaRows.forEach(([lbl, val]) => {
fn(8.5); tc(107,114,128); tR(lbl + ":", XR - 42, ry);
fb(8.5); tc(17,24,39); tR(val, XR, ry);
ry += 5;
});
// Row 1 divider
const row1Y = Math.max(ly, ry) + 4;
@ -1302,19 +1294,34 @@ function buildPDF() {
if (ctParts.length) { fn(8); tc(107,114,128); tL(ctParts.join(" "), ML, ly2); ly2 += 5; }
}
// ── Row 2 right: INVOICE + meta ──
fb(24); tc(30,45,69); tR(td("invoice"), XR, ry2); ry2 += 10;
const metaRows = [
iNo ? [td("invoice-no"), iNo] : null,
iDate ? [td("invoice-date"), fmtDate(iDate)] : null,
pCode ? [td("project-code"), pCode] : null,
iCur ? [td("invoice-currency"), iCur] : null,
].filter(Boolean);
metaRows.forEach(([lbl, val]) => {
fn(8.5); tc(107,114,128); tR(lbl + ":", XR - 42, ry2);
fb(8.5); tc(17,24,39); tR(val, XR, ry2);
ry2 += 5;
});
// ── Row 2 right: Payment ──
if (pTerm > 0 || showBank) {
fb(7); tc(107,114,128); tL(td("payment").toUpperCase(), XM_L, ry2); ry2 += 5;
if (pTerm > 0) {
const ts = `${td("payment-terms")}: ${pTerm} ${td("payment-days")}${pPayBy ? ` ${td("pay-by")}: ${pPayBy}` : ""}`;
fn(8.5); tc(17,24,39); tL(ts, XM_L, ry2); ry2 += 5;
}
if (showBank) {
const LLBL = 46;
const payRows = [
pAcct ? [td("account-holder"), pAcct] : null,
pIban ? [td("account-no"), pIban] : null,
pBic ? [td("bank-bic"), pBic] : null,
(pBadr1||pBadr2) ? [td("bank-address"), [pBadr1,pBadr2].filter(Boolean).join(", ")] : null,
].filter(Boolean);
payRows.forEach(([lbl, val]) => {
fn(8); tc(107,114,128); tL(lbl + ":", XM_L, ry2);
fn(8.5); tc(17,24,39);
const wrapped = sp(val, LW - LLBL - 2);
wrapped.forEach((line, i) => tL(line, XM_L + LLBL, ry2 + i * 4));
ry2 += Math.max(4.5, wrapped.length * 4);
});
if (pRef) {
fn(8); tc(107,114,128); tL(td("payment-ref") + ":", XM_L, ry2);
fb(8.5); tc(17,24,39); tL(pRef, XM_L + LLBL, ry2); ry2 += 5;
}
}
}
y = Math.max(ly2, ry2) + 5;