This commit is contained in:
Leonardo
2026-03-06 06:37:13 -03:00
parent d58dc21297
commit f733db8436
146 changed files with 43436 additions and 12779 deletions
+91 -10
View File
@@ -9,12 +9,44 @@ import PrimeVue from 'primevue/config'
import ConfirmationService from 'primevue/confirmationservice'
import ToastService from 'primevue/toastservice'
// ── Componentes PrimeVue globais (≥ 10 usos no projeto) ──────────────────────
import Button from 'primevue/button'
import InputText from 'primevue/inputtext'
import Tag from 'primevue/tag'
import FloatLabel from 'primevue/floatlabel'
import Toast from 'primevue/toast'
import IconField from 'primevue/iconfield'
import InputIcon from 'primevue/inputicon'
import Divider from 'primevue/divider'
import Card from 'primevue/card'
import SelectButton from 'primevue/selectbutton'
import Dialog from 'primevue/dialog'
import DataTable from 'primevue/datatable'
import Column from 'primevue/column'
import ConfirmDialog from 'primevue/confirmdialog'
import Menu from 'primevue/menu'
// ─────────────────────────────────────────────────────────────────────────────
import '@/assets/tailwind.css'
import '@/assets/styles.scss'
import { supabase } from '@/lib/supabase/client'
async function applyUserThemeEarly() {
// ✅ pt-BR (PrimeVue locale global)
const ptBR = {
firstDayOfWeek: 1,
dayNames: ['domingo','segunda-feira','terça-feira','quarta-feira','quinta-feira','sexta-feira','sábado'],
dayNamesShort: ['dom','seg','ter','qua','qui','sex','sáb'],
dayNamesMin: ['D','S','T','Q','Q','S','S'],
monthNames: ['janeiro','fevereiro','março','abril','maio','junho','julho','agosto','setembro','outubro','novembro','dezembro'],
monthNamesShort: ['jan','fev','mar','abr','mai','jun','jul','ago','set','out','nov','dez'],
today: 'Hoje',
clear: 'Limpar',
weekHeader: 'Sm',
dateFormat: 'dd/mm/yy'
}
async function applyUserThemeEarly () {
try {
const { data } = await supabase.auth.getUser()
const user = data?.user
@@ -34,7 +66,6 @@ async function applyUserThemeEarly() {
const root = document.documentElement
root.classList.toggle('app-dark', isDark)
// opcional: marca em storage pra teu layout composable ler depois
localStorage.setItem('ui_theme_mode', settings.theme_mode)
} catch {}
}
@@ -49,39 +80,69 @@ window.__fromVisibilityRefresh = false
window.__appBootstrapped = false
// ========================================
// 🛟 ao voltar da aba: refresh leve (sem concorrência + com flag global)
let refreshing = false
let refreshTimer = null
// 🛟 ao voltar da aba: refresh leve, sem martelar e sem rodar antes do app subir
let lastVisibilityRefreshAt = 0
document.addEventListener('visibilitychange', async () => {
if (document.visibilityState !== 'visible') return
// só depois do app montar (evita refresh no meio do bootstrap)
if (!window.__appBootstrapped) return
const now = Date.now()
// evita martelar: no máximo 1 refresh a cada 10s
// no máximo 1 refresh a cada 10s
if (now - lastVisibilityRefreshAt < 10_000) return
// se já tem refresh em andamento, não entra
if (window.__sessionRefreshing) return
// (opcional) se não houver user, não precisa refresh
try {
const { data } = await supabase.auth.getUser()
if (!data?.user) return
} catch {
// se falhar getUser, deixa tentar refreshSession mesmo assim
}
lastVisibilityRefreshAt = now
console.log('[VISIBILITY] Aba voltou -> refreshSession()')
try {
window.__sessionRefreshing = true
window.__fromVisibilityRefresh = true
await refreshSession()
// 🔔 avisa o app inteiro SOMENTE em áreas TENANT.
// Portal (/portal) e área global (/account) NÃO devem rehidratar tenantStore/menu.
try {
const path = router.currentRoute.value?.path || ''
const isTenantArea =
path.startsWith('/admin') ||
path.startsWith('/therapist') ||
path.startsWith('/saas')
if (isTenantArea) {
window.dispatchEvent(
new CustomEvent('app:session-refreshed', { detail: { source: 'visibility' } })
)
} else {
console.log('[VISIBILITY] refresh ok (skip event) - area não-tenant:', path)
}
} catch {
// se algo der errado, não dispare evento global por segurança
}
} finally {
window.__fromVisibilityRefresh = false
window.__sessionRefreshing = false
}
})
async function bootstrap () {
await initSession({ initial: true })
listenAuthChanges()
await applyUserThemeEarly()
const app = createApp(App)
@@ -94,19 +155,39 @@ async function bootstrap () {
// ✅ garante router pronto antes de montar
await router.isReady()
// ✅ PrimeVue global config (tema + locale pt-BR)
app.use(PrimeVue, {
locale: ptBR, // 🔥 isso traduz Calendar/DatePicker
theme: {
preset: Aura,
options: { darkModeSelector: '.app-dark' }
}
})
app.use(ToastService)
app.use(ConfirmationService)
// Registro global de componentes PrimeVue frequentes
app.component('Button', Button)
app.component('InputText', InputText)
app.component('Tag', Tag)
app.component('FloatLabel', FloatLabel)
app.component('Toast', Toast)
app.component('IconField', IconField)
app.component('InputIcon', InputIcon)
app.component('Divider', Divider)
app.component('Card', Card)
app.component('SelectButton', SelectButton)
app.component('Dialog', Dialog)
app.component('DataTable', DataTable)
app.component('Column', Column)
app.component('ConfirmDialog', ConfirmDialog)
app.component('Menu', Menu)
app.mount('#app')
// ✅ marca boot completo
window.__appBootstrapped = true
}
bootstrap()
bootstrap()