From f2083ad4117a47091497b778552aad797117f00f Mon Sep 17 00:00:00 2001 From: Ian Gulliver Date: Sun, 15 Feb 2026 18:08:33 -0800 Subject: [PATCH] Add constraint kind validation per level and reorder constraint form --- main.go | 16 ++++++++++++++++ static/trip.js | 42 ++++++++++++++++++++++++++---------------- 2 files changed, 42 insertions(+), 16 deletions(-) diff --git a/main.go b/main.go index 302a218..ea89289 100644 --- a/main.go +++ b/main.go @@ -638,6 +638,22 @@ func handleCreateConstraint(db *sql.DB) http.HandlerFunc { http.Error(w, "students must be different", http.StatusBadRequest) return } + switch body.Level { + case "student": + if body.Kind != "prefer" && body.Kind != "prefer_not" { + http.Error(w, "students may only use prefer or prefer not", http.StatusBadRequest) + return + } + case "parent": + if body.Kind != "must_not" { + http.Error(w, "parents may only use must not", http.StatusBadRequest) + return + } + case "admin": + default: + http.Error(w, "invalid level", http.StatusBadRequest) + return + } a, b := body.StudentAID, body.StudentBID if a > b { a, b = b, a diff --git a/static/trip.js b/static/trip.js index 54cbd49..6f83177 100644 --- a/static/trip.js +++ b/static/trip.js @@ -142,6 +142,30 @@ async function loadStudents() { const addRow = document.createElement('div'); addRow.className = 'constraint-add'; + const levelKinds = { + student: ['prefer', 'prefer_not'], + parent: ['must_not'], + admin: ['must', 'prefer', 'prefer_not', 'must_not'] + }; + const levelSelect = document.createElement('select'); + for (const level of ['student', 'parent', 'admin']) { + const opt = document.createElement('option'); + opt.value = level; + opt.textContent = level.charAt(0).toUpperCase() + level.slice(1); + levelSelect.appendChild(opt); + } + const kindSelect = document.createElement('select'); + const updateKinds = () => { + kindSelect.innerHTML = ''; + for (const kind of levelKinds[levelSelect.value]) { + const opt = document.createElement('option'); + opt.value = kind; + opt.textContent = kindLabels[kind]; + kindSelect.appendChild(opt); + } + }; + updateKinds(); + levelSelect.addEventListener('change', updateKinds); const studentSelect = document.createElement('select'); const defaultOpt = document.createElement('option'); defaultOpt.value = ''; @@ -154,20 +178,6 @@ async function loadStudents() { opt.textContent = other.name; studentSelect.appendChild(opt); } - const kindSelect = document.createElement('select'); - for (const kind of ['must', 'prefer', 'prefer_not', 'must_not']) { - const opt = document.createElement('option'); - opt.value = kind; - opt.textContent = kindLabels[kind]; - kindSelect.appendChild(opt); - } - const levelSelect = document.createElement('select'); - for (const level of ['student', 'parent', 'admin']) { - const opt = document.createElement('option'); - opt.value = level; - opt.textContent = level.charAt(0).toUpperCase() + level.slice(1); - levelSelect.appendChild(opt); - } const cAddBtn = document.createElement('button'); cAddBtn.className = 'input-action'; cAddBtn.textContent = '+'; @@ -182,9 +192,9 @@ async function loadStudents() { }); loadStudents(); }); - addRow.appendChild(studentSelect); - addRow.appendChild(kindSelect); addRow.appendChild(levelSelect); + addRow.appendChild(kindSelect); + addRow.appendChild(studentSelect); addRow.appendChild(cAddBtn); cDetails.appendChild(addRow);