diff --git a/js/app.js b/js/app.js
index 787d08a..99fdef5 100644
--- a/js/app.js
+++ b/js/app.js
@@ -1,13 +1,22 @@
-import { store } from './store.js';
-import { extractTasksFromText } from './utils/api.js';
-import { initGlobalErrorBoundary } from './utils/errorBoundary.js';
-import { analyzeWorkload } from './utils/scheduler.js';
-import { Toast } from './utils/toast.js';
+import { store } from "./store.js";
+import { extractTasksFromText } from "./utils/api.js";
+import { initGlobalErrorBoundary } from "./utils/errorBoundary.js";
+import { analyzeWorkload } from "./utils/scheduler.js";
+import { Toast } from "./utils/toast.js";
initGlobalErrorBoundary();
function getLabelColor(labelStr) {
- const colors = ['#ef4444', '#f59e0b', '#3b82f6', '#8b5cf6', '#10b981', '#ec4899', '#14b8a6', '#f97316'];
+ const colors = [
+ "#ef4444",
+ "#f59e0b",
+ "#3b82f6",
+ "#8b5cf6",
+ "#10b981",
+ "#ec4899",
+ "#14b8a6",
+ "#f97316",
+ ];
let hash = 0;
for (let i = 0; i < labelStr.length; i++) {
hash = labelStr.charCodeAt(i) + ((hash << 5) - hash);
@@ -22,11 +31,11 @@ function extractLabels(title) {
while ((match = labelRegex.exec(title)) !== null) {
labels.push(match[1]);
}
- const cleanTitle = title.replace(labelRegex, '').trim();
+ const cleanTitle = title.replace(labelRegex, "").trim();
return { cleanTitle, labels };
}
-let activeLabelFilter = '';
+let activeLabelFilter = "";
function generateSummary(tasks, subjects) {
const now = new Date();
@@ -37,8 +46,8 @@ function generateSummary(tasks, subjects) {
let weekCount = 0;
let subjectCount = {};
- tasks.forEach(t => {
- if (t.archived || t.status === 'Done' || !t.due_at) return;
+ tasks.forEach((t) => {
+ if (t.archived || t.status === "Done" || !t.due_at) return;
const d = new Date(t.due_at);
@@ -52,16 +61,16 @@ function generateSummary(tasks, subjects) {
weekCount++;
}
- const sub = subjects.find(s => s.id === t.subject_id);
- const name = sub ? sub.name : 'General';
+ const sub = subjects.find((s) => s.id === t.subject_id);
+ const name = sub ? sub.name : "General";
subjectCount[name] = (subjectCount[name] || 0) + 1;
});
const topSubject = Object.keys(subjectCount).length
? Object.keys(subjectCount).reduce((a, b) =>
- subjectCount[a] > subjectCount[b] ? a : b
+ subjectCount[a] > subjectCount[b] ? a : b,
)
- : 'no specific subject';
+ : "no specific subject";
return `
📅 Daily
@@ -76,114 +85,125 @@ function generateSummary(tasks, subjects) {
let currentMonthDate = new Date();
let selectedDate = null;
-let currentView = 'calendar'; // 'calendar', 'all-tasks', 'archived'
-
-const tasksSection = document.getElementById('tasks-section');
-const focusSection = document.getElementById('focus-section');
-const extractPreview = document.getElementById('extract-preview');
-const pasteInput = document.getElementById('paste-input');
-const extractBtn = document.getElementById('extract-btn');
-const clearBtn = document.getElementById('clear-btn');
-const addItemsBtn = document.getElementById('add-btn');
-const downloadBtn = document.getElementById('download-btn');
-const calendarDownloadBtn = document.getElementById('calendar-download-btn');
-const newTaskBtn = document.getElementById('add-task-btn');
-const labelFilterSelect = document.getElementById('label-filter');
+let currentView = "calendar"; // 'calendar', 'all-tasks', 'archived'
+
+const tasksSection = document.getElementById("tasks-section");
+const focusSection = document.getElementById("focus-section");
+const extractPreview = document.getElementById("extract-preview");
+const pasteInput = document.getElementById("paste-input");
+const extractBtn = document.getElementById("extract-btn");
+const clearBtn = document.getElementById("clear-btn");
+const addItemsBtn = document.getElementById("add-btn");
+const downloadBtn = document.getElementById("download-btn");
+const calendarDownloadBtn = document.getElementById("calendar-download-btn");
+const newTaskBtn = document.getElementById("add-task-btn");
+const labelFilterSelect = document.getElementById("label-filter");
if (labelFilterSelect) {
- labelFilterSelect.addEventListener('change', (e) => {
+ labelFilterSelect.addEventListener("change", (e) => {
activeLabelFilter = e.target.value;
renderTasks();
});
}
const SUBJECT_COLORS = [
- 'var(--color-text-info)',
- 'var(--color-text-success)',
- 'var(--color-text-purple)',
- 'var(--color-text-warning)',
- 'var(--color-text-danger)',
- 'var(--color-text-secondary)',
+ "var(--color-text-info)",
+ "var(--color-text-success)",
+ "var(--color-text-purple)",
+ "var(--color-text-warning)",
+ "var(--color-text-danger)",
+ "var(--color-text-secondary)",
];
let selectedNewSubjectColor = SUBJECT_COLORS[0];
function escapeHtml(s) {
return String(s)
- .replace(/&/g, '&')
- .replace(//g, '>')
- .replace(/"/g, '"');
+ .replace(/&/g, "&")
+ .replace(//g, ">")
+ .replace(/"/g, """);
}
-const newSubjectModal = document.getElementById('new-subject-modal');
-const newSubjectName = document.getElementById('new-subject-name');
-const newSubjectColorsEl = document.getElementById('new-subject-colors');
-const newSubjectCancel = document.getElementById('new-subject-cancel');
-const newSubjectSave = document.getElementById('new-subject-save');
-const addSubjectBtn = document.getElementById('add-subject-btn');
+const newSubjectModal = document.getElementById("new-subject-modal");
+const newSubjectName = document.getElementById("new-subject-name");
+const newSubjectColorsEl = document.getElementById("new-subject-colors");
+const newSubjectCancel = document.getElementById("new-subject-cancel");
+const newSubjectSave = document.getElementById("new-subject-save");
+const addSubjectBtn = document.getElementById("add-subject-btn");
function syncNewSubjectColorSwatches() {
if (!newSubjectColorsEl) return;
- newSubjectColorsEl.querySelectorAll('.subject-color-swatch').forEach(btn => {
- const on = btn.dataset.color === selectedNewSubjectColor;
- btn.classList.toggle('subject-color-swatch--selected', on);
- btn.setAttribute('aria-pressed', on ? 'true' : 'false');
- });
+ newSubjectColorsEl
+ .querySelectorAll(".subject-color-swatch")
+ .forEach((btn) => {
+ const on = btn.dataset.color === selectedNewSubjectColor;
+ btn.classList.toggle("subject-color-swatch--selected", on);
+ btn.setAttribute("aria-pressed", on ? "true" : "false");
+ });
}
function openNewSubjectModal() {
if (!newSubjectModal || !newSubjectName) return;
- newSubjectName.value = '';
+ newSubjectName.value = "";
selectedNewSubjectColor = SUBJECT_COLORS[0];
syncNewSubjectColorSwatches();
- newSubjectModal.style.display = 'flex';
+ newSubjectModal.style.display = "flex";
newSubjectName.focus();
}
function renderSidebarSubjects() {
- const listEl = document.getElementById('subjects-sidebar-list');
+ const listEl = document.getElementById("subjects-sidebar-list");
if (!listEl) return;
const subjects = store.subjects;
const tasks = store.tasks;
const countBySubject = {};
- subjects.forEach(s => {
+ subjects.forEach((s) => {
countBySubject[s.id] = 0;
});
- tasks.forEach(t => {
- if (t.archived || !t.subject_id || countBySubject[t.subject_id] === undefined) return;
+ tasks.forEach((t) => {
+ if (
+ t.archived ||
+ !t.subject_id ||
+ countBySubject[t.subject_id] === undefined
+ )
+ return;
countBySubject[t.subject_id]++;
});
- listEl.innerHTML = subjects.map(s => {
- const n = countBySubject[s.id] ?? 0;
- const safeColor = s.color ? escapeHtml(s.color) : 'var(--color-text-info)';
- return `