diff --git a/app/config.yml b/app/config.yml
index 9178ce3..5702c3b 100644
--- a/app/config.yml
+++ b/app/config.yml
@@ -119,6 +119,10 @@ charge-to:
vat-id: "US-EIN-12-3456789"
reg-no: ""
currency: USD
+ project-codes:
+ - AC-100
+ - AC-110
+ - AC-200
- display: Example NGO
name: Example Non-Profit Organisation
address1: 45 Charity Lane
@@ -131,6 +135,10 @@ charge-to:
vat-id: "GB123456789"
reg-no: "01234567"
currency: GBP
+ project-codes:
+ - NGO-2026-01
+ - NGO-2026-02
+ - NGO-2026-03
# ── Project codes ──────────────────────────────────────────────────────────────
project-codes:
diff --git a/app/index.html b/app/index.html
index 2ff8e71..31eb867 100644
--- a/app/index.html
+++ b/app/index.html
@@ -693,6 +693,20 @@ function buildForm() {
calcPayBy(); // compute initial pay-by from default 7-day term
}
+// ── Project-code dropdown ─────────────────────────────────────────────────────
+function updateProjectCodes(codes) {
+ const arr = (codes && codes.length) ? codes : (cfg["project-codes"] || []);
+ const sel = document.getElementById("pcode");
+ if (!sel) return;
+ const prev = sel.value;
+ sel.innerHTML = ``
+ + arr.map(pc => ``).join("")
+ + ``;
+ sel.value = arr.includes(prev) ? prev : "";
+ const wrap = document.getElementById("pcode-other-wrap");
+ if (wrap) wrap.style.display = sel.value === "__other__" ? "block" : "none";
+}
+
// ── Fill charge-to ────────────────────────────────────────────────────────────
function fillChargeTo(v) {
const f = (id, val) => { const el = document.getElementById(id); if (el) el.value = val ?? ""; };
@@ -704,10 +718,12 @@ function fillChargeTo(v) {
if (v === "") {
["ctn","ca1","ca2","ca3","ca4","cc","cph","cem","cvat","creg"].forEach(id => f(id, ""));
fields?.classList.add("locked");
+ updateProjectCodes(null); // restore global project codes
return;
}
if (v === "__other__") {
fields?.classList.remove("locked");
+ updateProjectCodes(null); // restore global project codes
return;
}
const ct = (cfg["charge-to"] || [])[+v];
@@ -719,6 +735,9 @@ function fillChargeTo(v) {
f("cvat", ct["vat-id"]); f("creg", ct["reg-no"]);
fields?.classList.add("locked");
+ // Swap project codes to this recipient's list (falls back to global if none defined)
+ updateProjectCodes(ct["project-codes"] || null);
+
// Auto-set invoice currency from recipient config
if (ct.currency) {
const icurEl = document.getElementById("icur");