modified: src/App.jsx

modified:   src/components/AppShell.jsx
new file:   src/config/permissions.js
new file:   src/hooks/useAuth.js
new file:   src/pages/UsersPage.jsx
new file:   src/repositories/userRepository.js
This commit is contained in:
2026-05-05 22:49:20 -03:00
parent 06acf8cc61
commit bb5200664a
6 changed files with 717 additions and 22 deletions

View File

@@ -1,9 +1,11 @@
import { useEffect, useMemo, useState } from 'react'
import { ROLE_LABELS, ROLE_NAV_ITEMS } from '../config/permissions.js'
import { profileRepository } from '../repositories/profileRepository.js'
import { BrandLogo } from './Brand.jsx'
const navItems = [
// Todos os itens de navegação com seus ícones e metadados
const ALL_NAV_ITEMS = [
{ href: '/inicio', label: 'Painel', icon: 'pulse', activePaths: ['/inicio', '/home', '/dashboard'] },
{ href: '/agenda', label: 'Agenda', icon: 'calendar' },
{ href: '/pacientes', label: 'Pacientes', icon: 'users', exact: true },
@@ -16,6 +18,8 @@ const navItems = [
activePaths: ['/camunicacao', '/comunicacao', '/mensagens'],
},
{ href: '/relatorios', label: 'Relatorios', icon: 'chart' },
{ href: '/profissionais', label: 'Profissionais', icon: 'users' },
{ href: '/usuarios', label: 'Usuarios', icon: 'shield' },
{ href: '/configuracoes', label: 'Configuracoes', icon: 'settings', activePaths: ['/configuracoes', '/config'] },
]
@@ -36,9 +40,10 @@ const titles = {
'/perfil': 'Perfil',
'/configuracoes': 'Configuracoes',
'/config': 'Configuracoes',
'/usuarios': 'Usuarios',
}
export function AppShell({ children, currentPath, navigate, routeTitle }) {
export function AppShell({ children, currentPath, navigate, role, routeTitle }) {
const [menuOpen, setMenuOpen] = useState(false)
const [quickSearch, setQuickSearch] = useState('')
const [viewerProfile, setViewerProfile] = useState({ name: 'Usuario', role: 'Usuario do Sistema' })
@@ -51,24 +56,46 @@ export function AppShell({ children, currentPath, navigate, routeTitle }) {
return routeTitle || titles[currentPath] || 'MediConnect'
}, [currentPath, routeTitle])
// Filtra os itens de navegação com base no role do usuário
const navItems = useMemo(() => {
if (!role) return []
const allowedPaths = ROLE_NAV_ITEMS[role]?.map((item) => item.path) ?? []
return ALL_NAV_ITEMS.filter((item) =>
allowedPaths.some(
(allowed) => item.href === allowed || item.activePaths?.includes(allowed),
),
)
}, [role])
useEffect(() => {
let active = true
profileRepository.getCurrentUserProfile()
profileRepository
.getCurrentUserProfile()
.then((profile) => {
if (!active || !profile) return
setViewerProfile({
name: profile.name || 'Usuario',
role: profile.role || 'Usuario do Sistema',
role: ROLE_LABELS[role] || profile.role || 'Usuario do Sistema',
})
})
.catch(() => {})
.catch(() => {
// Fallback: usa o label do role diretamente
if (active && role) {
setViewerProfile((prev) => ({
...prev,
role: ROLE_LABELS[role] || 'Usuario do Sistema',
}))
}
})
return () => {
active = false
}
}, [])
}, [role])
function goTo(path) {
setMenuOpen(false)
@@ -303,10 +330,10 @@ function AppIcon({ className = 'size-5', name }) {
)
}
if (name === 'dollar') {
if (name === 'shield') {
return (
<svg {...common}>
<path d="M12 2v20M17 6.5C15.8 5.4 14.2 5 12.5 5 9.9 5 8 6.2 8 8s1.6 2.7 4.2 3.3C15 12 17 13 17 15.5S14.8 19 12 19c-2 0-3.8-.6-5-1.8" />
<path d="M12 3 5 6v5c0 4.5 3 8.5 7 10 4-1.5 7-5.5 7-10V6l-7-3Z" />
</svg>
)
}
@@ -361,4 +388,4 @@ function getInitials(name) {
.map((part) => part[0])
.join('')
.toUpperCase()
}
}