import { useState } from 'react' import Alert from '@mui/material/Alert' import Box from '@mui/material/Box' import Button from '@mui/material/Button' import FormControl from '@mui/material/FormControl' import FormControlLabel from '@mui/material/FormControlLabel' import InputLabel from '@mui/material/InputLabel' import Link from '@mui/material/Link' import MenuItem from '@mui/material/MenuItem' import Radio from '@mui/material/Radio' import RadioGroup from '@mui/material/RadioGroup' import Select from '@mui/material/Select' import Stack from '@mui/material/Stack' import TextField from '@mui/material/TextField' import Typography from '@mui/material/Typography' import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' import { useUnit } from 'effector-react' import { Link as RouterLink, useNavigate } from 'react-router-dom' import { fetchMyCart } from '@/entities/cart/api/cart-api' import { createOrder } from '@/entities/order/api/order-api' import { fetchMyAddresses } from '@/entities/user/api/address-api' import { DELIVERY_CARRIER_OPTIONS, type DeliveryCarrierCode } from '@/shared/constants/delivery-carrier' import { formatPriceRub } from '@/shared/lib/format-price' import { $user } from '@/shared/model/auth' export function CheckoutPage() { const user = useUnit($user) const qc = useQueryClient() const navigate = useNavigate() const [deliveryType, setDeliveryType] = useState<'delivery' | 'pickup'>('delivery') const [pickupPayment, setPickupPayment] = useState<'online' | 'on_pickup'>('online') const [deliveryCarrier, setDeliveryCarrier] = useState('RUSSIAN_POST') const [addressId, setAddressId] = useState('') const [comment, setComment] = useState('') const cartQuery = useQuery({ queryKey: ['me', 'cart'], queryFn: fetchMyCart, enabled: Boolean(user), }) const addressesQuery = useQuery({ queryKey: ['me', 'addresses'], queryFn: fetchMyAddresses, enabled: Boolean(user), }) const defaultAddressId = addressesQuery.data?.items?.find((a) => a.isDefault)?.id ?? '' const selectedAddressId = addressId || defaultAddressId const createMut = useMutation({ mutationFn: () => createOrder({ deliveryType, deliveryCarrier: deliveryType === 'delivery' ? deliveryCarrier : null, paymentMethod: deliveryType === 'delivery' ? 'online' : pickupPayment, addressId: deliveryType === 'delivery' ? selectedAddressId : null, comment: comment.trim() || null, }), onSuccess: async (res) => { await qc.invalidateQueries({ queryKey: ['me', 'cart'] }) navigate(`/me/orders/${res.orderId}`, { replace: true }) }, }) if (!user) { return ( Чтобы оформить заказ, нужно войти. Перейдите на страницу{' '} Вход . ) } const items = cartQuery.data?.items ?? [] const itemsSubtotalCents = items.reduce((s, x) => s + x.product.priceCents * x.qty, 0) const deliveryFeeCents = deliveryType === 'delivery' && items.length > 0 ? 50000 : 0 const total = itemsSubtotalCents + deliveryFeeCents const addresses = addressesQuery.data?.items ?? [] const hasOverLimit = items.some((x) => x.qty > x.product.quantity) return ( Оформление заказа {cartQuery.isSuccess && items.length === 0 && ( Корзина пуста. Вернитесь в{' '} каталог . )} {items.length > 0 && ( Позиции {items.map((x) => { const available = x.product.quantity const over = x.qty > available return ( {x.product.title}: {x.qty} шт. (доступно {available}) ) })} )} {hasOverLimit && ( Некоторые позиции превышают доступное количество. Вернитесь в{' '} корзину {' '} и скорректируйте количество. )} Способ получения {deliveryType === 'delivery' && ( <> Служба доставки { const v = String(e.target.value) as DeliveryCarrierCode setDeliveryCarrier(v) }} > {DELIVERY_CARRIER_OPTIONS.map((o) => ( } label={o.label} /> ))} Адрес доставки {addresses.length === 0 && ( У вас нет адресов доставки. Добавьте адрес в{' '} кабинете . )} Стоимость доставки ориентировочно 300 ₽. Точная цена будет скорректирована после расчёта. В сумме заказа сейчас заложено {items.length > 0 ? formatPriceRub(deliveryFeeCents) : '500 ₽'} до уточнения. )} {deliveryType === 'pickup' && ( <> Самовывоз: адрес доставки не нужен. Адрес точки выдачи указан на странице{' '} О нас . Оплата { const v = String(e.target.value) if (v === 'online' || v === 'on_pickup') setPickupPayment(v) }} > } label="Онлайн-оплата" /> } label="Оплатить при получении" /> {pickupPayment === 'on_pickup' && ( Оплатите заказ наличными или картой при выдаче на самовывозе. )} )} setComment(e.target.value)} fullWidth multiline minRows={2} /> Товары: {formatPriceRub(itemsSubtotalCents)} {deliveryType === 'delivery' && ( Доставка: {formatPriceRub(deliveryFeeCents)} )} Итого: {formatPriceRub(total)} {createMut.isError && {(createMut.error as Error).message}} ) }