Ajuste rotas, Menus, Layout, Permissãoes UserRoleGuard
This commit is contained in:
@@ -5,13 +5,19 @@ import { useRouter } from 'vue-router'
|
||||
import { sessionUser, sessionRole } from '@/app/session'
|
||||
import { supabase } from '@/lib/supabase/client'
|
||||
|
||||
import { useRoleGuard } from '@/composables/useRoleGuard'
|
||||
|
||||
const router = useRouter()
|
||||
const pop = ref(null)
|
||||
|
||||
function isAdminRole (r) {
|
||||
return r === 'admin' || r === 'tenant_admin'
|
||||
}
|
||||
// ------------------------------------------------------
|
||||
// RBAC (Tenant): fonte da verdade para permissões por papel
|
||||
// ------------------------------------------------------
|
||||
const { role, canSee, isPatient } = useRoleGuard()
|
||||
|
||||
// ------------------------------------------------------
|
||||
// UI labels (nome/iniciais)
|
||||
// ------------------------------------------------------
|
||||
const initials = computed(() => {
|
||||
const name = sessionUser.value?.user_metadata?.full_name || sessionUser.value?.email || ''
|
||||
const parts = String(name).trim().split(/\s+/).filter(Boolean)
|
||||
@@ -25,15 +31,30 @@ const label = computed(() => {
|
||||
return name || sessionUser.value?.email || 'Conta'
|
||||
})
|
||||
|
||||
/**
|
||||
* sublabel:
|
||||
* Aqui eu recomendo exibir o papel do TENANT (role do useRoleGuard),
|
||||
* porque é ele que realmente governa a UI dentro da clínica.
|
||||
*
|
||||
* Se você preferir manter sessionRole como rótulo "global", ok,
|
||||
* mas isso pode confundir quando o usuário estiver em contextos diferentes.
|
||||
*/
|
||||
const sublabel = computed(() => {
|
||||
const r = sessionRole.value
|
||||
const r = role.value || sessionRole.value
|
||||
if (!r) return 'Sessão'
|
||||
if (isAdminRole(r)) return 'Administrador'
|
||||
|
||||
// tenant roles (confirmados no banco): tenant_admin | therapist | patient
|
||||
if (r === 'tenant_admin') return 'Administrador'
|
||||
if (r === 'therapist') return 'Terapeuta'
|
||||
if (r === 'patient') return 'Paciente'
|
||||
|
||||
// fallback (caso venha algo diferente)
|
||||
return r
|
||||
})
|
||||
|
||||
// ------------------------------------------------------
|
||||
// Popover helpers
|
||||
// ------------------------------------------------------
|
||||
function toggle (e) {
|
||||
pop.value?.toggle(e)
|
||||
}
|
||||
@@ -44,35 +65,9 @@ function close () {
|
||||
} catch {}
|
||||
}
|
||||
|
||||
function goMyProfile() {
|
||||
close()
|
||||
|
||||
// Navegação segura para Account → Profile
|
||||
safePush(
|
||||
{ name: 'account-profile' },
|
||||
'/account/profile'
|
||||
)
|
||||
}
|
||||
|
||||
function goSettings () {
|
||||
close()
|
||||
|
||||
const r = sessionRole.value
|
||||
|
||||
if (isAdminRole(r) || r === 'therapist') {
|
||||
// rota por name (como você já usa)
|
||||
router.push({ name: 'ConfiguracoesAgenda' })
|
||||
return
|
||||
}
|
||||
|
||||
if (r === 'patient') {
|
||||
router.push('/patient/portal')
|
||||
return
|
||||
}
|
||||
|
||||
router.push('/')
|
||||
}
|
||||
|
||||
// ------------------------------------------------------
|
||||
// Navegação segura (NAME com fallback)
|
||||
// ------------------------------------------------------
|
||||
async function safePush (target, fallback) {
|
||||
try {
|
||||
await router.push(target)
|
||||
@@ -90,6 +85,35 @@ async function safePush (target, fallback) {
|
||||
}
|
||||
}
|
||||
|
||||
function goMyProfile () {
|
||||
close()
|
||||
|
||||
// Navegação segura para Account → Profile
|
||||
safePush(
|
||||
{ name: 'account-profile' },
|
||||
'/account/profile'
|
||||
)
|
||||
}
|
||||
|
||||
function goSettings () {
|
||||
close()
|
||||
|
||||
// ✅ Decide por RBAC (tenant role), não por sessionRole
|
||||
if (canSee('settings.view')) {
|
||||
router.push({ name: 'ConfiguracoesAgenda' })
|
||||
return
|
||||
}
|
||||
|
||||
// Se não pode ver configurações, manda paciente pro portal.
|
||||
// (Se amanhã você criar outro papel, esta regra continua segura.)
|
||||
if (isPatient.value) {
|
||||
router.push('/patient/portal')
|
||||
return
|
||||
}
|
||||
|
||||
router.push('/')
|
||||
}
|
||||
|
||||
function goSecurity () {
|
||||
close()
|
||||
|
||||
@@ -150,6 +174,7 @@ async function signOut () {
|
||||
<Popover ref="pop" appendTo="body">
|
||||
<div class="min-w-[220px] p-1">
|
||||
<Button
|
||||
v-if="canSee('settings.view')"
|
||||
label="Configurações"
|
||||
icon="pi pi-cog"
|
||||
text
|
||||
@@ -164,14 +189,14 @@ async function signOut () {
|
||||
class="w-full justify-start"
|
||||
@click="goSecurity"
|
||||
/>
|
||||
|
||||
<Button
|
||||
label="Meu Perfil"
|
||||
icon="pi pi-user"
|
||||
text
|
||||
class="w-full justify-start"
|
||||
@click="goMyProfile"
|
||||
/>
|
||||
|
||||
<Button
|
||||
label="Meu Perfil"
|
||||
icon="pi pi-user"
|
||||
text
|
||||
class="w-full justify-start"
|
||||
@click="goMyProfile"
|
||||
/>
|
||||
|
||||
<div class="my-1 border-t border-[var(--surface-border)]" />
|
||||
|
||||
@@ -186,4 +211,4 @@ async function signOut () {
|
||||
</div>
|
||||
</Popover>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
Reference in New Issue
Block a user