Online Automated Morning & Evening Routine Planner

Morning & Evening Routine Planner

Good Morning!

Completion

0%

Wind Down

Completion

0%

Morning Routine Tasks

Evening Routine Tasks

Loading your routine...

${task.duration} minutes

`; }).join(''); }; const renderSettingsList = (type, tasks) => { const listEl = DOM[`${type}SettingsList`]; listEl.innerHTML = tasks.map(task => `
${task.name} (${task.duration} mins)
`).join(''); }; const updateProgress = () => { const calcProgress = (tasks) => { if (tasks.length === 0) return 0; const completedCount = tasks.filter(t => completions[todayKey] && completions[todayKey][t.id]).length; return Math.round((completedCount / tasks.length) * 100); }; DOM.morningProgressText.textContent = `${calcProgress(morningTasks)}%`; DOM.eveningProgressText.textContent = `${calcProgress(eveningTasks)}%`; }; // --- FIRESTORE OPERATIONS --- const addTask = async (type, name, duration) => { const appId = typeof __app_id !== 'undefined' ? __app_id : 'default-app-id'; const collectionPath = `/artifacts/${appId}/users/${userId}/${type}_tasks`; await addDoc(collection(db, collectionPath), { name, duration: Number(duration), createdAt: new Date() }); }; const deleteTask = async (type, taskId) => { if (!confirm("Are you sure you want to delete this task?")) return; const appId = typeof __app_id !== 'undefined' ? __app_id : 'default-app-id'; await deleteDoc(doc(db, `/artifacts/${appId}/users/${userId}/${type}_tasks`, taskId)); }; const toggleCompletion = async (taskId) => { const newCompletions = { ...(completions[todayKey] || {}) }; newCompletions[taskId] = !newCompletions[taskId]; const appId = typeof __app_id !== 'undefined' ? __app_id : 'default-app-id'; const completionRef = doc(db, `/artifacts/${appId}/users/${userId}/completions`, todayKey); await setDoc(completionRef, newCompletions); }; // --- PDF EXPORT --- const downloadPDF = () => { const { jsPDF } = window.jspdf; const doc = new jsPDF(); doc.setFontSize(18); doc.text("My Daily Routine Plan", 14, 22); doc.autoTable({ startY: 30, head: [['Morning Routine', 'Duration (mins)']], body: morningTasks.map(t => [t.name, t.duration]), theme: 'grid', headStyles: { fillColor: [79, 70, 229] } }); doc.autoTable({ startY: doc.lastAutoTable.finalY + 10, head: [['Evening Routine', 'Duration (mins)']], body: eveningTasks.map(t => [t.name, t.duration]), theme: 'grid', headStyles: { fillColor: [79, 70, 229] } }); doc.save("daily_routine_plan.pdf"); }; // --- INITIALIZATION --- document.addEventListener('DOMContentLoaded', async () => { // Assign DOM elements Object.assign(DOM, { currentDate: document.getElementById('current-date'), morningRoutineList: document.getElementById('morning-routine-list'), eveningRoutineList: document.getElementById('evening-routine-list'), morningSettingsList: document.getElementById('morning-settings-list'), eveningSettingsList: document.getElementById('evening-settings-list'), addMorningTaskForm: document.getElementById('add-morning-task-form'), addEveningTaskForm: document.getElementById('add-evening-task-form'), morningProgressText: document.getElementById('morning-progress-text'), eveningProgressText: document.getElementById('evening-progress-text'), morningNoTasks: document.getElementById('morning-no-tasks'), eveningNoTasks: document.getElementById('evening-no-tasks'), downloadPdfBtn: document.getElementById('download-pdf-btn'), loadingMessage: document.getElementById('loading-message') }); DOM.currentDate.textContent = new Date().toLocaleDateString('en-US', { weekday: 'long', year: 'numeric', month: 'long', day: 'numeric' }); // Event Listeners DOM.addMorningTaskForm.addEventListener('submit', (e) => { e.preventDefault(); addTask('morning', document.getElementById('morning-task-name').value, document.getElementById('morning-task-duration').value); e.target.reset(); }); DOM.addEveningTaskForm.addEventListener('submit', (e) => { e.preventDefault(); addTask('evening', document.getElementById('evening-task-name').value, document.getElementById('evening-task-duration').value); e.target.reset(); }); document.getElementById('tab-content-settings').addEventListener('click', (e) => { if (e.target.closest('.delete-task-btn')) { const { taskId, type } = e.target.closest('.delete-task-btn').dataset; deleteTask(type, taskId); } }); document.getElementById('morning-routine-list').addEventListener('change', (e) => { if (e.target.classList.contains('task-checkbox')) toggleCompletion(e.target.dataset.taskId); }); document.getElementById('evening-routine-list').addEventListener('change', (e) => { if (e.target.classList.contains('task-checkbox')) toggleCompletion(e.target.dataset.taskId); }); DOM.downloadPdfBtn.addEventListener('click', downloadPDF); // Firebase Initialization try { const firebaseConfig = JSON.parse(typeof __firebase_config !== 'undefined' ? __firebase_config : '{}'); const appId = typeof __app_id !== 'undefined' ? __app_id : 'default-app-id'; if (!firebaseConfig.apiKey) throw new Error("Firebase config missing."); const app = initializeApp(firebaseConfig); db = getFirestore(app); auth = getAuth(app); onAuthStateChanged(auth, (user) => { if (user) { userId = user.uid; if (morningTasksUnsubscribe) morningTasksUnsubscribe(); if (eveningTasksUnsubscribe) eveningTasksUnsubscribe(); if (completionsUnsubscribe) completionsUnsubscribe(); const createListener = (type) => { const q = query(collection(db, `/artifacts/${appId}/users/${userId}/${type}_tasks`), orderBy("createdAt")); return onSnapshot(q, (snap) => { if (type === 'morning') morningTasks = snap.docs.map(d => ({ id: d.id, ...d.data() })); else eveningTasks = snap.docs.map(d => ({ id: d.id, ...d.data() })); renderRoutines(); }); }; morningTasksUnsubscribe = createListener('morning'); eveningTasksUnsubscribe = createListener('evening'); const completionRef = doc(db, `/artifacts/${appId}/users/${userId}/completions`, todayKey); completionsUnsubscribe = onSnapshot(completionRef, (docSnap) => { completions[todayKey] = docSnap.exists() ? docSnap.data() : {}; updateProgress(); }); } }); if (typeof __initial_auth_token !== 'undefined' && __initial_auth_token) await signInWithCustomToken(auth, __initial_auth_token); else await signInAnonymously(auth); } catch (error) { console.error("Init Error:", error); DOM.loadingMessage.innerHTML = `

Could not connect. ${error.message}

`; } lucide.createIcons(); });
Scroll to Top