Ajuste rotas, Menus, Layout, Permissãoes UserRoleGuard

This commit is contained in:
Leonardo
2026-02-24 12:04:59 -03:00
parent b1c0cb47c0
commit d58dc21297
15 changed files with 1925 additions and 259 deletions

View File

@@ -7,11 +7,39 @@ import { useConfirm } from 'primevue/useconfirm'
import { supabase } from '@/lib/supabase/client'
import { useTenantStore } from '@/stores/tenantStore'
const route = useRoute()
const router = useRouter()
const toast = useToast()
const confirm = useConfirm()
const tenantStore = useTenantStore()
async function getCurrentTenantId () {
// ajuste para o nome real no seu store
return tenantStore.tenantId || tenantStore.currentTenantId || tenantStore.tenant?.id
}
async function getCurrentMemberId (tenantId) {
const { data: authData, error: authError } = await supabase.auth.getUser()
if (authError) throw authError
const uid = authData?.user?.id
if (!uid) throw new Error('Sessão inválida.')
const { data, error } = await supabase
.from('tenant_members')
.select('id')
.eq('tenant_id', tenantId)
.eq('user_id', uid)
.eq('status', 'active')
.single()
if (error) throw error
if (!data?.id) throw new Error('Responsible member not found')
return data.id
}
// ------------------------------------------------------
// Accordion: abre 1 por vez + scroll
// ------------------------------------------------------
@@ -400,6 +428,8 @@ async function getOwnerId () {
// ------------------------------------------------------
const PACIENTES_COLUNAS_PERMITIDAS = new Set([
'owner_id',
'tenant_id',
'responsible_member_id',
// Sessão 1
'nome_completo',
@@ -688,12 +718,14 @@ async function createPatient (payload) {
}
async function updatePatient (id, payload) {
const ownerId = await getOwnerId()
const { error } = await supabase
.from('patients')
.update({ ...payload, updated_at: new Date().toISOString() })
.update({
...payload,
updated_at: new Date().toISOString()
})
.eq('id', id)
.eq('owner_id', ownerId)
if (error) throw error
}
@@ -840,38 +872,55 @@ async function fetchAll () {
watch(() => route.params?.id, fetchAll, { immediate: true })
onMounted(fetchAll)
async function resolveTenantContextOrFail () {
const { data: authData, error: authError } = await supabase.auth.getUser()
if (authError) throw authError
const uid = authData?.user?.id
if (!uid) throw new Error('Sessão inválida.')
const { data, error } = await supabase
.from('tenant_members')
.select('id, tenant_id')
.eq('user_id', uid)
.eq('status', 'active')
.order('created_at', { ascending: false }) // se existir
.limit(1)
.single()
if (error) throw error
if (!data?.tenant_id || !data?.id) throw new Error('Responsible member not found')
return { tenantId: data.tenant_id, memberId: data.id }
}
// ------------------------------------------------------
// Submit
// ------------------------------------------------------
async function onSubmit () {
if (saving.value) return
// validações...
saving.value = true
try {
saving.value = true
const ownerId = await getOwnerId()
const { tenantId, memberId } = await resolveTenantContextOrFail()
const payload = sanitizePayload(form.value, ownerId)
let id = patientId.value
// multi-tenant obrigatório
payload.tenant_id = tenantId
payload.responsible_member_id = memberId
if (isEdit.value) {
await updatePatient(id, payload)
await updatePatient(patientId.value, payload)
toast.add({ severity: 'success', summary: 'Salvo', detail: 'Paciente atualizado.', life: 2500 })
} else {
const created = await createPatient(payload)
id = created?.id
if (!id) throw new Error('Falha ao obter ID do paciente criado.')
router.replace(`${getAreaBase()}/patients/cadastro/${id}`)
toast.add({ severity: 'success', summary: 'Salvo', detail: 'Paciente cadastrado.', life: 2500 })
// opcional: router.push(`${getAreaBase()}/patients/${created.id}`)
}
await replacePatientGroups(id, grupoIdSelecionado.value || null)
await replacePatientTags(id, tagIdsSelecionadas.value || [])
// Avatar por último, mas dentro do mesmo fluxo (sem toast de sucesso)
await maybeUploadAvatar(ownerId, id)
// ✅ um sucesso só
toast.add({ severity: 'success', summary: 'Salvo', detail: 'Paciente salvo.', life: 2500 })
} catch (err) {
toast.add({ severity: 'error', summary: 'Erro', detail: err?.message || 'Falha ao salvar paciente', life: 4000 })
} catch (e) {
console.error(e)
toast.add({ severity: 'error', summary: 'Erro', detail: e?.message || 'Falha ao salvar paciente.', life: 4000 })
} finally {
saving.value = false
}