Show baseline/reference form in a modal with live month preview
Replaces the small inline form with a centred modal dialog. When both dates are selected, a live chip list shows every month covered (up to 36 months) so it is immediately clear what periods will be loaded. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
cfee3e96b9
commit
10441a4761
@ -375,10 +375,48 @@ function showLoadForm(op) {
|
||||
state.loadDataOp = op;
|
||||
document.getElementById('load-data-title').textContent =
|
||||
op === 'baseline' ? 'Load Baseline' : 'Load Reference';
|
||||
document.getElementById('load-data-form').classList.remove('hidden');
|
||||
document.getElementById('load-date-from').value = '';
|
||||
document.getElementById('load-date-to').value = '';
|
||||
document.getElementById('load-note').value = '';
|
||||
document.getElementById('load-date-preview').classList.add('hidden');
|
||||
document.getElementById('load-data-modal').classList.remove('hidden');
|
||||
document.getElementById('load-date-from').focus();
|
||||
}
|
||||
|
||||
function hideLoadModal() {
|
||||
document.getElementById('load-data-modal').classList.add('hidden');
|
||||
}
|
||||
|
||||
function updateDatePreview() {
|
||||
const fromVal = document.getElementById('load-date-from').value;
|
||||
const toVal = document.getElementById('load-date-to').value;
|
||||
const preview = document.getElementById('load-date-preview');
|
||||
const chips = document.getElementById('load-date-chips');
|
||||
const label = preview.querySelector('.load-preview-label');
|
||||
|
||||
if (!fromVal || !toVal) { preview.classList.add('hidden'); return; }
|
||||
|
||||
const from = new Date(fromVal + 'T00:00:00');
|
||||
const to = new Date(toVal + 'T00:00:00');
|
||||
if (isNaN(from) || isNaN(to) || from > to) { preview.classList.add('hidden'); return; }
|
||||
|
||||
const months = [];
|
||||
const cur = new Date(from.getFullYear(), from.getMonth(), 1);
|
||||
const end = new Date(to.getFullYear(), to.getMonth(), 1);
|
||||
while (cur <= end) { months.push(new Date(cur)); cur.setMonth(cur.getMonth() + 1); }
|
||||
|
||||
const fmt = new Intl.DateTimeFormat('en-US', { month: 'short', year: 'numeric' });
|
||||
label.textContent = `${months.length} month${months.length !== 1 ? 's' : ''} covered`;
|
||||
|
||||
if (months.length <= 36) {
|
||||
chips.innerHTML = months.map(m => `<span class="date-chip">${fmt.format(m)}</span>`).join('');
|
||||
} else {
|
||||
chips.innerHTML = `<span class="date-chip-summary">${months.length} months — ${fmt.format(months[0])} → ${fmt.format(months[months.length - 1])}</span>`;
|
||||
}
|
||||
|
||||
preview.classList.remove('hidden');
|
||||
}
|
||||
|
||||
async function submitLoadData() {
|
||||
const date_from = document.getElementById('load-date-from').value;
|
||||
const date_to = document.getElementById('load-date-to').value;
|
||||
@ -394,7 +432,7 @@ async function submitLoadData() {
|
||||
try {
|
||||
showStatus(`Loading ${state.loadDataOp}...`, 'info');
|
||||
const result = await api('POST', `/versions/${state.selectedVersionId}/${state.loadDataOp}`, body);
|
||||
document.getElementById('load-data-form').classList.add('hidden');
|
||||
hideLoadModal();
|
||||
showStatus(`${state.loadDataOp} loaded — ${result.rows_affected} rows`, 'success');
|
||||
} catch (err) {
|
||||
showStatus(err.message, 'error');
|
||||
@ -879,9 +917,10 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
document.getElementById('vbtn-toggle').addEventListener('click', toggleVersionStatus);
|
||||
document.getElementById('vbtn-delete').addEventListener('click', deleteVersion);
|
||||
document.getElementById('btn-load-submit').addEventListener('click', submitLoadData);
|
||||
document.getElementById('btn-load-cancel').addEventListener('click', () => {
|
||||
document.getElementById('load-data-form').classList.add('hidden');
|
||||
});
|
||||
document.getElementById('btn-load-cancel').addEventListener('click', hideLoadModal);
|
||||
document.getElementById('btn-load-close').addEventListener('click', hideLoadModal);
|
||||
document.getElementById('load-date-from').addEventListener('change', updateDatePreview);
|
||||
document.getElementById('load-date-to').addEventListener('change', updateDatePreview);
|
||||
|
||||
// forecast view buttons
|
||||
document.getElementById('btn-forecast-refresh').addEventListener('click', loadForecastData);
|
||||
|
||||
@ -94,18 +94,6 @@
|
||||
<button class="btn" id="vbtn-toggle">Close Version</button>
|
||||
<button class="btn btn-danger" id="vbtn-delete">Delete</button>
|
||||
</div>
|
||||
<div id="load-data-form" class="inline-form hidden">
|
||||
<h3 id="load-data-title">Load Baseline</h3>
|
||||
<div class="form-row">
|
||||
<label>Date From<input type="date" id="load-date-from" /></label>
|
||||
<label>Date To<input type="date" id="load-date-to" /></label>
|
||||
<label>Note<input type="text" id="load-note" placeholder="optional" /></label>
|
||||
</div>
|
||||
<div class="form-actions">
|
||||
<button id="btn-load-submit" class="btn btn-primary">Load</button>
|
||||
<button id="btn-load-cancel" class="btn">Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ===== FORECAST VIEW ===== -->
|
||||
@ -170,6 +158,31 @@
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<!-- Load baseline / reference modal -->
|
||||
<div id="load-data-modal" class="modal-overlay hidden">
|
||||
<div class="modal load-data-modal">
|
||||
<div class="modal-header">
|
||||
<span id="load-data-title">Load Baseline</span>
|
||||
<button id="btn-load-close" class="btn-icon">×</button>
|
||||
</div>
|
||||
<div id="load-data-body">
|
||||
<div class="load-form-fields">
|
||||
<label>Date From<input type="date" id="load-date-from" /></label>
|
||||
<label>Date To<input type="date" id="load-date-to" /></label>
|
||||
<label>Note<input type="text" id="load-note" placeholder="optional" /></label>
|
||||
</div>
|
||||
<div id="load-date-preview" class="load-date-preview hidden">
|
||||
<div class="load-preview-label"></div>
|
||||
<div id="load-date-chips" class="date-chips"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button id="btn-load-submit" class="btn btn-primary">Load</button>
|
||||
<button id="btn-load-cancel" class="btn">Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Table preview modal -->
|
||||
<div id="modal-overlay" class="modal-overlay hidden">
|
||||
<div class="modal">
|
||||
|
||||
@ -312,6 +312,83 @@ body {
|
||||
#modal-body { padding: 16px 18px; overflow-y: auto; flex: 1; font-size: 12px; }
|
||||
.modal-footer { padding: 10px 18px; border-top: 1px solid #eee; display: flex; justify-content: flex-end; gap: 8px; }
|
||||
|
||||
/* ============================================================
|
||||
LOAD BASELINE / REFERENCE MODAL
|
||||
============================================================ */
|
||||
.load-data-modal { width: 480px; max-height: 80vh; }
|
||||
|
||||
#load-data-body {
|
||||
padding: 20px 24px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.load-form-fields {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.load-form-fields label {
|
||||
font-size: 11px;
|
||||
color: #555;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.load-form-fields input[type=date],
|
||||
.load-form-fields input[type=text] {
|
||||
border: 1px solid #dce1e7;
|
||||
padding: 7px 10px;
|
||||
border-radius: 3px;
|
||||
font-size: 13px;
|
||||
color: #333;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.load-form-fields input[type=date]:focus,
|
||||
.load-form-fields input[type=text]:focus {
|
||||
outline: none;
|
||||
border-color: #2980b9;
|
||||
box-shadow: 0 0 0 2px rgba(41,128,185,.15);
|
||||
}
|
||||
|
||||
.load-date-preview { display: flex; flex-direction: column; gap: 8px; }
|
||||
.load-date-preview.hidden { display: none; }
|
||||
|
||||
.load-preview-label {
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
color: #7f8c8d;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.04em;
|
||||
}
|
||||
|
||||
.date-chips {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.date-chip {
|
||||
background: #eaf4fb;
|
||||
color: #1a6fa8;
|
||||
border: 1px solid #c5dff0;
|
||||
padding: 3px 9px;
|
||||
border-radius: 12px;
|
||||
font-size: 11px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.date-chip-summary {
|
||||
font-size: 12px;
|
||||
color: #555;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.preview-section h4 { font-size: 12px; margin-bottom: 6px; color: #555; }
|
||||
.preview-section + .preview-section { margin-top: 16px; }
|
||||
.preview-table { border-collapse: collapse; width: 100%; font-size: 11px; }
|
||||
|
||||
Loading…
Reference in New Issue
Block a user