cart pop-up

This commit is contained in:
2025-06-24 15:53:07 +02:00
parent 5de09aa13b
commit 98a4125804
5 changed files with 101 additions and 70 deletions

View File

@ -1,31 +1,58 @@
<template> <template>
<div class="w-full p-[50px] bg-bg-light dark:bg-bg-dark border border-button rounded-2xl h-full"> <div ref="dropdownRef">
<div class="flex items-center h-[205px]" v-if="productStore.productList"> <i @click="openCart = !openCart" class="uil uil-shopping-cart text-[31px] cursor-pointer"></i>
<div class="w-[205px] h-full flex items-center justify-center"> <div v-if="openCart" class="max-w-[1067px] w-full absolute top-[130px] z-50 right-20">
<img :src="`https://www.yourgold.cz/api/public/file/${productStore.productList[0]?.cover_picture_uuid}.webp`" <div
alt="pics" class="w-auto h-full" /> class="w-full p-[50px] bg-bg-light dark:bg-bg-dark border border-button rounded-2xl h-full space-y-[55px]">
</div> <div class="pb-[25px] border-b border-block" v-if="productStore.productList">
<div class="flex flex-col justify-between h-full w-full gap-[7px] sm:gap-[15px] max-w-[250px]" <div class="flex items-center h-[205px]">
@click="productStore.addToCart(productStore.productList[0])"> <div class="w-[205px] h-full flex items-center justify-center">
<h3 <img :src="`https://www.yourgold.cz/api/public/file/${productStore.productList[0]?.cover_picture_uuid}.webp`"
class="text-[10px] sm:text-base md:text-lg text-xl font-bold leading-[130%] sm:leading-[150%] text-bg-dark"> alt="pics" class="w-auto h-full" />
{{ productStore.productList[0]?.name }} </div>
</h3> <div class="flex flex-col justify-between h-full w-full gap-[7px] sm:gap-[15px]"
<div class=""> @click="productStore.addToCart(productStore.productList[0])">
<h3
class="text-[10px] sm:text-base md:text-lg text-xl font-bold leading-[130%] sm:leading-[150%] text-bg-dark max-w-[250px]">
{{ productStore.productList[0]?.name }}
</h3>
<div class="flex flex-col gap-[10px]">
<p
class="text-accent-green-light font-inter text-[12px] sm:text-[21px] md:text-2xl leading-[150%] font-bold">
{{ productStore.productList[0]?.formatted_price }}
</p>
<div class="flex items-center gap-4 text-xl">
<p class="cursor-pointer">-</p>
<div class="w-11 min-h-11 border border-button flex items-center justify-center">{{
count }}
</div>
<p>+</p>
</div>
</div>
</div>
</div>
</div>
<div class="flex items-center justify-between">
<h4 class="h4-uppercase-bold-inter">Celková částka</h4>
<p <p
class="text-accent-green-light font-inter text-[12px] sm:text-[21px] md:text-2xl leading-[150%] font-bold"> class="text-accent-green-light font-inter text-[12px] sm:text-[21px] md:text-2xl leading-[150%] font-bold">
{{ productStore.productList[0]?.formatted_price }} {{ productStore.productList[0]?.formatted_price }}
</p> </p>
<div class="">
</div>
</div> </div>
<UiButtonArrow class="w-full" type="fill" :arrow="true" :full="true">Přejít k pokladně</UiButtonArrow>
</div> </div>
</div> </div>
<UiButtonArrow class="w-full" type="fill" :arrow="true">Přejít k pokladně</UiButtonArrow>
</div> </div>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { onClickOutside } from "@vueuse/core";
const count = ref(1)
const productStore = useProductStore() const productStore = useProductStore()
const openCart = ref(false);
const dropdownRef = ref(null);
onClickOutside(dropdownRef, () => {
openCart.value = false
});
</script> </script>

View File

@ -18,7 +18,7 @@
<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]">
<i class="uil uil-user text-[31px] cursor-pointer"></i> <i class="uil uil-user text-[31px] cursor-pointer"></i>
<i @click="openCart = !openCart" class="uil uil-shopping-cart text-[31px] cursor-pointer"></i> <CartPopup />
</div> </div>
<div class="flex"> <div class="flex">
<LangSwitcher /> <LangSwitcher />
@ -30,9 +30,6 @@
{{ $t('eshop') }} {{ $t('eshop') }}
</button> </button>
</div> </div>
<div v-if="openCart" class="max-w-[1067px] w-full absolute top-[130px] z-50 right-20">
<CartPopup />
</div>
</div> </div>
</UiContainer> </UiContainer>
</div> </div>
@ -219,7 +216,6 @@ import LangSwitcher from "./LangSwitcher.vue";
const menuStore = useMenuStore(); const menuStore = useMenuStore();
const productStore = useProductStore(); const productStore = useProductStore();
const open = ref(false); const open = ref(false);
const openCart = ref(false);
const colorMode = useColorMode(); const colorMode = useColorMode();
// productStore.getCart() // productStore.getCart()

