KSvend Claude Sonnet 4.6 commited on
Commit
a86413f
·
1 Parent(s): 1b15a5f

feat: add month picker to define-area sidebar and wire up season state

Browse files

Adds season-start/season-end dropdowns (Jan–Dec) to the Analysis season
form-group, a year-boundary wrap hint, and surfaces the selected season in
the confirm summary and submit payload as season_start / season_end.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

Files changed (2) hide show
  1. frontend/index.html +51 -0
  2. frontend/js/app.js +20 -0
frontend/index.html CHANGED
@@ -241,6 +241,53 @@
241
  </div>
242
  </div>
243
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
244
  </div><!-- /sidebar-body -->
245
 
246
  <div class="map-sidebar-footer">
@@ -343,6 +390,10 @@
343
  <span id="confirm-period-end">—</span>
344
  </span>
345
  </div>
 
 
 
 
346
  <div class="confirm-row">
347
  <span class="confirm-row-label">Indicators</span>
348
  <span id="confirm-indicators" class="confirm-row-value">0</span>
 
241
  </div>
242
  </div>
243
 
244
+ <!-- Analysis season -->
245
+ <div class="form-group">
246
+ <label class="label">Analysis season</label>
247
+ <p style="font-size: var(--text-xxs); color: var(--ink-muted); margin-bottom: var(--space-3);">
248
+ Select the months relevant to your analysis. For year-round monitoring, leave as Jan–Dec.
249
+ </p>
250
+ <div class="date-row">
251
+ <div>
252
+ <label class="label" for="season-start" style="font-size: var(--text-xxs);">Start month</label>
253
+ <select id="season-start" class="input">
254
+ <option value="1" selected>January</option>
255
+ <option value="2">February</option>
256
+ <option value="3">March</option>
257
+ <option value="4">April</option>
258
+ <option value="5">May</option>
259
+ <option value="6">June</option>
260
+ <option value="7">July</option>
261
+ <option value="8">August</option>
262
+ <option value="9">September</option>
263
+ <option value="10">October</option>
264
+ <option value="11">November</option>
265
+ <option value="12">December</option>
266
+ </select>
267
+ </div>
268
+ <div>
269
+ <label class="label" for="season-end" style="font-size: var(--text-xxs);">End month</label>
270
+ <select id="season-end" class="input">
271
+ <option value="1">January</option>
272
+ <option value="2">February</option>
273
+ <option value="3">March</option>
274
+ <option value="4">April</option>
275
+ <option value="5">May</option>
276
+ <option value="6">June</option>
277
+ <option value="7">July</option>
278
+ <option value="8">August</option>
279
+ <option value="9">September</option>
280
+ <option value="10">October</option>
281
+ <option value="11">November</option>
282
+ <option value="12" selected>December</option>
283
+ </select>
284
+ </div>
285
+ </div>
286
+ <p id="season-wrap-hint" style="font-size: var(--text-xxs); color: var(--iris); margin-top: var(--space-2); display: none;">
287
+ ↻ Season crosses year boundary
288
+ </p>
289
+ </div>
290
+
291
  </div><!-- /sidebar-body -->
292
 
293
  <div class="map-sidebar-footer">
 
390
  <span id="confirm-period-end">—</span>
391
  </span>
392
  </div>
393
+ <div class="confirm-row">
394
+ <span class="confirm-row-label">Season</span>
395
+ <span id="confirm-season" class="confirm-row-value">January – December</span>
396
+ </div>
397
  <div class="confirm-row">
398
  <span class="confirm-row-label">Indicators</span>
399
  <span id="confirm-indicators" class="confirm-row-value">0</span>
frontend/js/app.js CHANGED
@@ -14,6 +14,8 @@ const state = {
14
  session: null, // { email, token }
15
  aoi: null, // { name, bbox }
16
  timeRange: null, // { start, end }
 
 
17
  indicators: [], // string[]
18
  jobId: null, // string
19
  jobData: null, // full job response
@@ -238,6 +240,16 @@ function setupDefineArea() {
238
  document.getElementById('date-start').value = _isoDate(yearAgo);
239
  document.getElementById('date-end').value = _isoDate(today);
240
 
 
 
 
 
 
 
 
 
 
 
241
  // Continue
242
  continueBtn.addEventListener('click', () => {
243
  const name = document.getElementById('area-name').value.trim() || 'Unnamed area';
@@ -246,6 +258,8 @@ function setupDefineArea() {
246
 
247
  state.aoi = { name, bbox: _currentBbox };
248
  state.timeRange = { start: startVal, end: endVal };
 
 
249
 
250
  navigate('indicators');
251
  }, { once: true });
@@ -285,6 +299,10 @@ function setupConfirm() {
285
  document.getElementById('confirm-period-end').textContent = state.timeRange?.end || '—';
286
  document.getElementById('confirm-indicators').textContent = state.indicators.length;
287
 
 
 
 
 
288
  // Auto-fill email from session
289
  const emailInput = document.getElementById('confirm-email');
290
  if (state.session && state.session.email) {
@@ -315,6 +333,8 @@ function setupConfirm() {
315
  },
316
  indicator_ids: state.indicators,
317
  email,
 
 
318
  };
319
 
320
  try {
 
14
  session: null, // { email, token }
15
  aoi: null, // { name, bbox }
16
  timeRange: null, // { start, end }
17
+ seasonStart: 1, // 1-12
18
+ seasonEnd: 12, // 1-12
19
  indicators: [], // string[]
20
  jobId: null, // string
21
  jobData: null, // full job response
 
240
  document.getElementById('date-start').value = _isoDate(yearAgo);
241
  document.getElementById('date-end').value = _isoDate(today);
242
 
243
+ // Season wrap hint
244
+ const seasonStartEl = document.getElementById('season-start');
245
+ const seasonEndEl = document.getElementById('season-end');
246
+ const wrapHint = document.getElementById('season-wrap-hint');
247
+ function updateWrapHint() {
248
+ wrapHint.style.display = (parseInt(seasonStartEl.value) > parseInt(seasonEndEl.value)) ? '' : 'none';
249
+ }
250
+ seasonStartEl.addEventListener('change', updateWrapHint);
251
+ seasonEndEl.addEventListener('change', updateWrapHint);
252
+
253
  // Continue
254
  continueBtn.addEventListener('click', () => {
255
  const name = document.getElementById('area-name').value.trim() || 'Unnamed area';
 
258
 
259
  state.aoi = { name, bbox: _currentBbox };
260
  state.timeRange = { start: startVal, end: endVal };
261
+ state.seasonStart = parseInt(document.getElementById('season-start').value);
262
+ state.seasonEnd = parseInt(document.getElementById('season-end').value);
263
 
264
  navigate('indicators');
265
  }, { once: true });
 
299
  document.getElementById('confirm-period-end').textContent = state.timeRange?.end || '—';
300
  document.getElementById('confirm-indicators').textContent = state.indicators.length;
301
 
302
+ const monthNames = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
303
+ const seasonText = `${monthNames[state.seasonStart - 1]} – ${monthNames[state.seasonEnd - 1]}`;
304
+ document.getElementById('confirm-season').textContent = seasonText;
305
+
306
  // Auto-fill email from session
307
  const emailInput = document.getElementById('confirm-email');
308
  if (state.session && state.session.email) {
 
333
  },
334
  indicator_ids: state.indicators,
335
  email,
336
+ season_start: state.seasonStart,
337
+ season_end: state.seasonEnd,
338
  };
339
 
340
  try {