190 lines
4.3 KiB
Vue
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>
|