ZERADO
This commit is contained in:
+151
-58
@@ -2,64 +2,105 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { supabase } from '@/lib/supabase/client'
|
||||
|
||||
function normalizeKey(k) {
|
||||
function normalizeKey (k) {
|
||||
return String(k || '').trim()
|
||||
}
|
||||
|
||||
function uniqKeys (rows, field) {
|
||||
const list = []
|
||||
const seen = new Set()
|
||||
for (const r of (rows || [])) {
|
||||
const key = normalizeKey(r?.[field])
|
||||
if (!key) continue
|
||||
if (seen.has(key)) continue
|
||||
seen.add(key)
|
||||
list.push(key)
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
export const useEntitlementsStore = defineStore('entitlements', {
|
||||
state: () => ({
|
||||
loading: false,
|
||||
// =========================
|
||||
// Tenant entitlements (B)
|
||||
// =========================
|
||||
tenantLoading: false,
|
||||
loadedForTenant: null,
|
||||
features: [], // array reativo de feature_key liberadas
|
||||
raw: [],
|
||||
error: null,
|
||||
loadedAt: null
|
||||
tenantFeatures: [],
|
||||
tenantRaw: [],
|
||||
tenantError: null,
|
||||
tenantLoadedAt: null,
|
||||
|
||||
// =========================
|
||||
// User entitlements (A)
|
||||
// =========================
|
||||
userLoading: false,
|
||||
loadedForUser: null,
|
||||
userFeatures: [],
|
||||
userRaw: [],
|
||||
userError: null,
|
||||
userLoadedAt: null
|
||||
}),
|
||||
|
||||
getters: {
|
||||
can: (state) => (featureKey) => state.features.includes(featureKey),
|
||||
has: (state) => (featureKey) => state.features.includes(featureKey)
|
||||
/**
|
||||
* ✅ Sem scope: união de tenant + user entitlements.
|
||||
* Um terapeuta com plano pessoal (therapist_pro) tem features em userFeatures,
|
||||
* não em tenantFeatures — ambos devem ser verificados.
|
||||
*/
|
||||
has: (state) => (featureKey, scope = null) => {
|
||||
const key = normalizeKey(featureKey)
|
||||
if (!key) return false
|
||||
|
||||
if (scope === 'tenant') return state.tenantFeatures.includes(key)
|
||||
if (scope === 'user') return state.userFeatures.includes(key)
|
||||
|
||||
// sem scope: true se qualquer uma das origens tiver a feature
|
||||
return state.tenantFeatures.includes(key) || state.userFeatures.includes(key)
|
||||
},
|
||||
|
||||
can: (state) => (featureKey, scope = null) => {
|
||||
const key = normalizeKey(featureKey)
|
||||
if (!key) return false
|
||||
|
||||
if (scope === 'tenant') return state.tenantFeatures.includes(key)
|
||||
if (scope === 'user') return state.userFeatures.includes(key)
|
||||
|
||||
return state.tenantFeatures.includes(key) || state.userFeatures.includes(key)
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
async fetch(tenantId, opts = {}) {
|
||||
// =========================
|
||||
// Compat: fetch() continua existindo
|
||||
// =========================
|
||||
async fetch (tenantId, opts = {}) {
|
||||
return this.loadForTenant(tenantId, opts)
|
||||
},
|
||||
|
||||
clear() {
|
||||
clear () {
|
||||
return this.invalidate()
|
||||
},
|
||||
|
||||
/**
|
||||
* Carrega entitlements do tenant.
|
||||
* Importante: quando o plano muda, tenantId é o mesmo,
|
||||
* então você DEVE chamar com { force: true }.
|
||||
*
|
||||
* opts:
|
||||
* - force: ignora cache do tenant
|
||||
* - maxAgeMs: se definido, recarrega quando loadedAt estiver velho
|
||||
*/
|
||||
async loadForTenant(tenantId, { force = false, maxAgeMs = 0 } = {}) {
|
||||
// =========================
|
||||
// Tenant (clinic) — view v_tenant_entitlements
|
||||
// =========================
|
||||
async loadForTenant (tenantId, { force = false, maxAgeMs = 0 } = {}) {
|
||||
if (!tenantId) {
|
||||
this.invalidate()
|
||||
this.invalidateTenant()
|
||||
return
|
||||
}
|
||||
|
||||
const sameTenant = this.loadedForTenant === tenantId
|
||||
const hasLoadedAt = typeof this.loadedAt === 'number'
|
||||
const isFresh =
|
||||
sameTenant &&
|
||||
hasLoadedAt &&
|
||||
maxAgeMs > 0 &&
|
||||
Date.now() - this.loadedAt < maxAgeMs
|
||||
const same = this.loadedForTenant === tenantId
|
||||
const hasLoadedAt = typeof this.tenantLoadedAt === 'number'
|
||||
const isFresh = same && hasLoadedAt && maxAgeMs > 0 && (Date.now() - this.tenantLoadedAt < maxAgeMs)
|
||||
|
||||
if (!force && sameTenant && (maxAgeMs === 0 || isFresh)) return
|
||||
if (!force && same && (maxAgeMs === 0 || isFresh)) return
|
||||
|
||||
this.loading = true
|
||||
this.error = null
|
||||
this.tenantLoading = true
|
||||
this.tenantError = null
|
||||
|
||||
try {
|
||||
// ✅ Modelo B: entitlements por tenant (view)
|
||||
const { data, error } = await supabase
|
||||
.from('v_tenant_entitlements')
|
||||
.select('feature_key')
|
||||
@@ -68,40 +109,92 @@ export const useEntitlementsStore = defineStore('entitlements', {
|
||||
if (error) throw error
|
||||
|
||||
const rows = data ?? []
|
||||
this.tenantRaw = rows
|
||||
this.tenantFeatures = uniqKeys(rows, 'feature_key')
|
||||
|
||||
// normaliza, remove vazios e duplicados
|
||||
const list = []
|
||||
const seen = new Set()
|
||||
for (const r of rows) {
|
||||
const key = normalizeKey(r?.feature_key)
|
||||
if (!key) continue
|
||||
if (seen.has(key)) continue
|
||||
seen.add(key)
|
||||
list.push(key)
|
||||
}
|
||||
|
||||
this.raw = rows
|
||||
this.features = list
|
||||
this.loadedForTenant = tenantId
|
||||
this.loadedAt = Date.now()
|
||||
this.tenantLoadedAt = Date.now()
|
||||
} catch (e) {
|
||||
this.error = e
|
||||
this.raw = []
|
||||
this.features = []
|
||||
this.tenantError = e
|
||||
this.tenantRaw = []
|
||||
this.tenantFeatures = []
|
||||
this.loadedForTenant = tenantId
|
||||
this.loadedAt = Date.now()
|
||||
this.tenantLoadedAt = Date.now()
|
||||
} finally {
|
||||
this.loading = false
|
||||
this.tenantLoading = false
|
||||
}
|
||||
},
|
||||
|
||||
invalidate() {
|
||||
// =========================
|
||||
// User (therapist personal) — view v_user_entitlements
|
||||
// =========================
|
||||
async loadForUser (userId, { force = false, maxAgeMs = 0 } = {}) {
|
||||
if (!userId) {
|
||||
this.invalidateUser()
|
||||
return
|
||||
}
|
||||
|
||||
const same = this.loadedForUser === userId
|
||||
const hasLoadedAt = typeof this.userLoadedAt === 'number'
|
||||
const isFresh = same && hasLoadedAt && maxAgeMs > 0 && (Date.now() - this.userLoadedAt < maxAgeMs)
|
||||
|
||||
if (!force && same && (maxAgeMs === 0 || isFresh)) return
|
||||
|
||||
this.userLoading = true
|
||||
this.userError = null
|
||||
|
||||
try {
|
||||
const { data, error } = await supabase
|
||||
.from('v_user_entitlements')
|
||||
.select('feature_key')
|
||||
.eq('user_id', userId)
|
||||
|
||||
if (error) throw error
|
||||
|
||||
const rows = data ?? []
|
||||
this.userRaw = rows
|
||||
this.userFeatures = uniqKeys(rows, 'feature_key')
|
||||
|
||||
this.loadedForUser = userId
|
||||
this.userLoadedAt = Date.now()
|
||||
} catch (e) {
|
||||
this.userError = e
|
||||
this.userRaw = []
|
||||
this.userFeatures = []
|
||||
this.loadedForUser = userId
|
||||
this.userLoadedAt = Date.now()
|
||||
} finally {
|
||||
this.userLoading = false
|
||||
}
|
||||
},
|
||||
|
||||
// =========================
|
||||
// Invalidate granular
|
||||
// =========================
|
||||
invalidateTenant () {
|
||||
this.tenantLoading = false
|
||||
this.loadedForTenant = null
|
||||
this.features = []
|
||||
this.raw = []
|
||||
this.error = null
|
||||
this.loadedAt = null
|
||||
this.loading = false
|
||||
this.tenantFeatures = []
|
||||
this.tenantRaw = []
|
||||
this.tenantError = null
|
||||
this.tenantLoadedAt = null
|
||||
},
|
||||
|
||||
invalidateUser () {
|
||||
this.userLoading = false
|
||||
this.loadedForUser = null
|
||||
this.userFeatures = []
|
||||
this.userRaw = []
|
||||
this.userError = null
|
||||
this.userLoadedAt = null
|
||||
},
|
||||
|
||||
// =========================
|
||||
// Invalidate geral (compat)
|
||||
// =========================
|
||||
invalidate () {
|
||||
this.invalidateTenant()
|
||||
this.invalidateUser()
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
@@ -0,0 +1,23 @@
|
||||
// src/stores/menuStore.js
|
||||
import { defineStore } from 'pinia'
|
||||
|
||||
export const useMenuStore = defineStore('menuStore', {
|
||||
state: () => ({
|
||||
model: [],
|
||||
key: null, // assinatura do contexto (uid+tenant+role)
|
||||
ready: false
|
||||
}),
|
||||
|
||||
actions: {
|
||||
setMenu (key, model) {
|
||||
this.key = key || null
|
||||
this.model = Array.isArray(model) ? model : []
|
||||
this.ready = true
|
||||
},
|
||||
reset () {
|
||||
this.model = []
|
||||
this.key = null
|
||||
this.ready = false
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -1,26 +1,60 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { ref } from 'vue'
|
||||
import { computed, ref } from 'vue'
|
||||
import { supabase } from '@/lib/supabase/client'
|
||||
|
||||
export const useTenantFeaturesStore = defineStore('tenantFeatures', () => {
|
||||
const loading = ref(false)
|
||||
const lastError = ref(null)
|
||||
const lastFetchedAt = ref(null)
|
||||
|
||||
// Cache por tenant: { [tenantId]: { [feature_key]: boolean } }
|
||||
const featuresByTenant = ref({})
|
||||
|
||||
// Marca o último tenant buscado (útil pra debug)
|
||||
const loadedForTenantId = ref(null)
|
||||
const features = ref({}) // { patients: true/false, ... }
|
||||
|
||||
function isEnabled(key) {
|
||||
return !!features.value?.[key]
|
||||
function getTenantMap (tenantId) {
|
||||
if (!tenantId) return {}
|
||||
return featuresByTenant.value?.[tenantId] || {}
|
||||
}
|
||||
|
||||
function invalidate() {
|
||||
loadedForTenantId.value = null
|
||||
features.value = {}
|
||||
// 🔎 Se você passar tenantId, lê desse tenant; se não, tenta o último carregado
|
||||
// Modelo opt-out: se a feature não está configurada (key ausente do mapa), retorna true por padrão.
|
||||
// Só retorna false quando explicitamente desabilitada no banco.
|
||||
function isEnabled (key, tenantId = null) {
|
||||
const tid = tenantId || loadedForTenantId.value
|
||||
if (!tid) return false
|
||||
const map = getTenantMap(tid)
|
||||
if (!(key in map)) return true // não configurada = habilitada por padrão
|
||||
return !!map[key]
|
||||
}
|
||||
|
||||
async function fetchForTenant(tenantId, { force = false } = {}) {
|
||||
function invalidate (tenantId = null) {
|
||||
lastError.value = null
|
||||
if (!tenantId) {
|
||||
loadedForTenantId.value = null
|
||||
featuresByTenant.value = {}
|
||||
return
|
||||
}
|
||||
// invalida apenas um tenant
|
||||
const copy = { ...featuresByTenant.value }
|
||||
delete copy[tenantId]
|
||||
featuresByTenant.value = copy
|
||||
if (loadedForTenantId.value === tenantId) loadedForTenantId.value = null
|
||||
}
|
||||
|
||||
async function fetchForTenant (tenantId, { force = false } = {}) {
|
||||
if (!tenantId) return
|
||||
if (!force && loadedForTenantId.value === tenantId) return
|
||||
|
||||
// se já tem cache e não é force, não busca de novo
|
||||
if (!force && featuresByTenant.value?.[tenantId]) {
|
||||
loadedForTenantId.value = tenantId
|
||||
return
|
||||
}
|
||||
|
||||
loading.value = true
|
||||
lastError.value = null
|
||||
|
||||
try {
|
||||
const { data, error } = await supabase
|
||||
.from('tenant_features')
|
||||
@@ -32,35 +66,60 @@ export const useTenantFeaturesStore = defineStore('tenantFeatures', () => {
|
||||
const map = {}
|
||||
for (const row of data || []) map[row.feature_key] = !!row.enabled
|
||||
|
||||
features.value = map
|
||||
featuresByTenant.value = {
|
||||
...featuresByTenant.value,
|
||||
[tenantId]: map
|
||||
}
|
||||
|
||||
loadedForTenantId.value = tenantId
|
||||
lastFetchedAt.value = new Date().toISOString()
|
||||
} catch (e) {
|
||||
lastError.value = e
|
||||
// importante: se falhar, mantém cache anterior (se existir)
|
||||
// e relança para a página poder mostrar toast se quiser
|
||||
throw e
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function setForTenant(tenantId, key, enabled) {
|
||||
async function setForTenant (tenantId, key, enabled) {
|
||||
if (!tenantId) throw new Error('tenantId missing')
|
||||
|
||||
lastError.value = null
|
||||
|
||||
const payload = { tenant_id: tenantId, feature_key: key, enabled: !!enabled }
|
||||
|
||||
const { error } = await supabase
|
||||
.from('tenant_features')
|
||||
.upsert(
|
||||
{ tenant_id: tenantId, feature_key: key, enabled: !!enabled },
|
||||
{ onConflict: 'tenant_id,feature_key' }
|
||||
)
|
||||
.upsert(payload, { onConflict: 'tenant_id,feature_key' })
|
||||
|
||||
if (error) throw error
|
||||
|
||||
// atualiza cache local
|
||||
if (loadedForTenantId.value === tenantId) {
|
||||
features.value = { ...features.value, [key]: !!enabled }
|
||||
if (error) {
|
||||
lastError.value = error
|
||||
throw error
|
||||
}
|
||||
|
||||
// Atualiza cache local do tenant (mesmo que ainda não tenha sido carregado)
|
||||
const current = getTenantMap(tenantId)
|
||||
featuresByTenant.value = {
|
||||
...featuresByTenant.value,
|
||||
[tenantId]: { ...current, [key]: !!enabled }
|
||||
}
|
||||
loadedForTenantId.value = tenantId
|
||||
}
|
||||
|
||||
// (opcional) útil pra debug rápido na tela
|
||||
const currentFeatures = computed(() => getTenantMap(loadedForTenantId.value))
|
||||
|
||||
return {
|
||||
loading,
|
||||
features,
|
||||
lastError,
|
||||
lastFetchedAt,
|
||||
|
||||
loadedForTenantId,
|
||||
featuresByTenant,
|
||||
currentFeatures,
|
||||
|
||||
isEnabled,
|
||||
invalidate,
|
||||
fetchForTenant,
|
||||
|
||||
+82
-51
@@ -2,70 +2,119 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { supabase } from '@/lib/supabase/client'
|
||||
|
||||
// ✅ normaliza roles vindas do backend (tenant_members / RPC my_tenants)
|
||||
// - seu projeto quer usar clinic_admin como nome canônico
|
||||
function normalizeTenantRole (role) {
|
||||
/**
|
||||
* Normaliza o role de tenant levando em conta o kind do tenant.
|
||||
*
|
||||
* Regras:
|
||||
* tenant_admin / admin + kind = 'therapist' → 'therapist'
|
||||
* tenant_admin / admin + kind = clinic_* → 'clinic_admin'
|
||||
* tenant_admin / admin + kind desconhecido → 'clinic_admin' (padrão legado)
|
||||
* qualquer outro role → pass-through
|
||||
*/
|
||||
function normalizeTenantRole (role, kind) {
|
||||
const r = String(role || '').trim()
|
||||
if (!r) return null
|
||||
|
||||
// ✅ legado: alguns bancos / RPCs retornam tenant_admin
|
||||
if (r === 'tenant_admin') return 'clinic_admin'
|
||||
const isAdmin = (r === 'tenant_admin' || r === 'admin')
|
||||
|
||||
// (opcional) se em algum lugar vier 'admin' (profiles), também normaliza:
|
||||
if (r === 'admin') return 'clinic_admin'
|
||||
if (isAdmin) {
|
||||
const k = String(kind || '').trim()
|
||||
if (k === 'therapist' || k === 'saas') return 'therapist'
|
||||
if (k === 'supervisor') return 'supervisor'
|
||||
return 'clinic_admin'
|
||||
}
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
function readSavedTenant () {
|
||||
const id = localStorage.getItem('tenant_id')
|
||||
if (!id) return null
|
||||
try {
|
||||
const raw = localStorage.getItem('tenant')
|
||||
const obj = raw ? JSON.parse(raw) : null
|
||||
return { id, role: obj?.role ?? null }
|
||||
} catch {
|
||||
return { id, role: null }
|
||||
}
|
||||
}
|
||||
|
||||
function persistTenant (tenantId, role) {
|
||||
if (!tenantId) return clearPersistedTenant()
|
||||
localStorage.setItem('tenant_id', tenantId)
|
||||
localStorage.setItem('tenant', JSON.stringify({ id: tenantId, role }))
|
||||
}
|
||||
|
||||
function clearPersistedTenant () {
|
||||
localStorage.removeItem('tenant_id')
|
||||
localStorage.removeItem('tenant')
|
||||
}
|
||||
|
||||
export const useTenantStore = defineStore('tenant', {
|
||||
state: () => ({
|
||||
loading: false,
|
||||
loaded: false,
|
||||
|
||||
user: null, // auth user
|
||||
memberships: [], // [{ tenant_id, role, status }]
|
||||
user: null,
|
||||
memberships: [],
|
||||
activeTenantId: null,
|
||||
activeRole: null,
|
||||
|
||||
needsTenantLink: false,
|
||||
error: null
|
||||
}),
|
||||
|
||||
getters: {
|
||||
tenantId: (s) => s.activeTenantId,
|
||||
currentTenantId: (s) => s.activeTenantId,
|
||||
role: (s) => s.activeRole,
|
||||
tenant: (s) => (s.activeTenantId ? { id: s.activeTenantId, role: s.activeRole } : null),
|
||||
hasActiveTenant: (s) => !!s.activeTenantId
|
||||
},
|
||||
|
||||
actions: {
|
||||
async ensureLoaded () {
|
||||
if (this.loaded) return
|
||||
if (this.loading) {
|
||||
await new Promise((resolve) => {
|
||||
const t = setInterval(() => {
|
||||
if (!this.loading) { clearInterval(t); resolve() }
|
||||
}, 50)
|
||||
})
|
||||
return
|
||||
}
|
||||
await this.loadSessionAndTenant()
|
||||
},
|
||||
|
||||
async loadSessionAndTenant () {
|
||||
if (this.loading) return
|
||||
this.loading = true
|
||||
this.error = null
|
||||
|
||||
try {
|
||||
// 1) auth user (estável)
|
||||
const { data, error } = await supabase.auth.getSession()
|
||||
if (error) throw error
|
||||
|
||||
this.user = data?.session?.user ?? null
|
||||
|
||||
// sem sessão -> limpa estado e storage
|
||||
if (!this.user) {
|
||||
this.memberships = []
|
||||
this.activeTenantId = null
|
||||
this.activeRole = null
|
||||
this.needsTenantLink = false
|
||||
this.loaded = true
|
||||
|
||||
localStorage.removeItem('tenant_id')
|
||||
localStorage.removeItem('tenant')
|
||||
|
||||
clearPersistedTenant()
|
||||
return
|
||||
}
|
||||
|
||||
// 2) memberships via RPC
|
||||
const { data: mem, error: mErr } = await supabase.rpc('my_tenants')
|
||||
if (mErr) throw mErr
|
||||
|
||||
this.memberships = Array.isArray(mem) ? mem : []
|
||||
|
||||
// 3) tenta restaurar tenant salvo
|
||||
const savedTenantId = localStorage.getItem('tenant_id')
|
||||
// ✅ FIX: só restaura o tenant salvo se pertence ao usuário atual.
|
||||
// Sem isso, usuário B herdava o tenant_id do usuário A (mesma máquina),
|
||||
// carregava com role errado e o menu ficava incorreto.
|
||||
const saved = readSavedTenant()
|
||||
const savedTenantId = saved?.id || null
|
||||
|
||||
let activeMembership = null
|
||||
|
||||
@@ -73,6 +122,10 @@ export const useTenantStore = defineStore('tenant', {
|
||||
activeMembership = this.memberships.find(
|
||||
x => x.tenant_id === savedTenantId && x.status === 'active'
|
||||
)
|
||||
if (!activeMembership) {
|
||||
console.warn('[tenantStore] tenant salvo não pertence a este usuário, limpando.')
|
||||
clearPersistedTenant()
|
||||
}
|
||||
}
|
||||
|
||||
// fallback: primeiro active
|
||||
@@ -81,37 +134,26 @@ export const useTenantStore = defineStore('tenant', {
|
||||
}
|
||||
|
||||
this.activeTenantId = activeMembership?.tenant_id ?? null
|
||||
this.activeRole = normalizeTenantRole(activeMembership?.role, activeMembership?.kind)
|
||||
|
||||
// ✅ normaliza role aqui (tenant_admin -> clinic_admin)
|
||||
this.activeRole = normalizeTenantRole(activeMembership?.role)
|
||||
|
||||
// persiste tenant se existir
|
||||
if (this.activeTenantId) {
|
||||
localStorage.setItem('tenant_id', this.activeTenantId)
|
||||
localStorage.setItem('tenant', JSON.stringify({
|
||||
id: this.activeTenantId,
|
||||
role: this.activeRole
|
||||
}))
|
||||
persistTenant(this.activeTenantId, this.activeRole)
|
||||
} else {
|
||||
clearPersistedTenant()
|
||||
}
|
||||
|
||||
// se logou mas não tem vínculo ativo
|
||||
this.needsTenantLink = !this.activeTenantId
|
||||
|
||||
this.loaded = true
|
||||
} catch (e) {
|
||||
console.warn('[tenantStore] loadSessionAndTenant falhou:', e)
|
||||
this.error = e
|
||||
|
||||
// ⚠️ NÃO zera tudo agressivamente por erro transitório.
|
||||
// Mantém o que já tinha (se tiver), mas marca loaded pra não travar o app.
|
||||
if (!this.user) {
|
||||
this.memberships = []
|
||||
this.activeTenantId = null
|
||||
this.activeRole = null
|
||||
this.needsTenantLink = false
|
||||
|
||||
localStorage.removeItem('tenant_id')
|
||||
localStorage.removeItem('tenant')
|
||||
clearPersistedTenant()
|
||||
}
|
||||
|
||||
this.loaded = true
|
||||
@@ -126,25 +168,16 @@ export const useTenantStore = defineStore('tenant', {
|
||||
)
|
||||
|
||||
this.activeTenantId = found?.tenant_id ?? null
|
||||
|
||||
// ✅ normaliza role também ao trocar tenant
|
||||
this.activeRole = normalizeTenantRole(found?.role)
|
||||
|
||||
this.activeRole = normalizeTenantRole(found?.role, found?.kind)
|
||||
this.needsTenantLink = !this.activeTenantId
|
||||
|
||||
if (this.activeTenantId) {
|
||||
localStorage.setItem('tenant_id', this.activeTenantId)
|
||||
localStorage.setItem('tenant', JSON.stringify({
|
||||
id: this.activeTenantId,
|
||||
role: this.activeRole
|
||||
}))
|
||||
persistTenant(this.activeTenantId, this.activeRole)
|
||||
} else {
|
||||
localStorage.removeItem('tenant_id')
|
||||
localStorage.removeItem('tenant')
|
||||
clearPersistedTenant()
|
||||
}
|
||||
},
|
||||
|
||||
// opcional mas recomendado
|
||||
reset () {
|
||||
this.user = null
|
||||
this.memberships = []
|
||||
@@ -153,9 +186,7 @@ export const useTenantStore = defineStore('tenant', {
|
||||
this.needsTenantLink = false
|
||||
this.error = null
|
||||
this.loaded = false
|
||||
|
||||
localStorage.removeItem('tenant_id')
|
||||
localStorage.removeItem('tenant')
|
||||
clearPersistedTenant()
|
||||
}
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user