fix langs

This commit is contained in:
2025-06-25 21:19:40 +02:00
parent 9d7fd3d52a
commit edf3036e6a
24 changed files with 266 additions and 776 deletions

View File

@ -1,7 +0,0 @@
@font-face {
font-family: "Bounded";
src: url("/fonts/Bounded/Bounded-Variable.ttf") format("truetype");
font-weight: 100 900;
font-style: normal;
font-display: swap;
}

View File

@ -12,7 +12,6 @@
"@tailwindcss/vite": "^4.1.8",
"@vueuse/core": "^13.3.0",
"nuxt": "^3.17.4",
"pocketbase": "^0.26.0",
"tailwindcss": "^4.1.7",
"vue": "^3.5.14",
"vue-router": "^4.5.1",
@ -1827,8 +1826,6 @@
"pluralize": ["pluralize@8.0.0", "", {}, "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA=="],
"pocketbase": ["pocketbase@0.26.1", "", {}, "sha512-fjcPDpxyqTZCwqGUTPUV7vssIsNMqHxk9GxbhxYHPEf18RqX2d9cpSqbbHk7aas30jqkgptuKfG7aY/Mytjj3g=="],
"portfinder": ["portfinder@1.0.37", "", { "dependencies": { "async": "^3.2.6", "debug": "^4.3.6" } }, "sha512-yuGIEjDAYnnOex9ddMnKZEMFE0CcGo6zbfzDklkmT1m5z734ss6JMzN9rNB3+RR7iS+F10D4/BVIaXOyh8PQKw=="],
"possible-typed-array-names": ["possible-typed-array-names@1.1.0", "", {}, "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg=="],

View File

@ -3,7 +3,7 @@
<UButton color="neutral" variant="subtle" trailing-icon="i-lucide-chevron-down"
class="bg-bg-light dark:bg-bg-dark m-0 ring-0 text-xl font-medium uppercase cursor-pointer hover:bg-inherit text-text-light dark:text-text-dark"
block @click="isOpen = !isOpen">
{{ menuStore.selectedCountry }}/{{ menuStore.selectedCurrency?.iso_code }}
{{ $session.cookieData.value.country.iso_code }}/{{ $session.cookieData.value.currency.iso_code }}
</UButton>
<div class="absolute ring-0 top-12 p-0 m-0 border-none w-48 z-50" v-if="isOpen">
@ -15,7 +15,7 @@
class="bg-inherit w-full ring-0 cursor-pointer focus:ring-0 outline-none focus-visible:ring-0 space-y-1">
<div class="p-0" @click="openDrop('country')">
<div class="flex items-center gap-2 text-xl font-medium uppercase text-text-light dark:text-text-dark">
{{ menuStore.selectedCountry }} <span> <i
{{ $session.currentCountryIso }} <span> <i
class="uil uil-angle-down text-2xl font-light cursor-pointer"></i></span>
</div>
</div>
@ -23,12 +23,9 @@
<div v-if="dropCountry"
class="rounded-[5px] data-highlighted:not-data-disabled:before:bg-button/50 bg-inherit ring-0 cursor-pointer w-full focus:ring-0 outline-none focus-visible:ring-0 border border-button py-[10px] px-[5px]">
<div class="overflow-auto h-[200px] w-full">
<p @click="() => {
menuStore.selectedCountry = item.iso_code
dropCountry = false
}"
<p @click="() => { $session.setCountry(item.iso_code); $session.loadSession(); dropCountry = false }"
class="w-full hover:bg-block dark:hover:bg-button pl-2 py-2 text-base text-text-light dark:text-text-dark rounded-[5px]"
v-for="item in menuStore.countryList">
v-for="item in menuStore.countries" :key="item.iso_code">
{{ item?.name }}
</p>
</div>
@ -41,7 +38,7 @@
class="bg-inherit w-full ring-0 cursor-pointer focus:ring-0 outline-none focus-visible:ring-0 space-y-1">
<div class="p-0" @click="openDrop()">
<div class="flex items-center gap-2 text-xl font-medium uppercase text-text-light dark:text-text-dark">
{{ menuStore.selectedCurrency?.iso_code }}<span> <i
{{ $session.currentCurrencyIso }}<span> <i
class="uil uil-angle-down text-2xl font-light cursor-pointer"></i></span>
</div>
</div>
@ -49,12 +46,9 @@
<div v-if="dropCurrency"
class="rounded-[5px] data-highlighted:not-data-disabled:before:bg-button/50 bg-inherit ring-0 cursor-pointer w-full focus:ring-0 outline-none focus-visible:ring-0 border border-button py-[10px] px-[5px]">
<div class="overflow-auto w-full">
<p @click="() => {
menuStore.selectedCurrency = item
dropCurrency = false
}"
<p @click="() => { $session.setCurrency(item.iso_code); $session.loadSession(); dropCurrency = false }"
class="w-full hover:bg-block dark:hover:bg-button pl-1 py-2 text-base text-text-light dark:text-text-dark rounded-[5px]"
v-for="item in menuStore.currencies">
v-for="item in menuStore.currencies" :key="item.iso_code">
{{ item?.name }}
</p>
</div>
@ -69,6 +63,8 @@
<script setup lang="ts">
import { onClickOutside } from "@vueuse/core";
const {$session} = useNuxtApp();
const isOpen = ref(false);
const menuStore = useMenuStore();
@ -87,22 +83,6 @@ function openDrop(type?: string) {
}
}
watchEffect(() => {
if (
!menuStore.selectedCountry &&
menuStore.countryList &&
menuStore.countryList.length > 0
) {
menuStore.selectedCountry = menuStore.countryList[0].iso_code;
}
if (
!menuStore.selectedCurrency &&
menuStore.currencies &&
menuStore.currencies.length > 0
) {
menuStore.selectedCurrency = menuStore.currencies[0];
}
});
onClickOutside(dropdownRef, () => {
isOpen.value = false

View File

@ -5,8 +5,9 @@
<UiContainer class="relative">
<div class="hidden h-[120px] w-full items-center gap-[145px] xl:flex">
<ul class="flex items-center justify-between whitespace-nowrap w-full">
<li v-for="(item, index) in menuStore.menu" @click="menuStore.navigateToItem(item)" :key="index"
:class="['hover:text-accent-green-light dark:hover:text-accent-green-dark cursor-pointer text-lg transition-all text-inter', route.params.slug === item.front_menu_lang[0].link_rewrite && 'text-accent-green-light dark:text-accent-green-dark font-bold underline']">
<li v-for="(item, index) in menuStore.menu" @click="menuStore.navigateToItem(item)" :key="item.id"
:class="['hover:text-accent-green-light dark:hover:text-accent-green-dark cursor-pointer text-lg transition-all text-inter',
route.params.id == item.id ? 'text-accent-green-light dark:text-accent-green-dark font-bold underline' : false]">
0{{ index + 1 }} <br />
{{ item.front_menu_lang[0].name }}
</li>
@ -27,8 +28,8 @@
<ThemeSwitcher />
<button @click="menuStore.navigateToShop" :class="[
'cursor-pointer transition-all text-inter',
menuStore.menuItems?.find(item => (item.id_page === route.params.id) && (item.page_name === 'shop'))
? 'text-accent-green-light dark:text-accent-green-dark font-bold pb-1 border-b-2'
route.params.id == 5
? 'text-accent-green-light dark:text-accent-green-dark font-bold pb-1 border-b-2 bg-accented px-6 py-3 rounded-xl'
: 'hover:bg-button-hover bg-button text-white font-medium rounded-xl px-6 py-3'
]">
{{ $t('eshop') }}

