import '@signature.digital/catalog';
import { html, render } from '@design.estate/dees-element';
type TWorkspaceView = 'inbox' | 'compose' | 'sign' | 'audit' | 'developers' | 'templates' | 'team' | 'settings';
type TDocumentRow = {
id: string;
title: string;
status: 'awaiting' | 'signed' | 'draft' | 'declined';
recipients: Array<{ name: string; initials: string; signed: boolean }>;
updated: string;
sender: string;
pages: number;
deadline?: string;
};
const workspaceViews: TWorkspaceView[] = ['inbox', 'compose', 'sign', 'audit', 'developers', 'templates', 'team', 'settings'];
const appDocuments: TDocumentRow[] = [
{ id: 'app_doc_001', title: 'Platform Services Agreement - App-owned data', status: 'awaiting', recipients: [{ name: 'Sarah Chen', initials: 'SC', signed: true }, { name: 'David Park', initials: 'DP', signed: false }], updated: 'just now', sender: 'App Service', pages: 14, deadline: 'May 5' },
{ id: 'app_doc_002', title: 'Security Addendum - Catalog Integration', status: 'draft', recipients: [{ name: 'Philipp K.', initials: 'PK', signed: false }], updated: '12 min ago', sender: 'App Service', pages: 5 },
{ id: 'app_doc_003', title: 'Completed Vendor NDA - Signed from App', status: 'signed', recipients: [{ name: 'Lila Brooks', initials: 'LB', signed: true }, { name: 'Philipp K.', initials: 'PK', signed: true }], updated: '1h ago', sender: 'App Service', pages: 3 },
];
const isWorkspaceView = (view: string): view is TWorkspaceView => workspaceViews.includes(view as TWorkspaceView);
const routeFromLocation = (): { view: TWorkspaceView; documentId: string } => {
const [view = '', documentId = ''] = globalThis.location.hash.replace(/^#/, '').split(':');
return { view: isWorkspaceView(view) ? view : 'inbox', documentId };
};
const hashForRoute = (view: TWorkspaceView, documentId = ''): string => {
return documentId && (view === 'sign' || view === 'audit') ? `#${view}:${documentId}` : `#${view}`;
};
let currentRoute = routeFromLocation();
let currentView = currentRoute.view;
let activeDocumentId = currentRoute.documentId;
let appRoot: HTMLElement | null = null;
let routeChangeFrame: number | null = null;
const createAppRoot = () => {
document.getElementById('signature-digital-app')?.remove();
appRoot = document.createElement('div');
appRoot.id = 'signature-digital-app';
document.body.append(appRoot);
};
const handleViewChange = (event: Event) => {
const view = (event as CustomEvent<{ view?: TWorkspaceView }>).detail?.view;
if (!view || !isWorkspaceView(view)) return;
currentView = view;
const nextHash = hashForRoute(view, activeDocumentId);
if (globalThis.location.hash !== nextHash) {
globalThis.location.hash = nextHash.slice(1);
}
};
const handleDocumentOpen = (event: Event) => {
const document = (event as CustomEvent<{ document?: TDocumentRow }>).detail?.document;
if (!document) return;
activeDocumentId = document.id;
};
const handleWorkspaceViewRequest = (event: Event) => {
const view = (event as CustomEvent<{ view?: TWorkspaceView }>).detail?.view;
if (!view || !isWorkspaceView(view)) return;
currentView = view;
const nextHash = hashForRoute(view, activeDocumentId);
if (globalThis.location.hash !== nextHash) {
globalThis.location.hash = nextHash.slice(1);
} else {
renderApp();
}
};
const handleRouteChange = () => {
if (routeChangeFrame !== null) {
globalThis.cancelAnimationFrame(routeChangeFrame);
}
routeChangeFrame = globalThis.requestAnimationFrame(() => {
routeChangeFrame = null;
currentRoute = routeFromLocation();
currentView = currentRoute.view;
activeDocumentId = currentRoute.documentId;
renderApp();
});
};
const renderApp = () => {
if (!appRoot) createAppRoot();
render(
html`
`,
appRoot!
);
};
const run = async () => {
createAppRoot();
document.body.addEventListener('view-change', handleViewChange);
document.body.addEventListener('document-open', handleDocumentOpen);
document.body.addEventListener('workspace-view-request', handleWorkspaceViewRequest);
globalThis.addEventListener('popstate', handleRouteChange);
globalThis.addEventListener('hashchange', handleRouteChange);
renderApp();
};
run();