This commit is contained in:
parent
887ea75e8b
commit
2b8a5e5774
@ -15,6 +15,8 @@ ENV BSPB_MERCHANT_ID=TT00001
|
||||
ENV BSPB_MERCHANT_PASSWORD=ztTGre1OBZg3
|
||||
ENV BSPB_API_URL=https://pgtest.bspb.ru:5443
|
||||
|
||||
ENV VITE_BASE_URL=https://paxton.koptilnya.xyz
|
||||
|
||||
EXPOSE 80
|
||||
|
||||
CMD ["node", "/app/server/index.mjs"]
|
||||
|
||||
44
components/cart/SummaryCartItem.vue
Normal file
44
components/cart/SummaryCartItem.vue
Normal 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>
|
||||
@ -1,9 +1,15 @@
|
||||
import { createSharedComposable } from '@vueuse/core'
|
||||
import { createSharedComposable, useStorage } from '@vueuse/core'
|
||||
|
||||
export const useCheckout = createSharedComposable(() => {
|
||||
const router = useRouter()
|
||||
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 = [
|
||||
{
|
||||
step: 1,
|
||||
@ -41,6 +47,9 @@ export const useCheckout = createSharedComposable(() => {
|
||||
}
|
||||
|
||||
return {
|
||||
contacts,
|
||||
setContacts,
|
||||
|
||||
checkoutSteps,
|
||||
currentCheckoutStep,
|
||||
|
||||
|
||||
@ -3,7 +3,19 @@ export default defineNuxtConfig({
|
||||
ssr: true,
|
||||
compatibilityDate: '2025-05-15',
|
||||
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'],
|
||||
i18n: {
|
||||
locales: [
|
||||
|
||||
@ -20,6 +20,7 @@
|
||||
"@nuxtjs/i18n": "^10.0.4",
|
||||
"@tanstack/vue-query": "^5.75.5",
|
||||
"@tanstack/vue-query-devtools": "^5.87.1",
|
||||
"@vee-validate/nuxt": "^4.15.1",
|
||||
"@vueuse/core": "^13.1.0",
|
||||
"axios": "^1.12.2",
|
||||
"dayjs": "^1.11.13",
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
<template>
|
||||
<div class="cart">
|
||||
</pre>
|
||||
<div class="cart__items">
|
||||
<div
|
||||
v-for="cartItem in cart?.line_items"
|
||||
|
||||
@ -1,11 +1,20 @@
|
||||
<template>
|
||||
<div class="contacts">
|
||||
<form class="contacts" @submit.prevent="onSubmit">
|
||||
<div>
|
||||
<UInput
|
||||
id="name"
|
||||
v-model="name"
|
||||
v-bind="nameAttrs"
|
||||
name="name"
|
||||
size="xl"
|
||||
placeholder=" "
|
||||
:ui="{ base: 'peer' }"
|
||||
class="relative"
|
||||
:invalid="Boolean(errors.name)"
|
||||
:help="errors.name"
|
||||
class="relative w-100"
|
||||
:color="errors.name ? 'error' : 'neutral'"
|
||||
highlight
|
||||
autofocus
|
||||
>
|
||||
<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="[
|
||||
@ -18,12 +27,25 @@
|
||||
</label>
|
||||
</UInput>
|
||||
|
||||
<div v-if="errors?.name" style="color: #ff6467">
|
||||
{{ errors?.name }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<UInput
|
||||
id="surname"
|
||||
v-model="surname"
|
||||
v-bind="surnameAttrs"
|
||||
name="surname"
|
||||
size="xl"
|
||||
placeholder=" "
|
||||
:ui="{ base: 'peer' }"
|
||||
class="relative"
|
||||
:invalid="Boolean(errors.surname)"
|
||||
:help="errors.surname"
|
||||
class="relative w-100"
|
||||
:color="errors.surname ? '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="[
|
||||
@ -36,13 +58,26 @@
|
||||
</label>
|
||||
</UInput>
|
||||
|
||||
<div v-if="errors?.surname" style="color: #ff6467">
|
||||
{{ errors?.surname }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<UInput
|
||||
id="phone"
|
||||
v-model="phone"
|
||||
v-bind="phoneAttrs"
|
||||
v-maska="'+7 (###) ###-##-##'"
|
||||
name="phone"
|
||||
size="xl"
|
||||
placeholder=" "
|
||||
:ui="{ base: 'peer' }"
|
||||
class="relative"
|
||||
:invalid="Boolean(errors.phone)"
|
||||
:help="errors.phone"
|
||||
class="relative w-100"
|
||||
:color="errors.phone ? '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="[
|
||||
@ -55,13 +90,26 @@
|
||||
</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"
|
||||
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="[
|
||||
@ -74,24 +122,76 @@
|
||||
</label>
|
||||
</UInput>
|
||||
|
||||
<div v-if="errors?.email" style="color: #ff6467">
|
||||
{{ errors?.email }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<UButton
|
||||
size="xl"
|
||||
label="продолжить"
|
||||
class="justify-center text-center"
|
||||
@click="nextStep"
|
||||
type="submit"
|
||||
:disabled="errors && Object.keys(errors).length > 0"
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { useCheckout } from '../../composables/useCheckout'
|
||||
|
||||
const name = ref('')
|
||||
const surname = ref('')
|
||||
const phone = ref('')
|
||||
const email = ref('')
|
||||
const { setContacts, nextStep } = useCheckout()
|
||||
|
||||
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({
|
||||
layout: 'checkout',
|
||||
|
||||
@ -1,12 +1,119 @@
|
||||
<template>
|
||||
<div class="summary">
|
||||
<div class="summary__info">
|
||||
<h3>в заказе • {{ 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>
|
||||
|
||||
<script setup lang="ts">
|
||||
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 { 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}`
|
||||
window.open(redirectUrl, '_blank')
|
||||
@ -17,6 +124,27 @@ definePageMeta({
|
||||
})
|
||||
</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>
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import https from 'node:https'
|
||||
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 merchantPassword = process.env.BSPB_MERCHANT_PASSWORD!
|
||||
const apiUrl = process.env.BSPB_API_URL!
|
||||
@ -18,18 +18,9 @@ export default defineEventHandler(async () => {
|
||||
rejectUnauthorized: false,
|
||||
})
|
||||
|
||||
const data = {
|
||||
order: {
|
||||
typeRid: 'Purchase',
|
||||
amount: 100,
|
||||
currency: 'RUB',
|
||||
title: 'Название заказа',
|
||||
description: 'Описание заказа',
|
||||
hppRedirectUrl: 'http://localhost:3000/cart',
|
||||
},
|
||||
}
|
||||
const orderData = await readBody(event)
|
||||
|
||||
const response = await axios.post(`${apiUrl}/order`, data, {
|
||||
const response = await axios.post(`${apiUrl}/order`, orderData, {
|
||||
httpsAgent: agent,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
|
||||
39
yarn.lock
39
yarn.lock
@ -2500,6 +2500,15 @@
|
||||
hookable "^5.5.3"
|
||||
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":
|
||||
version "0.30.3"
|
||||
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"
|
||||
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":
|
||||
version "7.7.7"
|
||||
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"
|
||||
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:
|
||||
version "1.1.2"
|
||||
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"
|
||||
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"
|
||||
resolved "https://registry.yarnpkg.com/mlly/-/mlly-1.8.0.tgz#e074612b938af8eba1eaf43299cbc89cb72d824e"
|
||||
integrity sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g==
|
||||
@ -8197,6 +8221,11 @@ type-check@^0.4.0, type-check@~0.4.0:
|
||||
dependencies:
|
||||
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:
|
||||
version "5.1.0"
|
||||
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"
|
||||
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:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/vite-dev-rpc/-/vite-dev-rpc-1.1.0.tgz#a54be63cc4dbb127bce1360e4b12d9038087c204"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user