карта ПВЗ
All checks were successful
Deploy / build (push) Successful in 2m21s

This commit is contained in:
alsaze 2025-10-17 17:10:14 +03:00
parent 887ea75e8b
commit 2b8a5e5774
10 changed files with 418 additions and 95 deletions

View File

@ -15,6 +15,8 @@ ENV BSPB_MERCHANT_ID=TT00001
ENV BSPB_MERCHANT_PASSWORD=ztTGre1OBZg3 ENV BSPB_MERCHANT_PASSWORD=ztTGre1OBZg3
ENV BSPB_API_URL=https://pgtest.bspb.ru:5443 ENV BSPB_API_URL=https://pgtest.bspb.ru:5443
ENV VITE_BASE_URL=https://paxton.koptilnya.xyz
EXPOSE 80 EXPOSE 80
CMD ["node", "/app/server/index.mjs"] CMD ["node", "/app/server/index.mjs"]

View File

@ -0,0 +1,44 @@
<template>
<div class="summary-cart-item">
<img
class="summary-cart-item__image"
:src="productsData?.images[0]?.src"
alt="cart?.image"
>
<div class="summary-cart-item__attributes">
{{ size }}
</div>
</div>
</template>
<script setup lang="ts">
const props = defineProps({
summaryCartItem: {
type: String,
required: true,
},
})
const { productsData, size } = useProduct(props?.summaryCartItem?.variation_id)
</script>
<style lang="scss">
.summary-cart-item {
max-width: 600px;
display: flex;
flex-direction: column;
gap: 4px;
&__image {
width: 120px;
}
&__attributes {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
}
}
</style>

View File

