Files
your-gold/stores/menuStore.ts
2025-07-03 15:24:28 +02:00

270 lines
6.9 KiB
TypeScript

import { useStore } from './store'
import type {
Country,
Currency,
FrontMenu,
GenericResponse,
GenericResponseItems,
Language,
UIFrontMenu,
} from '~/types'
import { useMyFetch } from '#imports'
function buildTreeRecursive(
data: (FrontMenu | UIFrontMenu)[],
parentId: number,
): UIFrontMenu[] {
const children = data.filter(
(item): item is UIFrontMenu =>
item.id_parent === parentId && !item.is_default,
)
return children.map(item => ({
...item,
children: buildTreeRecursive(data, item.id),
}))
}
export const useMenuStore = defineStore('menuStore', () => {
const store = useStore()
const { $i18n } = useNuxtApp()
// const session = useSession();
const { $session } = useNuxtApp()
const router = useRouter()
const route = useRoute()
const openMenu = ref(false)
const openDropDown = ref(false)
const defaultMenu = ref()
const menu = ref([] as UIFrontMenu[])
const menuItems = ref([] as FrontMenu[])
// curr/country
const selectedCountry = ref({} as Country)
const selectedPhoneCountry = ref({} as Country)
const selectedCurrency = ref({} as Currency)
const selectedLanguage = ref({} as Language)
const countries = ref([] as Country[])
const currencies = ref([] as Currency[])
const languages = ref([] as Language[])
const getLocales = async () => {
const { data: countriesList } = await useMyFetch<
GenericResponse<Country[]>
>(`/api/public/country/list`)
countries.value = countriesList
selectedCountry.value = countriesList.find(
country => country.iso_code === $session.currentCountryIso.value,
) as Country
selectedPhoneCountry.value = countriesList.find(
country => country.iso_code === $session.currentCountryIso.value,
) as Country
const { data: currenciesList } = await useMyFetch<
GenericResponseItems<Currency[]>
>(`/api/public/currencies`)
currencies.value = currenciesList.items
selectedCurrency.value = currenciesList.items.find(
currency => currency.iso_code === $session.currentCurrencyIso.value,
) as Currency
const { data: languagesList } = await useMyFetch<
GenericResponseItems<Language[]>
>(`/api/public/languages`)
languages.value = languagesList.items
selectedLanguage.value = languagesList.items.find(
language => language.iso_code === $session.currentLanguageIso.value,
) as Language
}
const loadMenu = async () => {
try {
const { data } = await useMyFetch<GenericResponse<FrontMenu[]>>(
`/api/public/front/menu`,
{
onErrorOccured: (err, status) => {
console.log(err, status)
},
},
)
menuItems.value = data
const root = data.find(item => item.is_root) as UIFrontMenu
defaultMenu.value = data.find(item => item.is_default)
if (root) {
menu.value = buildTreeRecursive(data, root.id)
}
else {
console.warn('Root menu item not found')
menu.value = []
}
}
catch (error) {
console.log(error)
}
}
const navigateToItem = (item?: UIFrontMenu) => {
if (item) {
router.push({
params: { slug: item.front_menu_lang[0].link_rewrite, id: item.id },
name: `id-slug___${$i18n.locale.value}`,
})
openDropDown.value = false
}
else {
router.push({
params: {
slug: defaultMenu.value.front_menu_lang[0].link_rewrite,
id: defaultMenu.value.id,
},
name: `id-slug___${$i18n.locale.value}`,
})
}
}
function navigateToShop() {
navigateToItem(menuItems.value?.find(item => item.id === 5))
}
function getProductMenu() {
return menuItems.value?.find(item => item.id === 14)
}
const getFirstImage = (size: 'l' | 'm' | 's' = 'm', needbaseurl: boolean) => {
const req = useRequestEvent()
const url = useRequestURL()
// let img = "";
const img: string[] = []
for (const s in store.components) {
if (store.components[s].front_section.img.length === 0) continue
img.push(
`/api/public/file/${store.components[s].front_section.img[0]}_${size}.webp`,
)
if (img.length > 0) break
}
if (img.length > 0) {
if (needbaseurl) {
return `${req?.headers.get('x-forwarded-proto') || url.protocol}://${
req?.headers.get('x-forwarded-host')
|| url.host
|| req?.headers.get('host')
}${img[0]}`
}
return img[0]
}
return ''
}
const headMeta = computed(() => {
const item = menuItems.value?.find(
item => item.id.toString() === route.params.id,
)
const meta = {
title: item?.front_menu_lang[0].meta_title,
htmlAttrs: {
lang: $i18n.locale.value,
},
link: [
// { rel: "manifest", href: "/api/manifest.json" }
{ rel: 'icon', type: 'image/x-icon', href: '/favicon.png' },
],
script: [
{
src: 'https://leiadmin.com/leitag.js?lei=894500UT83EISNNA8D04&color=dark',
defer: true,
},
],
meta: [
{
hid: 'description',
name: 'description',
content: item?.front_menu_lang[0].meta_description,
},
{
property: 'og:title',
content: item?.front_menu_lang[0].meta_title,
},
{
property: 'og:description',
content: item?.front_menu_lang[0].meta_description,
},
{
property: 'og:image',
content: getFirstImage('m', true),
},
{
property: 'twitter:title',
content: item?.front_menu_lang[0].meta_title,
},
{
property: 'twitter:description',
content: item?.front_menu_lang[0].meta_description,
},
{
property: 'twitter:image',
content: getFirstImage('m', true),
},
],
}
const preload = getFirstImage('l', false)
if (preload) {
meta.link.push({ rel: 'preload', as: 'image', href: preload } as never)
}
return meta
})
const formatPrice = (value: number): string => {
return value.toLocaleString(selectedLanguage.value.iso_code, {
minimumFractionDigits: selectedCurrency.value.precision,
maximumFractionDigits: selectedCurrency.value.precision,
currency: selectedCurrency.value.iso_code,
style: 'currency',
currencyDisplay: 'symbol',
currencySign: 'accounting',
})
}
// watches
watch(
() => $session.cookieData,
async () => {
await getLocales()
await loadMenu()
await store.getMinValue()
await store.getCalculator()
},
{ deep: true },
)
return {
menu,
menuItems,
openMenu,
openDropDown,
currencies,
languages,
countries,
selectedCountry,
selectedCurrency,
selectedPhoneCountry,
selectedLanguage,
defaultMenu,
headMeta,
navigateToShop,
loadMenu,
navigateToItem,
getLocales,
getProductMenu,
formatPrice,
}
})