f084656712
Agenda (multi-secretária): - audit_log genérico + autoria (created/updated/canceled_by) + soft-delete + version (lock otimista) - status novo vocabulário + índice único PARCIAL (libera slot ao cancelar/faltar) - endpoints: falta, remarcar, restaurar, historico, pendencias (a reagendar), faltas, familia - presença: heartbeat (DB última visita + Dragonfly ao vivo, janela 45s) - frontend: StackModal, AgendaDetailModal, AgendaPresence; lista a-reagendar; pacienteId no fluxo de criação; chips de família + badge de faltas no modal RBAC por cargo: funcoes.permissoes/nivel; gate de menu por cargo (array vazio herda role); hierarquia só-gerencia-abaixo no backend Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
32 lines
1.1 KiB
TypeScript
32 lines
1.1 KiB
TypeScript
export const ACTIVE_PLUGINS_KEY = 'SCOREODONTO_ACTIVE_PLUGINS';
|
|
export const PLUGIN_CONFIG_KEY = 'SCOREODONTO_PLUGIN_CONFIG';
|
|
|
|
export const getActivePlugins = (): string[] => {
|
|
try { return JSON.parse(localStorage.getItem(ACTIVE_PLUGINS_KEY) || '[]'); }
|
|
catch { return []; }
|
|
};
|
|
|
|
export const isPluginActive = (id: string): boolean => getActivePlugins().includes(id);
|
|
|
|
export const togglePlugin = (id: string): boolean => {
|
|
const active = getActivePlugins();
|
|
const wasActive = active.includes(id);
|
|
const next = wasActive ? active.filter(p => p !== id) : [...active, id];
|
|
localStorage.setItem(ACTIVE_PLUGINS_KEY, JSON.stringify(next));
|
|
return !wasActive;
|
|
};
|
|
|
|
export const getPluginConfig = (id: string): Record<string, string> => {
|
|
try {
|
|
const all = JSON.parse(localStorage.getItem(PLUGIN_CONFIG_KEY) || '{}');
|
|
return all[id] || {};
|
|
} catch { return {}; }
|
|
};
|
|
|
|
export const savePluginConfig = (id: string, config: Record<string, string>) => {
|
|
try {
|
|
const all = JSON.parse(localStorage.getItem(PLUGIN_CONFIG_KEY) || '{}');
|
|
localStorage.setItem(PLUGIN_CONFIG_KEY, JSON.stringify({ ...all, [id]: config }));
|
|
} catch {}
|
|
};
|