Skip to content

Commit 64cdfd0

Browse files
fixed some bugs
1 parent 90e2f26 commit 64cdfd0

3 files changed

Lines changed: 80 additions & 87 deletions

File tree

.claude/settings.local.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@
2828
"mcp__plugin_cloudflare_cloudflare-observability__query_worker_observability",
2929
"mcp__plugin_cloudflare_cloudflare-builds__set_active_account",
3030
"Bash(git rm *)",
31-
"Bash(echo \"exit=$?\")"
31+
"Bash(echo \"exit=$?\")",
32+
"Bash(sed -i '' '861s|\\(\\(state.completedPomos % state.settings.longEvery === 0\\) ? state.settings.longBreakMins : state.settings.breakMins\\)|\\(isLongBreak\\(state\\) ? state.settings.longBreakMins : state.settings.breakMins\\)|' tools/pomodoro.html)",
33+
"Bash(sed -n '861p' tools/pomodoro.html)"
3234
]
3335
}
3436
}

tools/assignments.html

Lines changed: 42 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -598,62 +598,52 @@ <h1>Assignments</h1>
598598
const DAY_NAMES = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];
599599

600600
// ─────────────── Date helpers ───────────────
601-
const todayKey = () => {
602-
const d = new Date();
603-
return `${d.getFullYear()}-${String(d.getMonth()+1).padStart(2,'0')}-${String(d.getDate()).padStart(2,'0')}`;
604-
};
601+
const DAY_MS = 86400000;
602+
const dateKey = (d) => `${d.getFullYear()}-${String(d.getMonth()+1).padStart(2,'0')}-${String(d.getDate()).padStart(2,'0')}`;
603+
const parseDateKey = (s) => { const [y, m, d] = s.split('-').map(Number); return new Date(y, m - 1, d); };
604+
const todayKey = () => dateKey(new Date());
605+
const dateKeyFromTs = (ts) => dateKey(new Date(ts));
606+
function yesterdayKey() {
607+
const d = new Date(); d.setDate(d.getDate() - 1);
608+
return dateKey(d);
609+
}
605610
function dayDiff(dateStr) {
606-
// days from today (negative = past). Date-only comparison.
607-
const [y, m, d] = dateStr.split('-').map(Number);
608-
const target = new Date(y, m - 1, d);
609-
const today = new Date();
610-
today.setHours(0, 0, 0, 0);
611-
target.setHours(0, 0, 0, 0);
612-
return Math.round((target - today) / (24 * 60 * 60 * 1000));
611+
// Date-only comparison; negative = past.
612+
const target = parseDateKey(dateStr); target.setHours(0, 0, 0, 0);
613+
const today = new Date(); today.setHours(0, 0, 0, 0);
614+
return Math.round((target - today) / DAY_MS);
613615
}
614616
function dueLabel(dateStr) {
615617
const diff = dayDiff(dateStr);
616618
if (diff < 0) return `${Math.abs(diff)}d overdue`;
617619
if (diff === 0) return 'Due today';
618620
if (diff === 1) return 'Due tomorrow';
619621
if (diff < 7) return `Due in ${diff} days`;
620-
const [y, m, d] = dateStr.split('-').map(Number);
621-
const dt = new Date(y, m - 1, d);
622-
return `Due ${dt.toLocaleDateString(undefined, { month: 'short', day: 'numeric' })}`;
623-
}
624-
function dateKeyFromTs(ts) {
625-
const d = new Date(ts);
626-
return `${d.getFullYear()}-${String(d.getMonth()+1).padStart(2,'0')}-${String(d.getDate()).padStart(2,'0')}`;
627-
}
628-
function yesterdayKey() {
629-
const d = new Date(); d.setDate(d.getDate() - 1);
630-
return dateKeyFromTs(d.getTime());
622+
return `Due ${parseDateKey(dateStr).toLocaleDateString(undefined, { month: 'short', day: 'numeric' })}`;
631623
}
632624
function completionRelative(ts) {
633625
if (!ts) return 'Completed';
634626
const dk = dateKeyFromTs(ts);
635627
if (dk === todayKey()) return 'Completed today';
636628
if (dk === yesterdayKey()) return 'Completed yesterday';
637629
const d = new Date(ts);
638-
const diffDays = Math.round((Date.now() - ts) / 86400000);
630+
const diffDays = Math.round((Date.now() - ts) / DAY_MS);
639631
if (diffDays < 7) return `Completed ${d.toLocaleDateString(undefined, { weekday: 'long' })}`;
640632
return `Completed ${d.toLocaleDateString(undefined, { month: 'short', day: 'numeric' })}`;
641633
}
642634
function completionGroupLabel(key) {
643635
if (key === 'earlier') return 'Earlier';
644636
if (key === todayKey()) return 'Today';
645637
if (key === yesterdayKey()) return 'Yesterday';
646-
const [Y, M, D] = key.split('-').map(Number);
647-
const dt = new Date(Y, M - 1, D);
648-
const diffDays = Math.round((Date.now() - dt.getTime()) / 86400000);
638+
const dt = parseDateKey(key);
639+
const diffDays = Math.round((Date.now() - dt.getTime()) / DAY_MS);
649640
if (diffDays < 7) return dt.toLocaleDateString(undefined, { weekday: 'long' });
650641
return dt.toLocaleDateString(undefined, { month: 'long', day: 'numeric' });
651642
}
652643

