128 lines
3.3 KiB
TypeScript
128 lines
3.3 KiB
TypeScript
import { defineStore } from 'pinia'
|
|
import { ref, watch, computed, inject } from 'vue'
|
|
import { api } from 'boot/axios'
|
|
import { useAuthStore } from 'stores/auth'
|
|
import { useI18n } from 'vue-i18n'
|
|
import type { WebApp } from '@twa-dev/types'
|
|
|
|
|
|
interface AppSettings {
|
|
fontSize: number
|
|
locale: string
|
|
timeZoneBot: { tz: string, offset: number, offsetString: string }
|
|
localeBot: string
|
|
}
|
|
|
|
const defaultFontSize = 16
|
|
|
|
const defaultSettings: AppSettings = {
|
|
fontSize: defaultFontSize,
|
|
locale: 'en-US',
|
|
timeZoneBot: { tz: 'Europe/Moscow', offset: 3, offsetString: '+03:00' },
|
|
localeBot: 'en-US'
|
|
}
|
|
|
|
export const useSettingsStore = defineStore('settings', () => {
|
|
const { locale: i18nLocale } = useI18n()
|
|
const authStore = useAuthStore()
|
|
const settings = ref<AppSettings>({ ...defaultSettings })
|
|
const tg = inject<WebApp>('tg')
|
|
|
|
const isInit = ref(false)
|
|
|
|
const currentFontSize = computed(() => settings.value?.fontSize ?? defaultFontSize)
|
|
|
|
const supportLocale = [
|
|
{ value: 'en-US', label: 'English' },
|
|
{ value: 'ru-RU', label: 'Русский' }
|
|
]
|
|
|
|
const supportFontSizes = [
|
|
{ value: 12, label: 'settings__fontsize_small' },
|
|
{ value: 16, label: 'settings__fontsize_medium' },
|
|
{ value: 20, label: 'settings__fontsize_large' }
|
|
]
|
|
|
|
const detectLocale = (): string => {
|
|
const localeMap = {
|
|
ru: 'ru-RU',
|
|
en: 'en-US'
|
|
} as const satisfies Record<string, string>
|
|
|
|
type LocaleCode = keyof typeof localeMap
|
|
|
|
const normLocale = (locale?: string): string | undefined => {
|
|
if (!locale) return undefined
|
|
const code = locale.split('-')[0] as LocaleCode
|
|
return localeMap[code] ?? undefined
|
|
}
|
|
|
|
const tgLang = tg?.initDataUnsafe?.user?.language_code
|
|
const normalizedTgLang = normLocale(tgLang)
|
|
|
|
return normalizedTgLang ?? normLocale(navigator.language) ?? 'en-US'
|
|
}
|
|
|
|
const updateCssVariable = () => {
|
|
document.documentElement.style.setProperty(
|
|
'--dynamic-font-size',
|
|
`${currentFontSize.value}px`
|
|
)
|
|
}
|
|
|
|
const applyLocale = () => {
|
|
if (settings.value.locale && i18nLocale) {
|
|
i18nLocale.value = settings.value.locale
|
|
}
|
|
}
|
|
|
|
const init = async () => {
|
|
if (authStore.isAuth) {
|
|
try {
|
|
const { data } = await api.get('/customer/settings')
|
|
settings.value = {
|
|
fontSize: data.data.fontSize || defaultSettings.fontSize,
|
|
locale: data.data.locale || detectLocale(),
|
|
timeZoneBot: data.data.timeZone || defaultSettings.timeZoneBot,
|
|
localeBot: data.data.localeBot || detectLocale()
|
|
}
|
|
} catch {
|
|
settings.value.locale = detectLocale()
|
|
}
|
|
} else {
|
|
settings.value = {
|
|
...defaultSettings,
|
|
locale: detectLocale()
|
|
}
|
|
}
|
|
updateCssVariable()
|
|
applyLocale()
|
|
isInit.value = true
|
|
}
|
|
|
|
const saveSettings = async () => {
|
|
await api.put('/customer/settings', settings.value)
|
|
}
|
|
|
|
const updateSettings = async (newSettings: Partial<AppSettings>) => {
|
|
settings.value = { ...settings.value, ...newSettings }
|
|
updateCssVariable()
|
|
applyLocale()
|
|
await saveSettings()
|
|
}
|
|
|
|
watch(() => authStore.isAuth, (newVal) => {
|
|
if (newVal !== undefined) void init()
|
|
}, { immediate: true })
|
|
|
|
return {
|
|
settings,
|
|
supportLocale,
|
|
supportFontSizes,
|
|
isInit,
|
|
currentFontSize,
|
|
init,
|
|
updateSettings
|
|
}
|
|
})
|