карты пвз
Some checks failed
Deploy / build (push) Failing after 7s

This commit is contained in:
alsaze 2025-11-13 16:24:10 +03:00
parent bd4edfdade
commit f857c40ca2
8 changed files with 141 additions and 20 deletions

View File

@ -1,6 +1,37 @@
<template> <template>
<div> <div>
<UPageCard> <teleport
v-if="isMobile && isSummary" to="footer"
>
<UPageCard
class="pay-block--mobile"
variant="ghost"
:ui="{
body: 'w-full',
footer: 'hidden',
}"
>
<template #body>
<div class="d-flex flex-row">
<div>
<div v-if="cartSum">
<ProductPrice :is-headline="false" :price="cartSum" />
</div>
<div>{{ `${cart?.line_items?.length} шт` }}</div>
</div>
<UButton
class="justify-center text-center w-full ml10"
size="xl"
:label="pay ? 'оформить заказ' : 'перейти к оформлению'"
@click="pay ? createOrder() : router.push(`/checkout/delivery`)"
/>
</div>
</template>
</UPageCard>
</teleport>
<UPageCard v-else>
<template #body> <template #body>
<div>товары {{ `(${cart?.line_items?.length} шт)` }}</div> <div>товары {{ `(${cart?.line_items?.length} шт)` }}</div>
<div v-if="cartSum"> <div v-if="cartSum">
@ -22,15 +53,23 @@
<script setup lang="ts"> <script setup lang="ts">
import type { IBspb } from '~/server/shared/types/bspb' import type { IBspb } from '~/server/shared/types/bspb'
import { useMediaQuery } from '@vueuse/core'
defineProps({ defineProps({
pay: { pay: {
type: Boolean, type: Boolean,
default: false, default: false,
}, },
isSummary: {
type: Boolean,
default: false,
},
}) })
const router = useRouter() const router = useRouter()
const isMobile = useMediaQuery('(max-width: 1280px)', {
ssrWidth: 768,
})
const { cart, cartSum } = useCart() const { cart, cartSum } = useCart()
const createOrder = async () => { const createOrder = async () => {
@ -50,3 +89,15 @@ const createOrder = async () => {
window.open(redirectUrl, '_blank') window.open(redirectUrl, '_blank')
} }
</script> </script>
<style lang="scss">
.pay-block {
&--mobile {
position: sticky;
bottom: 0;
left: 0;
right: 0;
z-index: 100;
}
}
</style>

View File

@ -23,6 +23,10 @@ export const useCart = () => {
cartItem?.variation_id === item?.variation_id), 1) cartItem?.variation_id === item?.variation_id), 1)
} }
const cartRemoveAllItems = () => {
cart.value = { line_items: [] }
}
const cartProducts = computed(() => cart?.value?.line_items?.map((line_item) => { const cartProducts = computed(() => cart?.value?.line_items?.map((line_item) => {
const { productsData } = useProduct(line_item?.variation_id.toString()) const { productsData } = useProduct(line_item?.variation_id.toString())
return productsData return productsData
@ -37,6 +41,7 @@ export const useCart = () => {
cart, cart,
cartAddItem, cartAddItem,
cartRemoveItem, cartRemoveItem,
cartRemoveAllItems,
cartProducts, cartProducts,
cartSum, cartSum,

View File

@ -34,14 +34,17 @@ export const useCheckout = createSharedComposable(() => {
{ {
step: 1, step: 1,
title: isMobile.value ? 'mobileDelivery' : 'delivery', title: isMobile.value ? 'mobileDelivery' : 'delivery',
route: 'delivery',
}, },
{ {
step: 2, step: 2,
title: isMobile.value ? 'mobileContacts' : 'contacts', title: isMobile.value ? 'mobileContacts' : 'contacts',
route: 'contacts',
}, },
{ {
step: 3, step: 3,
title: isMobile.value ? 'mobileSummary' : 'summary', title: isMobile.value ? 'mobileSummary' : 'summary',
route: 'summary',
}, },
] ]
@ -57,7 +60,7 @@ export const useCheckout = createSharedComposable(() => {
const findIndex = checkoutSteps.findIndex(value => value.step === currentCheckoutStep.value.step) const findIndex = checkoutSteps.findIndex(value => value.step === currentCheckoutStep.value.step)
if (findIndex !== 0) { if (findIndex !== 0) {
currentCheckoutStep.value = checkoutSteps[findIndex - 1] currentCheckoutStep.value = checkoutSteps[findIndex - 1]
router.push(`/checkout/${currentCheckoutStep?.value.title}`) router.push(`/checkout/${currentCheckoutStep?.value.route}`)
} }
else { else {
router.push(`/cart`) router.push(`/cart`)
@ -68,12 +71,12 @@ export const useCheckout = createSharedComposable(() => {
const findIndex = checkoutSteps.findIndex(value => value.step === currentCheckoutStep.value.step) const findIndex = checkoutSteps.findIndex(value => value.step === currentCheckoutStep.value.step)
if (findIndex + 1 !== checkoutSteps.length) { if (findIndex + 1 !== checkoutSteps.length) {
currentCheckoutStep.value = checkoutSteps[findIndex + 1] currentCheckoutStep.value = checkoutSteps[findIndex + 1]
router.push(`/checkout/${currentCheckoutStep?.value.title}`) router.push(`/checkout/${currentCheckoutStep?.value.route}`)
} }
} }
function setStep(pathName: string) { function setStep(pathName: string) {
currentCheckoutStep.value = checkoutSteps.find(value => value.title === pathName) || checkoutSteps[0] currentCheckoutStep.value = checkoutSteps.find(value => value.route === pathName) || checkoutSteps[0]
router.push(`/checkout/${pathName}`) router.push(`/checkout/${pathName}`)
} }

View File

@ -12,19 +12,28 @@
</div> </div>
</header> </header>
<main class="main"> <main class="main" :style="showFooter ? 'margin-bottom: 54px' : 'margin-bottom: 0'">
<UContainer class="container"> <UContainer class="container">
<slot /> <slot />
</UContainer> </UContainer>
</main> </main>
<footer class="footer" :class="{ 'footer--hidden': !showFooter }" />
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { useCheckout } from '../composables/useCheckout' import { useMediaQuery } from '@vueuse/core'
import { useCheckout } from '~/composables/useCheckout'
const route = useRoute()
const { t } = useI18n()
const isMobile = useMediaQuery('(max-width: 1280px)', {
ssrWidth: 768,
})
const showFooter = computed(() => route.path !== '/checkout/delivery' && isMobile.value)
const { previewStep, currentCheckoutStep, checkoutSteps } = useCheckout() const { previewStep, currentCheckoutStep, checkoutSteps } = useCheckout()
const { t } = useI18n()
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@ -63,8 +72,27 @@ const { t } = useI18n()
} }
} }
.footer {
position: fixed;
bottom: 0;
left: 0;
right: 0;
z-index: 100;
height: 70px;
background-color: #0f172b;
&--hidden {
display: none;
}
}
.main { .main {
flex: 1; flex: 1;
margin-top: 54px; margin-top: 54px;
margin-bottom: 64px;
&__hide-footer {
margin-bottom: 0 !important;
}
} }
</style> </style>

View File

@ -32,15 +32,20 @@
</UContainer> </UContainer>
</main> </main>
<!-- <footer class="footer"> --> <footer class="footer" :class="{ 'footer--hidden': !(route.path === '/cart' && isMobile) }" />
<!-- Footer -->
<!-- </footer> -->
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { useMediaQuery } from '@vueuse/core'
const route = useRoute()
const router = useRouter() const router = useRouter()
const { cart } = useCart() const { cart } = useCart()
const isMobile = useMediaQuery('(max-width: 1280px)', {
ssrWidth: 768,
})
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@ -106,12 +111,22 @@ const { cart } = useCart()
} }
} }
.main { .footer {
flex: 1; position: fixed;
margin-top: 54px; bottom: 0;
left: 0;
right: 0;
z-index: 100;
height: 70px;
background-color: #0f172b;
&--hidden {
display: none;
}
} }
.footer { .main {
margin-top: auto; flex: 1;
margin-block: 54px 64px;
} }
</style> </style>

View File

@ -9,7 +9,7 @@
</div> </div>
</div> </div>
<PayBlock /> <PayBlock :is-summary="true" />
</div> </div>
</template> </template>
@ -18,7 +18,7 @@ import { useCart } from '~/composables'
import PayBlock from '../components/PayBlock.vue' import PayBlock from '../components/PayBlock.vue'
const route = useRoute() const route = useRoute()
const { cart } = useCart() const { cart, cartRemoveAllItems } = useCart()
const { checkoutContacts, checkoutPickupPoint } = useCheckout() const { checkoutContacts, checkoutPickupPoint } = useCheckout()
onMounted(async () => { onMounted(async () => {
@ -46,6 +46,8 @@ onMounted(async () => {
status: 'processing', status: 'processing',
}, },
}) })
cartRemoveAllItems()
}) })
</script> </script>
@ -63,6 +65,7 @@ onMounted(async () => {
@include mobile { @include mobile {
margin-top: 20px; margin-top: 20px;
flex-direction: column; flex-direction: column;
padding-inline: 16px;
} }
&__items { &__items {

View File

@ -1,5 +1,5 @@
<template> <template>
<form class="contacts" @submit.prevent="onSubmit"> <form v-if="checkoutContacts" class="contacts" @submit.prevent="onSubmit">
<div> <div>
<UInput <UInput
id="name" id="name"
@ -138,7 +138,7 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { useCheckout } from '../../composables/useCheckout' import { useCheckout } from '~/composables/useCheckout'
const { checkoutContacts, setCheckoutContacts, nextStep } = useCheckout() const { checkoutContacts, setCheckoutContacts, nextStep } = useCheckout()
@ -199,11 +199,17 @@ definePageMeta({
</script> </script>
<style lang="scss"> <style lang="scss">
@use '~/assets/scss/utils' as *;
.contacts { .contacts {
margin-inline: auto; margin-inline: auto;
max-width: 400px; max-width: 400px;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 16px; gap: 16px;
@include mobile {
padding-inline: 10px;
}
} }
</style> </style>

View File

@ -58,7 +58,9 @@
</div> </div>
</div> </div>
<PayBlock pay /> <ClientOnly>
<PayBlock pay :is-summary="true" />
</ClientOnly>
</div> </div>
</template> </template>
@ -85,10 +87,18 @@ definePageMeta({
flex-direction: row; flex-direction: row;
justify-content: space-between; justify-content: space-between;
@include mobile {
flex-direction: column;
}
&__info { &__info {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 16px; gap: 16px;
@include mobile {
margin-bottom: 26px;
}
} }
&__items { &__items {