refactor: replace Jinja templates with static frontend pages
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* Hoover — router.js
|
||||
*
|
||||
* Hash-based SPA router with reactive state (triggers re-render on
|
||||
* navigation). Link component for client-side navigation.
|
||||
*/
|
||||
|
||||
import { reactive } from './reactivity.js';
|
||||
import { h } from './vdom.js';
|
||||
|
||||
/**
|
||||
* Hash-based router.
|
||||
*
|
||||
* const router = createRouter({
|
||||
* '/dashboard': () => h('#comp', { component: DashboardPage, key: '/dashboard' }, []),
|
||||
* '/interfaces': () => h('#comp', { component: InterfacesPage, key: '/interfaces' }, []),
|
||||
* '*': () => h('#comp', { component: NotFoundPage, key: '*' }, []),
|
||||
* });
|
||||
*
|
||||
* Reactive `router.state.path` updates trigger re-renders automatically.
|
||||
*/
|
||||
export function createRouter(routes) {
|
||||
const initialPath = location.hash.slice(1) || '/dashboard';
|
||||
if (!location.hash) location.hash = initialPath;
|
||||
|
||||
const state = reactive({ path: initialPath });
|
||||
|
||||
window.addEventListener('hashchange', () => {
|
||||
state.path = location.hash.slice(1) || '/dashboard';
|
||||
});
|
||||
|
||||
const component = () => {
|
||||
const handler = routes[state.path] || routes['*'];
|
||||
if (!handler) {
|
||||
return h('div', { class: 'card' },
|
||||
h('div', { class: 'text-muted' }, `404 — Not found: ${state.path}`));
|
||||
}
|
||||
try {
|
||||
return handler();
|
||||
} catch (e) {
|
||||
return h('div', { class: 'card' },
|
||||
h('div', { class: 'text-muted' }, `Error: ${e.message || String(e)}`));
|
||||
}
|
||||
};
|
||||
|
||||
return { state, navigate: (p) => { location.hash = p; }, component };
|
||||
}
|
||||
|
||||
/**
|
||||
* Client-side navigation link component.
|
||||
* Sets `location.hash` without full page navigation.
|
||||
*/
|
||||
export function Link(props) {
|
||||
const { path, class: cls, children, ...rest } = props || {};
|
||||
return h('a', {
|
||||
href: '#' + path,
|
||||
class: cls || '',
|
||||
'on:click': (e) => { e.preventDefault(); location.hash = path; },
|
||||
...rest,
|
||||
}, children || []);
|
||||
}
|
||||
Reference in New Issue
Block a user