Add delivery addresses to profile, cart, and orders
This commit is contained in:
@@ -1,11 +1,19 @@
|
||||
<script setup lang="ts">
|
||||
import { useMutation } from '@vue/apollo-composable';
|
||||
import { SubmitCalculationOrderDocument } from '~/composables/graphql/generated';
|
||||
import { useMutation, useQuery } from '@vue/apollo-composable';
|
||||
import {
|
||||
MyDeliveryAddressesDocument,
|
||||
SubmitCalculationOrderDocument,
|
||||
type MyDeliveryAddressesQuery,
|
||||
} from '~/composables/graphql/generated';
|
||||
import { useClientCart } from '~/composables/useClientCart';
|
||||
import { useCounterpartyProfile } from '~/composables/useCounterpartyProfile';
|
||||
|
||||
type DeliveryAddressItem = MyDeliveryAddressesQuery['myDeliveryAddresses'][number];
|
||||
|
||||
const { isComplete: isCounterpartyComplete, loading: counterpartyLoading } = useCounterpartyProfile();
|
||||
const submitMutation = useMutation(SubmitCalculationOrderDocument, { throws: 'never' });
|
||||
const deliveryAddressesQuery = useQuery(MyDeliveryAddressesDocument);
|
||||
|
||||
const {
|
||||
items: cartItems,
|
||||
totalPositions,
|
||||
@@ -16,10 +24,34 @@ const {
|
||||
removeProduct,
|
||||
clearCart,
|
||||
} = useClientCart();
|
||||
|
||||
const selectedDeliveryAddressId = ref('');
|
||||
const sending = ref(false);
|
||||
const success = ref('');
|
||||
const errorMessage = ref('');
|
||||
|
||||
const deliveryAddresses = computed<DeliveryAddressItem[]>(() => deliveryAddressesQuery.result.value?.myDeliveryAddresses ?? []);
|
||||
const hasDeliveryAddresses = computed(() => deliveryAddresses.value.length > 0);
|
||||
|
||||
watch(
|
||||
deliveryAddresses,
|
||||
(addresses) => {
|
||||
if (addresses.length < 1) {
|
||||
selectedDeliveryAddressId.value = '';
|
||||
return;
|
||||
}
|
||||
|
||||
const hasCurrentSelection = addresses.some((address) => address.id === selectedDeliveryAddressId.value);
|
||||
if (hasCurrentSelection) {
|
||||
return;
|
||||
}
|
||||
|
||||
const defaultAddress = addresses.find((address) => address.isDefault);
|
||||
selectedDeliveryAddressId.value = defaultAddress?.id || addresses[0]?.id || '';
|
||||
},
|
||||
{ immediate: true },
|
||||
);
|
||||
|
||||
function lineVolume(productId: string) {
|
||||
const item = cartItems.value.find((entry) => entry.productId === productId);
|
||||
if (!item) {
|
||||
@@ -56,6 +88,11 @@ async function submitCart() {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!selectedDeliveryAddressId.value) {
|
||||
errorMessage.value = 'Выберите адрес доставки в профиле.';
|
||||
return;
|
||||
}
|
||||
|
||||
if (cartItems.value.length < 1) {
|
||||
errorMessage.value = 'Добавьте хотя бы одну позицию в корзину.';
|
||||
return;
|
||||
@@ -74,6 +111,7 @@ async function submitCart() {
|
||||
thickness: Number(item.parameters.thickness),
|
||||
color: item.parameters.color,
|
||||
},
|
||||
deliveryAddressId: selectedDeliveryAddressId.value,
|
||||
},
|
||||
});
|
||||
|
||||
@@ -97,7 +135,7 @@ async function submitCart() {
|
||||
<section class="space-y-6">
|
||||
<h1 class="text-3xl font-extrabold text-[#0f2f20]">Корзина</h1>
|
||||
|
||||
<div v-if="counterpartyLoading.value" class="alert surface-card border-0">
|
||||
<div v-if="counterpartyLoading" class="alert surface-card border-0">
|
||||
Проверяем карточку контрагента...
|
||||
</div>
|
||||
<div v-else-if="!isCounterpartyComplete" class="alert alert-warning">
|
||||
@@ -105,6 +143,40 @@ async function submitCart() {
|
||||
<NuxtLink to="/profile" class="link link-hover font-semibold">профиле</NuxtLink>.
|
||||
</div>
|
||||
|
||||
<div class="surface-card rounded-3xl p-4 md:p-5">
|
||||
<h2 class="text-lg font-bold text-[#123824]">Адрес доставки</h2>
|
||||
|
||||
<div v-if="deliveryAddressesQuery.loading" class="alert mt-3 surface-card border-0">
|
||||
Загружаем адреса...
|
||||
</div>
|
||||
<div v-else-if="!hasDeliveryAddresses" class="alert alert-warning mt-3">
|
||||
Адреса не добавлены.
|
||||
<NuxtLink to="/profile" class="link link-hover font-semibold">Добавить адрес в профиле</NuxtLink>
|
||||
</div>
|
||||
<div v-else class="mt-3 space-y-2">
|
||||
<label
|
||||
v-for="address in deliveryAddresses"
|
||||
:key="address.id"
|
||||
class="flex cursor-pointer items-start gap-3 rounded-2xl border border-[#d6ebde] bg-white/75 p-3"
|
||||
>
|
||||
<input
|
||||
v-model="selectedDeliveryAddressId"
|
||||
type="radio"
|
||||
name="delivery-address"
|
||||
class="radio radio-success mt-1"
|
||||
:value="address.id"
|
||||
>
|
||||
<span>
|
||||
<span class="block font-semibold text-[#123824]">
|
||||
{{ address.label || 'Адрес доставки' }}
|
||||
<span v-if="address.isDefault" class="badge badge-success ml-2">Основной</span>
|
||||
</span>
|
||||
<span class="block text-sm text-[#355947]">{{ address.unrestrictedValue || address.address }}</span>
|
||||
</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h2 class="text-xl font-bold text-[#123824]">Позиции</h2>
|
||||
|
||||
<div v-if="cartItems.length === 0" class="alert surface-card border-0">
|
||||
@@ -155,7 +227,7 @@ async function submitCart() {
|
||||
|
||||
<button
|
||||
class="btn w-full border-0 bg-[#139957] text-white hover:bg-[#0d854a]"
|
||||
:disabled="sending || counterpartyLoading.value || !isCounterpartyComplete || cartItems.length === 0"
|
||||
:disabled="sending || counterpartyLoading || !isCounterpartyComplete || !selectedDeliveryAddressId || cartItems.length === 0"
|
||||
@click="submitCart"
|
||||
>
|
||||
{{ sending ? 'Отправляем…' : 'Оформить заявку' }}
|
||||
|
||||
Reference in New Issue
Block a user