base commit

This commit is contained in:
@kirill.komarov
2026-04-30 22:34:55 +05:00
parent 123d86091d
commit 9139a24093
46 changed files with 2023 additions and 153 deletions
+79 -22
View File
@@ -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()}
>