93 lines
3.5 KiB
TypeScript
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;
|
|
}
|
|
}));
|