View File

@ -14,11 +14,11 @@
group: 'px-[5px] py-[10px]',
item: 'hover:bg-block dark:hover:bg-button rounded-[5px] data-highlighted:not-data-disabled:before:bg-button/50',
}"
@update:model-value="setLocale"
@update:model-value="setLocale($event); $session.setLanguage($event); $session.loadSession()"
>
<template #leading="{ modelValue }">
<div class="flex items-center gap-2 text-xl font-medium uppercase">
{{ locales.find((item) => item.code === modelValue)?.code }}
{{ locales.find((item: any) => item.code === modelValue)?.code }}
</div>
</template>
@ -39,20 +39,10 @@
</template>
<script setup lang="ts">
import { useI18n } from "#imports";
const { locale, locales, setLocale } = useI18n();
const {$session} = useNuxtApp();
const isOpen = ref(false);
const selectedLocaleCode = ref(locale.value);
const selectedIcon = ref(
locales.value.find((item) => item.code === locale.value)?.icon
);
watch(selectedLocaleCode, async (newCode) => {
if (newCode !== locale.value) {
await setLocale(newCode);
}
});
</script>

File diff suppressed because one or more lines are too long

View File

@ -7,8 +7,8 @@
</h2>
</div>
<div class="space-y-[40px] sm:space-55-75">
<div v-for="(item, index) in component.front_section_lang[0].data.section_1.text_blocks"
:key="index" class="grid grid-cols-7 md:grid-cols-4 xl:grid-cols-2">
<div v-for="(item, index) in component.front_section_lang[0].data.section_1.text_blocks" :key="index"
class="grid grid-cols-7 md:grid-cols-4 xl:grid-cols-2">
<div class="flex gap-[200px]">
<h4 class="h4-uppercase-bold-inter">0{{ index + 1 }}</h4>
<h4 class="hidden xl:block h4-uppercase-bold-inter w-full whitespace-nowrap">
@ -29,8 +29,8 @@
{{ component.front_section_lang[0].data.section_2.title }}
</h2>
<div class="grid sm:grid-cols-2 xl:grid-cols-4 gap-[30px] auto-cols-fr auto-rows-fr">
<div class="border border-border rounded-2xl p-8 flex flex-col justify-between gap-[55px]" v-for="(item, index) in component.front_section_lang[0].data.section_2
.text_blocks" :key="index">
<div class="border border-border rounded-2xl p-8 flex flex-col justify-between gap-[55px]"
v-for="(item, index) in component.front_section_lang[0].data.section_2.text_blocks" :key="index">
<div>
<h4 class="h4-uppercase-bold-inter">0{{ index + 1 }}</h4>
<h4 class="h4-uppercase-bold-inter">{{ item.block_title }}</h4>
@ -57,8 +57,7 @@
{{ component.front_section_lang[0].data.section_3.title }}
</h2>
<div class="flex flex-col space-25-55">
<p v-for="(item, index) in component.front_section_lang[0].data.section_3
.text_blocks" :key="index">
<p v-for="(item, index) in component.front_section_lang[0].data.section_3.text_blocks" :key="index">
{{ item }}
</p>
</div>
@ -75,7 +74,8 @@
backgroundSize: 'cover',
backgroundPosition: 'center',
}" />
<p class="xl:col-start-2 xl:col-end-3">{{ component.front_section_lang[0].data.section_4.description_second }}</p>
<p class="xl:col-start-2 xl:col-end-3">{{ component.front_section_lang[0].data.section_4.description_second
}}</p>
</div>
</UiContainer>
</template>

