canina/frontend/application/lib/store/settingsStore.ts
2026-08-17 09:57:23 +03:30

93 lines
3.5 KiB
TypeScript

"use client";
import { create } from "zustand";
import api from "../services/api";
export interface ScientificTerm {
key: string;
term: string;
definition: string;
wikiId: string;
}
interface SettingsStore {
texts: Record<string, string>;
scientificTerms: Record<string, ScientificTerm>;
isLoading: boolean;
isInitialized: boolean;
fetchSettings: () => Promise<void>;
getText: (key: string, fallback: string) => string;
getBoolean: (key: string, fallback: boolean) => boolean;
}
export const useSettingsStore = create<SettingsStore>()((set, get) => ({
texts: {},
scientificTerms: {},
isLoading: false,
isInitialized: false,
fetchSettings: async () => {
set({ isLoading: true });
try {
const [textsRes, termsRes] = await Promise.all([
api.get('/settings/ui-texts'),
api.get('/settings/scientific-terms'),
]);
const textsObj: Record<string, string> = {};
if (Array.isArray(textsRes.data)) {
textsRes.data.forEach((item: { key: string; value: string }) => {
textsObj[item.key] = item.value;
});
}
const termsObj: Record<string, ScientificTerm> = {};
if (Array.isArray(termsRes.data)) {
termsRes.data.forEach((item: ScientificTerm) => {
termsObj[item.key] = item;
});
}
set({ texts: textsObj, scientificTerms: termsObj });
} catch (error) {
console.error("Failed to fetch settings/ui-texts:", error);
} finally {
set({ isLoading: false, isInitialized: true });
}
},
getText: (key, fallback) => {
const texts = get().texts;
if (!texts) return fallback;
const value =
texts[key] ??
texts[key.toLowerCase()] ??
texts[key.toUpperCase()];
if (value === undefined || value === null || value === '') {
// Special aliases
if (key === 'contact_phone') return texts['CONTACT_PHONE'] || texts['footer_phone'] || texts['maintenance_contact_phone'] || fallback;
if (key === 'contact_phone_link') return texts['CONTACT_PHONE_LINK'] || texts['maintenance_contact_phone_link'] || (texts['contact_phone'] ? `tel:${texts['contact_phone'].replace(/[^0-9+]/g, '')}` : fallback);
if (key === 'site_logo') return texts['BRAND_LOGO_URL'] || texts['brand_logo_url'] || fallback;
if (key === 'site_logo_text_en') return texts['BRAND_LOGO_TEXT_EN'] || fallback;
if (key === 'site_logo_text_fa') return texts['BRAND_LOGO_TEXT_FA'] || texts['brand_name_fa'] || fallback;
if (key === 'site_logo_subtitle') return texts['BRAND_LOGO_SUBTITLE'] || texts['brand_subtitle'] || fallback;
if (key === 'shipping_fee') return texts['SHIPPING_FEE'] || texts['standardShippingFee'] || fallback;
if (key === 'free_shipping_threshold') return texts['FREE_SHIPPING_THRESHOLD'] || texts['freeShippingThreshold'] || fallback;
if (key === 'min_order_amount') return texts['MIN_ORDER_AMOUNT'] || texts['minOrderAmount'] || fallback;
if (key === 'charity_round_step') return texts['CHARITY_ROUND_STEP'] || texts['charityRoundStep'] || fallback;
if (key === 'tax_percentage') return texts['TAX_PERCENTAGE'] || texts['taxPercentage'] || fallback;
return fallback;
}
return value;
},
getBoolean: (key, fallback) => {
const texts = get().texts;
if (!texts) return fallback;
const value =
texts[key] ??
texts[key.toLowerCase()] ??
texts[key.toUpperCase()];
if (value === undefined || value === null || value === '') {
return fallback;
}
return value === 'true' || value === '1' || (value as unknown) === true;
}
}));