base commit
This commit is contained in:
@@ -22,6 +22,7 @@ export function CheckoutPage() {
|
||||
const user = useUnit($user)
|
||||
const qc = useQueryClient()
|
||||
const navigate = useNavigate()
|
||||
const [deliveryType, setDeliveryType] = useState<'delivery' | 'pickup'>('delivery')
|
||||
const [addressId, setAddressId] = useState('')
|
||||
const [comment, setComment] = useState('')
|
||||
|
||||
@@ -41,7 +42,12 @@ export function CheckoutPage() {
|
||||
const selectedAddressId = addressId || defaultAddressId
|
||||
|
||||
const createMut = useMutation({
|
||||
mutationFn: () => createOrder({ addressId: selectedAddressId, comment: comment.trim() || null }),
|
||||
mutationFn: () =>
|
||||
createOrder({
|
||||
deliveryType,
|
||||
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 })
|
||||
@@ -61,7 +67,11 @@ export function CheckoutPage() {
|
||||
}
|
||||
|
||||
const items = cartQuery.data?.items ?? []
|
||||
const total = items.reduce((s, x) => s + x.product.priceCents * x.qty, 0)
|
||||
const itemsSubtotalCents = items.reduce((s, x) => s + x.product.priceCents * x.qty, 0)
|
||||
const totalQty = items.reduce((s, x) => s + x.qty, 0)
|
||||
const deliveryFeeCents =
|
||||
deliveryType === 'delivery' && items.length > 0 ? 50000 * Math.max(1, Math.ceil(totalQty / 2)) : 0
|
||||
const total = itemsSubtotalCents + deliveryFeeCents
|
||||
const addresses = addressesQuery.data?.items ?? []
|
||||
const hasOverLimit = items.some((x) => x.qty > (x.product.inStock ? x.product.quantity : 1))
|
||||
const hasMadeToOrder = items.some((x) => !x.product.inStock)
|
||||
@@ -117,29 +127,63 @@ export function CheckoutPage() {
|
||||
)}
|
||||
|
||||
<FormControl size="small" fullWidth>
|
||||
<InputLabel id="addr-label">Адрес доставки</InputLabel>
|
||||
<InputLabel id="delivery-type-label">Способ получения</InputLabel>
|
||||
<Select
|
||||
labelId="addr-label"
|
||||
label="Адрес доставки"
|
||||
value={selectedAddressId}
|
||||
onChange={(e) => setAddressId(String(e.target.value))}
|
||||
labelId="delivery-type-label"
|
||||
label="Способ получения"
|
||||
value={deliveryType}
|
||||
onChange={(e) => {
|
||||
const v = String(e.target.value)
|
||||
if (v === 'delivery' || v === 'pickup') setDeliveryType(v)
|
||||
}}
|
||||
>
|
||||
{addresses.map((a) => (
|
||||
<MenuItem key={a.id} value={a.id}>
|
||||
{(a.label?.trim() ? `${a.label}: ` : '') + a.addressLine}
|
||||
</MenuItem>
|
||||
))}
|
||||
<MenuItem value="delivery">Доставка</MenuItem>
|
||||
<MenuItem value="pickup">Самовывоз</MenuItem>
|
||||
</Select>
|
||||
</FormControl>
|
||||
|
||||
{addresses.length === 0 && (
|
||||
<Alert severity="warning">
|
||||
У вас нет адресов доставки. Добавьте адрес в{' '}
|
||||
<Typography component={RouterLink} to="/me/addresses" sx={{ textDecoration: 'underline' }}>
|
||||
кабинете
|
||||
</Typography>
|
||||
.
|
||||
</Alert>
|
||||
{deliveryType === 'delivery' && (
|
||||
<>
|
||||
<FormControl size="small" fullWidth>
|
||||
<InputLabel id="addr-label">Адрес доставки</InputLabel>
|
||||
<Select
|
||||
labelId="addr-label"
|
||||
label="Адрес доставки"
|
||||
value={selectedAddressId}
|
||||
onChange={(e) => setAddressId(String(e.target.value))}
|
||||
>
|
||||
{addresses.map((a) => (
|
||||
<MenuItem key={a.id} value={a.id}>
|
||||
{(a.label?.trim() ? `${a.label}: ` : '') + a.addressLine}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Select>
|
||||
</FormControl>
|
||||
|
||||
{addresses.length === 0 && (
|
||||
<Alert severity="warning">
|
||||
У вас нет адресов доставки. Добавьте адрес в{' '}
|
||||
<Typography component={RouterLink} to="/me/addresses" sx={{ textDecoration: 'underline' }}>
|
||||
кабинете
|
||||
</Typography>
|
||||
.
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
<Alert severity="info">
|
||||
Стоимость доставки: 500 ₽ за каждые 2 единицы (минимум 500 ₽).
|
||||
{items.length > 0 && (
|
||||
<>
|
||||
{' '}
|
||||
В этом заказе: {totalQty} шт. → доставка {formatPriceRub(deliveryFeeCents)}.
|
||||
</>
|
||||
)}
|
||||
</Alert>
|
||||
</>
|
||||
)}
|
||||
|
||||
{deliveryType === 'pickup' && (
|
||||
<Alert severity="info">Самовывоз: адрес доставки не нужен. Мы свяжемся с вами для согласования.</Alert>
|
||||
)}
|
||||
|
||||
<TextField
|
||||
@@ -151,12 +195,25 @@ export function CheckoutPage() {
|
||||
minRows={2}
|
||||
/>
|
||||
|
||||
<Typography variant="h6">Итого: {formatPriceRub(total)}</Typography>
|
||||
<Stack spacing={0.25}>
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
Товары: {formatPriceRub(itemsSubtotalCents)}
|
||||
</Typography>
|
||||
{deliveryType === 'delivery' && (
|
||||
<Typography variant="body2" color="text.secondary">
|
||||
Доставка: {formatPriceRub(deliveryFeeCents)}
|
||||
</Typography>
|
||||
)}
|
||||
<Typography variant="h6">Итого: {formatPriceRub(total)}</Typography>
|
||||
</Stack>
|
||||
|
||||
<Button
|
||||
variant="contained"
|
||||
disabled={
|
||||
items.length === 0 || addresses.length === 0 || !selectedAddressId || hasOverLimit || createMut.isPending
|
||||
items.length === 0 ||
|
||||
hasOverLimit ||
|
||||
createMut.isPending ||
|
||||
(deliveryType === 'delivery' && (addresses.length === 0 || !selectedAddressId))
|
||||
}
|
||||
onClick={() => createMut.mutate()}
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user