feat(plugins): Salas como add-on por conta (pessoa-cêntrico) + Visualizar como biomédico

Superadmin / Visualizar como:
- adiciona BIOMÉDICO(A) à lista de preview do superadmin
- enterPreview ativa os plugins (RX/Salas/Profissionais) p/ teste; exitPreview restaura

Locação de Salas — ativação POR USUÁRIO (independe de clínica):
- backend: tabela usuario_plugins + GET/POST /api/me/plugins (authGuard, sem tenant)
- sala continua dona=owner_usuario_id (pessoa) + salaID, clinica_id opcional
- backend.ts: getMyPlugins/setMyPlugin/hydrateMyPlugins; login + App montam o hydrate
- isViewAllowed: 'salas' liberado se plugin ativo na conta; catálogo 'plugins' p/ não-paciente
- Sidebar: entrada ADD-ONS/PLUGINS p/ papéis operacionais ativarem
- PluginsView: toggle de locacao-salas persiste no servidor
- escopo: só locacao-salas é server-backed (RX/Profissionais seguem localStorage)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
VPS 4 Builder
2026-06-13 15:04:25 +02:00
parent 98728b4e57
commit ca7eba4531
5 changed files with 108 additions and 1 deletions
+6 -1
View File
@@ -1,7 +1,7 @@
import React from 'react';
import {
Users, Calendar as CalendarIcon, LayoutDashboard,
DollarSign, RefreshCw, Activity, BookOpen, Award, Megaphone, LogOut, ClipboardList, Bell, Building2, User, BarChart3, Settings, FileText, Puzzle, ScanLine, Monitor, UsersRound, GraduationCap, UserSearch, Briefcase, TrendingUp, Eye, FlaskConical, DoorOpen
DollarSign, RefreshCw, Activity, BookOpen, Award, Megaphone, LogOut, ClipboardList, Bell, Building2, User, BarChart3, Settings, FileText, Puzzle, ScanLine, Monitor, UsersRound, GraduationCap, UserSearch, Briefcase, TrendingUp, Eye, FlaskConical, DoorOpen, Sparkles
} from 'lucide-react';
import { ToothIcon } from './ToothIcon.tsx';
import { HybridBackend } from '../services/backend.ts';
@@ -43,6 +43,10 @@ export const Sidebar: React.FC<SidebarProps> = ({ activeTab, setActiveTab }) =>
if (activePluginIds.includes('profissionais-marketplace') && currentRole !== 'superadmin' && currentRole !== 'paciente') {
pluginMenuItems.push({ id: 'marketplace-profissionais', label: 'PROFISSIONAIS', icon: UserSearch, color: '#ea580c' });
}
// Catálogo de add-ons (por conta): qualquer usuário operacional pode abrir p/ ativar (ex.: Salas).
if (currentRole !== 'superadmin' && currentRole !== 'paciente') {
pluginMenuItems.push({ id: 'plugins', label: 'ADD-ONS / PLUGINS', icon: Puzzle, color: '#64748b' });
}
const menuItems = [
{ id: 'superadmin-overview', label: 'VISÃO GERAL', icon: TrendingUp },
@@ -163,6 +167,7 @@ export const Sidebar: React.FC<SidebarProps> = ({ activeTab, setActiveTab }) =>
{[
{ role: 'donoclinica', label: 'DONO DE CLÍNICA', icon: Building2 },
{ role: 'dentista', label: 'DENTISTA', icon: ToothIcon },
{ role: 'biomedico', label: 'BIOMÉDICO(A)', icon: Sparkles },
{ role: 'protetico', label: 'PROTÉTICO', icon: FlaskConical },
{ role: 'paciente', label: 'PACIENTE', icon: User },
].map(({ role, label, icon: Icon }) => (