2 Commits

Author SHA1 Message Date
c18497b3fa remove pocketbase 2025-07-01 13:17:16 +02:00
bf317d2e34 button with image 2025-07-01 11:47:25 +02:00
18 changed files with 161 additions and 819 deletions

View File

@ -18,7 +18,7 @@
<div class="flex items-center h-[100px] sm:h-[205px]"> <div class="flex items-center h-[100px] sm:h-[205px]">
<div <div
class="min-w-[100px] sm:min-w-[205px] flex items-center justify-center h-[100px] sm:h-[205px]"> class="min-w-[100px] sm:min-w-[205px] flex items-center justify-center h-[100px] sm:h-[205px]">
<img :src="`/api/public/file/${item.picture_uuid}.webp`" <img :src="`https://www.yourgold.cz/api/public/file/${item.picture_uuid}.webp`"
alt="" class="max-w-full max-h-full object-contain"> alt="" class="max-w-full max-h-full object-contain">
</div> </div>
@ -66,14 +66,10 @@
</p> </p>
</div> </div>
<UiButtonArrow @click="() => { <UiButtonArrow @click="() => {
if (userStore.isLogged) { menuStore.navigateToItem(menuStore.menuItems?.find((item) => item.id === 12))
menuStore.navigateToItem(menuStore.menuItems?.find((item) => item.id === 12))
} else {
menuStore.navigateToItem(menuStore.menuItems?.find((item) => item.id === 11))
}
openCart = false openCart = false
}" class="w-full" type="fill" :arrow="true" :full="true">{{ userStore.isLogged ? }" class="w-full" type="fill" :arrow="true" :full="true">{{
$t('to_checkout') : $t('login') }} $t('to_checkout') }}
</UiButtonArrow> </UiButtonArrow>
</div> </div>
<div v-else <div v-else
@ -96,7 +92,6 @@ const productStore = useProductStore()
const openCart = ref(false); const openCart = ref(false);
const menuStore = useMenuStore() const menuStore = useMenuStore()
const userStore = useUserStore()
const dropdownRef = ref(null); const dropdownRef = ref(null);
onClickOutside(dropdownRef, () => { onClickOutside(dropdownRef, () => {

View File

@ -4,7 +4,7 @@
<div class="w-full border-b border-border"> <div class="w-full border-b border-border">
<UiContainer class="relative"> <UiContainer class="relative">
<div class="hidden h-[120px] w-full items-center gap-[145px] xl:flex"> <div class="hidden h-[120px] w-full items-center gap-[145px] xl:flex">
<ul class="flex items-center justify-between gap-5 whitespace-nowrap w-full"> <ul class="flex items-center justify-between whitespace-nowrap w-full">
<li v-for="(item, index) in menuStore.menu" @click="menuStore.navigateToItem(item)" :key="item.id" <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', :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.toString() ? 'text-accent-green-light dark:text-accent-green-dark font-bold underline' : false]"> route.params.id == item.id.toString() ? 'text-accent-green-light dark:text-accent-green-dark font-bold underline' : false]">
@ -18,12 +18,13 @@
</ClientOnly> </ClientOnly>
<div class="w-full flex items-center justify-between"> <div class="w-full flex items-center justify-between">
<div class="flex items-center gap-[30px]"> <div class="flex items-center gap-[30px]">
<div> <div>
<i v-if="!userStore.isLogged" <i v-if="!userStore.isLogged"
@click="menuStore.navigateToItem(menuStore.menuItems?.find((item) => item.id === 11))" @click="menuStore.navigateToItem(menuStore.menuItems?.find((item) => item.id === 11))"
class="uil uil-user text-[31px] cursor-pointer"></i> class="uil uil-user text-[31px] cursor-pointer"></i>
<div v-else class="py-[6px] px-3 border border-block rounded-sm"> <div v-else class="py-[6px] px-3 border border-block rounded-sm">
{{ userStore.user }} <!-- {{ userStore.user }} -->
Arina Yakovenko
</div> </div>
</div> </div>
<CartPopup /> <CartPopup />
@ -34,7 +35,7 @@
</div> </div>
<ThemeSwitcher /> <ThemeSwitcher />
<button @click="menuStore.navigateToShop" :class="[ <button @click="menuStore.navigateToShop" :class="[
'cursor-pointer transition-all text-inter whitespace-nowrap', 'cursor-pointer transition-all text-inter',
route.params.id == '5' route.params.id == '5'
? 'text-accent-green-light dark:text-accent-green-dark font-bold pb-1 border-b-2' ? 'text-accent-green-light dark:text-accent-green-dark font-bold pb-1 border-b-2'
: 'hover:bg-button-hover bg-button text-white font-medium rounded-xl px-6 py-3' : 'hover:bg-button-hover bg-button text-white font-medium rounded-xl px-6 py-3'
@ -56,14 +57,7 @@
</ClientOnly> </ClientOnly>
<div class="flex items-center gap-6"> <div class="flex items-center gap-6">
<div class="flex items-center gap-[30px]"> <div class="flex items-center gap-[30px]">
<div> <i class="uil uil-user text-[31px] cursor-pointer"></i>
<i v-if="!userStore.isLogged"
@click="menuStore.navigateToItem(menuStore.menuItems?.find((item) => item.id === 11))"
class="uil uil-user text-[31px] cursor-pointer"></i>
<div v-else class="py-[6px] px-3 border border-block rounded-sm">
{{ userStore.user }}
</div>
</div>
<CartPopup /> <CartPopup />
</div> </div>
<div class="flex"> <div class="flex">
@ -109,14 +103,7 @@
</ClientOnly> </ClientOnly>
<div class="flex items-center gap-6"> <div class="flex items-center gap-6">
<div class="flex items-center gap-[30px]"> <div class="flex items-center gap-[30px]">
<div> <i class="uil uil-user text-[31px] cursor-pointer"></i>
<i v-if="!userStore.isLogged"
@click="menuStore.navigateToItem(menuStore.menuItems?.find((item) => item.id === 11))"
class="uil uil-user text-[31px] cursor-pointer"></i>
<div v-else class="py-[6px] px-3 border border-block rounded-sm">
{{ userStore.user }}
</div>
</div>
<CartPopup /> <CartPopup />
</div> </div>
<i variant="subtle" block class="uil uil-apps text-[30px] cursor-pointer" @click="open = !open"></i> <i variant="subtle" block class="uil uil-apps text-[30px] cursor-pointer" @click="open = !open"></i>
@ -178,10 +165,6 @@
@click="menuStore.navigateToItem()" /> @click="menuStore.navigateToItem()" />
</ClientOnly> </ClientOnly>
<div class="flex items-center gap-6"> <div class="flex items-center gap-6">
<div>
<i @click="!userStore.isLogged && menuStore.navigateToItem(menuStore.menuItems?.find((item) => item.id === 11))"
class="uil uil-user text-[30px] cursor-pointer"></i>
</div>
<CartPopup /> <CartPopup />
<i variant="subtle" block class="uil uil-apps text-[30px] cursor-pointer" @click="open = !open"></i> <i variant="subtle" block class="uil uil-apps text-[30px] cursor-pointer" @click="open = !open"></i>
</div> </div>

View File

@ -0,0 +1,6 @@
<template>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Modi perspiciatis adipisci quam odio natus odit excepturi
eveniet vitae. Fugit dicta officiis quos quia debitis perspiciatis porro ducimus earum placeat sunt?
</template>
<script lang="ts"></script>

View File

@ -1,47 +1,49 @@
<template> <template>
<UiContainer> <UiContainer>
<div class="xl:w-[85%] mx-auto"> <div class="w-[85%] mx-auto">
<div class="space-25-55"> <div v-if="userStore.isLogged" class="space-25-55">
<div class="w-full flex items-center sm:justify-center">
<div <div class="w-full flex items-center justify-center">
class="flex items-center justify-between sm:justify-center sm:gap-[25px] text-gray dark:text-button-disabled w-full sm:w-auto"> <div class="flex justify-between">
<div class="sm:px-6 sm:py-3 mx-auto"> <div class="flex items-center gap-[25px] text-gray dark:text-button-disabled">
{{ $t("login") }} <div class="px-6 py-3 mx-auto">
</div> {{ $t("login") }}
<div </div>
class="cursor-pointer transition-all text-inter hover:bg-button-hover bg-button text-white font-medium rounded-xl px-3 py-1 sm:px-6 sm:py-3"> <div
{{ $t("address") }} class="cursor-pointer transition-all text-inter hover:bg-button-hover bg-button text-white font-medium rounded-xl px-6 py-3">
</div> {{ $t("address") }}
<div class="sm:px-6 sm:py-3 mx-auto"> </div>
{{ $t("summary") }} <div class="px-6 py-3 mx-auto">
</div> {{ $t("summary") }}
<div class="hidden sm:block sm:px-6 sm:py-3 sm:mx-auto"> </div>
{{ $t("order_placed") }} <div class="px-6 py-3 mx-auto">
{{ $t("order_placed") }}
</div>
</div> </div>
</div> </div>
</div> </div>
<div class="space-y-[25px] sm:space-y-[30px]"> <div class="space-y-[30px]">
<h2 class="h2-bold-bounded"> <h2 class="h2-bold-bounded">
{{ $t("Account address") }} {{ $t("Account address") }}
</h2> </h2>
<div class="flex flex-col gap-[30px] sm:flex-row"> <div class="flex flex-col gap-[30px] xl:flex-row">
<div class="flex flex-col sm:w-1/2 gap-[25px] sm:gap-[30px]"> <div class="flex flex-col w-1/2 gap-[30px]">
<CheckoutInput v-model="checkoutStore.userName" :id="1" disabled>{{ $t("first_name") <CheckoutInput v-model="checkoutStore.userName" :id="1" disabled>{{ $t("first_name")
}} </CheckoutInput> }} </CheckoutInput>
<CheckoutInput v-model="checkoutStore.lastName" :id="2" disabled>{{ $t("surname") <CheckoutInput v-model="checkoutStore.lastName" :id="2" disabled>{{ $t("surname")
}} </CheckoutInput> }} </CheckoutInput>
<CheckoutInput v-model="checkoutStore.address" :id="3" disabled>{{ $t("address") <CheckoutInput v-model="checkoutStore.address" :id="3" disabled>{{ $t("address")
}} </CheckoutInput> }} </CheckoutInput>
<CheckoutInput v-model="checkoutStore.postCode" :id="4" disabled>{{ $t("post_code") <CheckoutInput v-model="checkoutStore.postCode" :id="4" disabled>{{ $t("post_code")
}} </CheckoutInput> }} </CheckoutInput>
</div> </div>
<div class="flex flex-col sm:w-1/2 gap-[30px]"> <div class="flex flex-col w-1/2 gap-[30px]">
<CheckoutInput v-model="checkoutStore.city" :id="5" disabled>{{ $t("city") <CheckoutInput v-model="checkoutStore.city" :id="5" disabled>{{ $t("city")
}} </CheckoutInput> }} </CheckoutInput>
<CheckoutInput v-model="checkoutStore.country" :id="6" disabled>{{ $t("country") <CheckoutInput v-model="checkoutStore.country" :id="6" disabled>{{ $t("country")
}} </CheckoutInput> }} </CheckoutInput>
<CheckoutInput v-model="checkoutStore.accountPhoneNumber" :id="7" disabled>{{ $t("phone") <CheckoutInput v-model="checkoutStore.accountPhoneNumber" :id="7" disabled>{{ $t("phone")
}} </CheckoutInput> }} </CheckoutInput>
</div> </div>
</div> </div>
</div> </div>
@ -49,27 +51,23 @@
<h2 class="h2-bold-bounded"> <h2 class="h2-bold-bounded">
{{ $t("Shipping details") }} {{ $t("Shipping details") }}
</h2> </h2>
<div class="flex flex-col gap-2"> <div class="relative border border-block rounded-lg px-6 h-[67px] w-full">
<div <div class="flex items-center gap-[10px]">
:class="['flex items-center gap-[10px] relative border border-block rounded-lg h-[50px] sm:h-[67px] w-full', checkoutStore.vUseAccountPhoneNumber && 'px-6']"> <div class="flex items-center gap-[25px]" v-if="!checkoutStore.vUseAccountPhoneNumber">
<div class="flex items-center gap-5 sm:gap-[25px]"
v-if="!checkoutStore.vUseAccountPhoneNumber">
<div class="flex flex-col items-start gap-[25px]"> <div class="flex flex-col items-start gap-[25px]">
<div ref="dropdownIsoRef" <div ref="dropdownIsoRef"
class="pl-5 sm:pl-[25px] relative w-full ring-0 cursor-pointer focus:ring-0 outline-none focus-visible:ring-0"> class="pl-[25px] relative w-full ring-0 cursor-pointer focus:ring-0 outline-none focus-visible:ring-0">
<div class="p-0" @click="dropIso = !dropIso"> <div class="p-0" @click="dropIso = !dropIso">
<div <div
class="flex items-center gap-2 text-base sm:text-xl font-medium uppercase text-text-light dark:text-text-dark"> class="flex items-center gap-2 text-xl font-medium uppercase text-text-light dark:text-text-dark">
<p class="hidden sm:block">{{ checkoutStore.selectedIso.name }}</p> {{ checkoutStore.selectedIso.name }} <span> <i
<p class="sm:hidden">{{ checkoutStore.selectedIso.iso_code }}</p>
<span> <i
class="uil uil-angle-down text-2xl font-light cursor-pointer"></i></span> class="uil uil-angle-down text-2xl font-light cursor-pointer"></i></span>
</div> </div>
</div> </div>
<div v-if="dropIso" <div v-if="dropIso"
class="absolute w-[130px] sm:w-full mt-2 left-0 bg-bg-light dark:bg-bg-dark rounded-[5px] data-highlighted:not-data-disabled:before:bg-button/50 ring-0 cursor-pointer focus:ring-0 outline-none focus-visible:ring-0 border border-button py-[10px] px-[5px]"> class="absolute w-full mt-2 left-0 bg-bg-light dark:bg-bg-dark rounded-[5px] data-highlighted:not-data-disabled:before:bg-button/50 ring-0 cursor-pointer focus:ring-0 outline-none focus-visible:ring-0 border border-button py-[10px] px-[5px]">
<div class="overflow-auto h-[200px] w-full overflow-x-hidden"> <div class="overflow-auto h-[200px] w-full">
<p @click="() => { checkoutStore.selectedIso = item; dropIso = false; checkoutStore.changePrefix(item.call_prefix as string) }" <p @click="() => { checkoutStore.selectedIso = item; dropIso = false; checkoutStore.changePrefix(item.call_prefix as string) }"
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]" 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.countries" :key="item.iso_code"> v-for="item in menuStore.countries" :key="item.iso_code">
@ -79,24 +77,23 @@
</div> </div>
</div> </div>
</div> </div>
<p class="text-sm sm:text-xl border-r pr-[10px] border-block">{{ <p class="text-xl">{{ checkoutStore.currentPrefix }}</p>
checkoutStore.currentPrefix }}</p>
</div> </div>
<input id="phone" <input
:value="checkoutStore.vUseAccountPhoneNumber ? checkoutStore.accountPhoneNumber : checkoutStore.phoneNumber" :value="checkoutStore.vUseAccountPhoneNumber ? checkoutStore.accountPhoneNumber : checkoutStore.phoneNumber"
:disabled="checkoutStore.vUseAccountPhoneNumber" @input="(e) => { :disabled="checkoutStore.vUseAccountPhoneNumber" @input="(e) => {
if (!checkoutStore.vUseAccountPhoneNumber) { if (!checkoutStore.vUseAccountPhoneNumber) {
checkoutStore.phoneNumber = (e.target as HTMLInputElement).value; checkoutStore.phoneNumber = (e.target as HTMLInputElement).value;
} }
}" type="tel" placeholder="123 xxxx xxx" }" type="tel" placeholder="123 xxxx xxx"
class="placeholder:text-sm sm:placeholder:text-xl placeholder:text-gray placeholder:uppercase dark:placeholder:text-bg-light rounded-lg h-[50px] sm:h-[67px] w-full focus:outline-none focus:ring-0 focus:border-0" /> class="placeholder:text-xl placeholder:text-gray placeholder:uppercase dark:placeholder:text-bg-light rounded-lg h-[67px] w-full focus:outline-none focus:ring-0 focus:border-0" />
</div> </div>
<p v-if="checkoutStore.phoneValidation === false && !checkoutStore.vUseAccountPhoneNumber" <p v-if="checkoutStore.phoneValidation === false && !checkoutStore.vUseAccountPhoneNumber"
class="text-red-500">Invalid phone number</p> class="text-red-500">Invalid phone number</p>
</div> </div>
<div class="flex items-center gap-2"> <div class="flex items-center gap-2">
<input id="checkbox" @change="(event: Event) => { <input @change="(event: Event) => {
const target = event.target as HTMLInputElement const target = event.target as HTMLInputElement
target.checked ? checkoutStore.vUseAccountPhoneNumber = true : checkoutStore.vUseAccountPhoneNumber = false target.checked ? checkoutStore.vUseAccountPhoneNumber = true : checkoutStore.vUseAccountPhoneNumber = false
checkoutStore.phoneValidation = null checkoutStore.phoneValidation = null
@ -104,24 +101,23 @@
<p>{{ $t('use_account_phone') }}</p> <p>{{ $t('use_account_phone') }}</p>
</div> </div>
</div> </div>
<div class="space-y-[30px] h-full"> <div class="space-y-[30px]">
<h2 class="h2-bold-bounded"> <h2 class="h2-bold-bounded">
{{ $t("Select delivery address") }} {{ $t("Select delivery address") }}
</h2> </h2>
<div <div class="flex items-center justify-center gap-[25px] h-[225px]">
class="flex flex-col md:flex-row items-center justify-center gap-[10px] sm:gap-[25px] md:h-[225px]"> <div class="w-[500px] flex flex-col gap-4 h-full">
<div class="w-full sm:w-[500px] flex flex-col gap-4 h-full">
<div v-for="(item, index) in checkoutStore.addressesList" :key="index" <div v-for="(item, index) in checkoutStore.addressesList" :key="index"
:class="['flex min-h-[200px] md:h-full flex-col py-[15px] px-[25px] gap-[15px] rounded-lg border-2', checkoutStore.activeAddress === item ? 'border-button' : 'border-block']"> :class="['flex h-full flex-col py-[15px] px-[25px] gap-[15px] rounded-lg border-2', checkoutStore.activeAddress === item ? 'border-button' : 'border-block']">
<div <div
:class="['flex flex-col justify-between gap-[10px] h-full', checkoutStore.activeAddress !== item && 'text-gray dark:text-button-disabled']"> :class="['flex flex-col justify-between mt-1 h-full', checkoutStore.activeAddress !== item && 'text-gray dark:text-button-disabled']">
<span>{{ item.address.name }} {{ item.address.surname }}</span> <span>{{ item.address.name }} {{ item.address.surname }}</span>
<span>{{ item.address.street }}</span> <span>{{ item.address.street }}</span>
<span>{{ item.address.postcode }} {{ item.address.city }}</span> <span>{{ item.address.postcode }} {{ item.address.city }}</span>
<span>{{ item.address.country_iso }}</span> <span>{{ item.address.country_iso }}</span>
</div> </div>
<div class="flex items-center gap-2 border-t pt-[15px] border-block"> <div class="flex items-center gap-2 border-t pt-[15px] border-block">
<input id="checkbox" :checked="checkoutStore.activeAddress ? true : false" @change="(event: Event) => { <input :checked="checkoutStore.activeAddress ? true : false" @change="(event: Event) => {
const target = event.target as HTMLInputElement const target = event.target as HTMLInputElement
target.checked ? checkoutStore.activeAddress = item : checkoutStore.activeAddress = null; target.checked ? checkoutStore.activeAddress = item : checkoutStore.activeAddress = null;
checkoutStore.isOpen = false; checkoutStore.isOpen = false;
@ -135,7 +131,7 @@
checkoutStore.isOpen = !checkoutStore.isOpen checkoutStore.isOpen = !checkoutStore.isOpen
checkoutStore.activeAddress = null checkoutStore.activeAddress = null
}" }"
:class="['cursor-pointer w-full sm:w-[500px] py-[15px] px-[25px] rounded-lg border-2 flex flex-col items-center justify-center min-h-[200px] md:h-full', checkoutStore.isOpen ? 'border-button text-button' : 'text-gray border-block ']"> :class="['cursor-pointer w-[500px] py-[15px] px-[25px] rounded-lg border-2 flex flex-col items-center justify-center h-full', checkoutStore.isOpen ? 'border-button text-button' : 'text-gray border-block ']">
<h4 <h4
:class="['font-inter text-base leading-[150%] uppercase text-[16px] sm:text-[20px] border-b', checkoutStore.isOpen ? 'border-button' : 'border-gray']"> :class="['font-inter text-base leading-[150%] uppercase text-[16px] sm:text-[20px] border-b', checkoutStore.isOpen ? 'border-button' : 'border-gray']">
{{ $t("add_new_address") }} {{ $t("add_new_address") }}
@ -146,7 +142,7 @@
<div v-if="checkoutStore.isOpen" <div v-if="checkoutStore.isOpen"
class="flex flex-col items-center gap-[30px] justify-center w-full"> class="flex flex-col items-center gap-[30px] justify-center w-full">
<div class="flex flex-col gap-[30px] xl:flex-row w-full"> <div class="flex flex-col gap-[30px] xl:flex-row w-full">
<div class="flex flex-col sm:w-1/2 gap-[25px] sm:gap-[30px]"> <div class="flex flex-col w-1/2 gap-[30px]">
<CheckoutInput v-model="checkoutStore.vNewAddressName" :placeholder="$t('first_name')" <CheckoutInput v-model="checkoutStore.vNewAddressName" :placeholder="$t('first_name')"
:id="8">{{ $t("first_name") }} :id="8">{{ $t("first_name") }}
</CheckoutInput> </CheckoutInput>
@ -157,7 +153,7 @@
:id="10">{{ $t("city") }} :id="10">{{ $t("city") }}
</CheckoutInput> </CheckoutInput>
</div> </div>
<div class="flex flex-col sm:w-1/2 gap-[25px] sm:gap-[30px]"> <div class="flex flex-col w-1/2 gap-[30px]">
<CheckoutInput v-model="checkoutStore.vNewAddressSurname" :placeholder="$t('surname')" <CheckoutInput v-model="checkoutStore.vNewAddressSurname" :placeholder="$t('surname')"
:id="11">{{ $t("surname") }} :id="11">{{ $t("surname") }}
</CheckoutInput> </CheckoutInput>
@ -167,10 +163,10 @@
</p> </p>
<div ref="dropdownCountryRef" <div ref="dropdownCountryRef"
class="relative w-full ring-0 cursor-pointer focus:ring-0 outline-none focus-visible:ring-0"> class="relative w-full ring-0 cursor-pointer focus:ring-0 outline-none focus-visible:ring-0">
<div class="border border-block placeholder:text-gray dark:placeholder:text-button-disabled rounded-lg px-6 h-[50px] sm:h-[67px] w-full focus:outline-none focus:ring-0 focus:border-2 flex items-center justify-start" <div class="border border-block placeholder:text-gray dark:placeholder:text-button-disabled rounded-lg px-6 h-[67px] w-full focus:outline-none focus:ring-0 focus:border-2 flex items-center justify-start"
@click="dropCountry = !dropCountry"> @click="dropCountry = !dropCountry">
<div <div
class="flex items-center gap-2 text-base sm:text-xl font-medium uppercase text-text-light dark:text-text-dark"> class="flex items-center gap-2 text-xl font-medium uppercase text-text-light dark:text-text-dark">
{{ checkoutStore.vNewAddressCountry ? {{ checkoutStore.vNewAddressCountry ?
checkoutStore.vNewAddressCountry.name : '-' }} <span> <i checkoutStore.vNewAddressCountry.name : '-' }} <span> <i
class="uil uil-angle-down text-2xl font-light cursor-pointer"></i></span> class="uil uil-angle-down text-2xl font-light cursor-pointer"></i></span>
@ -230,6 +226,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { LazyColorScheme } from '#components';
import CheckoutInput from '../ui/CheckoutInput.vue'; import CheckoutInput from '../ui/CheckoutInput.vue';
import { onClickOutside } from "@vueuse/core"; import { onClickOutside } from "@vueuse/core";

View File

@ -1,223 +0,0 @@
<template>
<UiContainer>
<div class="xl:w-[85%] mx-auto space-25-55">
<div class="space-25-55">
<div class="w-full flex items-center sm:justify-center">
<div
class="flex items-center justify-between sm:justify-center sm:gap-[25px] text-gray dark:text-button-disabled w-full sm:w-auto">
<div class="sm:px-6 sm:py-3 mx-auto">
{{ $t("login") }}
</div>
<div class="sm:px-6 sm:py-3 mx-auto">
{{ $t("address") }}
</div>
<div
class="cursor-pointer transition-all text-inter hover:bg-button-hover bg-button text-white font-medium rounded-xl px-3 py-1 sm:px-6 sm:py-3">
{{ $t("summary") }}
</div>
<div class="hidden sm:block sm:px-6 sm:py-3 sm:mx-auto">
{{ $t("order_placed") }}
</div>
</div>
</div>
</div>
<div class="grid grid-cols-3 gap-[30px]">
<div class="col-start-1 col-end-3 space-y-5">
<h4 class="h4-uppercase-bold-inter">{{ component.front_section_lang[0].data.product_list }}</h4>
<div class="border-2 border-block rounded-[15px] p-[50px] space-25-55">
<div v-for="(item, index) in checkoutStore.products" :key="index">
<div class="flex items-center h-[150px]">
<div class="min-w-[150px] flex items-center justify-center h-[150px]">
<img :src="`/api/public/file/${item.picture_uuid}.webp`" alt=""
class="max-w-full max-h-full object-contain">
</div>
<div class="flex flex-col justify-between min-h-full w-full gap-[7px] sm:gap-[15px]">
<div class="w-full flex items-center justify-between">
<h3
class="text-[10px] sm:text-base md:text-lg text-xl font-bold leading-[130%] sm:leading-[150%] max-w-[100px] sm:max-w-[200px] md:max-w-[250px]">
{{ item.name }}
</h3>
</div>
<div class="flex w-full justify-between gap-[10px]">
<p
class="text-accent-green-light dark:text-accent-green-dark font-inter text-[12px] sm:text-[21px] md:text-2xl leading-[150%] font-bold">
{{ item.total_price }}
</p>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="flex flex-col items-center gap-[30px]">
<div class="space-y-5 w-full">
<h4 class="h4-uppercase-bold-inter">{{ component.front_section_lang[0].data.account_address }}
</h4>
<div
class="border-2 border-block rounded-[8px] px-[25px] py-[15px] flex flex-col gap-1 text-xl">
<span>{{ checkoutStore.defaultAddress?.address.name }} {{
checkoutStore.defaultAddress?.address.surname }}</span>
<span>{{ checkoutStore.defaultAddress?.address.street }}</span>
<span>{{ checkoutStore.defaultAddress?.address.postcode }} {{
checkoutStore.defaultAddress?.address.city }}</span>
</div>
</div>
<div class="flex flex-col space-y-5 w-full h-full">
<h4 class="h4-uppercase-bold-inter">{{ component.front_section_lang[0].data.note }}</h4>
<textarea v-model="checkoutStore.vNote"
class="border-2 border-block rounded-[8px] p-3 w-full flex-1 resize-none placeholder:text-button"
name="rty" id="1" :placeholder="component.front_section_lang[0].data.note"></textarea>
</div>
</div>
<div class="col-start-1 col-end-3 space-y-5">
<h4 class="h4-uppercase-bold-inter">Typ doručení</h4>
<div class="border-2 border-block rounded-[15px] p-[50px] space-y-[25px] text-xl">
<div @click="checkoutStore.setCurrentDelivery(delivery)"
v-for="delivery in checkoutStore.deliveryOption" class="flex flex-col cursor-pointer">
<div class="flex items-end justify-between">
<div class="flex gap-[15px]">
<div class="mt-1 w-4 h-4 border-2 border-button rounded-full">
<div v-if="checkoutStore.currentDelivery === delivery"
class="w-full h-full border-3 border-bg-light dark:border-bg-dark rounded-full bg-button">
</div>
</div>
<div class="flex flex-col">
<span>{{ delivery.delivery_supplier_name }}</span>
<span>{{ delivery.country_name }}</span>
</div>
</div>
<p class="font-inter text-[12px] sm:text-[21px] md:text-2xl leading-[150%] font-bold">
{{ menuStore.formatPrice(Number(delivery.shippment_price)) }}
</p>
</div>
</div>
</div>
</div>
<div class="space-y-5 w-full flex flex-col h-full">
<h4 class="h4-uppercase-bold-inter">{{ component.front_section_lang[0].data.payment_method }}</h4>
<div
class="border-2 border-block rounded-[8px] px-[25px] py-[15px] flex-1 flex flex-col gap-1 text-xl overflow-auto">
<UCarousel :prevIcon="'i-lucide-chevron-left'" :nextIcon="'i-lucide-chevron-right'" :ui="{
viewport: 'h-full',
container: 'h-full',
item: 'h-full',
prev: 'ring-0 text-button disable:text-block p-0 ring-inset ring-accented bg-inherit disabled:bg-inherit',
next: 'ring-0 text-button disable:text-block p-0 text-[30px] bg-inherit disabled:bg-inherit',
arrows: ''
}" :prev="{ size: 'xl' }" :next="{ size: 'xl' }" arrows :items="checkoutStore.paymentMethods"
class="relative max-w-full mx-10 h-full">
<template #default="{ item }">
<div class="flex flex-col items-start justify-between h-full">
<span>{{ item.bank_name }}</span>
<span>{{ item.country_name }}</span>
<span>{{ item.street_and_number }}</span>
<span>{{ item.iban }}</span>
<span>{{ item.swift }}</span>
</div>
</template>
</UCarousel>
</div>
</div>
</div>
<div class="w-full border-y-2 border-block p-[25px] flex flex-col gap-[15px] text-xl">
<div class="flex items-center justify-between">
<p>{{ component.front_section_lang[0].data.subtotal }}</p>
<p>5,043.18</p>
</div>
<div class="flex items-center justify-between">
<p>{{ component.front_section_lang[0].data.shipping_cost }}</p>
<p>5,043.18</p>
</div>
<div class="flex items-center justify-between uppercase">
<p>{{ component.front_section_lang[0].data.total }}</p>
<p
class="text-accent-green-light dark:text-accent-green-dark font-inter text-[12px] sm:text-[21px] md:text-2xl leading-[150%] font-bold">
5,043.18
</p>
</div>
</div>
<div class="flex justify-between mt-1">
<div class="flex flex-col gap-1 text-white w-full">
<div class="flex gap-3 text-black dark:text-white items-center">
<input v-model="checkoutStore.vLegal" type="checkbox" id="first" name="first" />
<!-- <label for="first" class="text-sm leading-snug">
{{ $t("I accept ") }}
<NuxtLink target="_blank"
:to="{ name: 'lang-info-name', params: { lang: menuStore.selectedLanguage.iso_code, name: 'legal_statement.html' } }"
class="underline cursor-pointer">
{{ $t("the legal statement*") }}
</NuxtLink>
</label> -->
<p class="text-lg"> {{ $t("I accept ") }} {{ $t("the legal statement*") }}</p>
</div>
<span v-if="checkoutStore.legalValidation" class="text-xs text-red-600 ml-6">
{{ $t("You need to accept this") }}
</span>
<div class="flex gap-3 text-black dark:text-white items-center mt-2">
<input v-model="checkoutStore.vTerms" type="checkbox" id="second" name="second" />
<!-- <label for="second" class="text-sm leading-snug">
{{ $t("I accept ") }}
<NuxtLink target="_blank"
:to="{ name: 'lang-info-name', params: { lang: menuStore.selectedLanguage.iso_code, name: 'general_terms_and_conditions.html' } }"
class="underline cursor-pointer">
{{ $t("general terms and conditions*") }}
</NuxtLink>
</label> -->
<p class="text-lg"> {{ $t("I accept ") }} {{ $t("general terms and conditions*") }}</p>
</div>
<span v-if="checkoutStore.termsValidation" class="text-xs text-red-600 ml-6">
{{ $t("You need to accept this") }}
</span>
</div>
<UiButtonArrow type="fill" :arrow="true">
{{ $t("Buy") }}
</UiButtonArrow>
</div>
</div>
</UiContainer>
</template>
<script setup lang="ts">
import { UCarousel } from '#components';
const checkoutStore = useCheckoutStore();
const productStore = useProductStore()
const menuStore = useMenuStore()
checkoutStore.getOrder()
checkoutStore.getBankAccount()
checkoutStore.getUserCart()
checkoutStore.getDeliveryOptions()
checkoutStore.getDefAddress()
defineProps<{
component: {
id: number
name: string
img: string[]
component_name: string
is_no_lang: boolean
page_name: string
front_section_lang: {
data: {
product_list: string
account_address: string
note: string
delivery_type: string
payment_method: string
subtotal: string
shipping_cost: string
total: string
accept: string
legal: string
terms: string
}
id_front_section: number
id_lang: number
}[]
}
}>();
</script>

View File

@ -3,19 +3,12 @@
<UiContainer class="flex flex-col gap-24"> <UiContainer class="flex flex-col gap-24">
<div <div
class="grid grid-cols-1 md:grid-cols-2 gap-[75px] xl:gap-0 xl:grid-cols-none xl:grid-flow-col auto-cols-max justify-between"> class="grid grid-cols-1 md:grid-cols-2 gap-[75px] xl:gap-0 xl:grid-cols-none xl:grid-flow-col auto-cols-max justify-between">
<div> <div v-for="(item, index) in component.front_section_lang[0].data" :key="index"
<div v-for="(item, key) in contact" :key="key" class="flex flex-col gap-[25px] sm:gap-8 max-w-[280px]"> class="flex flex-col gap-[25px] sm:gap-8 max-w-[280px]">
<h3 v-if="key == 'header'" class="h4-uppercase-bold-inter">{{ item }}</h3> <h3 class="h4-uppercase-bold-inter">{{ item.title }}</h3>
<div v-else class="transition-all text-inter">{{ item }}</div> <div class="cursor-pointer hover:text-text-light/80 dark:hover:text-text-dark/70 transition-all text-inter"
</div> v-for="(el, indexEl) in item.children" :key="indexEl">
</div> {{ el.title }}
<div v-for="(section, index) in docs" :key="index" class="flex flex-col gap-[25px] sm:gap-8 max-w-[280px]">
<h3 class="h4-uppercase-bold-inter">{{ section.translation }}</h3>
<div v-for="(item, key) in section.data" :key="key">
<div class="cursor-pointer hover:text-text-light/80 dark:hover:text-text-dark/70 transition-all text-inter">
<a target="_blank" :href="`/api/public/document/${item.name}`">{{ item.translation }}</a>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -29,17 +22,38 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import type { GenericResponse, Footer } from '~/types'; defineProps<{
component: {
id: number
name: string
img: string[]
component_name: string
is_no_lang: boolean
page_name: string
front_section_lang: {
data: {
title: string
children: {
title: string
value: 'email' | 'address' | 'certificate' | 'document' | 'form' | 'info'
link?: string
}[]
}[]
id_front_section: number
id_lang: number
}[]
}
}>();
const menuStore = useMenuStore(); const menuStore = useMenuStore();
const colorMode = useColorMode(); const colorMode = useColorMode();
const { data } = await useMyFetch<GenericResponse<Footer>>('/api/public/front/footer', {}); const isDark = computed({
get() {
return colorMode.value === "dark";
const contact = ref(data.data.contact) },
const docs = ref(data.data.docs) set(_isDark) {
colorMode.preference = _isDark ? "dark" : "light";
},
const isDark = computed(() => colorMode.value === "dark"); });
</script> </script>

View File

@ -28,7 +28,7 @@
]"> ]">
<div v-for="(item, index) in productStore.productList" :key="index" <div v-for="(item, index) in productStore.productList" :key="index"
class="w-[200px] sm:w-[260px] md:w-[290px] sm:py-5 sm:px-[15px] py-[15px] px-[10px] bg-block rounded-2xl flex flex-col items-center gap-5 sm:gap-7"> class="w-[200px] sm:w-[260px] md:w-[290px] sm:py-5 sm:px-[15px] py-[15px] px-[10px] bg-block rounded-2xl flex flex-col items-center gap-5 sm:gap-7">
<img :src="`/api/public/file/${item.cover_picture_uuid}.webp`" alt="pics" <img :src="`https://www.yourgold.cz/api/public/file/${item.cover_picture_uuid}.webp`" alt="pics"
class="max-h-[150px] sm:max-h-[180px] md:max-h-[205px]" /> class="max-h-[150px] sm:max-h-[180px] md:max-h-[205px]" />
<div class="flex flex-col justify-between h-full"> <div class="flex flex-col justify-between h-full">
<div class="flex flex-col gap-[10px] sm:gap-[15px] w-full"> <div class="flex flex-col gap-[10px] sm:gap-[15px] w-full">

View File

@ -7,7 +7,7 @@
<!-- product --> <!-- product -->
<div v-for="(item, index) in productStore.productList" :key="index" <div v-for="(item, index) in productStore.productList" :key="index"
class="w-[200px] sm:w-[260px] md:w-[290px] sm:py-5 sm:px-[15px] py-[15px] px-[10px] bg-block rounded-2xl flex flex-col items-center gap-5 sm:gap-7"> class="w-[200px] sm:w-[260px] md:w-[290px] sm:py-5 sm:px-[15px] py-[15px] px-[10px] bg-block rounded-2xl flex flex-col items-center gap-5 sm:gap-7">
<img :src="`/api/public/file/${item.cover_picture_uuid}.webp`" alt="pics" <img :src="`https://www.yourgold.cz/api/public/file/${item.cover_picture_uuid}.webp`" alt="pics"
class="max-h-[150px] sm:max-h-[180px] md:max-h-[205px]" /> class="max-h-[150px] sm:max-h-[180px] md:max-h-[205px]" />
<div class="flex flex-col justify-between h-full"> <div class="flex flex-col justify-between h-full">
<div class="flex flex-col gap-[10px] sm:gap-[15px] w-full"> <div class="flex flex-col gap-[10px] sm:gap-[15px] w-full">

View File

@ -1,10 +1,9 @@
<template> <template>
<div <div
class="w-[150px] sm:w-[260px] md:w-[330px] px-2 py-3 sm:py-5 sm:px-[15px] bg-block rounded-2xl flex flex-col items-center gap-[15px] sm:gap-[50px]"> class="w-[150px] sm:w-[260px] md:w-[330px] px-2 py-3 sm:py-5 sm:px-[15px] bg-block rounded-2xl flex flex-col items-center gap-[15px] sm:gap-[50px]">
<img :src="`/api/public/file/${props.product?.cover_picture_uuid}.webp`" alt="Product Image" :class="[ <img :src="`https://www.yourgold.cz/api/public/file/${props.product?.cover_picture_uuid}.webp`" alt="Product Image"
'h-[95px] sm:min-h-[180px] md:min-h-[205px] rounded-[5px]', class="h-[95px] sm:h-[180px] md:h-[205px] rounded-[5px]"
isError ? 'max-w-[50%]' : '' onerror="this.onerror=null; this.src='/photo.svg';" />
]" @error="handleImageError" />
<div class="flex flex-col justify-between h-full w-full gap-[7px] sSm:gap-[15px]"> <div class="flex flex-col justify-between h-full w-full gap-[7px] sSm:gap-[15px]">
<div class="flex flex-col gap-[7px] sm:gap-[15px] w-full"> <div class="flex flex-col gap-[7px] sm:gap-[15px] w-full">
@ -34,11 +33,4 @@ const props = defineProps({
}); });
const productStore = useProductStore() const productStore = useProductStore()
const isError = ref(false);
function handleImageError(event: Event) {
isError.value = true;
(event.target as HTMLImageElement).src = '/photo.svg';
}
</script> </script>