653644
function nextOccurrence(rule, fromDateStr) {
654645
if (!rule) return null;
655-
const [y, m, d] = fromDateStr.split('-').map(Number);
656-
const cur = new Date(y, m - 1, d);
646+
const cur = parseDateKey(fromDateStr);
657647
for (let i = 1; i <= 366; i++) {
658648
const next = new Date(cur);
659649
next.setDate(cur.getDate() + i);
@@ -662,7 +652,7 @@ <h1>Assignments</h1>
662652
if (rule.kind === 'daily') match = true;
663653
else if (rule.kind === 'weekly' && rule.days && rule.days.length) match = rule.days.includes(dow);
664654
if (!match) continue;
665-
const ds = `${next.getFullYear()}-${String(next.getMonth()+1).padStart(2,'0')}-${String(next.getDate()).padStart(2,'0')}`;
655+
const ds = dateKey(next);
666656
if (rule.until && ds > rule.until) return null;
667657
return ds;
668658
}
@@ -759,7 +749,6 @@ <h1>Assignments</h1>
759749
classes.push({ id: crypto.randomUUID().slice(0,8), name: name.slice(0,40), color: selectedSwatch });
760750
save(K_CLASSES, classes);
761751
elClassName.value = '';
762-
// rotate to next color for convenience
763752
const next = PALETTE[(PALETTE.indexOf(selectedSwatch) + 1) % PALETTE.length];
764753
selectedSwatch = next;
765754
renderAll();
@@ -790,7 +779,7 @@ <h1>Assignments</h1>
790779
b.title = DAY_NAMES[i];
791780
b.addEventListener('click', () => {
792781
if (formRepeatDays.includes(i)) formRepeatDays = formRepeatDays.filter(x => x !== i);
793-
else formRepeatDays = [...formRepeatDays, i].sort();
782+
else formRepeatDays = [...formRepeatDays, i].sort((a, b) => a - b);
794783
renderDayPills();
795784
});
796785
elRepeatDays.appendChild(b);
@@ -801,8 +790,7 @@ <h1>Assignments</h1>
801790
elRepeatDays.style.display = v === 'weekly' ? '' : 'none';
802791
elRepeatUntilWrap.style.display = v !== 'none' ? '' : 'none';
803792
if (v === 'weekly' && formRepeatDays.length === 0 && elAddDue.value) {
804-
const [y, m, d] = elAddDue.value.split('-').map(Number);
805-
if (y) formRepeatDays = [new Date(y, m - 1, d).getDay()];
793+
formRepeatDays = [parseDateKey(elAddDue.value).getDay()];
806794
renderDayPills();
807795
}
808796
}
@@ -825,8 +813,10 @@ <h1>Assignments</h1>
825813
elAddSubmit.disabled = false;
826814
}
827815
}
828-
// default due date = today
829816
elAddDue.value = todayKey();
817+
elAddDue.addEventListener('focus', () => {
818+
if (!editingId && !elAddDue.value) elAddDue.value = todayKey();
819+
});
830820

