// SimpleNote Web - Main Application import { api } from './api.js'; import { renderLogin, initLoginHandlers } from './views/login.js'; import { renderProjects } from './views/projects.js'; import { renderProjectView } from './views/projectView.js'; import { renderDashboard } from './views/dashboard.js'; import { renderDocument } from './views/document.js'; import { renderEditor } from './views/editor.js'; class App { constructor() { this.currentView = null; this.state = { token: localStorage.getItem('sn_token'), view: 'projects', // Default to projects view params: {} }; } async init() { if (!this.state.token) { this.renderLogin(); return; } api.setToken(this.state.token); try { await api.login(this.state.token); this.render(); } catch (e) { this.state.token = null; localStorage.removeItem('sn_token'); this.renderLogin(); } } renderLogin() { const app = document.getElementById('app'); app.innerHTML = renderLogin(); initLoginHandlers(async (token) => { try { await api.login(token); this.state.token = token; this.state.view = 'projects'; this.render(); } catch (e) { return 'Invalid token'; } }); } async render() { const app = document.getElementById('app'); switch (this.state.view) { case 'projects': await renderProjects(this); break; case 'project': await renderProjectView(this); break; case 'dashboard': await renderDashboard(this); break; case 'document': await renderDocument(this); break; case 'editor': renderEditor(this); break; default: await renderProjects(this); } } navigate(view, params = {}) { this.state.view = view; this.state.params = params; this.render(); } showToast(message, type = 'info') { const container = document.getElementById('toast-container'); const toast = document.createElement('div'); toast.className = `toast ${type}`; const escapedMessage = this.escapeHtml(message); toast.innerHTML = ` ${escapedMessage} `; container.appendChild(toast); setTimeout(() => toast.remove(), 4000); } escapeHtml(str) { if (!str) return ''; const div = document.createElement('div'); div.textContent = str; return div.innerHTML; } async confirmDelete(message) { return new Promise((resolve) => { const backdrop = document.createElement('div'); backdrop.className = 'modal-backdrop'; const escapedMessage = this.escapeHtml(message); backdrop.innerHTML = ` `; document.body.appendChild(backdrop); backdrop.querySelector('#cancel-btn').onclick = () => { backdrop.remove(); resolve(false); }; backdrop.querySelector('#confirm-btn').onclick = () => { backdrop.remove(); resolve(true); }; backdrop.onclick = (e) => { if (e.target === backdrop) { backdrop.remove(); resolve(false); } }; }); } } window.app = new App(); app.init(); // Keyboard shortcuts document.addEventListener('keydown', (e) => { if (e.key === 'Escape' && window.app.state.view === 'editor') { window.app.navigate('project', { id: window.app.state.params.projectId }); } if ((e.ctrlKey || e.metaKey) && e.key === 'n' && (window.app.state.view === 'projects' || window.app.state.view === 'project')) { e.preventDefault(); if (window.app.state.view === 'project') { window.showNewDocModal(window.app.state.params.id, ''); } else { window.showNewProjectModal(); } } });