270 lines
6.9 KiB
TypeScript
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,
|
|
}
|
|
})
|