@ -1,9 +1,15 @@
import { createSharedComposable } from '@vueuse/core' import { createSharedComposable, useStorage } from '@vueuse/core'
export const useCheckout = createSharedComposable(() => { export const useCheckout = createSharedComposable(() => {
const router = useRouter() const router = useRouter()
const route = useRoute() const route = useRoute()
const contacts = useStorage('checkout-contacts', { name: '', surname: '', phone: '', email: '' })
const setContacts = (data: { name: string, surname: string, phone: string, email: string }) => {
contacts.value = data
}
const checkoutSteps = [ const checkoutSteps = [
{ {
step: 1, step: 1,
@ -41,6 +47,9 @@ export const useCheckout = createSharedComposable(() => {
} }
return { return {
contacts,
setContacts,
checkoutSteps, checkoutSteps,
currentCheckoutStep, currentCheckoutStep,

View File

@ -3,7 +3,19 @@ export default defineNuxtConfig({
ssr: true, ssr: true,
compatibilityDate: '2025-05-15', compatibilityDate: '2025-05-15',
devtools: { enabled: true }, devtools: { enabled: true },
modules: ['@nuxt/ui', '@nuxt/image', '@nuxt/icon', '@nuxt/fonts', '@nuxtjs/i18n'], modules: [
'@nuxt/ui',
'@nuxt/image',
'@nuxt/icon',
'@nuxt/fonts',
'@nuxtjs/i18n',
[
'@vee-validate/nuxt',
{
autoImports: true,
},
],
],
css: ['~/assets/css/main.css', '~/assets/scss/main.scss'], css: ['~/assets/css/main.css', '~/assets/scss/main.scss'],
i18n: { i18n: {
locales: [ locales: [

View File

@ -20,6 +20,7 @@
"@nuxtjs/i18n": "^10.0.4", "@nuxtjs/i18n": "^10.0.4",
"@tanstack/vue-query": "^5.75.5", "@tanstack/vue-query": "^5.75.5",
"@tanstack/vue-query-devtools": "^5.87.1", "@tanstack/vue-query-devtools": "^5.87.1",
"@vee-validate/nuxt": "^4.15.1",
"@vueuse/core": "^13.1.0", "@vueuse/core": "^13.1.0",
"axios": "^1.12.2", "axios": "^1.12.2",
"dayjs": "^1.11.13", "dayjs": "^1.11.13",

View File

@ -1,6 +1,5 @@
<template> <template>
<div class="cart"> <div class="cart">
</pre>
<div class="cart__items"> <div class="cart__items">
<div <div
v-for="cartItem in cart?.line_items" v-for="cartItem in cart?.line_items"

View File

@ -1,97 +1,197 @@
<template> <template>
<div class="contacts"> <form class="contacts" @submit.prevent="onSubmit">
<UInput <div>
v-model="name" <UInput
size="xl" id="name"
placeholder=" " v-model="name"
:ui="{ base: 'peer' }" v-bind="nameAttrs"
class="relative" name="name"
> size="xl"
<label placeholder=" "
class="pointer-events-none absolute left-3 text-base transition-all peer-focus:-top-3 peer-focus:text-highlighted peer-focus:text-sm peer-focus:font-medium" :class="[ :ui="{ base: 'peer' }"
name :invalid="Boolean(errors.name)"
? '-top-3 text-sm text-highlighted font-medium' :help="errors.name"
: 'top-3 text-dimmed peer-placeholder-shown:top-2 peer-placeholder-shown:text-base peer-placeholder-shown:text-dimmed', class="relative w-100"
]" :color="errors.name ? 'error' : 'neutral'"
highlight
autofocus
> >
<span class="inline-flex bg-default px-1">Имя</span> <label
</label> class="pointer-events-none absolute left-3 text-base transition-all peer-focus:-top-3 peer-focus:text-highlighted peer-focus:text-sm peer-focus:font-medium" :class="[
</UInput> name
? '-top-3 text-sm text-highlighted font-medium'
: 'top-3 text-dimmed peer-placeholder-shown:top-2 peer-placeholder-shown:text-base peer-placeholder-shown:text-dimmed',
]"
>
<span class="inline-flex bg-default px-1">Имя</span>
</label>
</UInput>
<UInput <div v-if="errors?.name" style="color: #ff6467">
v-model="surname" {{ errors?.name }}
size="xl" </div>
placeholder=" " </div>
:ui="{ base: 'peer' }"
class="relative"
>
<label
class="pointer-events-none absolute left-3 text-base transition-all peer-focus:-top-3 peer-focus:text-highlighted peer-focus:text-sm peer-focus:font-medium" :class="[
surname
? '-top-3 text-sm text-highlighted font-medium'
: 'top-3 text-dimmed peer-placeholder-shown:top-2 peer-placeholder-shown:text-base peer-placeholder-shown:text-dimmed',
]"
>
<span class="inline-flex bg-default px-1">Фамилия</span>
</label>
</UInput>
<UInput <div>
v-model="phone" <UInput
v-maska="'+7 (###) ###-##-##'" id="surname"
size="xl" v-model="surname"
placeholder=" " v-bind="surnameAttrs"
:ui="{ base: 'peer' }" name="surname"
class="relative" size="xl"
> placeholder=" "
<label :ui="{ base: 'peer' }"
class="pointer-events-none absolute left-3 text-base transition-all peer-focus:-top-3 peer-focus:text-highlighted peer-focus:text-sm peer-focus:font-medium" :class="[ :invalid="Boolean(errors.surname)"
phone :help="errors.surname"
? '-top-3 text-sm text-highlighted font-medium' class="relative w-100"
: 'top-3 text-dimmed peer-placeholder-shown:top-2 peer-placeholder-shown:text-base peer-placeholder-shown:text-dimmed', :color="errors.surname ? 'error' : 'neutral'"
]" highlight
> >
<span class="inline-flex bg-default px-1">телефон</span> <label
</label> class="pointer-events-none absolute left-3 text-base transition-all peer-focus:-top-3 peer-focus:text-highlighted peer-focus:text-sm peer-focus:font-medium" :class="[
</UInput> surname
? '-top-3 text-sm text-highlighted font-medium'
: 'top-3 text-dimmed peer-placeholder-shown:top-2 peer-placeholder-shown:text-base peer-placeholder-shown:text-dimmed',
]"
>
<span class="inline-flex bg-default px-1">Фамилия</span>
</label>
</UInput>
<UInput <div v-if="errors?.surname" style="color: #ff6467">
v-model="email" {{ errors?.surname }}
size="xl" </div>
placeholder=" " </div>
:ui="{ base: 'peer' }"
class="relative" <div>
trailing-icon="i-lucide-at-sign" <UInput
> id="phone"
<label v-model="phone"
class="pointer-events-none absolute left-3 text-base transition-all peer-focus:-top-3 peer-focus:text-highlighted peer-focus:text-sm peer-focus:font-medium" :class="[ v-bind="phoneAttrs"
email v-maska="'+7 (###) ###-##-##'"
? '-top-3 text-sm text-highlighted font-medium' name="phone"
: 'top-3 text-dimmed peer-placeholder-shown:top-2 peer-placeholder-shown:text-base peer-placeholder-shown:text-dimmed', size="xl"
]" placeholder=" "
:ui="{ base: 'peer' }"
:invalid="Boolean(errors.phone)"
:help="errors.phone"
class="relative w-100"
:color="errors.phone ? 'error' : 'neutral'"
highlight
> >
<span class="inline-flex bg-default px-1">email</span> <label
</label> class="pointer-events-none absolute left-3 text-base transition-all peer-focus:-top-3 peer-focus:text-highlighted peer-focus:text-sm peer-focus:font-medium" :class="[
</UInput> phone
? '-top-3 text-sm text-highlighted font-medium'
: 'top-3 text-dimmed peer-placeholder-shown:top-2 peer-placeholder-shown:text-base peer-placeholder-shown:text-dimmed',
]"
>
<span class="inline-flex bg-default px-1">телефон</span>
</label>
</UInput>
<div v-if="errors?.phone" style="color: #ff6467">
{{ errors?.phone }}
</div>
</div>
<div>
<UInput
id="email"
v-model="email"
v-bind="emailAttrs"
name="email"
size="xl"
placeholder=" "
:ui="{ base: 'peer' }"
class="relative w-100"
trailing-icon="i-lucide-at-sign"
:invalid="Boolean(errors.email)"
:help="errors.email"
:color="errors.email ? 'error' : 'neutral'"
highlight
>
<label
class="pointer-events-none absolute left-3 text-base transition-all peer-focus:-top-3 peer-focus:text-highlighted peer-focus:text-sm peer-focus:font-medium" :class="[
email
? '-top-3 text-sm text-highlighted font-medium'
: 'top-3 text-dimmed peer-placeholder-shown:top-2 peer-placeholder-shown:text-base peer-placeholder-shown:text-dimmed',
]"
>
<span class="inline-flex bg-default px-1">email</span>
</label>
</UInput>
<div v-if="errors?.email" style="color: #ff6467">
{{ errors?.email }}
</div>
</div>
<UButton <UButton
size="xl" size="xl"
label="продолжить" label="продолжить"
class="justify-center text-center" class="justify-center text-center"
@click="nextStep" type="submit"
:disabled="errors && Object.keys(errors).length > 0"
/> />
</div> </form>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { useCheckout } from '../../composables/useCheckout' import { useCheckout } from '../../composables/useCheckout'
const name = ref('') const { setContacts, nextStep } = useCheckout()
const surname = ref('')
const phone = ref('')
const email = ref('')
const { nextStep } = useCheckout() const { errors, handleSubmit, defineField } = useForm({
initialValues: {
name: '',
surname: '',
phone: '',
email: '',
},
validationSchema: {
name(value: string) {
if (!value)
return 'Укажите имя'
if (value.trim().length < 2)
return 'Минимум 2 символа'
return true
},
surname(value: string) {
if (!value)
return 'Укажите фамилию'
if (value.trim().length < 2)
return 'Минимум 2 символа'
return true
},
phone(value: string) {
if (!value)
return 'Укажите телефон'
const digits = (value || '').replace(/\D/g, '')
if (digits.length < 11)
return 'Введите корректный телефон'
return true
},
email(value: string) {
if (!value)
return 'Укажите email'
const re = /^[^\s@]+@[^\s@][^\s.@]*\.[^\s@]+$/
if (!re.test(value))
return 'Введите корректный email'
return true
},
},
})
const [name, nameAttrs] = defineField('name')
const [surname, surnameAttrs] = defineField('surname')
const [phone, phoneAttrs] = defineField('phone')
const [email, emailAttrs] = defineField('email')
const onSubmit = handleSubmit((values) => {
setContacts(values)
nextStep()
})
definePageMeta({ definePageMeta({
layout: 'checkout', layout: 'checkout',

View File

@ -1,12 +1,119 @@
<template> <template>
<UButton label="СОздать ОредЕр" @click="createOrder" /> <div class="summary">
<div class="summary__info">
<h3>в заказе &nbsp;&bull;&nbsp; {{ cart?.line_items?.length }} шт</h3>
<div class="summary__items">
<div
v-for="cartItem in cart?.line_items"
:key="cartItem.variation_id"
>
<SummaryCartItem :summary-cart-item="cartItem" />
</div>
</div>
<div class="space-y-2">
<h3 class="d-flex gap-1 text-center align-items-center">
Yandex
<UButton
size="sm"
class="text-muted-foreground"
variant="ghost"
icon="i-ph-pencil-simple-line"
@click="onEditDelivery"
/>
</h3>
<div class="flex items-center gap-2">
<UIcon name="i-ph-user" class="text-muted-foreground" />
<span>{{ contacts?.name }} {{ contacts?.surname }}</span>
</div>
<div class="flex items-center gap-2">
<UIcon name="i-ph-user" class="text-muted-foreground" />
<span>{{ contacts?.name }} {{ contacts?.surname }}</span>
</div>
<div class="flex items-center gap-2">
<UIcon name="i-ph-user" class="text-muted-foreground" />
<span>{{ contacts?.name }} {{ contacts?.surname }}</span>
</div>
<div class="flex items-center gap-2">
<UIcon name="i-ph-user" class="text-muted-foreground" />
<span>{{ contacts?.name }} {{ contacts?.surname }}</span>
</div>
<div class="flex items-center gap-2">
<UIcon name="i-ph-user" class="text-muted-foreground" />
<span>{{ contacts?.name }} {{ contacts?.surname }}</span>
</div>
</div>
<div class="space-y-2">
<h3 class="d-flex gap-1 text-center align-items-center">
Получатель
<UButton
size="sm"
class="text-muted-foreground"
variant="ghost"
icon="i-ph-pencil-simple-line"
@click="onEditContacts"
/>
</h3>
<div class="flex items-center gap-2">
<UIcon name="i-ph-user" class="text-muted-foreground" />
<span>{{ contacts?.name }} {{ contacts?.surname }}</span>
</div>
<div class="flex items-center gap-2">
<UIcon name="i-ph-envelope-simple" class="text-muted-foreground" />
<span>{{ contacts?.email }}</span>
</div>
<div class="flex items-center gap-2">
<UIcon name="i-ph-phone" class="text-muted-foreground" />
<span>{{ contacts?.phone }}</span>
</div>
</div>
</div>
<div>
<UButton label="СОздать ОредЕр" @click="createOrder" />
</div>
</div>
</template> </template>
<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 SummaryCartItem from '../../components/cart/SummaryCartItem.vue'
const { cart } = useCart()
const { contacts } = useCheckout()
function onEditDelivery() {
console.log('pizda')
}
function onEditContacts() {
console.log('pizda')
}
const createOrder = async () => { const createOrder = async () => {
const { data } = await useFetch<IBspb>('/api/bspb') const { data } = await useFetch<IBspb>('/api/bspb', {
method: 'POST',
body: {
order: {
typeRid: 'Purchase',
amount: 100,
currency: 'RUB',
hppRedirectUrl: `${import.meta.env.VITE_BASE_URL}/cart`,
},
},
})
const redirectUrl = `${data?.value?.order?.hppUrl}?orderId=${data?.value?.order?.id}&password=${data.value?.order?.password}` const redirectUrl = `${data?.value?.order?.hppUrl}?orderId=${data?.value?.order?.id}&password=${data.value?.order?.password}`
window.open(redirectUrl, '_blank') window.open(redirectUrl, '_blank')
@ -17,6 +124,27 @@ definePageMeta({
}) })
</script> </script>
<style scoped lang="scss"> <style lang="scss">
@use '~/assets/scss/utils' as *;
.summary {
max-width: 1200px;
margin-inline: auto;
padding-inline: 16px;
display: flex;
flex-direction: row;
justify-content: space-between;
&__info {
display: flex;
flex-direction: column;
gap: 16px;
}
&__items {
display: flex;
flex-direction: row;
gap: 4px;
}
}
</style> </style>

View File

@ -1,8 +1,8 @@
import https from 'node:https' import https from 'node:https'
import axios from 'axios' import axios from 'axios'
import { defineEventHandler } from 'h3' import { defineEventHandler, readBody } from 'h3'
export default defineEventHandler(async () => { export default defineEventHandler(async (event) => {
const merchantId = process.env.BSPB_MERCHANT_ID! const merchantId = process.env.BSPB_MERCHANT_ID!
const merchantPassword = process.env.BSPB_MERCHANT_PASSWORD! const merchantPassword = process.env.BSPB_MERCHANT_PASSWORD!
const apiUrl = process.env.BSPB_API_URL! const apiUrl = process.env.BSPB_API_URL!
@ -18,18 +18,9 @@ export default defineEventHandler(async () => {
rejectUnauthorized: false, rejectUnauthorized: false,
}) })
const data = { const orderData = await readBody(event)
order: {
typeRid: 'Purchase',
amount: 100,
currency: 'RUB',
title: 'Название заказа',
description: 'Описание заказа',
hppRedirectUrl: 'http://localhost:3000/cart',
},
}
const response = await axios.post(`${apiUrl}/order`, data, { const response = await axios.post(`${apiUrl}/order`, orderData, {
httpsAgent: agent, httpsAgent: agent,
headers: { headers: {
'Content-Type': 'application/json', 'Content-Type': 'application/json',

View File

@ -2500,6 +2500,15 @@
hookable "^5.5.3" hookable "^5.5.3"
unhead "2.0.19" unhead "2.0.19"
"@vee-validate/nuxt@^4.15.1":
version "4.15.1"
resolved "https://registry.yarnpkg.com/@vee-validate/nuxt/-/nuxt-4.15.1.tgz#4062be82b364f5b16fa1be31aa3be59c47012ba7"
integrity sha512-vy+BYUmwy7d01js8jg3qApyrE8/nJHbHvPZNYZSe+hTQEblNqyVt+MnD1incyxMCcivED8FX5w4rjxdoUn7iMQ==
dependencies:
"@nuxt/kit" "^3.13.2"
local-pkg "^0.5.0"
vee-validate "4.15.1"
"@vercel/nft@^0.30.2": "@vercel/nft@^0.30.2":
version "0.30.3" version "0.30.3"
resolved "https://registry.yarnpkg.com/@vercel/nft/-/nft-0.30.3.tgz#ab09a7f22ec7b354fcbe2d79f3d8c0c8adfbcc89" resolved "https://registry.yarnpkg.com/@vercel/nft/-/nft-0.30.3.tgz#ab09a7f22ec7b354fcbe2d79f3d8c0c8adfbcc89"
@ -2645,6 +2654,13 @@
resolved "https://registry.yarnpkg.com/@vue/devtools-api/-/devtools-api-6.6.4.tgz#cbe97fe0162b365edc1dba80e173f90492535343" resolved "https://registry.yarnpkg.com/@vue/devtools-api/-/devtools-api-6.6.4.tgz#cbe97fe0162b365edc1dba80e173f90492535343"
integrity sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g== integrity sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==
"@vue/devtools-api@^7.5.2":
version "7.7.7"
resolved "https://registry.yarnpkg.com/@vue/devtools-api/-/devtools-api-7.7.7.tgz#5ef5f55f60396220725a273548c0d7ee983d5d34"
integrity sha512-lwOnNBH2e7x1fIIbVT7yF5D+YWhqELm55/4ZKf45R9T8r9dE2AIOy8HKjfqzGsoTHFbWbr337O4E0A0QADnjBg==
dependencies:
"@vue/devtools-kit" "^7.7.7"
"@vue/devtools-core@^7.7.7": "@vue/devtools-core@^7.7.7":
version "7.7.7" version "7.7.7"
resolved "https://registry.yarnpkg.com/@vue/devtools-core/-/devtools-core-7.7.7.tgz#9885e2ecb7b462cca8e629d9cff0ab00bfd30d63" resolved "https://registry.yarnpkg.com/@vue/devtools-core/-/devtools-core-7.7.7.tgz#9885e2ecb7b462cca8e629d9cff0ab00bfd30d63"
@ -5482,6 +5498,14 @@ listhen@^1.5.6, listhen@^1.9.0:
untun "^0.1.3" untun "^0.1.3"
uqr "^0.1.2" uqr "^0.1.2"
local-pkg@^0.5.0:
version "0.5.1"
resolved "https://registry.yarnpkg.com/local-pkg/-/local-pkg-0.5.1.tgz#69658638d2a95287534d4c2fff757980100dbb6d"
integrity sha512-9rrA30MRRP3gBD3HTGnC6cDFpaE1kVDWxWgqWJUN0RvDNAo+Nz/9GxB+nHOH0ifbVFy0hSA1V6vFDvnx54lTEQ==
dependencies:
mlly "^1.7.3"
pkg-types "^1.2.1"
local-pkg@^1.0.0, local-pkg@^1.1.1, local-pkg@^1.1.2: local-pkg@^1.0.0, local-pkg@^1.1.1, local-pkg@^1.1.2:
version "1.1.2" version "1.1.2"
resolved "https://registry.yarnpkg.com/local-pkg/-/local-pkg-1.1.2.tgz#c03d208787126445303f8161619dc701afa4abb5" resolved "https://registry.yarnpkg.com/local-pkg/-/local-pkg-1.1.2.tgz#c03d208787126445303f8161619dc701afa4abb5"
@ -6139,7 +6163,7 @@ mkdirp-classic@^0.5.2, mkdirp-classic@^0.5.3:
resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113"
integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==
mlly@^1.3.0, mlly@^1.7.1, mlly@^1.7.2, mlly@^1.7.4, mlly@^1.8.0: mlly@^1.3.0, mlly@^1.7.1, mlly@^1.7.2, mlly@^1.7.3, mlly@^1.7.4, mlly@^1.8.0:
version "1.8.0" version "1.8.0"
resolved "https://registry.yarnpkg.com/mlly/-/mlly-1.8.0.tgz#e074612b938af8eba1eaf43299cbc89cb72d824e" resolved "https://registry.yarnpkg.com/mlly/-/mlly-1.8.0.tgz#e074612b938af8eba1eaf43299cbc89cb72d824e"
integrity sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g== integrity sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==
@ -8197,6 +8221,11 @@ type-check@^0.4.0, type-check@~0.4.0:
dependencies: dependencies:
prelude-ls "^1.2.1" prelude-ls "^1.2.1"
type-fest@^4.8.3:
version "4.41.0"
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-4.41.0.tgz#6ae1c8e5731273c2bf1f58ad39cbae2c91a46c58"
integrity sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==
type-fest@^5.0.0: type-fest@^5.0.0:
version "5.1.0" version "5.1.0"
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-5.1.0.tgz#30ba6dc2acde4f73732417031f8ac19a0afcb5b7" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-5.1.0.tgz#30ba6dc2acde4f73732417031f8ac19a0afcb5b7"
@ -8516,6 +8545,14 @@ vaul-vue@0.4.1:
reka-ui "^2.0.0" reka-ui "^2.0.0"
vue "^3.4.5" vue "^3.4.5"
vee-validate@4.15.1:
version "4.15.1"
resolved "https://registry.yarnpkg.com/vee-validate/-/vee-validate-4.15.1.tgz#66e787e88916baa05f42e53bc0848e0878d50f91"
integrity sha512-DkFsiTwEKau8VIxyZBGdO6tOudD+QoUBPuHj3e6QFqmbfCRj1ArmYWue9lEp6jLSWBIw4XPlDLjFIZNLdRAMSg==
dependencies:
"@vue/devtools-api" "^7.5.2"
type-fest "^4.8.3"
vite-dev-rpc@^1.1.0: vite-dev-rpc@^1.1.0:
version "1.1.0" version "1.1.0"
resolved "https://registry.yarnpkg.com/vite-dev-rpc/-/vite-dev-rpc-1.1.0.tgz#a54be63cc4dbb127bce1360e4b12d9038087c204" resolved "https://registry.yarnpkg.com/vite-dev-rpc/-/vite-dev-rpc-1.1.0.tgz#a54be63cc4dbb127bce1360e4b12d9038087c204"