Create order

This commit is contained in:
hamid zarghami
2026-06-23 12:31:39 +03:30
parent f83d0743c6
commit 7130c304c5
12 changed files with 247 additions and 119 deletions
+104 -57
View File
@@ -4,7 +4,7 @@ import * as Yup from 'yup'
import { toast } from 'react-toastify'
import { useNavigate } from 'react-router-dom'
import { useCreateOrder } from './useOrderData'
import { useCreateUser } from '@/pages/customers/hooks/useUsersData'
import { useCreateUser, useCreateUserAddress } from '@/pages/customers/hooks/useUsersData'
import { useGetFoods } from '@/pages/food/hooks/useFoodData'
import { useGetRestaurantShipmentMethods } from '@/pages/shipmentMethod/hooks/useShipmentMethodData'
import { useGetRestaurantPaymentMethods } from '@/pages/paymentMethods/hooks/usePaymentMethodData'
@@ -21,6 +21,7 @@ import type { RestaurantShipmentMethod } from '@/pages/shipmentMethod/types/Type
import type { RestaurantPaymentMethod } from '@/pages/paymentMethods/types/Types'
import type { UserSavedAddress, UserWithAddresses } from '@/pages/customers/types/Types'
import { mapSavedAddressToOrderAddress } from '../utils/mapSavedAddress'
import { mapFormAddressToCreateUserAddress } from '../utils/mapFormAddressToCreateUserAddress'
import { Pages } from '@/config/Pages'
import type { ErrorType } from '@/helpers/types'
import { extractErrorMessage } from '@/config/func'
@@ -40,10 +41,8 @@ export interface CreateOrderFormValues {
}
const emptyUserAddress = (): CreateOrderUserAddress => ({
fullName: '',
title: '',
phone: '',
city: '',
province: '',
address: '',
postalCode: '',
latitude: 0,
@@ -66,7 +65,10 @@ export const useCreateOrderForm = () => {
const navigate = useNavigate()
const { mutate: createOrder, isPending: isCreating } = useCreateOrder()
const { mutateAsync: createUser, isPending: isCreatingUser } = useCreateUser()
const { mutateAsync: createUserAddress, isPending: isCreatingAddress } =
useCreateUserAddress()
const [customerAddresses, setCustomerAddresses] = useState<UserSavedAddress[]>([])
const [customerUserId, setCustomerUserId] = useState<string | null>(null)
const [selectedAddressId, setSelectedAddressId] = useState<string | null>(null)
const [isNewCustomer, setIsNewCustomer] = useState(false)
@@ -126,16 +128,14 @@ export const useCreateOrderForm = () => {
if (selectedDelivery?.method === DeliveryMethodEnum.DeliveryCourier) {
const address = values.userAddress
if (
!address.fullName ||
!address.phone ||
!address.city ||
!address.province ||
!address.address
) {
if (!address.title || !address.phone || !address.address) {
toast.error('لطفاً آدرس تحویل را کامل کنید')
return
}
if (!address.latitude || !address.longitude) {
toast.error('لطفاً موقعیت روی نقشه را انتخاب کنید')
return
}
}
if (selectedDelivery?.method === DeliveryMethodEnum.DeliveryCar) {
@@ -146,11 +146,17 @@ export const useCreateOrderForm = () => {
}
}
const submitOrder = () => {
if (
selectedDelivery?.method === DeliveryMethodEnum.DineIn &&
!values.tableNumber.trim()
) {
toast.error('لطفاً شماره میز را وارد کنید')
return
}
const submitOrder = (userId: string, addressId?: string) => {
const payload: CreateOrderType = {
userPhone: values.userPhone,
firstName: values.firstName,
lastName: values.lastName,
userId,
items: values.items,
deliveryMethodId: values.deliveryMethodId,
paymentMethodId: values.paymentMethodId,
@@ -160,16 +166,15 @@ export const useCreateOrderForm = () => {
payload.description = values.description.trim()
}
if (values.tableNumber.trim()) {
if (
selectedDelivery?.method === DeliveryMethodEnum.DineIn &&
values.tableNumber.trim()
) {
payload.tableNumber = values.tableNumber.trim()
}
if (selectedDelivery?.method === DeliveryMethodEnum.DeliveryCourier) {
payload.userAddress = {
...values.userAddress,
latitude: Number(values.userAddress.latitude) || 0,
longitude: Number(values.userAddress.longitude) || 0,
}
if (selectedDelivery?.method === DeliveryMethodEnum.DeliveryCourier && addressId) {
payload.addressId = addressId
}
if (selectedDelivery?.method === DeliveryMethodEnum.DeliveryCar) {
@@ -192,20 +197,66 @@ export const useCreateOrderForm = () => {
})
}
const registerNewCustomer = async () => {
const registerNewCustomer = async (): Promise<string | null> => {
if (!isNewCustomer) {
submitOrder()
return
return customerUserId
}
const response = await createUser({
phone: values.userPhone.trim(),
firstName: values.firstName.trim(),
lastName: values.lastName.trim(),
})
const userId = response.data.user.id
setCustomerUserId(userId)
setIsNewCustomer(false)
return userId
}
const resolveAddressId = async (userId: string): Promise<string | undefined> => {
if (selectedDelivery?.method !== DeliveryMethodEnum.DeliveryCourier) {
return undefined
}
if (selectedAddressId) {
return selectedAddressId
}
const response = await createUserAddress({
userId,
...mapFormAddressToCreateUserAddress(
values.userAddress,
customerAddresses.length === 0
),
})
return response.data.id
}
const submitFlow = async () => {
try {
await createUser({
phone: values.userPhone.trim(),
firstName: values.firstName.trim(),
lastName: values.lastName.trim(),
})
setIsNewCustomer(false)
submitOrder()
const userId = await registerNewCustomer()
if (!userId) {
toast.error('کاربر انتخاب نشده است')
return
}
let addressId: string | undefined
try {
addressId = await resolveAddressId(userId)
} catch (error) {
toast.error(extractErrorMessage(error as ErrorType, 'خطا در ثبت آدرس'))
return
}
if (
selectedDelivery?.method === DeliveryMethodEnum.DeliveryCourier &&
!addressId
) {
toast.error('لطفاً آدرس تحویل را انتخاب کنید')
return
}
submitOrder(userId, addressId)
} catch (error) {
toast.error(extractErrorMessage(error as ErrorType, 'خطا در ثبت مشتری'))
}
@@ -216,42 +267,30 @@ export const useCreateOrderForm = () => {
return
}
await registerNewCustomer()
await submitFlow()
},
})
const getCustomerFullName = useCallback(
(firstName?: string, lastName?: string) =>
[firstName ?? formik.values.firstName, lastName ?? formik.values.lastName]
.filter(Boolean)
.join(' '),
// eslint-disable-next-line react-hooks/exhaustive-deps
[formik.values.firstName, formik.values.lastName]
)
const applySavedAddress = useCallback(
(address: UserSavedAddress, fullName?: string) => {
formik.setFieldValue(
'userAddress',
mapSavedAddressToOrderAddress(address, fullName ?? getCustomerFullName())
)
(address: UserSavedAddress) => {
formik.setFieldValue('userAddress', mapSavedAddressToOrderAddress(address))
setSelectedAddressId(address.id)
},
[formik, getCustomerFullName]
[formik]
)
const selectManualAddress = useCallback(() => {
setSelectedAddressId(null)
formik.setFieldValue('userAddress', {
...emptyUserAddress(),
fullName: getCustomerFullName(),
phone: formik.values.userPhone,
})
}, [formik, getCustomerFullName])
}, [formik])
const handleUserFound = useCallback(
(user: UserWithAddresses) => {
setIsNewCustomer(false)
setCustomerUserId(user.id)
const addresses = user.addresses ?? []
setCustomerAddresses(addresses)
@@ -259,7 +298,6 @@ export const useCreateOrderForm = () => {
setSelectedAddressId(null)
formik.setFieldValue('userAddress', {
...emptyUserAddress(),
fullName: getCustomerFullName(user.firstName, user.lastName),
phone: user.phone || formik.values.userPhone,
})
return
@@ -267,22 +305,21 @@ export const useCreateOrderForm = () => {
const defaultAddress =
addresses.find((address) => address.isDefault) ?? addresses[0]
applySavedAddress(
defaultAddress,
[user.firstName, user.lastName].filter(Boolean).join(' ')
)
applySavedAddress(defaultAddress)
},
[applySavedAddress, formik, getCustomerFullName]
[applySavedAddress, formik]
)
const clearCustomerData = useCallback(() => {
setIsNewCustomer(false)
setCustomerUserId(null)
setCustomerAddresses([])
setSelectedAddressId(null)
formik.setFieldValue('userAddress', emptyUserAddress())
}, [formik])
const handleUserNotFound = useCallback(() => {
setCustomerUserId(null)
setCustomerAddresses([])
setSelectedAddressId(null)
formik.setFieldValue('userAddress', emptyUserAddress())
@@ -397,6 +434,15 @@ export const useCreateOrderForm = () => {
[formik]
)
const handleLocationSelect = useCallback(
(lat: number, lng: number) => {
setSelectedAddressId(null)
formik.setFieldValue('userAddress.latitude', lat)
formik.setFieldValue('userAddress.longitude', lng)
},
[formik]
)
const removeItem = (foodId: string) => {
formik.setFieldValue(
'items',
@@ -418,7 +464,7 @@ export const useCreateOrderForm = () => {
addFoodToOrder,
updateItemQuantity,
removeItem,
isSubmitting: isCreating || isCreatingUser,
isSubmitting: isCreating || isCreatingUser || isCreatingAddress,
customerAddresses,
selectedAddressId,
handleUserFound,
@@ -427,6 +473,7 @@ export const useCreateOrderForm = () => {
applySavedAddress,
selectManualAddress,
handleAddressFieldChange,
handleLocationSelect,
}
}