feat: certificates, landing pages, ai tutor, website update, compliance

This commit is contained in:
Rotimi Best
2026-05-18 03:47:22 +01:00
parent c31ad63955
commit ac3a2c14a7
644 changed files with 56050 additions and 5439 deletions
@@ -0,0 +1,69 @@
import type { SidePanelDefinition, SidePanelScope } from './types';
class SidePanelStore {
private definitions = $state<Map<string, SidePanelDefinition>>(new Map());
activePanelId = $state<string | null>(null);
panelProps = $state<Record<string, unknown>>({});
register(definition: SidePanelDefinition) {
this.definitions.set(definition.id, definition);
}
list(): SidePanelDefinition[] {
return Array.from(this.definitions.values());
}
get(id: string): SidePanelDefinition | undefined {
return this.definitions.get(id);
}
get activeDefinition(): SidePanelDefinition | null {
if (!this.activePanelId) return null;
return this.definitions.get(this.activePanelId) ?? null;
}
open(id: string, props: Record<string, unknown> = {}) {
if (!this.definitions.has(id)) {
console.warn(`sidePanel.open: no panel registered with id "${id}"`);
return;
}
this.activePanelId = id;
this.panelProps = props;
}
toggle(id: string, props: Record<string, unknown> = {}) {
if (this.activePanelId === id) {
this.close();
return;
}
this.open(id, props);
}
close() {
this.activePanelId = null;
this.panelProps = {};
}
closeIfScope(scope: SidePanelScope) {
if (!this.activePanelId) return;
const def = this.definitions.get(this.activePanelId);
if (!def) return;
if (def.scope === scope) {
this.close();
}
}
reset() {
this.close();
}
}
export const sidePanel = new SidePanelStore();