Files
agenciapsilmno/src/layout/AppMenuFooterPanel.vue
2026-02-18 22:36:45 -03:00

190 lines
4.3 KiB
Vue

<script setup>
import { computed, ref } from 'vue'
import { useRouter } from 'vue-router'
import { sessionUser, sessionRole } from '@/app/session'
import { supabase } from '@/lib/supabase/client'
const router = useRouter()
const pop = ref(null)
function isAdminRole (r) {
return r === 'admin' || r === 'tenant_admin'
}
const initials = computed(() => {
const name = sessionUser.value?.user_metadata?.full_name || sessionUser.value?.email || ''
const parts = String(name).trim().split(/\s+/).filter(Boolean)
const a = parts[0]?.[0] || 'U'
const b = parts.length > 1 ? parts[parts.length - 1][0] : ''
return (a + b).toUpperCase()
})
const label = computed(() => {
const name = sessionUser.value?.user_metadata?.full_name
return name || sessionUser.value?.email || 'Conta'
})
const sublabel = computed(() => {
const r = sessionRole.value
if (!r) return 'Sessão'
if (isAdminRole(r)) return 'Administrador'
if (r === 'therapist') return 'Terapeuta'
if (r === 'patient') return 'Paciente'
return r
})
function toggle (e) {
pop.value?.toggle(e)
}
function close () {
try {
pop.value?.hide()
} catch {}
}
function goMyProfile () {
close()
// navegação segura por name
safePush(
{ name: 'MeuPerfil' },
'/me/perfil'
)
}
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/conta')
return
}
router.push('/')
}
async function safePush (target, fallback) {
try {
await router.push(target)
} catch (e) {
// fallback quando o "name" não existe no router
if (fallback) {
try {
await router.push(fallback)
} catch {
await router.push('/')
}
} else {
await router.push('/')
}
}
}
function goSecurity () {
close()
// ✅ 1) tenta por NAME (recomendado)
// ✅ 2) fallback: caminhos mais prováveis do teu projeto
// Ajuste/defina a rota no router como name: 'AdminSecurity' para ficar perfeito
safePush(
{ name: 'AdminSecurity' },
'/admin/settings/security'
)
}
async function signOut () {
close()
try {
await supabase.auth.signOut()
} catch {
// se falhar, ainda assim manda pro login
} finally {
router.push('/auth/login')
}
}
</script>
<template>
<div class="sticky bottom-0 z-20 border-t border-[var(--surface-border)] bg-[var(--surface-card)]">
<button
type="button"
class="w-full px-3 py-3 flex items-center gap-3 hover:bg-[var(--surface-ground)] transition"
@click="toggle"
>
<!-- avatar -->
<img
v-if="sessionUser.value?.user_metadata?.avatar_url"
:src="sessionUser.value.user_metadata.avatar_url"
class="h-9 w-9 rounded-xl object-cover border border-[var(--surface-border)]"
/>
<div
v-else
class="h-9 w-9 rounded-xl border border-[var(--surface-border)] bg-[var(--surface-ground)] grid place-items-center text-sm font-semibold"
>
{{ initials }}
</div>
<!-- labels -->
<div class="min-w-0 flex-1 text-left">
<div class="truncate text-sm font-semibold text-[var(--text-color)]">
{{ label }}
</div>
<div class="truncate text-xs text-[var(--text-color-secondary)]">
{{ sublabel }}
</div>
</div>
<i class="pi pi-angle-up text-xs opacity-70" />
</button>
<Popover ref="pop" appendTo="body">
<div class="min-w-[220px] p-1">
<Button
label="Configurações"
icon="pi pi-cog"
text
class="w-full justify-start"
@click="goSettings"
/>
<Button
label="Segurança"
icon="pi pi-shield"
text
class="w-full justify-start"
@click="goSecurity"
/>
<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)]" />
<Button
label="Sair"
icon="pi pi-sign-out"
severity="danger"
text
class="w-full justify-start"
@click="signOut"
/>
</div>
</Popover>
</div>
</template>