summary checkout
This commit is contained in:
@ -18,8 +18,7 @@
|
|||||||
</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]">
|
||||||
<p @click="menuStore.navigateToItem(menuStore.menuItems?.find((item) => item.id === 13))" class="cursor-pointer">button</p>
|
<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>
|
||||||
|
@ -23,13 +23,13 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="grid grid-cols-3 gap-[30px]">
|
<div class="grid grid-cols-3 gap-[30px]">
|
||||||
<div class="col-start-1 col-end-3 space-y-5">
|
<div class="col-start-1 col-end-3 space-y-5">
|
||||||
<h4 class="h4-uppercase-bold-inter">Seznam produktů</h4>
|
<h4 class="h4-uppercase-bold-inter">{{ component.front_section_lang[0].data.product_list }}</h4>
|
||||||
<div class="border-2 border-block rounded-2xl p-[50px] space-25-55">
|
<div class="border-2 border-block rounded-[15px] p-[50px] space-25-55">
|
||||||
<div v-for="(item, index) in checkoutStore.products" :key="index">
|
<div v-for="(item, index) in checkoutStore.products" :key="index">
|
||||||
<div class="flex items-center h-[150px]">
|
<div class="flex items-center h-[150px]">
|
||||||
<div class="min-w-[150px] flex items-center justify-center h-[150px]">
|
<div class="min-w-[150px] flex items-center justify-center h-[150px]">
|
||||||
<img :src="`/api/public/file/${item.picture_uuid}.webp`"
|
<img :src="`/api/public/file/${item.picture_uuid}.webp`" alt=""
|
||||||
alt="" class="max-w-full max-h-full object-contain">
|
class="max-w-full max-h-full object-contain">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-col justify-between min-h-full w-full gap-[7px] sm:gap-[15px]">
|
<div class="flex flex-col justify-between min-h-full w-full gap-[7px] sm:gap-[15px]">
|
||||||
@ -50,10 +50,12 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="">
|
<div class="flex flex-col items-center gap-[30px]">
|
||||||
<div class="space-y-5">
|
<div class="space-y-5 w-full">
|
||||||
<h4 class="h4-uppercase-bold-inter">Adresa účtu</h4>
|
<h4 class="h4-uppercase-bold-inter">{{ component.front_section_lang[0].data.account_address }}
|
||||||
<div class="border-2 border-block rounded-2xl px-2 py-3 flex flex-col gap-1">
|
</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 }} {{
|
<span>{{ checkoutStore.defaultAddress?.address.name }} {{
|
||||||
checkoutStore.defaultAddress?.address.surname }}</span>
|
checkoutStore.defaultAddress?.address.surname }}</span>
|
||||||
<span>{{ checkoutStore.defaultAddress?.address.street }}</span>
|
<span>{{ checkoutStore.defaultAddress?.address.street }}</span>
|
||||||
@ -61,17 +63,161 @@
|
|||||||
checkoutStore.defaultAddress?.address.city }}</span>
|
checkoutStore.defaultAddress?.address.city }}</span>
|
||||||
</div>
|
</div>
|
||||||
</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>
|
||||||
|
<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>
|
||||||
</div>
|
</div>
|
||||||
</UiContainer>
|
</UiContainer>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { UCarousel } from '#components';
|
||||||
|
|
||||||
const checkoutStore = useCheckoutStore();
|
const checkoutStore = useCheckoutStore();
|
||||||
const productStore = useProductStore()
|
const productStore = useProductStore()
|
||||||
|
const menuStore = useMenuStore()
|
||||||
|
|
||||||
|
checkoutStore.getOrder()
|
||||||
|
checkoutStore.getBankAccount()
|
||||||
checkoutStore.getUserCart()
|
checkoutStore.getUserCart()
|
||||||
checkoutStore.getDeliveryOptions()
|
checkoutStore.getDeliveryOptions()
|
||||||
checkoutStore.getDefAddress()
|
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>
|
</script>
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
<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"
|
<img :src="`/api/public/file/${props.product?.cover_picture_uuid}.webp`" alt="Product Image" :class="[
|
||||||
class="h-[95px] sm:h-[180px] md:h-[205px] rounded-[5px]"
|
'h-[95px] sm:min-h-[180px] md:min-h-[205px] rounded-[5px]',
|
||||||
onerror="this.onerror=null; this.src='/photo.svg';" />
|
isError ? 'max-w-[50%]' : ''
|
||||||
|
]" @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">
|
||||||
@ -33,4 +34,11 @@ 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>
|
||||||
|
@ -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="#004F3D"/>
|
<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"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
Before Width: | Height: | Size: 598 B After Width: | Height: | Size: 598 B |
@ -1,5 +1,11 @@
|
|||||||
import type { GenericResponse, GenericResponseItems, UserCart } from "~/types";
|
import type { GenericResponse, GenericResponseItems, UserCart } from "~/types";
|
||||||
import type { AddressesList, UserAddressOfficial } from "~/types/checkout";
|
import type {
|
||||||
|
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";
|
import type { CartProduct } from "~/types/product";
|
||||||
@ -8,7 +14,12 @@ 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 showSummary = ref(false);
|
|
||||||
|
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[]>();
|
||||||
@ -137,8 +148,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
|
||||||
@ -186,8 +197,9 @@ export const useCheckoutStore = defineStore("checkoutStore", () => {
|
|||||||
autoClose: 5000,
|
autoClose: 5000,
|
||||||
dangerouslyHTMLString: true,
|
dangerouslyHTMLString: true,
|
||||||
});
|
});
|
||||||
// redirectToSummary();
|
menuStore.navigateToItem(
|
||||||
showSummary.value = true;
|
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,
|
||||||
@ -203,6 +215,7 @@ 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>>(
|
||||||
@ -261,19 +274,20 @@ export const useCheckoutStore = defineStore("checkoutStore", () => {
|
|||||||
const shippingPrice = ref();
|
const shippingPrice = ref();
|
||||||
async function getDeliveryOptions() {
|
async function getDeliveryOptions() {
|
||||||
try {
|
try {
|
||||||
const { data } = await useMyFetch<
|
const res = await useMyFetch<
|
||||||
GenericResponseItems<{
|
GenericResponseItems<object>
|
||||||
items: [
|
// {
|
||||||
{
|
// items: [
|
||||||
country_iso: string;
|
// {
|
||||||
country_name: string;
|
// country_iso: string;
|
||||||
delivery_supplier_id: number;
|
// country_name: string;
|
||||||
delivery_supplier_name: string;
|
// delivery_supplier_id: number;
|
||||||
id: number;
|
// delivery_supplier_name: string;
|
||||||
shippment_price: string;
|
// id: number;
|
||||||
}
|
// shippment_price: string;
|
||||||
];
|
// }
|
||||||
}>
|
// ];
|
||||||
|
// }
|
||||||
>(`/api/restricted/cart/checkout/delivery-options`, {
|
>(`/api/restricted/cart/checkout/delivery-options`, {
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
@ -286,7 +300,28 @@ export const useCheckoutStore = defineStore("checkoutStore", () => {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(data);
|
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;
|
deliveryOption.value = data.items;
|
||||||
currentDelivery.value = data.items[0];
|
currentDelivery.value = data.items[0];
|
||||||
shippingPrice.value = data.items[0].shippment_price;
|
shippingPrice.value = data.items[0].shippment_price;
|
||||||
@ -296,6 +331,12 @@ export const useCheckoutStore = defineStore("checkoutStore", () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const setCurrentDelivery = (item: any) => {
|
||||||
|
shippingPrice.value = item.shippment_price;
|
||||||
|
currentDelivery.value = item;
|
||||||
|
fullPrice.value = Number(fullPrice.value) + Number(shippingPrice.value);
|
||||||
|
};
|
||||||
|
|
||||||
const defaultAddress = ref();
|
const defaultAddress = ref();
|
||||||
async function getDefAddress() {
|
async function getDefAddress() {
|
||||||
try {
|
try {
|
||||||
@ -327,6 +368,137 @@ export const useCheckoutStore = defineStore("checkoutStore", () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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,
|
||||||
@ -351,7 +523,6 @@ export const useCheckoutStore = defineStore("checkoutStore", () => {
|
|||||||
vNewAddressCode,
|
vNewAddressCode,
|
||||||
vNewAddressCity,
|
vNewAddressCity,
|
||||||
vNewAddressCountry,
|
vNewAddressCountry,
|
||||||
showSummary,
|
|
||||||
|
|
||||||
products,
|
products,
|
||||||
fullPrice,
|
fullPrice,
|
||||||
@ -360,6 +531,14 @@ export const useCheckoutStore = defineStore("checkoutStore", () => {
|
|||||||
currentDelivery,
|
currentDelivery,
|
||||||
shippingPrice,
|
shippingPrice,
|
||||||
defaultAddress,
|
defaultAddress,
|
||||||
|
paymentMethods,
|
||||||
|
currentPayment,
|
||||||
|
|
||||||
|
vLegal,
|
||||||
|
vTerms,
|
||||||
|
vNote,
|
||||||
|
legalValidation,
|
||||||
|
termsValidation,
|
||||||
|
|
||||||
changePrefix,
|
changePrefix,
|
||||||
getCheckout,
|
getCheckout,
|
||||||
@ -371,5 +550,9 @@ export const useCheckoutStore = defineStore("checkoutStore", () => {
|
|||||||
getUserCart,
|
getUserCart,
|
||||||
getDeliveryOptions,
|
getDeliveryOptions,
|
||||||
getDefAddress,
|
getDefAddress,
|
||||||
|
setCurrentDelivery,
|
||||||
|
getBankAccount,
|
||||||
|
getOrder,
|
||||||
|
setNewAddress,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
@ -11,7 +11,6 @@ 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
|
||||||
@ -40,42 +39,50 @@ 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<GenericResponse<Country[]>>(`/api/public/country/list`);
|
const { data: countriesList } = await useMyFetch<
|
||||||
|
GenericResponse<Country[]>
|
||||||
|
>(`/api/public/country/list`);
|
||||||
countries.value = countriesList;
|
countries.value = countriesList;
|
||||||
selectedCountry.value = countriesList.find((country) => country.iso_code === $session.currentCountryIso.value) as Country;
|
selectedCountry.value = countriesList.find(
|
||||||
selectedPhoneCountry.value = countriesList.find((country) => country.iso_code === $session.currentCountryIso.value) as Country;
|
(country) => country.iso_code === $session.currentCountryIso.value
|
||||||
|
) as Country;
|
||||||
|
selectedPhoneCountry.value = countriesList.find(
|
||||||
|
(country) => country.iso_code === $session.currentCountryIso.value
|
||||||
|
) as Country;
|
||||||
|
|
||||||
|
const { data: currenciesList } = await useMyFetch<
|
||||||
const { data: currenciesList } = await useMyFetch<GenericResponseItems<Currency[]>>(`/api/public/currencies`)
|
GenericResponseItems<Currency[]>
|
||||||
|
>(`/api/public/currencies`);
|
||||||
currencies.value = currenciesList.items;
|
currencies.value = currenciesList.items;
|
||||||
selectedCurrency.value = currenciesList.items.find((currency) => currency.iso_code === $session.currentCurrencyIso.value) as Currency;
|
selectedCurrency.value = currenciesList.items.find(
|
||||||
|
(currency) => currency.iso_code === $session.currentCurrencyIso.value
|
||||||
|
) as Currency;
|
||||||
|
|
||||||
const { data: languagesList } = await useMyFetch<GenericResponseItems<Language[]>>(`/api/public/languages`)
|
const { data: languagesList } = await useMyFetch<
|
||||||
|
GenericResponseItems<Language[]>
|
||||||
|
>(`/api/public/languages`);
|
||||||
languages.value = languagesList.items;
|
languages.value = languagesList.items;
|
||||||
selectedLanguage.value = languagesList.items.find((language) => language.iso_code === $session.currentLanguageIso.value) as Language;
|
selectedLanguage.value = languagesList.items.find(
|
||||||
|
(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`,
|
||||||
{
|
{
|
||||||
@ -100,7 +107,6 @@ export const useMenuStore = defineStore("menuStore", () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const navigateToItem = (item?: UIFrontMenu) => {
|
const navigateToItem = (item?: UIFrontMenu) => {
|
||||||
if (item) {
|
if (item) {
|
||||||
router.push({
|
router.push({
|
||||||
@ -127,15 +133,21 @@ 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(`/api/public/file/${store.components[s].front_section.img[0]}_${size}.webp`)
|
img.push(
|
||||||
if (img.length > 0) break;;
|
`/api/public/file/${store.components[s].front_section.img[0]}_${size}.webp`
|
||||||
|
);
|
||||||
|
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}://${req?.headers.get("x-forwarded-host") || url.host || req?.headers.get("host")}${img[0]}`;
|
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 img[0];
|
||||||
}
|
}
|
||||||
@ -197,16 +209,30 @@ export const useMenuStore = defineStore("menuStore", () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return meta;
|
return meta;
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const formatPrice = (value: number): string => {
|
||||||
|
return value.toLocaleString(selectedLanguage.value.iso_code, {
|
||||||
|
minimumFractionDigits: selectedCurrency.value.precision,
|
||||||
|
maximumFractionDigits: selectedCurrency.value.precision,
|
||||||
|
currency: selectedCurrency.value.iso_code,
|
||||||
|
style: "currency",
|
||||||
|
currencyDisplay: "symbol",
|
||||||
|
currencySign: "accounting",
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
// watches
|
// watches
|
||||||
watch(() => $session.cookieData, async () => {
|
watch(
|
||||||
await getLocales();
|
() => $session.cookieData,
|
||||||
await loadMenu();
|
async () => {
|
||||||
await store.getMinValue();
|
await getLocales();
|
||||||
await store.getCalculator();
|
await loadMenu();
|
||||||
}, { deep: true });
|
await store.getMinValue();
|
||||||
|
await store.getCalculator();
|
||||||
|
},
|
||||||
|
{ deep: true }
|
||||||
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
menu,
|
menu,
|
||||||
@ -222,9 +248,11 @@ export const useMenuStore = defineStore("menuStore", () => {
|
|||||||
selectedLanguage,
|
selectedLanguage,
|
||||||
defaultMenu,
|
defaultMenu,
|
||||||
headMeta,
|
headMeta,
|
||||||
|
|
||||||
navigateToShop,
|
navigateToShop,
|
||||||
loadMenu,
|
loadMenu,
|
||||||
navigateToItem,
|
navigateToItem,
|
||||||
getLocales,
|
getLocales,
|
||||||
|
formatPrice,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
@ -30,3 +30,42 @@ 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;
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user