831821
function resetForm() {
832822
editingId = null;
@@ -921,7 +911,6 @@ <h1>Assignments</h1>
921911
c.addEventListener('click', () => { filter.status = key; save(K_FILTER, filter); renderAll(); });
922912
elFilters.appendChild(c);
923913
});
924-
// divider via spacing
925914
if (classes.length) {
926915
const sep = document.createElement('span'); sep.style.width = '1px'; sep.style.alignSelf = 'stretch'; sep.style.background = 'var(--line)'; sep.style.margin = '0 .25rem';
927916
elFilters.appendChild(sep);
@@ -966,6 +955,7 @@ <h1>Assignments</h1>
966955

967956
function renderList() {
968957
const xs = filteredItems();
958+
const classMap = new Map(classes.map(c => [c.id, c]));
969959
elList.innerHTML = '';
970960
if (xs.length === 0) {
971961
const e = document.createElement('div');
@@ -991,21 +981,19 @@ <h1>Assignments</h1>
991981
header.className = 'group-header';
992982
header.textContent = completionGroupLabel(k);
993983
elList.appendChild(header);
994-
groups.get(k).forEach(it => elList.appendChild(renderItem(it)));
984+
groups.get(k).forEach(it => elList.appendChild(renderItem(it, classMap)));
995985
});
996986
} else {
997-
xs.forEach(it => elList.appendChild(renderItem(it)));
987+
xs.forEach(it => elList.appendChild(renderItem(it, classMap)));
998988
}
999989
elListMeta.textContent = xs.length ? `${xs.length} shown` : '';
1000990
}
1001991

1002-
function renderItem(it) {
1003-
const cls = classes.find(c => c.id === it.classId);
992+
function renderItem(it, classMap) {
993+
const cls = classMap.get(it.classId);
1004994
const u = urgencyClass(it);
1005995
const row = document.createElement('div');
1006996
row.className = 'item ' + u;
1007-
if (cls) row.style.setProperty('--class-color', cls.color);
1008-
1009997
const check = document.createElement('button');
1010998
check.className = 'item-check';
1011999
check.title = it.status === 'done' ? 'Mark as not done' : 'Mark done';
@@ -1111,9 +1099,9 @@ <h1>Assignments</h1>
11111099
del.textContent = '×';
11121100
del.title = 'Delete';
11131101
del.addEventListener('click', () => {
1114-
const snapshot = JSON.parse(JSON.stringify(items));
1102+
const index = items.indexOf(it);
11151103
const wasRecurring = !!it.recurrence && !it.spawnedChild;
1116-
items = items.filter(x => x.id !== it.id);
1104+
items.splice(index, 1);
11171105
save(K_ITEMS, items);
11181106
renderAll();
11191107
const msg = wasRecurring
@@ -1122,7 +1110,7 @@ <h1>Assignments</h1>
11221110
showToast(msg, {
11231111
duration: 5000,
11241112
action: { label: 'Undo', onClick: () => {
1125-
items = snapshot;
1113+
items.splice(Math.min(index, items.length), 0, it);
11261114
save(K_ITEMS, items);
11271115
renderAll();
11281116
}}
@@ -1146,11 +1134,14 @@ <h1>Assignments</h1>
11461134
const elStats = document.getElementById('stats-row');
11471135
const elDashSub = document.getElementById('dash-sub');
11481136
function renderStats() {
1149-
const open = items.filter(i => i.status !== 'done');
1150-
const overdue = open.filter(i => dayDiff(i.due) < 0).length;
1151-
const today = open.filter(i => dayDiff(i.due) === 0).length;
1152-
const week = open.filter(i => { const d = dayDiff(i.due); return d > 0 && d < 7; }).length;
1153-
const doneEver = items.filter(i => i.status === 'done').length;
1137+
let overdue = 0, today = 0, week = 0, doneEver = 0;
1138+
for (const i of items) {
1139+
if (i.status === 'done') { doneEver++; continue; }
1140+
const d = dayDiff(i.due);
1141+
if (d < 0) overdue++;
1142+
else if (d === 0) today++;
1143+
else if (d < 7) week++;
1144+
}
11541145
elStats.innerHTML = '';
11551146
[
11561147
[overdue, 'Overdue', 'overdue'],
@@ -1168,10 +1159,8 @@ <h1>Assignments</h1>
11681159

11691160
// ─────────────── Pomodoro handoff ───────────────
11701161
function sendToPomodoro(it) {
1171-
// load pomo state (or start a fresh one for today)
11721162
const today = todayKey();
1173-
let pomo;
1174-
try { pomo = JSON.parse(localStorage.getItem(K_POMO) || 'null'); } catch { pomo = null; }
1163+
let pomo = load(K_POMO, null);
11751164
if (!pomo || pomo.date !== today) {
11761165
pomo = {
11771166
date: today, queue: [], currentIdx: 0, phase: 'idle',
@@ -1188,9 +1177,8 @@ <h1>Assignments</h1>
11881177
plannedMins: mins,
11891178
sourceAssignmentId: it.id
11901179
});
1191-
localStorage.setItem(K_POMO, JSON.stringify(pomo));
1180+
save(K_POMO, pomo);
11921181

1193-
// mark as in progress
11941182
if (it.status === 'todo') {
11951183
it.status = 'doing';
11961184
save(K_ITEMS, items);

0 commit comments

Comments
 (0)