View File

@ -11,7 +11,9 @@
<p class="text-text-light sm:text-xl md:text-2xl font-medium">{{
component.front_section_lang[0].data.description }}</p>
</div>
<UiButtonArrow type="fill" :arrow="true">{{ $t('buy_gold') }}</UiButtonArrow>
<UiButtonArrow type="fill" :arrow="true">
{{ $t('buy_gold') }}
</UiButtonArrow>
</div>
<div class="flex gap-[10px] sm:gap-[30px]">
<div class="rounded-2xl h-[155px] sm:h-[225px] md:h-[280px] w-full" :style="{
@ -43,8 +45,9 @@
<div class="space-25-55-75">
<h2 class="h2-bold-bounded">{{ component.front_section_lang[0].data.section_2.title }}</h2>
<div class="space-y-[40px] sm:space-y-[50px]">
<p v-for="(item, index) in component.front_section_lang[0].data.section_2.text_blocks" :key="index">{{ item
}}</p>
<p v-for="(item, index) in component.front_section_lang[0].data.section_2.text_blocks" :key="index">
{{ item }}
</p>
</div>
</div>
<div class="w-full md:h-full rounded-2xl h-[327px] sm:h-[550px]" :style="{
@ -55,7 +58,8 @@
</div>
<div
class="grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-4 gap-y-[25px] sm:gap-y-[55px] xl:gap-y-0 gap-x-[30px]">
<h2 class="h2-bold-bounded sm:col-start-1 sm:col-end-3">{{ component.front_section_lang[0].data.section_3.title }}
<h2 class="h2-bold-bounded sm:col-start-1 sm:col-end-3">{{
component.front_section_lang[0].data.section_3.title }}
</h2>
<div v-for="(item, index) in component.front_section_lang[0].data.section_3.text_blocks" :key="index"
class="flex flex-col justify-between space-25-55">

View File

@ -29,8 +29,7 @@
</template>
<script lang="ts" setup>
defineProps<{ component: Component }>();
type Component = {
defineProps<{ component: {
id: number
name: string
img: string[]
@ -46,5 +45,6 @@ type Component = {
id_front_section: number
id_lang: number
}[]
};
} }>();
</script>

View File

