stackchain-dashboard/frontend/today-rollover.js
timmy 14a3e1ee8d
All checks were successful
CI / lint (pull_request) Successful in 1m33s
CI / build-release (pull_request) Successful in 6s
CI / release-candidate (pull_request) Has been skipped
feat: review Today work at day rollover (Closes #603)
2026-08-12 00:38:13 +00:00

38 lines
1.5 KiB
JavaScript

function createTodayRollover(options = {}) {
const now = options.now || (() => new Date());
const resolvedTimeZone = options.resolvedTimeZone || (() =>
Intl.DateTimeFormat().resolvedOptions().timeZone || 'UTC');
function timeZone() {
return options.timeZone?.() || resolvedTimeZone();
}
function localDate() {
if (options.localDate) return options.localDate();
const parts = new Intl.DateTimeFormat('en-CA', {
timeZone: timeZone(), year: 'numeric', month: '2-digit', day: '2-digit',
}).formatToParts(now());
const value = Object.fromEntries(parts.map(part => [part.type, part.value]));
return `${value.year}-${value.month}-${value.day}`;
}
function reviewState(plan) {
if (!Array.isArray(plan?.ids) || !plan.ids.length) return 'empty';
if (!plan.plan_date) return 'legacy';
return plan.plan_date === localDate() ? 'current' : 'stale';
}
function operation({ operation_id, base_revision, selected_ids, capacity_minutes, estimates = {} }) {
const ids = [...new Set((selected_ids || []).filter(id => typeof id === 'string' && id))];
const selected = new Set(ids);
return {
operation_id, action: 'rollover', item_id: 'plan', base_revision,
plan_date: localDate(), timezone: timeZone(), ids, capacity_minutes,
estimates: Object.fromEntries(Object.entries(estimates).filter(([id]) => selected.has(id))),
};
}
return { localDate, timeZone, reviewState, operation };
}
if (typeof module !== 'undefined' && module.exports) module.exports = createTodayRollover;