feat(terminal): add Life OS command interface
This commit is contained in:
1 parent
93d0487617
commit
8a1dee3c49
15 files changed
+321
-34
No files matched your search
@@ -0,0 +1,50 @@
|
||||
/* Shared record writes for forms and the Life OS terminal. */
|
||||
(() => {
|
||||
const board = () => {
|
||||
const current = sys().tasksBoard;
|
||||
return current && Array.isArray(current.goals) && Array.isArray(current.tasks) ? current : { goals: [], tasks: [] };
|
||||
};
|
||||
const validDate = value => !value || (/^\d{4}-\d{2}-\d{2}$/.test(value) && !Number.isNaN(Date.parse(`${value}T12:00:00`)) && new Date(`${value}T12:00:00`).getFullYear() === Number(value.slice(0, 4)) && new Date(`${value}T12:00:00`).getMonth() + 1 === Number(value.slice(5, 7)) && new Date(`${value}T12:00:00`).getDate() === Number(value.slice(8)));
|
||||
const required = (value, max) => {
|
||||
const result = String(value || '').trim();
|
||||
if (!result || result.length > max) throw new Error('invalidTitle');
|
||||
return result;
|
||||
};
|
||||
const persistBoard = data => { const state = sys(); state.tasksBoard = data; save('lifeos_system', state); renderAll(); };
|
||||
window.LifeOSActions = {
|
||||
board,
|
||||
createGoal({ title, description = '', targetDate = '', showOnDesktop = false }) {
|
||||
title = required(title, 100);
|
||||
if (!validDate(targetDate)) throw new Error('invalidDate');
|
||||
const goal = { id: `goal_${crypto.randomUUID()}`, title, description: String(description).trim().slice(0, 240), targetDate, showOnDesktop: Boolean(targetDate && showOnDesktop), done: false, createdAt: new Date().toISOString() };
|
||||
const data = board(); data.goals.unshift(goal); persistBoard(data); return goal;
|
||||
},
|
||||
createTask({ title, dueDate = '', goalId = '', priority = 'normal' }) {
|
||||
title = required(title, 140);
|
||||
if (!validDate(dueDate)) throw new Error('invalidDate');
|
||||
if (!['normal', 'high', 'low'].includes(priority)) throw new Error('invalidPriority');
|
||||
const data = board();
|
||||
if (goalId && !data.goals.some(goal => goal.id === goalId)) throw new Error('notFound');
|
||||
const task = { id: `task_${crypto.randomUUID()}`, title, dueDate, goalId, priority, done: false, createdAt: new Date().toISOString() };
|
||||
data.tasks.push(task); persistBoard(data); return task;
|
||||
},
|
||||
setTaskDone(id, done) {
|
||||
const data = board(), task = data.tasks.find(item => item.id === id);
|
||||
if (!task) throw new Error('notFound');
|
||||
task.done = done; task.completedAt = done ? new Date().toISOString() : null;
|
||||
persistBoard(data); return task;
|
||||
},
|
||||
createMemory({ date = day(), title, text = '', mood = 'cloudy', energy = 3, tags = [], location = '', taskId = '', replace = false }) {
|
||||
title = String(title || '').trim();
|
||||
if (title.length > 120) throw new Error('invalidTitle');
|
||||
if (!validDate(date) || !date) throw new Error('invalidDate');
|
||||
if (!['clear', 'light', 'cloudy', 'rain', 'storm'].includes(mood) || !Number.isInteger(Number(energy)) || Number(energy) < 1 || Number(energy) > 5) throw new Error('invalidValue');
|
||||
if (taskId && !board().tasks.some(task => task.id === taskId)) throw new Error('notFound');
|
||||
const all = mems(), old = all.find(item => item.date === date);
|
||||
if (old && !replace) throw new Error('memoryExists');
|
||||
const film = filmFor(mood, Number(energy)), now = new Date().toISOString();
|
||||
const memory = { ...old, id: old?.id || `memory_${crypto.randomUUID()}`, date, title, text: String(text).trim(), mood, energy: Number(energy), tags: [...new Set(tags.map(tag => String(tag).trim()).filter(Boolean))].slice(0, 12), location: String(location).trim().slice(0, 100), taskId, filmTitle: film.filmTitle, filmSubtitle: film.filmSubtitle, filmLine: film.filmLine, createdAt: old?.createdAt || now, updatedAt: now };
|
||||
save('lifeos_memories', [...all.filter(item => item.date !== date), memory].sort((a, b) => b.date.localeCompare(a.date))); renderAll(); return memory;
|
||||
}
|
||||
};
|
||||
})();
|
||||
Reference in new issue
Block a user