@ -1,7 +1,7 @@
<template>
<UiContainer class="flex py-[15px] xl:py-20 sm:py-0">
<div class="hidden xl:block rounded-2xl min-w-[40%] h-[830px]" :style="{
backgroundImage: `url('/api/files/${component.image_collection}/${component.section_id}/${component.section_img[0]}?thumb=1200x0')`,
backgroundImage: `url('/api/public/file/${component.img[0]}_l.webp')`,
backgroundSize: 'cover',
backgroundPosition: 'center',
}" />
@ -50,10 +50,9 @@
<div v-if="dropCountry"
class="mt-2 absolute bg-bg-light dark:bg-bg-dark rounded-[5px] ring-0 cursor-pointer w-full border border-button py-[10px] px-[5px] overflow-hidden">
<div class="overflow-y-auto h-[200px] w-full">
<p v-for="item in menuStore.countryList" @click="() => {
menuStore.selectedPhoneCountry = item
dropCountry = false
}" class="w-full truncate whitespace-nowrap overflow-hidden hover:bg-block dark:hover:bg-button pl-2 py-2 text-base text-text-light dark:text-text-dark rounded-[5px]"
<p v-for="item in menuStore.countries" :key="item.iso_code"
@click="() => { menuStore.selectedPhoneCountry = item; dropCountry = false }"
class="w-full truncate whitespace-nowrap overflow-hidden hover:bg-block dark:hover:bg-button pl-2 py-2 text-base text-text-light dark:text-text-dark rounded-[5px]"
:title="item.name">
{{ item.name }}
</p>
@ -62,14 +61,14 @@
</div>
<p class="text-sm sm:text-xl font-normal">{{ menuStore.selectedPhoneCountry.call_prefix
}}</p>
}}</p>
<input :placeholder="$t('phone')" type="text"
class="text-sm sm:text-xl placeholder:text-gray dark:placeholder:text-button-disabled text-bg-dark dark:text-bg-light px-6 h-[50px] sm:h-[67px] w-full focus:outline-none focus:ring-0" />
</div>
</div>
<div class="space-y-[15px]">
<p class="pl-6">{{ $t('account_type') }}</p>
<USelect v-model="selectedType" :items="component.section_lang_data.account_types"
<USelect v-model="selectedType" :items="component.front_section_lang[0].data.account_types"
value-key="name" :searchable="false" :ui="{
base: 'bg-inherit ring-0 cursor-pointer w-auto focus:ring-0 outline-none focus-visible:ring-0 h-[50px] sm:h-[67px] w-full p-0',
trailing: 'hidden w-full',
@ -84,8 +83,8 @@
<div
class="flex items-center justify-between gap-2 uppercase text-sm sm:text-xl border-2 border-block placeholder:text-gray dark:placeholder:text-button-disabled text-bg-dark dark:text-bg-light rounded-lg px-6 w-full h-[50px] sm:h-[67px]">
<p class="truncate whitespace-nowrap">
{{component.section_lang_data.account_types.find((item) => item.name ===
modelValue)?.name}}</p>
{{ component.front_section_lang[0].data.account_types.find((item) => item.name === modelValue)?.name }}
</p>
<span> <i
class="uil uil-angle-down text-2xl font-light cursor-pointer"></i></span>
</div>
@ -115,10 +114,10 @@
<div class="mt-[25px] sm:mt-[30px] w-full flex justify-center gap-3">
<p class="cursor-pointer hover:underline transition-all">{{
$t('is_account')
}}</p>
}}</p>
<p class="text-button cursor-pointer hover:text-button-hover">{{
$t('login')
}}</p>
}}</p>
</div>
</div>
</UiContainer>
@ -126,23 +125,32 @@
<script lang="ts" setup>
import { onClickOutside } from "@vueuse/core";
const props = defineProps<{ component: Component }>();
type Component = {
image_collection: string;
section_id: string;
section_img: string;
section_lang_data: {
account_types: [{
id: number,
name: string
}]
};
};
const props = defineProps<{
component: {
id: number
name: string
img: string[]
component_name: string
is_no_lang: boolean
page_name: string
front_section_lang: {
data: {
account_types: {
id: number,
name: string
}[]
}
id_front_section: number
id_lang: number
}[]
}
}>();
const menuStore = useMenuStore()
const dropdownRef = ref(null);
const dropCountry = ref()
const selectedType = ref(props.component.section_lang_data.account_types[0].name)
const selectedType = ref(props.component.front_section_lang[0].data.account_types[0].name)
onClickOutside(dropdownRef, () => {
dropCountry.value = false

View File

@ -168,6 +168,10 @@ import { ref } from "vue";
import Product from "./Product.vue";
import type { Feature, GenericResponse, GenericResponseChildren, GenericResponseItems, ProductType } from "~/types";
import CategoryTree from "./CategoryTree.vue";
const { $session } = useNuxtApp();
watch(() => $session.cookieData, async () => await getProducts(), { deep: true });
const props = defineProps<{
component: {

View File

@ -1,15 +0,0 @@
// import { ref } from 'vue';
import pocketbase from "pocketbase";
export const usePB = () => {
const nuxtApp = useNuxtApp();
const isServer = !!nuxtApp.ssrContext;
if (isServer) {
const pb = new pocketbase(process.env.POCKETBASE_URL || "http://127.0.0.1:8090");
return pb;
}
const pb = new pocketbase(window.location.origin);
return pb;
};

View File

@ -6,15 +6,15 @@ export default defineNuxtConfig({
// app: {
// pageTransition: { name: "page", mode: "out-in" },
// },
nitro: {
routeRules: {
"/api/**": {
proxy: {
to: `${process.env.POCKETBASE_URL || "http://127.0.0.1:8090"}/api/**`,
},
},
},
},
// nitro: {
// routeRules: {
// "/api/**": {
// proxy: {
// to: `${process.env.POCKETBASE_URL || "http://127.0.0.1:8090"}/api/**`,
// },
// },
// },
// },
modules: ["@pinia/nuxt", "@nuxt/eslint", "@nuxt/ui", "@nuxtjs/i18n", "@pinia/nuxt"],
@ -31,7 +31,7 @@ export default defineNuxtConfig({
optimizeTranslationDirective: false,
},
},
css: ["@/assets/fonts.css", "@/assets/main.css"],
css: [ "@/assets/main.css" ],
vite: {
plugins: [tailwindcss()],
build: {

View File

@ -18,7 +18,6 @@
"@tailwindcss/vite": "^4.1.8",
"@vueuse/core": "^13.3.0",
"nuxt": "^3.17.4",
"pocketbase": "^0.26.0",
"tailwindcss": "^4.1.7",
"vue": "^3.5.14",
"vue-router": "^4.5.1"

View File

@ -1,16 +1,11 @@
<template>
<KeepAlive>
<component
:is="component.componentInstance"
v-for="component in componentsList"
:key="component.name"
:component="component.component"
/>
<component :is="component.componentInstance" v-for="component in componentsList" :key="component.name"
:component="component.component" />
</KeepAlive>
</template>
<script setup>
// import { useStore } from "@/stores/store";
const route = useRoute();
const store = useStore();
const menuStore = useMenuStore();
@ -20,7 +15,7 @@ onMounted(() => {
menuStore.openMenu = false;
});
// useHead(menuStore.headMeta);
useHead(menuStore.headMeta);
const componentsList = await store.getComponents(route.params.id)

View File

@ -1,17 +1,12 @@
<template>
<KeepAlive>
<component
:is="component.componentInstance"
v-for="component in componentsList"
:key="component.name"
:component="component.component"
/>
<component :is="component.componentInstance" v-for="component in componentsList" :key="component.name"
:component="component.component" />
</KeepAlive>
</template>
<script setup>
import { useStore } from "@/stores/store";
const menuStore = useMenuStore();
const route = useRoute();
@ -26,6 +21,6 @@ onMounted(() => {
menuStore.openMenu = false;
});
// useHead(menuStore.headMeta);
useHead(menuStore.headMeta);
const componentsList = await store.getComponents(route.params.id);
</script>

View File

@ -20,16 +20,17 @@ declare module 'vue' {
export class Session {
cookieData = reactive({} as CookieData);
cookieData = ref({} as CookieData);
urlParams = new URLSearchParams()
currentLanguageIso = ref("" as string )
currentCountryIso = ref("" as string )
currentCurrencyIso = ref("" as string )
currentLanguageIso = ref("" as string)
currentCountryIso = ref("" as string)
currentCurrencyIso = ref("" as string)
route = {} as RouteLocation
router = {} as Router
i18n = {} as VueI18n
sessionOngoing: boolean = false
constructor(i18n: VueI18n, router: Router) {
this.route = router.currentRoute.value
@ -44,6 +45,8 @@ export class Session {
async loadSession() {
if (this.sessionOngoing) return
this.sessionOngoing = true
this.setQueryParams()
const { data } = await useMyFetch<GenericResponse<CookieData>>(`/api/public/cookie?${this.urlParams.toString()}`, {
headers: {
@ -53,10 +56,11 @@ export class Session {
throw new Error(`HTTP error: ${status}`);
},
});
this.cookieData = data;
this.currentCountryIso.value = this.cookieData.country.iso_code
this.currentLanguageIso.value = this.cookieData.language.iso_code
this.currentCurrencyIso.value = this.cookieData.currency.iso_code
this.cookieData.value = data;
this.currentCountryIso.value = this.cookieData.value.country.iso_code
this.currentLanguageIso.value = this.cookieData.value.language.iso_code
this.currentCurrencyIso.value = this.cookieData.value.currency.iso_code
setTimeout(() => this.sessionOngoing = false, 2000)
}
setLanguage(iso: string) {
@ -94,33 +98,23 @@ export class Session {
}
let session = {} as Session;
export const useSession = () => session;
export default defineNuxtPlugin(async (nuxtApp) => {
const loaded = [] as Array<string>;
const { $i18n: i18n } = nuxtApp as unknown as { $i18n: VueI18n };
const { $router: router } = nuxtApp as unknown as { $router: Router };
i18n.onBeforeLanguageSwitch = async (oldLocale, newLocale) => {
if (import.meta.browser) {
session.setLanguage(newLocale)
await session.loadSession()
}
i18n.onBeforeLanguageSwitch = async (_, newLocale) => {
if (loaded.includes(newLocale)) return;
try {
loaded.push(newLocale);
const { data } = await useMyFetch<GenericResponse<object>>(
"/api/public/front/translation"
);
i18n.setLocaleMessage(newLocale, data);
loaded.push(newLocale);
} catch (err) {
console.error("❌ Failed to load translation for locale:", newLocale);
throw err;
@ -130,9 +124,9 @@ export default defineNuxtPlugin(async (nuxtApp) => {
session = new Session(i18n, router)
const session = new Session(i18n, router)
await session.loadSession();
nuxtApp.vueApp.provide("session", session);
nuxtApp.provide("session", session);
});

View File

@ -3,6 +3,8 @@ import { defineNuxtPlugin } from "#app";
export default defineNuxtPlugin(async () => {
const menuStore = useMenuStore();
await menuStore.loadMenu();
await menuStore.getCountryList();
await menuStore.getCurrencies();
await menuStore.getLocales();
const store = useStore();
await store.getMinValue();
await store.getCalculator();
});

View File

@ -1,101 +0,0 @@
import type { CountryList, PartnersList } from "~/types";
export const useMapStore = defineStore("mapStore", () => {
const partnersList = ref<PartnersList[]>([
{
country_iso: "cz",
total: 9,
country_name: "Czech Republic",
},
{
country_iso: "de",
total: 1,
country_name: "Germany",
},
{
country_iso: "ie",
total: 1,
country_name: "Ireland",
},
{
country_iso: "nl",
total: 1,
country_name: "Netherlands",
},
{
country_iso: "pl",
total: 61,
country_name: "Poland",
},
]);
const customersList = ref([
"be",
"cz",
"de",
"dk",
"gb",
"ie",
"it",
"nl",
"no",
"pl",
"sk",
"at",
"lt",
"is",
"se"
]);
// async function getPartnersList() {
// try {
// const res = await fetch(
// `http://127.0.0.1:4000/api/public/partners/count`,
// {
// headers: {
// "Content-Type": "application/json",
// },
// }
// );
// if (!res.ok) {
// throw new Error(`HTTP error: ${res.status}`);
// }
// const data = await res.json();
// partnersList.value = data.data
// } catch (error) {
// console.error("getList error:", error);
// }
// }
// async function getCustomerList() {
// try {
// const res = await fetch(
// `http://127.0.0.1:4000/api/public/customer/countries`,
// {
// headers: {
// "Content-Type": "application/json",
// },
// }
// );
// if (!res.ok) {
// throw new Error(`HTTP error: ${res.status}`);
// }
// const data = await res.json();
// customersList.value = data.data
// } catch (error) {
// console.error("getList error:", error);
// }
// }
return {
partnersList,
customersList,
// getPartnersList,
// getCustomerList,
};
});

View File

@ -1,34 +1,16 @@
import { usePB } from "~/composables/usePB";
import type {
Country,
Currencies,
Currency,
FooterListResponse,
FrontMenu,
GenericResponse,
GenericResponseItems,
PBFooterItem,
Language,
UIFrontMenu,
UIMenuItem,
} from "~/types";
import { useStore } from "./store";
import { ref, watch } from "vue";
import { useMyFetch } from "#imports";
// import { useSession } from "~/plugins/01_i18n";
// 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)[],
@ -46,9 +28,10 @@ function buildTreeRecursive(
}
export const useMenuStore = defineStore("menuStore", () => {
const pb = usePB();
const store = useStore();
const { $i18n } = useNuxtApp();
// const session = useSession();
const { $session } = useNuxtApp();
const router = useRouter();
const route = useRoute();
@ -56,29 +39,43 @@ export const useMenuStore = defineStore("menuStore", () => {
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[]>();
const menu = ref([] as UIFrontMenu[]);
const menuItems = ref([] as FrontMenu[]);
// curr/country
const selectedCountry = ref();
const selectedPhoneCountry = ref();
const selectedCurrency = ref<Currencies>();
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: countrriesList } = await useMyFetch<GenericResponse<Country[]>>(`/api/public/country/list`);
countries.value = countrriesList;
selectedCountry.value = countrriesList.find((country) => country.iso_code === $session.currentCountryIso.value) as Country;
selectedPhoneCountry.value = countrriesList.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 {
// 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`,
@ -86,10 +83,6 @@ export const useMenuStore = defineStore("menuStore", () => {
onErrorOccured: (err, status) => {
console.log(err, status);
},
// onSuccess(data) {
// console.log(data.data, "data");
// },
}
);
@ -97,7 +90,6 @@ export const useMenuStore = defineStore("menuStore", () => {
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 {
@ -105,70 +97,11 @@ export const useMenuStore = defineStore("menuStore", () => {
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 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) {
@ -189,115 +122,108 @@ export const useMenuStore = defineStore("menuStore", () => {
};
function navigateToShop() {
console.log(menuItems.value);
navigateToItem(menuItems.value?.find((item) => item.id === 5));
}
// 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 getFirstImage = (size: "l" | "m" | "s" = "m", needbaseurl: boolean) => {
const req = useRequestEvent();
const url = useRequestURL();
let img = "";
// let img = "";
const img: string[] = []
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;
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?.items.find(
(item) => item.id_page === route.params.id
const item = menuItems.value?.find(
(item) => item.id.toString() === route.params.id
);
return {
title: item?.meta_title,
const meta = {
title: item?.front_menu_lang[0].meta_title,
htmlAttrs: {
lang: $i18n.locale.value,
},
link: [{ rel: "manifest", href: "/api/manifest.json" }],
link: [
// { rel: "manifest", href: "/api/manifest.json" }
],
meta: [
{
hid: "description",
name: "description",
content: item?.meta_description,
content: item?.front_menu_lang[0].meta_description,
},
{
property: "og:title",
content: item?.meta_title,
content: item?.front_menu_lang[0].meta_title,
},
{
property: "og:description",
content: item?.meta_description,
content: item?.front_menu_lang[0].meta_description,
},
{
property: "og:image",
content: getFirstImage(),
content: getFirstImage("m", true),
},
{
property: "twitter:title",
content: item?.meta_title,
content: item?.front_menu_lang[0].meta_title,
},
{
property: "twitter:description",
content: item?.meta_description,
content: item?.front_menu_lang[0].meta_description,
},
{
property: "twitter:image",
content: getFirstImage(),
content: getFirstImage("m", true),
},
],
};
const preload = getFirstImage("l", false);
if (preload) {
meta.link.push({ rel: "preload", as: "image", href: preload } as never);
}
return meta;
});
watch($i18n.locale, async () => {
// watches
watch(() => $session.cookieData, async () => {
await getLocales();
await loadMenu();
});
await store.getMinValue();
await store.getCalculator();
}, { deep: true });
watch(selectedCurrency, () => {
store.getCalculator();
});
return {
menu,
menuItems,
footerItems,
openMenu,
openDropDown,
countryList,
currencies,
languages,
countries,
selectedCountry,
selectedCurrency,
selectedPhoneCountry,
selectedLanguage,
defaultMenu,
headMeta,
navigateToShop,
loadMenu,
getCountryList,
navigateToItem,
// redirectToPage,
getCurrencies,
getLocales,
};
});

View File

@ -1,7 +1,5 @@
import { NuxtErrorBoundary } from "#components";
import { useMyFetch } from "#imports";
import type {
CartItem,
GenericResponse,
GenericResponseChildren,
GenericResponseItems,

View File

@ -1,16 +1,14 @@
import { useMyFetch } from "#imports";
// import { usePB } from "~/composables/usePB";
import type {
componentsListType,
GenericResponse,
PlanPrediction,
} from "~/types";
// import { useI18n } from "vue-i18n";
import type { FrontPageSection } from "~/types/frontSection";
export const useStore = defineStore("store", () => {
const currentPageID = ref("");
// const pb = usePB();
// const { $i18n } = useNuxtApp();
// calculator
const monthlySavings = ref(137);
@ -23,40 +21,14 @@ export const useStore = defineStore("store", () => {
const password = ref();
const components = ref({} as FrontPageSection[]);
// const getSections = async (id: string) => {
// pb.cancelRequest("menu_view");
// components.value = (
// await pb.collection<PBPageItem>("page_view").getList(1, 50, {
// filter: `id="${id}"&&(section_lang_id_lang="${
// $i18n.locale.value
// }"||section_is_no_lang=${true})`,
// sort: "page_section_id_position",
// })
// ).items as PBPageItem[];
// };
const getSections = async (id: string) => {
// if(!id){
// id = useMenuStore().defaultMenu.id
// }
// console.log(useMenuStore().defaultMenu);
const {data} = await useMyFetch<GenericResponse<FrontPageSection[]>>(
const { data } = await useMyFetch<GenericResponse<FrontPageSection[]>>(
`/api/public/front/sections/${id}`
)
// console.log(data, id, "data");
components.value = data
// return data
// pb.cancelRequest("menu_view");
// components.value = (
// await pb.collection<PBPageItem>("page_view").getList(1, 50, {
// filter: `id="${id}"&&(section_lang_id_lang="${
// $i18n.locale.value
// }"||section_is_no_lang=${true})`,
// sort: "page_section_id_position",
// })
// ).items as PBPageItem[];
};
async function getComponents(): Promise<componentsListType[]> {
@ -72,7 +44,6 @@ export const useStore = defineStore("store", () => {
for (const child of children) {
const componentName = child.front_section.component_name;
// const pageName = child.front_section.page_name;
if (!componentName) continue;
try {
@ -85,8 +56,7 @@ export const useStore = defineStore("store", () => {
name: componentName,
component: child.front_section,
componentInstance: nonReactiveComponent,
// data: child.front_section.front_section_lang[0].data || {} as unknown,
// data: {}
});
} catch (error) {
console.error(`Failed to load component ${componentName}`, error);
@ -133,11 +103,7 @@ export const useStore = defineStore("store", () => {
}
);
// if (!res.ok) {
// throw new Error(`HTTP error: ${res.status}`);
// }
// const data = await res.json();
minValue.value = data;
} catch (error) {
console.error("getList error:", error);
@ -169,8 +135,6 @@ export const useStore = defineStore("store", () => {
}
}
getCalculator();
getMinValue();
return {
currentPageID,
@ -185,5 +149,6 @@ export const useStore = defineStore("store", () => {
getCalculator,
getComponents,
getSections,
getMinValue,
};
});

View File

@ -1,115 +0,0 @@
version: "3"
vars:
REGISTRY: registry.ma-al.com
Version: "0.0.6"
BuildDate: $(date +"%Y-%m-%d %H:%M")
Company: Maal sp. z o.o.
CompanyUrl: "https://www.ma-al.com"
CompileStr: go build -ldflags "-s -w -X 'pocketbase/custom/version.Version={{.Version}}' -X 'pocketbase/custom/version.BuildDate={{.BuildDate}}' -X 'pocketbase/custom/version.Company={{.Company}}' -X 'pocketbase/custom/version.CompanyUrl={{.CompanyUrl}}'" -o ../.pocketbase/pocketbase .
tasks:
default:
cmds:
- task --list
silent: true
compile_musl:
aliases: [cm]
desc: "compiles pocketbase for musl"
env:
CGO_ENABLED: "0"
GOOS: "linux"
GOARCH: "amd64"
CC: "x86_64-linux-musl-gcc"
cmds:
- |
mkdir -p ./.output
cd ./backend
{{.CompileStr}}
compile_gnu:
aliases: [cg]
desc: "compiles pocketbase for gnu"
env:
CGO_ENABLED: "0"
GOOS: "linux"
GOARCH: "amd64"
cmds:
- |
mkdir -p ./.output
cd ./backend
{{.CompileStr}}
build_run_gnu:
aliases: [br]
desc: "compiles pocketbase for gnu"
env:
CGO_ENABLED: "0"
GOOS: "linux"
GOARCH: "amd64"
cmds:
- |
mkdir -p ./.output
cd ./backend
go build -ldflags "-s -w" -o ../.pocketbase/pocketbase .
cd ..
./.pocketbase/pocketbase serve --dir=./backend/pb_data
watch_backend:
aliases: [wb]
desc: "watch backend and compile"
cmds:
- |
cd ./backend
pwd
air -build.args_bin='serve --dir=./pb_data' -build.exclude_dir=pb_data,backups -build.include_ext=go
watch_front:
aliases: [wf]
desc: "build and watch frontend in dev mode"
cmds:
- |
bun run dev
preview_front:
aliases: [pf]
desc: "build and preview frontend"
cmds:
- |
bun run build && bun run preview
rebuild_front:
aliases: [rf]
desc: "remove all and install all packages"
cmds:
- |
rm -rf ./node_modules ./bun-lock ./.nuxt ./.output
bun install
# build_docker_image:
# aliases: [bdi]
# desc: "build docker image"
# cmds:
# - |
# bun run build
# task compile_gnu
# cat <<EOF > temp.Dockerfile
# FROM node:slim
# COPY ./.output /nuxt
# COPY ./.pocketbase/pocketbase /bin/
# RUN mkdir /data
# # ENTRYPOINT ["ash"]
# CMD ["pocketbase", "serve", "--dir=/data", "--proxy=http://localhost:3000", "--subcommand=node /nuxt/server/index.mjs", "--http=0.0.0.0:8090"]
# EOF
# docker build -t {{.REGISTRY}}/abrasive/abrasive:{{.Version}} -t {{.REGISTRY}}/abrasive/abrasive:latest -f temp.Dockerfile .
# rm temp.Dockerfile
# push_docker_image:
# aliases: [pdi]
# desc: "push docker image to registry server"
# cmds:
# - |
# docker push {{.REGISTRY}}/abrasive/abrasive:{{.Version}}
# docker push {{.REGISTRY}}/abrasive/abrasive:latest

View File

@ -9,30 +9,12 @@ export type componentsListType = {
componentInstance: DefineComponent;
};
export type Countries = {
call_prefix: string;
currency_iso_code: string;
iso_code: string;
name: string;
};
export type PartnersList = {
country_iso: string;
country_name: string;
total: number;
};
export type Currencies = {
iso_code: string;
name: string;
UpdatedAt: string;
iso_code_num: number;
precision: number;
sign: string;
active: boolean;
suffix: boolean;
};
export type FeatureValue = {
parent: number;
products_with_value: number;