diff --git a/src/components/Sidebar.js b/src/components/Sidebar.js new file mode 100644 index 0000000..24e2e6c --- /dev/null +++ b/src/components/Sidebar.js @@ -0,0 +1,48 @@ +import { auth } from '../services/auth.js'; +import { getPages } from '../pages/pagesRegistry.js'; + +export function renderSidebar() { + const sidebar = document.createElement('aside'); + sidebar.className = 'sidebar'; + + const appName = document.createElement('div'); + appName.className = 'sidebar-brand'; + appName.textContent = 'Aventa'; + + const nav = document.createElement('nav'); + nav.className = 'sidebar-nav'; + + const items = getPages().map(p => ({ label: p.label, hash: p.hash })); + + items.forEach(({ label, hash }) => { + const link = document.createElement('a'); + link.className = 'nav-link'; + link.href = hash; + link.textContent = label; + + if (window.location.hash === hash) { + link.classList.add('active'); + } + + nav.appendChild(link); + }); + + const footer = document.createElement('div'); + footer.className = 'sidebar-footer'; + + const logoutBtn = document.createElement('button'); + logoutBtn.className = 'logout-button'; + logoutBtn.textContent = 'Log out'; + logoutBtn.addEventListener('click', () => { + auth.logout(); + window.location.hash = '#login'; + }); + + footer.appendChild(logoutBtn); + + sidebar.appendChild(appName); + sidebar.appendChild(nav); + sidebar.appendChild(footer); + + return sidebar; +} diff --git a/src/pages/pagesRegistry.js b/src/pages/pagesRegistry.js new file mode 100644 index 0000000..e68ffe9 --- /dev/null +++ b/src/pages/pagesRegistry.js @@ -0,0 +1,53 @@ +function toLabel(name) { + return name + .replace(/([a-z])([A-Z])/g, '$1 $2') + .replace(/^./, s => s.toUpperCase()); +} + +function toHash(name) { + return `#${name.toLowerCase()}`; +} + +function findRender(mod) { + if (typeof mod.renderPage === 'function') return mod.renderPage; + for (const key of Object.keys(mod)) { + const val = mod[key]; + if (typeof val === 'function' && /^render/i.test(key)) return val; + } + if (typeof mod.default === 'function') return mod.default; + return null; +} + +const modules = import.meta.glob('./*.js', { eager: true }); + +const bannedPages = ['LoginPage.js']; + +const pages = Object.entries(modules) + .map(([path, mod]) => { + const file = path.split('/').pop(); + const base = file.replace('.js', ''); + if (bannedPages.includes(file)) return null; + + // Derive page name from filename, strip common suffix "Page" + const name = base.replace(/Page$/, ''); + const render = findRender(mod); + if (!render) return null; + + return { + path, + name, + label: toLabel(name), + hash: toHash(name), + render + }; + }) + .filter(Boolean) + .sort((a, b) => a.label.localeCompare(b.label)); + +export function getPages() { + return pages.slice(); +} + +export function getPageByHash(hash) { + return pages.find(p => p.hash === hash) || null; +} diff --git a/src/pages/test.js b/src/pages/test.js new file mode 100644 index 0000000..5579423 --- /dev/null +++ b/src/pages/test.js @@ -0,0 +1,11 @@ +export function renderDashboard() { + const container = document.createElement('div'); + container.className = 'dashboard'; + + container.innerHTML = ` +
esto es un test
+