Files
your-gold/stores/menuStore.ts
2025-06-25 12:43:42 +02:00

304 lines
7.7 KiB
TypeScript

import { usePB } from "~/composables/usePB";
import type {
Country,
Currencies,
Currency,
FooterListResponse,
FrontMenu,
GenericResponse,
GenericResponseItems,
PBFooterItem,
UIFrontMenu,
UIMenuItem,
} from "~/types";
import { useStore } from "./store";
import { ref, watch } from "vue";
import { useMyFetch } from "#imports";
// function buildTreeRecursive(
// data: (PBMenuItem | UIMenuItem)[],
// parentId: string
// ): UIMenuItem[] {
// const children = data.filter(
// (item): item is UIMenuItem =>
// item.id_parent === parentId && !item.is_default
// );
// return children.map((item) => ({
// ...item,
// children: buildTreeRecursive(data, item.id),
// }));
// }
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 pb = usePB();
const store = useStore();
const { $i18n } = useNuxtApp();
const router = useRouter();
const route = useRoute();
const openMenu = ref(false);
const openDropDown = ref(false);
const defaultMenu = ref();
// const menu = ref<UIMenuItem[]>([]);
// const menuItems = ref<MenuListResponse>();
const menu = ref<UIFrontMenu[]>([]);
const menuItems = ref<FrontMenu[]>();
const footerItems = ref<FooterListResponse>();
const countryList = ref<Country[]>();
const currencies = ref<Currency[]>();
// curr/country
const selectedCountry = ref();
const selectedPhoneCountry = ref();
const selectedCurrency = ref<Currencies>();
const loadMenu = async () => {
try {
// menuItems.value = (await pb
// .collection("menu_view")
// .getList<PBMenuItem>(1, 50, {
// filter: `id_lang="${$i18n.locale.value}"&&active=true`,
// sort: "position_id",
// })) as MenuListResponse;
const { data } = await useMyFetch<GenericResponse<FrontMenu[]>>(`/api/public/front/menu`, {
onErrorOccured: (err, status) => {
console.log(err, status);
},
// onSuccess(data) {
// console.log(data.data, "data");
// },
})
const root = data.find((item) => item.is_root) as UIFrontMenu;
defaultMenu.value = data.find((item) => item.is_default);
// console.log(menuNew, "data");
if (root) {
menu.value = buildTreeRecursive(data, root.id);
} else {
console.warn("Root menu item not found");
menu.value = [];
}
// const root = menuItems.value.items.find((item) => item.is_root);
// defaultMenu.value = menuItems.value.items.find((item) => item.is_default);
// if (root) {
// menu.value = buildTreeRecursive(menuItems.value.items, root.id);
// store.currentPageID = menu.value[0]?.id_page || "";
// } else {
// console.warn("Root menu item not found");
// menu.value = [];
// }
} catch (error) {
console.log(error);
}
};
const loadFooter = async () => {
try {
footerItems.value = (await pb
.collection("footer_view")
.getList<PBFooterItem>(1, 50, {
filter: `id_lang="${$i18n.locale.value}"`,
})) as FooterListResponse;
} catch (error) {
console.log(error);
}
};
const getCountryList = async () => {
try {
const { data } = await useMyFetch<GenericResponse<Country[]>>(
`/api/public/country/list`,
{
headers: {
"Content-Type": "application/json",
},
}
);
// if (!res.ok) {
// throw new Error(`HTTP error: ${res.status}`);
// }
// const data = await res.json();
countryList.value = data
if (countryList.value)
selectedPhoneCountry.value = countryList.value[0]
} catch (error) {
console.error("getList error:", error);
}
}
const getCurrencies = async () => {
try {
const { data } = await useMyFetch<GenericResponseItems<Currency[]>>(
`/api/public/currencies`,
{
headers: {
"Content-Type": "application/json",
},
onErrorOccured: (_, status) => { throw new Error(`HTTP error: ${status}`) },
}
);
// if (!res.ok) {
// throw new Error(`HTTP error: ${res.status}`);
// }
// const data = await res.json();
currencies.value = data.items
// console.log(data.items, "data");
} catch (error) {
console.error("getList error:", 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.link_rewrite,
id: defaultMenu.value.id_page,
},
name: `id-slug___${$i18n.locale.value}`,
});
}
};
function navigateToShop() {
navigateToItem(menuItems.value?.items.find(item => item.page_name === 'shop'))
}
// function redirectToPage(link_rewrite: string) {
// const page = menuItems.value?.items.find(
// (item) => item.link_rewrite === link_rewrite
// );
// if (!page?.id_page || !page?.link_rewrite) {
// console.warn(`Page not found or missing data for name: ${link_rewrite}`);
// return;
// }
// router.push({
// params: {
// id: page?.id_page,
// slug: page?.link_rewrite,
// },
// });
// }
const getFirstImage = () => {
const req = useRequestEvent();
const url = useRequestURL();
let img = "";
for (const s in store.components) {
store.components[s].section_img.map((item) => {
img = `${req?.headers.get("x-forwarded-proto") || url.protocol}://${req?.headers.get("x-forwarded-host") || req?.headers.get("host")
}/api/files/${store.components[s].image_collection}/${store.components[s].section_id
}/${item}?thumb=400x0`;
});
if (img.length > 0) return img;
}
return "";
};
const headMeta = computed(() => {
const item = menuItems.value?.items.find(
(item) => item.id_page === route.params.id
);
return {
title: item?.meta_title,
htmlAttrs: {
lang: $i18n.locale.value,
},
link: [{ rel: "manifest", href: "/api/manifest.json" }],
meta: [
{
hid: "description",
name: "description",
content: item?.meta_description,
},
{
property: "og:title",
content: item?.meta_title,
},
{
property: "og:description",
content: item?.meta_description,
},
{
property: "og:image",
content: getFirstImage(),
},
{
property: "twitter:title",
content: item?.meta_title,
},
{
property: "twitter:description",
content: item?.meta_description,
},
{
property: "twitter:image",
content: getFirstImage(),
},
],
};
});
watch($i18n.locale, async () => {
await loadMenu();
await loadFooter();
});
watch(selectedCurrency, () => {
store.getCalculator()
})
return {
menu,
menuItems,
footerItems,
openMenu,
openDropDown,
countryList,
currencies,
selectedCountry,
selectedCurrency,
selectedPhoneCountry,
defaultMenu,
headMeta,
navigateToShop,
loadMenu,
loadFooter,
getCountryList,
navigateToItem,
// redirectToPage,
getCurrencies
};
});