import { useState } from 'react' import Alert from '@mui/material/Alert' import Box from '@mui/material/Box' import Button from '@mui/material/Button' import Chip from '@mui/material/Chip' import Stack from '@mui/material/Stack' import Typography from '@mui/material/Typography' import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query' import { useForm } from 'react-hook-form' import { createMyAddress, deleteMyAddress, fetchMyAddresses, setMyAddressDefault, updateMyAddress, } from '@/entities/user/api/address-api' import type { ShippingAddress } from '@/entities/user/model/types' import { AddressFormDialog, type AddressFormValues } from '@/features/address-form' const defaultAddressForm = (isDefault: boolean): AddressFormValues => ({ label: '', recipientName: '', recipientPhone: '', addressLine: '', comment: '', lat: null, lng: null, isDefault, }) export function AddressesPage() { const queryClient = useQueryClient() const [open, setOpen] = useState(false) const [editing, setEditing] = useState(null) const addressesQuery = useQuery({ queryKey: ['me', 'addresses'], queryFn: fetchMyAddresses, }) const form = useForm({ defaultValues: defaultAddressForm(false), mode: 'onChange', }) const createMut = useMutation({ mutationFn: async () => { const v = form.getValues() if (v.lat === null || v.lng === null) throw new Error('Выберите точку на карте') await createMyAddress({ label: v.label.trim() || null, recipientName: v.recipientName.trim(), recipientPhone: v.recipientPhone.trim(), addressLine: v.addressLine.trim(), comment: v.comment.trim() || null, lat: v.lat, lng: v.lng, isDefault: v.isDefault, }) }, onSuccess: () => { void queryClient.invalidateQueries({ queryKey: ['me', 'addresses'] }) setOpen(false) }, }) const updateMut = useMutation({ mutationFn: async () => { const v = form.getValues() if (v.lat === null || v.lng === null) throw new Error('Выберите точку на карте') await updateMyAddress(editing!.id, { label: v.label.trim() || null, recipientName: v.recipientName.trim(), recipientPhone: v.recipientPhone.trim(), addressLine: v.addressLine.trim(), comment: v.comment.trim() || null, lat: v.lat, lng: v.lng, isDefault: v.isDefault, }) }, onSuccess: () => { void queryClient.invalidateQueries({ queryKey: ['me', 'addresses'] }) setOpen(false) }, }) const deleteMut = useMutation({ mutationFn: (id: string) => deleteMyAddress(id), onSuccess: () => void queryClient.invalidateQueries({ queryKey: ['me', 'addresses'] }), }) const defaultMut = useMutation({ mutationFn: (id: string) => setMyAddressDefault(id), onSuccess: () => void queryClient.invalidateQueries({ queryKey: ['me', 'addresses'] }), }) const error = createMut.error ?? updateMut.error ?? deleteMut.error ?? defaultMut.error const items = addressesQuery.data?.items ?? [] const openCreate = () => { setEditing(null) form.reset(defaultAddressForm(items.length === 0)) setOpen(true) } const openEdit = (a: ShippingAddress) => { setEditing(a) form.reset({ label: a.label ?? '', recipientName: a.recipientName, recipientPhone: a.recipientPhone, addressLine: a.addressLine, comment: a.comment ?? '', lat: a.lat, lng: a.lng, isDefault: a.isDefault, }) setOpen(true) } const handleSubmit = () => { if (editing) updateMut.mutate() else createMut.mutate() } return ( Адреса доставки Можно добавить несколько адресов. Для каждого адреса задаются ФИО и телефон получателя отдельно. {addressesQuery.isError && ( Не удалось загрузить адреса. Проверьте, что вы вошли в аккаунт и сервер запущен. )} {error && ( {(error as Error).message} )} {items.map((a) => ( {a.label?.trim() ? a.label : 'Адрес'} {a.isDefault && } {a.addressLine} Получатель: {a.recipientName} · {a.recipientPhone} {a.comment && ( Комментарий: {a.comment} )} {!a.isDefault && ( )} ))} {addressesQuery.isSuccess && items.length === 0 && ( Адресов пока нет — добавьте первый адрес доставки. )} setOpen(false)} editing={Boolean(editing)} form={form} onSubmit={handleSubmit} isPending={createMut.isPending || updateMut.isPending} /> ) }