feat(terminal): add Life OS command interface

This commit is contained in:
Codex committed 2026-09-28 12:07:57 +09:00
1 parent 93d0487617
commit 8a1dee3c49
15 files changed
+321 -34

No files matched your search

+4 -6
View File
@@ -43,11 +43,9 @@
event.preventDefault();
const form = event.currentTarget, input = form.querySelector('#task-new-title'), title = input.value.trim();
if (!title) return;
const data = board();
data.tasks.push({ id: `task_${crypto.randomUUID()}`, title, dueDate: form.querySelector('#task-new-date').value || '', goalId: form.querySelector('#task-new-goal').value || '', priority: form.querySelector('#task-new-priority').value || 'normal', done: false, createdAt: new Date().toISOString() });
persist(data); toast('tasks.taskAdded');
window.LifeOSActions.createTask({ title, dueDate: form.querySelector('#task-new-date').value || '', goalId: form.querySelector('#task-new-goal').value || '', priority: form.querySelector('#task-new-priority').value || 'normal' }); toast('tasks.taskAdded');
};
window.toggleTask = id => { const data = board(), task = data.tasks.find(item => item.id === id); if (!task) return; task.done = !task.done; task.completedAt = task.done ? new Date().toISOString() : null; persist(data); };
window.toggleTask = id => { const task = board().tasks.find(item => item.id === id); if (task) window.LifeOSActions.setTaskDone(id, !task.done); };
window.deleteTask = id => { const data = board(); data.tasks = data.tasks.filter(item => item.id !== id); persist(data); toast('tasks.taskRemoved'); };
window.openGoalForm = () => {
document.querySelector('#modal').innerHTML = `<div class="modal" onclick="if(event.target===this) closeModal()"><form class="modalbox goal-form" onsubmit="saveGoal(event)" role="dialog" aria-modal="true" aria-labelledby="goal-form-title"><button type="button" class="modal-close" onclick="closeModal()" aria-label="${LifeI18n.t('common.close')}">×</button><div class="eyebrow">${t('eyebrow')}</div><h2 id="goal-form-title">${t('goalTitle')}</h2><label>${t('goalPlaceholder')}<input id="goal-new-title" maxlength="100" required autofocus></label><label>${t('goalDescription')}<textarea id="goal-new-description" maxlength="240" rows="3"></textarea></label><label>${t('target')}<input id="goal-new-date" type="date" oninput="document.querySelector('#goal-new-desktop').disabled=!this.value"></label><label class="goal-pin-option"><input id="goal-new-desktop" type="checkbox" disabled>${t('pinOnCreate')}</label><div class="actions"><button class="primary" type="submit">${t('save')}</button><button class="secondary" type="button" onclick="closeModal()">${t('cancel')}</button></div></form></div>`;
@@ -55,8 +53,8 @@
};
window.saveGoal = event => {
event.preventDefault(); const title = document.querySelector('#goal-new-title').value.trim(); if (!title) return;
const data = board(); data.goals.unshift({ id: `goal_${crypto.randomUUID()}`, title, description: document.querySelector('#goal-new-description').value.trim(), targetDate: document.querySelector('#goal-new-date').value || '', showOnDesktop: document.querySelector('#goal-new-desktop').checked, done: false, createdAt: new Date().toISOString() });
document.querySelector('#modal').innerHTML = ''; persist(data); toast('tasks.goalCreated');
window.LifeOSActions.createGoal({ title, description: document.querySelector('#goal-new-description').value.trim(), targetDate: document.querySelector('#goal-new-date').value || '', showOnDesktop: document.querySelector('#goal-new-desktop').checked });
document.querySelector('#modal').innerHTML = ''; toast('tasks.goalCreated');
};
window.toggleGoalDesktop = id => { const data = board(), goal = data.goals.find(item => item.id === id); if (!goal || !goal.targetDate) return; goal.showOnDesktop = !goal.showOnDesktop; persist(data); };
window.renderDesktopGoalCountdowns = () => { const container = document.querySelector('#desktop-goal-countdowns'); if (!container) return; const goals = board().goals.filter(goal => !goal.done && goal.targetDate && goal.showOnDesktop); if (!goals.length) { container.innerHTML = ''; container.classList.add('hidden'); return; } container.classList.remove('hidden'); const now = new Date(), todayUtc = Date.UTC(now.getFullYear(), now.getMonth(), now.getDate()); container.innerHTML = `<div class="desktop-goal-heading">${t('countdown')}</div>${goals.map(goal => { const [year, month, date] = goal.targetDate.split('-').map(Number), delta = Math.round((Date.UTC(year, month - 1, date) - todayUtc) / 864e5), count = Math.abs(delta), label = delta === 0 ? t('todayTarget') : delta > 0 ? t('daysLeft', { count }) : t('daysOverdue', { count }); return `<button class="desktop-goal-card" onclick="openApp('tasks')"><span>${esc(goal.title)}</span><strong>${label}</strong><small>${dateLabel(goal.targetDate)}</small></button>`; }).join('')}`; };