/* kanban-modal.js — card create/edit modal */ (function () { 'use strict'; var modal = document.getElementById('cardModal'); var bsModal = new bootstrap.Modal(modal); var titleEl = document.getElementById('cardModalLabel'); var cardIdEl = document.getElementById('card-id'); var colIdEl = document.getElementById('card-column-id'); var laneIdEl = document.getElementById('card-lane-id'); var jobNumEl = document.getElementById('card-job-number'); var jobNameEl = document.getElementById('card-job-name'); var errEl = document.getElementById('card-modal-error'); var btnSave = document.getElementById('btn-save-card'); var btnDelete = document.getElementById('btn-delete-card'); var boardId = KANBAN.boardId; /* ── Helpers ─────────────────────────────────────────────── */ function post(url, data, cb) { var params = new URLSearchParams(); Object.keys(data).forEach(function (k) { params.append(k, data[k]); }); fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: params.toString() }) .then(function (r) { return r.json(); }) .then(cb) .catch(function (e) { showError('Network error: ' + e); }); } function showError(msg) { errEl.textContent = msg; errEl.classList.remove('d-none'); } function clearError() { errEl.textContent = ''; errEl.classList.add('d-none'); } /* ── Open for create ──────────────────────────────────────── */ function openCreate(bId, colId, laneId) { titleEl.textContent = 'Add Card'; cardIdEl.value = ''; colIdEl.value = colId || ''; laneIdEl.value = laneId || ''; jobNumEl.value = ''; jobNameEl.value = ''; btnDelete.classList.add('d-none'); clearError(); bsModal.show(); jobNumEl.focus(); } /* ── Open for edit ───────────────────────────────────────── */ function openEdit(id, colId, laneId, jobNum, jobName) { titleEl.textContent = 'Edit Card'; cardIdEl.value = id; colIdEl.value = colId; laneIdEl.value = laneId; jobNumEl.value = jobNum || ''; jobNameEl.value = jobName || ''; btnDelete.classList.remove('d-none'); clearError(); bsModal.show(); jobNumEl.focus(); } /* ── Save ─────────────────────────────────────────────────── */ btnSave.addEventListener('click', function () { clearError(); var id = cardIdEl.value; var colId = colIdEl.value; var laneId = laneIdEl.value; var jNum = jobNumEl.value.trim(); var jName = jobNameEl.value.trim(); if (!jNum && !jName) { showError('Enter at least a job number or job name.'); return; } if (id) { // Update existing post('/cards/' + id, { job_number: jNum, job_name: jName }, function (res) { if (res.ok) { bsModal.hide(); window.KanbanBoard.onCardUpdated(id, res.job_number, res.job_name); } else { showError(res.error || 'Save failed.'); } }); } else { // Create new — if no col/lane selected show column/lane picker if (!colId || !laneId) { showError('Please choose a column and swim lane first.'); return; } post('/cards', { board_id: boardId, column_id: colId, swim_lane_id: laneId, job_number: jNum, job_name: jName }, function (res) { if (res.ok) { bsModal.hide(); window.KanbanBoard.onCardCreated(res); } else { showError(res.error || 'Save failed.'); } }); } }); /* ── Delete ──────────────────────────────────────────────── */ btnDelete.addEventListener('click', function () { if (!confirm('Delete this card?')) return; var id = cardIdEl.value; post('/cards/' + id + '/delete', {}, function (res) { if (res.ok) { bsModal.hide(); window.KanbanBoard.onCardDeleted(id); } else { showError(res.error || 'Delete failed.'); } }); }); /* ── Column/Lane picker when Add Card clicked with no cell ── */ // Populated lazily from board data modal.addEventListener('shown.bs.modal', function () { if (!cardIdEl.value && (!colIdEl.value || !laneIdEl.value)) { injectPicker(); } }); function injectPicker() { if (document.getElementById('card-picker')) return; var picker = document.createElement('div'); picker.id = 'card-picker'; picker.className = 'row g-2 mb-3'; var colSel = ''; picker.innerHTML = '