provinans / frontend /src /session.ts
reversely's picture
Upload folder using huggingface_hub
c9a1ce7 verified
Raw
History Blame Contribute Delete
2.66 kB
// The reviewer session identity: the name and role every confirmation is attributed to. It comes from
// the per-user login (#128), set once when a reviewer signs in (LoginBar.tsx) and cleared on sign-out,
// not a field re-entered on each decision. PRD sections 4.4 and 8.4: each confirmed value records who
// confirmed it and in what role, so the identity has to be the session's.
//
// localStorage rather than sessionStorage, matching the session token: a reload should not drop a
// reviewer out of their session. The corpus is public de-identified TCGA data, and this is a
// local-first tool.
//
// Identity changes are observable. setIdentity and clearIdentity dispatch a window CustomEvent so a
// screen reflects login and logout without a reload; subscribeIdentity also listens for the cross-tab
// "storage" event so a sign-in in another tab updates this one.
const NAME_KEY = "endopath.reviewerName";
const ROLE_KEY = "endopath.reviewerRole";
const IDENTITY_EVENT = "endopath:identity";
// The roles PRD section 4.4 distinguishes: a licensed pathologist confirms the pathology variables; a
// data manager or curator abstracts the rest. Offered as a fixed set so the recorded role reads
// consistently across the ledger.
export const REVIEWER_ROLES = ["pathologist", "data manager", "curator"] as const;
export type ReviewerRole = (typeof REVIEWER_ROLES)[number];
export interface ReviewerIdentity {
name: string;
role: string;
}
export function getIdentity(): ReviewerIdentity {
return {
name: localStorage.getItem(NAME_KEY) ?? "",
role: localStorage.getItem(ROLE_KEY) ?? "",
};
}
export function setIdentity(identity: ReviewerIdentity): void {
localStorage.setItem(NAME_KEY, identity.name.trim());
localStorage.setItem(ROLE_KEY, identity.role.trim());
window.dispatchEvent(new CustomEvent(IDENTITY_EVENT));
}
export function clearIdentity(): void {
localStorage.removeItem(NAME_KEY);
localStorage.removeItem(ROLE_KEY);
window.dispatchEvent(new CustomEvent(IDENTITY_EVENT));
}
export function hasIdentity(): boolean {
const { name, role } = getIdentity();
return name.trim().length > 0 && role.trim().length > 0;
}
// Subscribe to identity changes: the in-tab CustomEvent from setIdentity/clearIdentity, and the
// cross-tab "storage" event so a sign-in or sign-out in another tab updates this one. Returns an
// unsubscribe.
export function subscribeIdentity(cb: () => void): () => void {
window.addEventListener(IDENTITY_EVENT, cb);
window.addEventListener("storage", cb);
return () => {
window.removeEventListener(IDENTITY_EVENT, cb);
window.removeEventListener("storage", cb);
};
}