125 lines
3.3 KiB
TypeScript
125 lines
3.3 KiB
TypeScript
import { defineStore } from 'pinia';
|
|
import { ref } from 'vue';
|
|
import { fetchWrapper } from '@KTXC/utils/helpers/fetch-wrapper';
|
|
|
|
export interface TenantState {
|
|
id: string | null;
|
|
domain: string | null;
|
|
label: string | null;
|
|
}
|
|
|
|
export interface TenantData extends TenantState {
|
|
settings?: Record<string, unknown>;
|
|
}
|
|
|
|
// Flush pending settings writes before the page unloads
|
|
if (typeof window !== 'undefined') {
|
|
window.addEventListener('beforeunload', () => {
|
|
useTenantStore().flushSettings();
|
|
});
|
|
}
|
|
|
|
export const useTenantStore = defineStore('tenantStore', () => {
|
|
// =========================================================================
|
|
// State
|
|
// =========================================================================
|
|
|
|
const tenant = ref<TenantState | null>(null);
|
|
const settings = ref<Record<string, unknown>>({});
|
|
|
|
// Pending batch for debounced writes
|
|
let _pendingSettings: Record<string, unknown> = {};
|
|
let _debounceTimer: ReturnType<typeof setTimeout> | null = null;
|
|
|
|
// =========================================================================
|
|
// Getters
|
|
// =========================================================================
|
|
|
|
function getSetting(key: string): unknown {
|
|
return settings.value[key] ?? null;
|
|
}
|
|
|
|
// =========================================================================
|
|
// Settings actions
|
|
// =========================================================================
|
|
|
|
function setSetting(key: string, value: unknown): void {
|
|
settings.value[key] = value;
|
|
|
|
// Batch writes with a 500 ms debounce — same pattern as userService
|
|
_pendingSettings[key] = value;
|
|
|
|
if (_debounceTimer !== null) {
|
|
clearTimeout(_debounceTimer);
|
|
}
|
|
|
|
_debounceTimer = setTimeout(() => {
|
|
_flush();
|
|
}, 500);
|
|
}
|
|
|
|
async function _flush(): Promise<void> {
|
|
if (Object.keys(_pendingSettings).length === 0) return;
|
|
|
|
const payload = { ..._pendingSettings };
|
|
_pendingSettings = {};
|
|
_debounceTimer = null;
|
|
|
|
try {
|
|
await fetchWrapper.patch('/tenant/settings', { data: payload });
|
|
} catch (error) {
|
|
console.error('Failed to save tenant settings:', error);
|
|
}
|
|
}
|
|
|
|
/** Force-flush any pending settings writes (called on beforeunload). */
|
|
async function flushSettings(): Promise<void> {
|
|
if (_debounceTimer !== null) {
|
|
clearTimeout(_debounceTimer);
|
|
_debounceTimer = null;
|
|
}
|
|
await _flush();
|
|
}
|
|
|
|
// =========================================================================
|
|
// Initialise from /init endpoint
|
|
// =========================================================================
|
|
|
|
function init(tenantData: Partial<TenantData> | null): void {
|
|
tenant.value = tenantData
|
|
? {
|
|
id: tenantData.id ?? null,
|
|
domain: tenantData.domain ?? null,
|
|
label: tenantData.label ?? null,
|
|
}
|
|
: null;
|
|
|
|
settings.value = (tenantData?.settings as Record<string, unknown>) ?? {};
|
|
}
|
|
|
|
function reset(): void {
|
|
tenant.value = null;
|
|
settings.value = {};
|
|
_pendingSettings = {};
|
|
if (_debounceTimer !== null) {
|
|
clearTimeout(_debounceTimer);
|
|
_debounceTimer = null;
|
|
}
|
|
}
|
|
|
|
return {
|
|
// State
|
|
tenant,
|
|
settings,
|
|
|
|
// Getters
|
|
getSetting,
|
|
|
|
// Actions
|
|
setSetting,
|
|
flushSettings,
|
|
init,
|
|
reset,
|
|
};
|
|
});
|