View File

@ -7,19 +7,19 @@
}" /> }" />
<div class="w-full sm:w-[80%] mx-auto my-auto xl:w-full xl:px-12 "> <div class="w-full sm:w-[80%] mx-auto my-auto xl:w-full xl:px-12 ">
<div class="space-25-55"> <div class="space-25-55">
<div class="flex flex-wrap-reverse gap-y-4 justify-between"> <div class="flex justify-between">
<h2 class="h2-bold-bounded">{{ $t('sign_up') }}</h2> <h2 class="h2-bold-bounded">{{ $t('sign_up') }}</h2>
<button @click="menuStore.navigateToItem()" <button
class="h-[40px] sm:h-[43px] px-[10px] sm:px-[17px] border border-gray dark:border-button-disabled text-gray dark:text-button-disabled hover:bg-gray transition-all hover:text-white rounded-[8px] cursor-pointer">{{ class="h-[40px] sm:h-[43px] px-[10px] sm:px-[17px] border border-gray dark:border-button-disabled text-gray dark:text-button-disabled hover:bg-gray transition-all hover:text-white rounded-[8px] cursor-pointer">{{
$t('back_to_home') }}</button> $t('back_to_home') }}</button>
</div> </div>
<div class="space-y-[25px] sm:space-y-[30px]"> <div class="space-y-[25px] sm:space-y-[30px]">
<p>{{ $t('current_information') }}</p> <p>Obecné informace</p>
<div class="grid grid-cols-1 md:grid-cols-2 gap-[30px]"> <div class="grid grid-cols-1 md:grid-cols-2 gap-[30px]">
<div class="space-y-[15px]"> <div class="space-y-[15px]">
<p class="pl-6">{{ $t('first_name') }}</p> <p class="pl-6">{{ $t('first_name') }}</p>
<input :placeholder="$t('first_name')" type="text" <input :placeholder="$t('first_name')" type="text"
class="text-sm sm:text-xl border border-block placeholder:text-gray dark:placeholder:text-button-disabled text-bg-dark dark:text-bg-light rounded-lg px-6 h-[50px] sm:h-[67px] w-full focus:outline-none focus:ring-0 focus:border-2" /> class="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 h-[50px] sm:h-[67px] w-full focus:outline-none focus:ring-0 focus:border-2" />
</div> </div>
<div class="space-y-[15px]"> <div class="space-y-[15px]">
<p class="pl-6">{{ $t('last_name') }}</p> <p class="pl-6">{{ $t('last_name') }}</p>
@ -29,7 +29,7 @@
<div class="space-y-[15px]"> <div class="space-y-[15px]">
<p class="pl-6">{{ $t('email') }}</p> <p class="pl-6">{{ $t('email') }}</p>
<input :placeholder="$t('email')" type="text" <input :placeholder="$t('email')" type="text"
class="text-sm sm:text-xl border border-block placeholder:text-gray dark:placeholder:text-button-disabled text-bg-dark dark:text-bg-light rounded-lg px-6 h-[50px] sm:h-[67px] w-full focus:outline-none focus:ring-0 focus:border-2" /> class="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 h-[50px] sm:h-[67px] w-full focus:outline-none focus:ring-0 focus:border-2" />
</div> </div>
<div class="space-y-[15px]" ref="dropdownRef"> <div class="space-y-[15px]" ref="dropdownRef">
<p class="pl-6">{{ $t('phone') }}</p> <p class="pl-6">{{ $t('phone') }}</p>
@ -48,7 +48,7 @@
</div> </div>
<div v-if="dropCountry" <div v-if="dropCountry"
class="mt-2 absolute bg-bg-light dark:bg-bg-dark rounded-[5px] ring-0 cursor-pointer w-[130px] sm:w-full border border-button py-[10px] px-[5px] overflow-hidden"> 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"> <div class="overflow-y-auto h-[200px] w-full">
<p v-for="item in menuStore.countries" :key="item.iso_code" <p v-for="item in menuStore.countries" :key="item.iso_code"
@click="() => { menuStore.selectedPhoneCountry = item; dropCountry = false }" @click="() => { menuStore.selectedPhoneCountry = item; dropCountry = false }"
@ -61,15 +61,14 @@
</div> </div>
<p class="text-sm sm:text-xl font-normal">{{ menuStore.selectedPhoneCountry.call_prefix <p class="text-sm sm:text-xl font-normal">{{ menuStore.selectedPhoneCountry.call_prefix
}}</p> }}</p>
<input id="phone" :placeholder="$t('phone')" type="text" <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" /> 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> </div>
<div class="space-y-[15px]"> <div class="space-y-[15px]">
<p class="pl-6">{{ $t('account_type') }}</p> <p class="pl-6">{{ $t('account_type') }}</p>
<USelect v-model="selectedType" <USelect v-model="selectedType" :items="component.front_section_lang[0].data.account_types"
:items="component.front_section_lang && component.front_section_lang[0].data.account_types"
value-key="name" :searchable="false" :ui="{ 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', 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', trailing: 'hidden w-full',
@ -84,9 +83,7 @@
<div <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]"> 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"> <p class="truncate whitespace-nowrap">
{{component.front_section_lang && {{ component.front_section_lang[0].data.account_types.find((item) => item.name === modelValue)?.name }}
component.front_section_lang[0].data.account_types.find((item) => item.name
=== modelValue)?.name}}
</p> </p>
<span> <i <span> <i
class="uil uil-angle-down text-2xl font-light cursor-pointer"></i></span> class="uil uil-angle-down text-2xl font-light cursor-pointer"></i></span>
@ -112,15 +109,14 @@
</div> </div>
</div> </div>
<div class="py-[25px] sm:py-12 border-b border-gray flex justify-center w-full"> <div class="py-[25px] sm:py-12 border-b border-gray flex justify-center w-full">
<UiButtonArrow type="fill" :arrow="true">{{ $t('sign_up') }}</UiButtonArrow> <UiButtonArrow type="fill" :arrow="true">{{ $t('login') }}</UiButtonArrow>
</div> </div>
<div class="mt-[25px] sm:mt-[30px] w-full flex justify-center gap-3"> <div class="mt-[25px] sm:mt-[30px] w-full flex justify-center gap-3">
<p class="cursor-pointer hover:underline transition-all">{{ <p class="cursor-pointer hover:underline transition-all">{{
$t('is_account') $t('is_account')
}}</p> }}</p>
<p @click="menuStore.navigateToItem(menuStore.menuItems?.find((item) => item.id === 11))" <p class="text-button cursor-pointer hover:text-button-hover">{{
class="text-button cursor-pointer hover:text-button-hover">{{ $t('login')
$t('login')
}}</p> }}</p>
</div> </div>
</div> </div>
@ -154,9 +150,7 @@ const menuStore = useMenuStore()
const dropdownRef = ref(null); const dropdownRef = ref(null);
const dropCountry = ref() const dropCountry = ref()
const selectedType = ref() const selectedType = ref(props.component.front_section_lang[0].data.account_types[0].name)
if (props.component.front_section_lang)
selectedType.value = props.component.front_section_lang[0].data.account_types[0].name
onClickOutside(dropdownRef, () => { onClickOutside(dropdownRef, () => {
dropCountry.value = false dropCountry.value = false

View File

@ -9,7 +9,7 @@
:placeholder="placeholder" :disabled="disabled" :placeholder="placeholder" :disabled="disabled"
@input="$emit('update:modelValue', ($event.target as HTMLInputElement).value)" @input="$emit('update:modelValue', ($event.target as HTMLInputElement).value)"
@focus="$emit('focus')" @blur="$emit('blur')" @focus="$emit('focus')" @blur="$emit('blur')"
class="border border-block placeholder:text-gray dark:placeholder:text-button-disabled rounded-lg px-6 h-[50px] sm:h-[67px] w-full focus:outline-none focus:ring-0 focus:border-2" /> class="border border-block placeholder:text-gray dark:placeholder:text-button-disabled rounded-lg px-6 h-[67px] w-full focus:outline-none focus:ring-0 focus:border-2" />
<i v-if="disabled" <i v-if="disabled"
class="uil uil-lock-alt text-[22px] absolute right-6 top-1/2 -translate-y-1/2 text-gray" /> class="uil uil-lock-alt text-[22px] absolute right-6 top-1/2 -translate-y-1/2 text-gray" />

View File

@ -1,3 +1,3 @@
<svg width="76" height="53" viewBox="0 0 76 53" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg width="76" height="53" viewBox="0 0 76 53" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M76 49.8V2C76 0.9 75.1 0 74 0H2C0.9 0 0 0.9 0 2V50C0 52.5 3.3 52 2 52H74C77 52 75.6 47.4 76 49.8ZM6 48L28 19.3L46.4 43.4L49.9 48H6ZM55 48L50.5 42.2L58 32.4L69.9 48H55ZM72 44L59.6 27.8C58.8 26.7 57.2 26.7 56.4 27.8L48 38.8L29.6 14.8C28.8 13.7 27.2 13.7 26.4 14.8L4 44.1V4H72V44ZM49 10C45.1 10 42 13.1 42 17C42 20.9 45.1 24 49 24C52.9 24 56 20.9 56 17C56 13.1 52.8 10 49 10ZM49 20C47.4 20 46 18.7 46 17C46 15.3 47.3 14 49 14C50.7 14 52 15.3 52 17C52 18.7 50.6 20 49 20Z" fill="#525252"/> <path d="M76 49.8V2C76 0.9 75.1 0 74 0H2C0.9 0 0 0.9 0 2V50C0 52.5 3.3 52 2 52H74C77 52 75.6 47.4 76 49.8ZM6 48L28 19.3L46.4 43.4L49.9 48H6ZM55 48L50.5 42.2L58 32.4L69.9 48H55ZM72 44L59.6 27.8C58.8 26.7 57.2 26.7 56.4 27.8L48 38.8L29.6 14.8C28.8 13.7 27.2 13.7 26.4 14.8L4 44.1V4H72V44ZM49 10C45.1 10 42 13.1 42 17C42 20.9 45.1 24 49 24C52.9 24 56 20.9 56 17C56 13.1 52.8 10 49 10ZM49 20C47.4 20 46 18.7 46 17C46 15.3 47.3 14 49 14C50.7 14 52 15.3 52 17C52 18.7 50.6 20 49 20Z" fill="#004F3D"/>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 598 B

After

Width:  |  Height:  |  Size: 598 B

View File

@ -1,26 +1,13 @@
import type { GenericResponse, GenericResponseItems, UserCart } from "~/types"; import type { GenericResponse } from "~/types";
import type { import type { AddressesList, UserAddressOfficial } from "~/types/checkout";
Address,
AddressesList,
CheckoutOrder,
Payment,
UserAddressOfficial,
} from "~/types/checkout";
import { validation } from "../utils/validation"; import { validation } from "../utils/validation";
import { REGEX_PHONE } from "../utils/regex"; import { REGEX_PHONE } from "../utils/regex";
import type { CartProduct } from "~/types/product";
export const useCheckoutStore = defineStore("checkoutStore", () => { export const useCheckoutStore = defineStore("checkoutStore", () => {
const { $toast } = useNuxtApp(); const { $toast } = useNuxtApp();
const menuStore = useMenuStore(); const menuStore = useMenuStore();
const selectedIso = ref(menuStore.selectedCountry); const selectedIso = ref(menuStore.selectedCountry);
const vLegal = ref(false);
const vTerms = ref(false);
const vNote = ref("");
const legalValidation = ref(false);
const termsValidation = ref(false);
// get address list // get address list
const addressesList = ref<AddressesList[]>(); const addressesList = ref<AddressesList[]>();
const activeAddress = ref<AddressesList | null>(); const activeAddress = ref<AddressesList | null>();
@ -148,8 +135,8 @@ export const useCheckoutStore = defineStore("checkoutStore", () => {
}; };
const phoneValidation = ref<boolean | null>(null); const phoneValidation = ref<boolean | null>(null);
// send checkout form
const userStore = useUserStore(); const userStore = useUserStore();
// send form
async function sendForm() { async function sendForm() {
let phoneNum = vUseAccountPhoneNumber.value let phoneNum = vUseAccountPhoneNumber.value
? accountPhoneNumber.value ? accountPhoneNumber.value
@ -197,9 +184,7 @@ export const useCheckoutStore = defineStore("checkoutStore", () => {
autoClose: 5000, autoClose: 5000,
dangerouslyHTMLString: true, dangerouslyHTMLString: true,
}); });
menuStore.navigateToItem( // redirectToSummary();
menuStore.menuItems?.find((item) => item.id === 13)
);
} else { } else {
$toast.error("Failed to send form. Please try again.", { $toast.error("Failed to send form. Please try again.", {
autoClose: 5000, autoClose: 5000,
@ -215,7 +200,6 @@ export const useCheckoutStore = defineStore("checkoutStore", () => {
activeAddress.value = item; activeAddress.value = item;
}; };
// get checkout
async function getCheckout() { async function getCheckout() {
try { try {
const res = await useMyFetch<GenericResponse<object>>( const res = await useMyFetch<GenericResponse<object>>(
@ -238,267 +222,6 @@ export const useCheckoutStore = defineStore("checkoutStore", () => {
} }
} }
// get user cart
const products = ref<CartProduct[]>();
const fullPrice = ref();
const fullProductsPrice = ref();
async function getUserCart() {
try {
const { data } = await useMyFetch<GenericResponse<UserCart>>(
`/api/public/user/cart`,
{
headers: {
"Content-Type": "application/json",
},
onErrorOccured: async (_, status) => {
throw createError({
statusCode: status,
statusMessage: `HTTP error: ${status}`,
});
},
}
);
products.value = data.cart_items;
fullPrice.value = data.total_value;
fullProductsPrice.value = data.total_value;
fullPrice.value = Number(fullPrice.value) + Number(shippingPrice.value);
} catch (error) {
console.error("getUserCart error:", error);
}
}
// get delivery options
const deliveryOption = ref();
const currentDelivery = ref();
const shippingPrice = ref();
async function getDeliveryOptions() {
try {
const res = await useMyFetch<
GenericResponseItems<object>
// {
// items: [
// {
// country_iso: string;
// country_name: string;
// delivery_supplier_id: number;
// delivery_supplier_name: string;
// id: number;
// shippment_price: string;
// }
// ];
// }
>(`/api/restricted/cart/checkout/delivery-options`, {
headers: {
"Content-Type": "application/json",
},
onErrorOccured: async (_, status) => {
throw createError({
statusCode: status,
statusMessage: `HTTP error: ${status}`,
});
},
});
const data = {
items: [
{
id: 31,
shippment_price: "2",
delivery_supplier_id: 4,
delivery_supplier_name: "Personal collection",
country_iso: "pl",
country_name: "Poland",
},
{
id: 34,
shippment_price: "20",
delivery_supplier_id: 1,
delivery_supplier_name: "Ceska Posta",
country_iso: "pl",
country_name: "Poland",
},
],
items_count: 2,
};
deliveryOption.value = data.items;
currentDelivery.value = data.items[0];
shippingPrice.value = data.items[0].shippment_price;
fullPrice.value = Number(fullPrice.value) + Number(shippingPrice.value);
} catch (error) {
console.error("getUserCart error:", error);
}
}
const setCurrentDelivery = (item: any) => {
shippingPrice.value = item.shippment_price;
currentDelivery.value = item;
fullPrice.value = Number(fullPrice.value) + Number(shippingPrice.value);
};
const defaultAddress = ref();
async function getDefAddress() {
try {
const { data } = await useMyFetch<
GenericResponse<{
addresses: [
{
is_default: string;
}
];
}>
>(`/api/public/user`, {
headers: {
"Content-Type": "application/json",
},
onErrorOccured: async (_, status) => {
throw createError({
statusCode: status,
statusMessage: `HTTP error: ${status}`,
});
},
});
defaultAddress.value = data.addresses.find(
(el: any) => el.is_default === true
);
} catch (error) {
console.error("getUserCart error:", error);
}
}
// get bank data
const paymentMethods = ref([] as Payment[]);
const fullAddress = ref<Address>();
const currentPayment = ref<Payment | null>(null);
async function getBankAccount() {
try {
const { data } = await useMyFetch<GenericResponse<Payment[]>>(
`/api/restricted/suitable-bank-accounts/${menuStore.selectedCurrency.iso_code}/${fullAddress.value?.country_iso}`,
{
headers: {
"Content-Type": "application/json",
},
onErrorOccured: async (_, status) => {
throw createError({
statusCode: status,
statusMessage: `HTTP error: ${status}`,
});
},
}
);
paymentMethods.value = data;
currentPayment.value = data[0];
} catch (error) {
console.error("getUserCart error:", error);
}
}
// get order (summary)
async function getOrder() {
try {
const { data } = await useMyFetch<GenericResponse<CheckoutOrder>>(
`/api/restricted/cart/checkout/order`,
{
headers: {
"Content-Type": "application/json",
},
onErrorOccured: async (_, status) => {
throw createError({
statusCode: status,
statusMessage: `HTTP error: ${status}`,
});
},
}
);
fullAddress.value = data.delivery_details.address;
console.log(fullAddress.value);
} catch (error) {
console.error("getOrder error:", error);
}
}
async function setNewAddress(index: number) {
currentPayment.value = paymentMethods.value.find(
(item, index) => index === index
);
}
// send summary form
async function sendSummaryForm() {
vLegal.value
? (legalValidation.value = false)
: (legalValidation.value = true);
vTerms.value
? (termsValidation.value = false)
: (termsValidation.value = true);
// if (vTerms.value && vLegal.value) {
// isModalOpen.value = true;
// }
try {
const res = await useMyFetch<GenericResponse<object>>(
`/api/restricted/cart/checkout/delivery`,
{
method: "PUT",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
accept_general_conditions: true,
accept_long_purchase: true,
address: fullAddress.value,
delivery_option_id: currentDelivery.value.id,
note: vNote.value,
}),
onErrorOccured: async (_, status) => {
throw createError({
statusCode: status,
statusMessage: `HTTP error: ${status}`,
});
},
}
);
putCheckoutBankAccount();
} catch (error) {
console.error("uploadAddress error:", error);
}
}
// put checkout bank-account
async function putCheckoutBankAccount() {
try {
const res = await useMyFetch<GenericResponse<object>>(
`restricted/cart/checkout/bank-account/${currentPayment.value?.id}`,
{
method: "PUT",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
accept_general_conditions: true,
accept_long_purchase: true,
address: fullAddress.value,
delivery_option_id: currentDelivery.value.id,
note: vNote.value,
}),
onErrorOccured: async (_, status) => {
throw createError({
statusCode: status,
statusMessage: `HTTP error: ${status}`,
});
},
}
);
} catch (error) {
console.error("uploadAddress error:", error);
}
}
return { return {
addressesList, addressesList,
activeAddress, activeAddress,
@ -524,22 +247,6 @@ export const useCheckoutStore = defineStore("checkoutStore", () => {
vNewAddressCity, vNewAddressCity,
vNewAddressCountry, vNewAddressCountry,
products,
fullPrice,
fullProductsPrice,
deliveryOption,
currentDelivery,
shippingPrice,
defaultAddress,
paymentMethods,
currentPayment,
vLegal,
vTerms,
vNote,
legalValidation,
termsValidation,
changePrefix, changePrefix,
getCheckout, getCheckout,
getAddressList, getAddressList,
@ -547,12 +254,5 @@ export const useCheckoutStore = defineStore("checkoutStore", () => {
changeActive, changeActive,
uploadAddress, uploadAddress,
sendForm, sendForm,
getUserCart,
getDeliveryOptions,
getDefAddress,
setCurrentDelivery,
getBankAccount,
getOrder,
setNewAddress,
}; };
}); });

View File

@ -11,6 +11,7 @@ import { useStore } from "./store";
import { useMyFetch } from "#imports"; import { useMyFetch } from "#imports";
// import { useSession } from "~/plugins/01_i18n"; // import { useSession } from "~/plugins/01_i18n";
function buildTreeRecursive( function buildTreeRecursive(
data: (FrontMenu | UIFrontMenu)[], data: (FrontMenu | UIFrontMenu)[],
parentId: number parentId: number
@ -39,50 +40,42 @@ export const useMenuStore = defineStore("menuStore", () => {
const defaultMenu = ref(); const defaultMenu = ref();
const menu = ref([] as UIFrontMenu[]); const menu = ref([] as UIFrontMenu[]);
const menuItems = ref([] as FrontMenu[]); const menuItems = ref([] as FrontMenu[]);
// curr/country // curr/country
const selectedCountry = ref({} as Country); const selectedCountry = ref({} as Country);
const selectedPhoneCountry = ref({} as Country); const selectedPhoneCountry = ref({} as Country);
const selectedCurrency = ref({} as Currency); const selectedCurrency = ref({} as Currency);
const selectedLanguage = ref({} as Language); const selectedLanguage = ref({} as Language);
const countries = ref([] as Country[]); const countries = ref([] as Country[]);
const currencies = ref([] as Currency[]); const currencies = ref([] as Currency[]);
const languages = ref([] as Language[]); const languages = ref([] as Language[]);
const getLocales = async () => { const getLocales = async () => {
const { data: countriesList } = await useMyFetch< const { data: countriesList } = await useMyFetch<GenericResponse<Country[]>>(`/api/public/country/list`);
GenericResponse<Country[]>
>(`/api/public/country/list`);
countries.value = countriesList; countries.value = countriesList;
selectedCountry.value = countriesList.find( selectedCountry.value = countriesList.find((country) => country.iso_code === $session.currentCountryIso.value) as Country;
(country) => country.iso_code === $session.currentCountryIso.value selectedPhoneCountry.value = countriesList.find((country) => country.iso_code === $session.currentCountryIso.value) as Country;
) as Country;
selectedPhoneCountry.value = countriesList.find(
(country) => country.iso_code === $session.currentCountryIso.value
) as Country;
const { data: currenciesList } = await useMyFetch<
GenericResponseItems<Currency[]> const { data: currenciesList } = await useMyFetch<GenericResponseItems<Currency[]>>(`/api/public/currencies`)
>(`/api/public/currencies`);
currencies.value = currenciesList.items; currencies.value = currenciesList.items;
selectedCurrency.value = currenciesList.items.find( selectedCurrency.value = currenciesList.items.find((currency) => currency.iso_code === $session.currentCurrencyIso.value) as Currency;
(currency) => currency.iso_code === $session.currentCurrencyIso.value
) as Currency;
const { data: languagesList } = await useMyFetch< const { data: languagesList } = await useMyFetch<GenericResponseItems<Language[]>>(`/api/public/languages`)
GenericResponseItems<Language[]>
>(`/api/public/languages`);
languages.value = languagesList.items; languages.value = languagesList.items;
selectedLanguage.value = languagesList.items.find( selectedLanguage.value = languagesList.items.find((language) => language.iso_code === $session.currentLanguageIso.value) as Language;
(language) => language.iso_code === $session.currentLanguageIso.value
) as Language;
}; };
const loadMenu = async () => { const loadMenu = async () => {
try { try {
const { data } = await useMyFetch<GenericResponse<FrontMenu[]>>( const { data } = await useMyFetch<GenericResponse<FrontMenu[]>>(
`/api/public/front/menu`, `/api/public/front/menu`,
{ {
@ -107,6 +100,7 @@ export const useMenuStore = defineStore("menuStore", () => {
} }
}; };
const navigateToItem = (item?: UIFrontMenu) => { const navigateToItem = (item?: UIFrontMenu) => {
if (item) { if (item) {
router.push({ router.push({
@ -133,21 +127,15 @@ export const useMenuStore = defineStore("menuStore", () => {
const req = useRequestEvent(); const req = useRequestEvent();
const url = useRequestURL(); const url = useRequestURL();
// let img = ""; // let img = "";
const img: string[] = []; const img: string[] = []
for (const s in store.components) { for (const s in store.components) {
if (store.components[s].front_section.img.length === 0) continue; if (store.components[s].front_section.img.length === 0) continue;
img.push( img.push(`/api/public/file/${store.components[s].front_section.img[0]}_${size}.webp`)
`/api/public/file/${store.components[s].front_section.img[0]}_${size}.webp` if (img.length > 0) break;;
);
if (img.length > 0) break;
} }
if (img.length > 0) { if (img.length > 0) {
if (needbaseurl) { if (needbaseurl) {
return `${req?.headers.get("x-forwarded-proto") || url.protocol}://${ return `${req?.headers.get("x-forwarded-proto") || url.protocol}://${req?.headers.get("x-forwarded-host") || url.host || req?.headers.get("host")}${img[0]}`;
req?.headers.get("x-forwarded-host") ||
url.host ||
req?.headers.get("host")
}${img[0]}`;
} }
return img[0]; return img[0];
} }
@ -167,9 +155,6 @@ export const useMenuStore = defineStore("menuStore", () => {
link: [ link: [
// { rel: "manifest", href: "/api/manifest.json" } // { rel: "manifest", href: "/api/manifest.json" }
], ],
script:[
{src:"https://leiadmin.com/leitag.js?lei=894500UT83EISNNA8D04&color=dark"}
],
meta: [ meta: [
{ {
hid: "description", hid: "description",
@ -209,30 +194,16 @@ export const useMenuStore = defineStore("menuStore", () => {
} }
return meta; return meta;
}); });
const formatPrice = (value: number): string => { // watches
return value.toLocaleString(selectedLanguage.value.iso_code, { watch(() => $session.cookieData, async () => {
minimumFractionDigits: selectedCurrency.value.precision, await getLocales();
maximumFractionDigits: selectedCurrency.value.precision, await loadMenu();
currency: selectedCurrency.value.iso_code, await store.getMinValue();
style: "currency", await store.getCalculator();
currencyDisplay: "symbol", }, { deep: true });
currencySign: "accounting",
});
};
// watches
watch(
() => $session.cookieData,
async () => {
await getLocales();
await loadMenu();
await store.getMinValue();
await store.getCalculator();
},
{ deep: true }
);
return { return {
menu, menu,
@ -248,11 +219,9 @@ export const useMenuStore = defineStore("menuStore", () => {
selectedLanguage, selectedLanguage,
defaultMenu, defaultMenu,
headMeta, headMeta,
navigateToShop, navigateToShop,
loadMenu, loadMenu,
navigateToItem, navigateToItem,
getLocales, getLocales,
formatPrice,
}; };
}); });

View File

@ -30,42 +30,3 @@ export interface UserAddressOfficial {
}; };
}; };
} }
export interface Payment {
bank_name: string;
city: string;
country_account_number: string;
country_iso: string;
country_name: string;
currency_iso: string;
iban: string;
id: number;
postcode: string;
street_and_number: string;
swift: string;
}
export interface CheckoutOrder {
cart_id: number;
currency_iso: string;
customer_id: number;
delivery_details: {
address: Address;
contact_email: string;
contact_phone_number: string;
delivery_option_id: number;
note: string;
};
payment_bank_account_id: number;
}
export interface Address {
city: string;
country_iso: {
str: string;
};
name: string;
postcode: string;
street: string;
surname: string;
}

View File

@ -1,26 +0,0 @@
export interface Footer {
data: {
contact: Contact
docs: FooterDoc[]
}
id: number
name: string
}
export interface Contact {
header: string
ownerAddress: string
ownerMail: string
}
export interface FooterDoc {
footer_section: string
translation: string
data: FooterPdf[]
}
export interface FooterPdf {
name: string
translation: string
guest_avaliable: boolean
}

View File

@ -125,5 +125,4 @@ export type {
PeriodToFirstPiece, PeriodToFirstPiece,
} from "./planPrediction"; } from "./planPrediction";
export type { Product } from "./product"; export type { Product } from "./product";
export type { FrontMenu, FrontMenuLang, UIFrontMenu } from "./frontMenu"; export type { FrontMenu, FrontMenuLang, UIFrontMenu } from "./frontMenu";
export type {Contact, Footer, FooterDoc, FooterPdf} from './footer'

View File

@ -11,22 +11,3 @@ export interface Product {
applied_tax_rate: number; applied_tax_rate: number;
tax_name: string; tax_name: string;
} }
export interface CartProduct {
cart_item_id: number;
link_rewrite: string;
name: string;
picture_uuid: string;
product_id: number;
quantity: number;
single_item_price: number;
total_price: number;
}
export interface UserCart {
cart_items: CartProduct[];
checkout_in_progress: boolean;
currency_iso: string;
id: number;
total_value: number;
}