Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,31 @@ <h2>Account overview</h2>
<button id="extract-btn" class="btn btn-primary" style="flex:2;" aria-label="Extract tasks with AI">Extract with AI →</button>
</div>

<div class="manual-task-entry" style="margin: 20px 20px 0; padding: 28px; border-radius: 18px; background: var(--color-background-primary); border: 1px solid var(--color-border-secondary); box-shadow: var(--shadow-sm);">
<div style="margin-bottom: 22px;">
<div class="paste-label" style="margin-bottom: 12px;">Manual Task Entry</div>
<div style="font-size: 12px; color: var(--color-text-tertiary); margin-bottom: 16px;">Use this form when AI extraction isn't needed.</div>
</div>

<label class="paste-label" for="manual-task-subject" style="margin-bottom: 12px; display:block;">Subject</label>
<select id="manual-task-subject" style="width:100%; padding:12px; border-radius:12px; border:1px solid var(--color-border-secondary); background: var(--color-background-secondary); color: var(--color-text-primary); margin-bottom:16px; box-sizing:border-box;">
<option value="">Select subject</option>
</select>

<label class="paste-label" for="manual-task-title" style="margin-bottom: 12px; display:block;">Task Title</label>
<input id="manual-task-title" type="text" placeholder="Enter task title" style="width:100%; padding:12px; border-radius:12px; border:1px solid var(--color-border-secondary); background: var(--color-background-secondary); color: var(--color-text-primary); margin-bottom:16px; box-sizing:border-box;">

<label class="paste-label" for="manual-task-date" style="margin-bottom: 12px; display:block;">Due Date</label>
<input id="manual-task-date" type="datetime-local" style="width:100%; padding:12px; border-radius:12px; border:1px solid var(--color-border-secondary); background: var(--color-background-secondary); color: var(--color-text-primary); margin-bottom:16px; box-sizing:border-box;">

<label class="paste-label" for="manual-task-notes" style="margin-bottom: 12px; display:block;">Notes <span style="font-weight:400; color: var(--color-text-tertiary); font-size: 12px;">(optional)</span></label>
<textarea id="manual-task-notes" rows="3" placeholder="Add notes for this task" style="width:100%; padding:12px; border-radius:12px; border:1px solid var(--color-border-secondary); background: var(--color-background-secondary); color: var(--color-text-primary); margin-bottom:18px; box-sizing:border-box;"></textarea>

<div class="paste-actions" style="margin: 0;">
<button id="manual-task-submit" class="btn btn-primary" style="width:100%;" aria-label="Add task">Add Task</button>
</div>
</div>

<div id="extract-preview" class="extract-preview">
<!-- Javascript will inject extracted items here -->
</div>
Expand Down
65 changes: 65 additions & 0 deletions js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -357,8 +357,29 @@ const newTaskEstimatedDuration = document.getElementById('new-task-estimated-dur
const newTaskDurationSwitch = document.getElementById('new-task-duration-switch');
const newTaskDurationMin = document.getElementById('new-task-duration-min');
const newTaskDurationHr = document.getElementById('new-task-duration-hr');
const manualTaskSubject = document.getElementById('manual-task-subject');
const manualTaskTitle = document.getElementById('manual-task-title');
const manualTaskDate = document.getElementById('manual-task-date');
const manualTaskNotes = document.getElementById('manual-task-notes');
const manualTaskSubmit = document.getElementById('manual-task-submit');
let selectedTaskDurationUnit = 'minutes';

function renderManualTaskSubjects() {
if (!manualTaskSubject) return;

manualTaskSubject.innerHTML = `
<option value="">Select subject</option>
${store.subjects.map(s => `<option value="${escapeHtml(s.id)}">${escapeHtml(s.name)}</option>`).join('')}
`;
}

function clearManualTaskForm() {
if (manualTaskSubject) manualTaskSubject.value = '';
if (manualTaskTitle) manualTaskTitle.value = '';
if (manualTaskDate) manualTaskDate.value = '';
if (manualTaskNotes) manualTaskNotes.value = '';
}

// Timer elements
const timerText = document.getElementById('timer-text');
const timerPathRemaining = document.getElementById('timer-path-remaining');
Expand Down Expand Up @@ -1647,6 +1668,7 @@ store.subscribe(renderFocusTasks);
store.subscribe(renderProfileSection);
store.subscribe(renderSidebarSubjects);
store.subscribe(renderStreak);
store.subscribe(renderManualTaskSubjects);

document.addEventListener('DOMContentLoaded', () => {
if (newSubjectColorsEl) {
Expand Down Expand Up @@ -1846,6 +1868,49 @@ newTaskModal.addEventListener('click', (e) => {
newTaskModal.style.display = 'none';
}
});

manualTaskSubmit?.addEventListener('click', async () => {
if (!manualTaskSubject || !manualTaskTitle || !manualTaskDate) return;

const subject_id = manualTaskSubject.value;
const rawTitle = manualTaskTitle.value.trim();
const dueDateValue = manualTaskDate.value;
const notes = manualTaskNotes ? manualTaskNotes.value.trim() : '';

if (!subject_id) {
Toast.show('Please select a subject', 'warning');
return;
}

if (!rawTitle) {
Toast.show('Please enter a task title', 'warning');
return;
}

if (!dueDateValue) {
Toast.show('Please select a due date', 'warning');
return;
}

const due_at = new Date(dueDateValue).toISOString();
const { cleanTitle, labels } = extractLabels(rawTitle);

const manualTask = {
title: cleanTitle || rawTitle,
subject_id,
due_at,
notes,
priority: 'medium',
status: 'Not Started',
archived: 0,
labels
};

const result = await store.addTasks([manualTask]);
if (result && result.inserted > 0) {
clearManualTaskForm();
}
});

function setNewTaskDurationUnit(unit) {
selectedTaskDurationUnit = unit;
Expand Down
4 changes: 3 additions & 1 deletion js/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ export const store = {
// Backend error
Toast.show(`❌ ${data.message || "Failed to add tasks"}`, 'error');
console.error('Add task error:', data);
return;
return data;
}

// ================= USER MESSAGES =================
Expand All @@ -151,9 +151,11 @@ export const store = {
this.tasks = await tasksRes.json();
this.notify();

return data;
} catch (e) {
console.error('Failed to add tasks', e);
Toast.show("❌ Network error. Please try again.", 'error');
return null;
}
},

Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.