View File

@ -10,6 +10,7 @@
: type === 'border' : type === 'border'
? 'border-button text-button group-hover:border-button-hover group-hover:text-button-hover border' ? 'border-button text-button group-hover:border-button-hover group-hover:text-button-hover border'
: 'border-button text-button dark:border-block dark:text-block group-hover:border-button-hover group-hover:text-button-hover border', : 'border-button text-button dark:border-block dark:text-block group-hover:border-button-hover group-hover:text-button-hover border',
full && 'w-full'
]" ]"
> >
<slot /> <slot />
@ -48,5 +49,8 @@ defineProps({
arrow: { arrow: {
type: Boolean, type: Boolean,
}, },
full: {
type: Boolean,
},
}); });
</script> </script>

View File

@ -1,15 +1,20 @@
import { NuxtErrorBoundary } from "#components"; import { NuxtErrorBoundary } from "#components";
import { useMyFetch } from "#imports"; import { useMyFetch } from "#imports";
import type { GenericResponse, GenericResponseItems, UserCart } from "~/types"; import type {
GenericResponse,
GenericResponseChildren,
GenericResponseItems,
UserCart,
} from "~/types";
import type { Product } from "~/types/product"; import type { Product } from "~/types/product";
export const useProductStore = defineStore("productStore", () => { export const useProductStore = defineStore("productStore", () => {
const productList = ref<Product>(); const productList = ref<Product[]>();
const modules = ref(); const modules = ref();
async function getList(count: number, categoryId = 1) { async function getList(count: number, categoryId = 1) {
try { try {
const { data } = await useMyFetch<GenericResponseItems<Product>>( const { data } = await useMyFetch<GenericResponseItems<[]>>(
`/api/public/products/category/${categoryId}?p=1&elems=${count}`, `/api/public/products/category/${categoryId}?p=1&elems=${count}`,
{ {
headers: { headers: {
@ -33,20 +38,18 @@ export const useProductStore = defineStore("productStore", () => {
async function getModules() { async function getModules() {
try { try {
const res = await fetch( const { data } = await useMyFetch<GenericResponseChildren<[]>>(
`http://127.0.0.1:4000/api/public/module/e_shop`, `/api/public/module/e_shop`,
{ {
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
}, },
onErrorOccured: (_, status) => {
throw new Error(`HTTP error: ${status}`);
},
} }
); );
if (!res.ok) {
throw new Error(`HTTP error: ${res.status}`);
}
const data = await res.json();
modules.value = data.children.find( modules.value = data.children.find(
(item: { id: number; name: string }) => (item: { id: number; name: string }) =>
item.name === "currency_rates_bar" item.name === "currency_rates_bar"
@ -58,22 +61,18 @@ export const useProductStore = defineStore("productStore", () => {
async function addToCart(product: Product) { async function addToCart(product: Product) {
try { try {
const res = await fetch( const { data } = await useMyFetch<GenericResponse<UserCart>>(
`http://127.0.0.1:4000/api/public/user/cart/item/add/${product.id}/1`, `/api/public/user/cart/item/add/${product.id}/1`,
{ {
method: "PUT", method: "PUT",
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
}, },
onErrorOccured: (_, status) => {
throw new Error(`HTTP error: ${status}`);
},
} }
); );
if (!res.ok) {
throw new Error(`HTTP error: ${res.status}`);
}
const data = await res.json();
console.log(data);
} catch (error) { } catch (error) {
console.error("getList error:", error); console.error("getList error:", error);
} }

View File

@ -1,6 +1,11 @@
import { useMyFetch } from "#imports"; import { useMyFetch } from "#imports";
import { usePB } from "~/composables/usePB"; import { usePB } from "~/composables/usePB";
import type { componentsListType, GenericResponse, PBPageItem, PlanPrediction } from "~/types"; import type {
componentsListType,
GenericResponse,
PBPageItem,
PlanPrediction,
} from "~/types";
// import { useI18n } from "vue-i18n"; // import { useI18n } from "vue-i18n";
export const useStore = defineStore("store", () => { export const useStore = defineStore("store", () => {
@ -11,20 +16,21 @@ export const useStore = defineStore("store", () => {
// calculator // calculator
const monthlySavings = ref(137); const monthlySavings = ref(137);
const storagePeriod = ref(10); const storagePeriod = ref(10);
const totalInvestment:Ref<number> = ref(0) const totalInvestment: Ref<number> = ref(0);
const minValue = ref() const minValue = ref();
// login // login
const email = ref() const email = ref();
const password = ref() const password = ref();
const components = ref({} as PBPageItem[]); const components = ref({} as PBPageItem[]);
const getSections = async (id: string) => { const getSections = async (id: string) => {
pb.cancelRequest("menu_view"); pb.cancelRequest("menu_view");
components.value = ( components.value = (
await pb.collection<PBPageItem>("page_view").getList(1, 50, { await pb.collection<PBPageItem>("page_view").getList(1, 50, {
filter: `id="${id}"&&(section_lang_id_lang="${$i18n.locale.value filter: `id="${id}"&&(section_lang_id_lang="${
}"||section_is_no_lang=${true})`, $i18n.locale.value
}"||section_is_no_lang=${true})`,
sort: "page_section_id_position", sort: "page_section_id_position",
}) })
).items as PBPageItem[]; ).items as PBPageItem[];
@ -72,18 +78,19 @@ export const useStore = defineStore("store", () => {
async function getCalculator() { async function getCalculator() {
try { try {
const {data} = await useMyFetch<GenericResponse<PlanPrediction>>( const { data } = await useMyFetch<GenericResponse<PlanPrediction>>(
`/api/public/plan-prediction/easy/calculate?monthly_deposit=${monthlySavings.value}&years=${storagePeriod.value}`, `/api/public/plan-prediction/easy/calculate?monthly_deposit=${monthlySavings.value}&years=${storagePeriod.value}`,
{ {
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
}, },
onErrorOccured: (_, status) => { throw new Error(`HTTP error: ${status}`) }, onErrorOccured: (_, status) => {
throw new Error(`HTTP error: ${status}`);
},
} }
); );
totalInvestment.value = data.total_investement_value totalInvestment.value = data.total_investement_value;
} catch (error) { } catch (error) {
console.error("getList error:", error); console.error("getList error:", error);
} }
@ -91,13 +98,15 @@ export const useStore = defineStore("store", () => {
async function getMinValue() { async function getMinValue() {
try { try {
const {data} = await useMyFetch<GenericResponse<number>>( const { data } = await useMyFetch<GenericResponse<number>>(
'/api/public/plan-prediction/free/minimum', "/api/public/plan-prediction/free/minimum",
{ {
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
}, },
onErrorOccured: (_, status) => { throw new Error(`HTTP error: ${status}`) }, onErrorOccured: (_, status) => {
throw new Error(`HTTP error: ${status}`);
},
} }
); );
@ -106,8 +115,7 @@ export const useStore = defineStore("store", () => {
// } // }
// const data = await res.json(); // const data = await res.json();
minValue.value = data minValue.value = data;
} catch (error) { } catch (error) {
console.error("getList error:", error); console.error("getList error:", error);
} }
@ -115,34 +123,31 @@ export const useStore = defineStore("store", () => {
async function logIn() { async function logIn() {
try { try {
const res = await fetch( const { data } = await useMyFetch<GenericResponse<object>>(
'http://127.0.0.1:4000/api/public/user/session/start', `/api/public/user/session/start`,
{ {
method: 'POST', method: "POST",
body: JSON.stringify({ body: JSON.stringify({
mail: email.value, mail: email.value,
password: password.value password: password.value,
}), }),
headers: { headers: {
"Content-Type": "application/json", "Content-Type": "application/json",
}, },
onErrorOccured: (_, status) => {
throw new Error(`HTTP error: ${status}`);
},
} }
); );
if (!res.ok) { minValue.value = data;
throw new Error(`HTTP error: ${res.status}`);
}
const data = await res.json();
minValue.value = data.data
} catch (error) { } catch (error) {
console.error("getList error:", error); console.error("getList error:", error);
} }
} }
getCalculator() getCalculator();
getMinValue() getMinValue();
return { return {
currentPageID, currentPageID,