stackchain-dashboard/frontend/agenda-replan.js
timmy dce9ae04c9
All checks were successful
CI / lint (pull_request) Successful in 1m23s
CI / build-release (pull_request) Successful in 4s
CI / release-candidate (pull_request) Has been skipped
fix: preserve deadline calendar days (Closes #719)
2026-08-13 07:56:26 +00:00

84 lines
2.5 KiB
JavaScript

function createAgendaReplan({ now = () => new Date(), update }) {
let items = [];
let index = 0;
let pending = false;
let active = false;
const dayKey = date => [
date.getFullYear(),
String(date.getMonth() + 1).padStart(2, '0'),
String(date.getDate()).padStart(2, '0'),
].join('-');
const dueDay = value => {
const match = String(value || '').match(/^(\d{4}-\d{2}-\d{2})(?:$|T)/);
return match ? match[1] : '';
};
const current = () => active ? items[index] || null : null;
const snapshot = () => ({
active,
index,
total: items.length,
current: current()?.key || null,
pending,
});
const advance = () => {
index += 1;
if (index >= items.length) active = false;
return { ok:true, done:!active };
};
const change = async dueDate => {
const item = current();
if (!item) return { ok:false, error:'No overdue deadline selected.' };
if (pending) return { ok:false, error:'Deadline update already in progress.' };
pending = true;
try {
await update(item, dueDate);
return advance();
} catch (error) {
return { ok:false, error:error?.message || 'Deadline could not be updated.' };
} finally {
pending = false;
}
};
return {
start(overdue) {
items = (overdue || []).slice().sort((left, right) =>
dueDay(left.due_date).localeCompare(dueDay(right.due_date)) ||
String(left.repository || '').localeCompare(String(right.repository || '')) ||
Number(left.number || 0) - Number(right.number || 0)
);
index = 0;
pending = false;
active = items.length > 0;
return snapshot();
},
snapshot,
current,
keep() {
if (pending) return Promise.resolve({ ok:false, error:'Deadline update already in progress.' });
if (!current()) return Promise.resolve({ ok:false, error:'No overdue deadline selected.' });
return Promise.resolve(advance());
},
tomorrow() {
const date = new Date(now());
date.setDate(date.getDate() + 1);
return change(dayKey(date) + 'T23:59:59Z');
},
choose(value) {
const chosen = String(value || '');
if (!/^\d{4}-\d{2}-\d{2}$/.test(chosen) || chosen <= dayKey(now())) {
return Promise.resolve({ ok:false, error:'Choose a future date.' });
}
return change(chosen + 'T23:59:59Z');
},
cancel() {
active = false;
pending = false;
return snapshot();
},
};
}
if (typeof module !== 'undefined' && module.exports) module.exports = createAgendaReplan;