This commit is contained in:
@@ -0,0 +1,335 @@
|
||||
import { type FC, useState } from 'react'
|
||||
import type { FormikProps } from 'formik'
|
||||
import { Edit2, Location } from 'iconsax-react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import Button from '@/components/Button'
|
||||
import Input from '@/components/Input'
|
||||
import RadioGroup from '@/components/RadioGroup'
|
||||
import Textarea from '@/components/Textarea'
|
||||
import DefaulModal from '@/components/DefaulModal'
|
||||
import LocationInput from '@/pages/settings/components/LocationInput'
|
||||
import LocationPicker from '@/pages/settings/components/LocationPicker'
|
||||
import { formatPrice } from '@/helpers/func'
|
||||
import type { CreateOrderFormValues } from '../hooks/useCreateOrderForm'
|
||||
import type { RestaurantPaymentMethod, RestaurantShipmentMethod } from '../hooks/useCreateOrderForm'
|
||||
import type { UserSavedAddress } from '@/pages/customers/types/Types'
|
||||
import CreateOrderAddressSelector from './CreateOrderAddressSelector'
|
||||
|
||||
interface CreateOrderDeliveryModalProps {
|
||||
open: boolean
|
||||
onClose: () => void
|
||||
formik: FormikProps<CreateOrderFormValues>
|
||||
deliveryMethods: RestaurantShipmentMethod[]
|
||||
cashPaymentMethod?: RestaurantPaymentMethod
|
||||
isCourierDelivery: boolean
|
||||
isCarDelivery: boolean
|
||||
isDineIn: boolean
|
||||
customerAddresses: UserSavedAddress[]
|
||||
selectedAddressId: string | null
|
||||
onSelectSavedAddress: (address: UserSavedAddress) => void
|
||||
onSelectManualAddress: () => void
|
||||
onAddressFieldChange: (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => void
|
||||
onLocationSelect: (lat: number, lng: number) => void
|
||||
}
|
||||
|
||||
const CreateOrderDeliveryModal: FC<CreateOrderDeliveryModalProps> = ({
|
||||
open,
|
||||
onClose,
|
||||
formik,
|
||||
deliveryMethods,
|
||||
cashPaymentMethod,
|
||||
isCourierDelivery,
|
||||
isCarDelivery,
|
||||
isDineIn,
|
||||
customerAddresses,
|
||||
selectedAddressId,
|
||||
onSelectSavedAddress,
|
||||
onSelectManualAddress,
|
||||
onAddressFieldChange,
|
||||
onLocationSelect,
|
||||
}) => {
|
||||
const { t } = useTranslation('global')
|
||||
const [isAddressModalOpen, setIsAddressModalOpen] = useState(false)
|
||||
const [isLocationModalOpen, setIsLocationModalOpen] = useState(false)
|
||||
|
||||
const getDeliveryLabel = (method: string) => {
|
||||
return t(`shipment.${method}`, { defaultValue: method })
|
||||
}
|
||||
|
||||
const isAddressReadOnly =
|
||||
selectedAddressId !== null && customerAddresses.length > 0
|
||||
|
||||
const handleMapLocationSelect = (lat: number, lng: number) => {
|
||||
onLocationSelect(lat, lng)
|
||||
setIsLocationModalOpen(false)
|
||||
}
|
||||
|
||||
const latitude = formik.values.userAddress.latitude
|
||||
const longitude = formik.values.userAddress.longitude
|
||||
const hasAddress = Boolean(formik.values.userAddress.address?.trim())
|
||||
|
||||
const handleConfirm = () => {
|
||||
formik.setFieldTouched('deliveryMethodId', true, false)
|
||||
onClose()
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<DefaulModal
|
||||
open={open}
|
||||
close={onClose}
|
||||
isHeader={true}
|
||||
title_header='تحویل و پرداخت'
|
||||
width={560}
|
||||
>
|
||||
<div className='p-1 max-h-[70vh] overflow-y-auto'>
|
||||
<div>
|
||||
<div className='text-sm mb-3'>روش تحویل</div>
|
||||
<RadioGroup
|
||||
items={deliveryMethods.map((method) => ({
|
||||
label:
|
||||
method.deliveryFee > 0
|
||||
? `${getDeliveryLabel(method.method)} (${formatPrice(method.deliveryFee)})`
|
||||
: getDeliveryLabel(method.method),
|
||||
value: method.id,
|
||||
}))}
|
||||
selected={formik.values.deliveryMethodId}
|
||||
onChange={(value) => {
|
||||
formik.setFieldValue('deliveryMethodId', value)
|
||||
formik.setFieldTouched('deliveryMethodId', true, false)
|
||||
}}
|
||||
/>
|
||||
{formik.touched.deliveryMethodId && formik.errors.deliveryMethodId && (
|
||||
<div className='text-xs text-red-500 mt-2'>
|
||||
{formik.errors.deliveryMethodId}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className='mt-6'>
|
||||
<div className='text-sm mb-3'>روش پرداخت</div>
|
||||
{cashPaymentMethod ? (
|
||||
<RadioGroup
|
||||
items={[
|
||||
{
|
||||
label: cashPaymentMethod.description
|
||||
? `پرداخت نقدی (${cashPaymentMethod.description})`
|
||||
: 'پرداخت نقدی',
|
||||
value: cashPaymentMethod.id,
|
||||
},
|
||||
]}
|
||||
selected={formik.values.paymentMethodId}
|
||||
onChange={(value) => formik.setFieldValue('paymentMethodId', value)}
|
||||
/>
|
||||
) : (
|
||||
<div className='text-xs text-red-500'>
|
||||
روش پرداخت نقدی فعال یافت نشد
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{isDineIn && (
|
||||
<div className='mt-6'>
|
||||
<Input
|
||||
label='شماره میز'
|
||||
name='tableNumber'
|
||||
placeholder='مثال: ۱۲'
|
||||
value={formik.values.tableNumber}
|
||||
onChange={formik.handleChange}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{isCourierDelivery && (
|
||||
<div className='mt-6 pt-5 border-t border-border border-dashed'>
|
||||
<div className='text-sm mb-3'>آدرس تحویل</div>
|
||||
|
||||
{customerAddresses.length > 0 && (
|
||||
<CreateOrderAddressSelector
|
||||
addresses={customerAddresses}
|
||||
selectedAddressId={selectedAddressId}
|
||||
onSelectAddress={onSelectSavedAddress}
|
||||
onSelectManual={onSelectManualAddress}
|
||||
/>
|
||||
)}
|
||||
|
||||
{hasAddress ? (
|
||||
<div className='flex items-start gap-2 p-3 bg-[#F8F9FC] rounded-xl'>
|
||||
<Location size={16} color='#8C90A3' className='flex-shrink-0 mt-0.5' />
|
||||
<div className='flex-1 min-w-0 text-xs'>
|
||||
{formik.values.userAddress.address}
|
||||
</div>
|
||||
<button
|
||||
type='button'
|
||||
onClick={() => setIsAddressModalOpen(true)}
|
||||
className='flex-shrink-0'
|
||||
>
|
||||
<Edit2 size={16} color='#000' />
|
||||
</button>
|
||||
</div>
|
||||
) : (
|
||||
<Button
|
||||
type='button'
|
||||
className='w-full'
|
||||
onClick={() => setIsAddressModalOpen(true)}
|
||||
>
|
||||
ثبت آدرس تحویل
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{isCarDelivery && (
|
||||
<div className='mt-6 pt-5 border-t border-border border-dashed'>
|
||||
<div className='text-sm mb-3'>اطلاعات خودرو</div>
|
||||
<div className='grid grid-cols-2 gap-4'>
|
||||
<Input
|
||||
label='مدل خودرو'
|
||||
name='carAddress.carModel'
|
||||
value={formik.values.carAddress.carModel}
|
||||
onChange={formik.handleChange}
|
||||
/>
|
||||
<Input
|
||||
label='رنگ خودرو'
|
||||
name='carAddress.carColor'
|
||||
value={formik.values.carAddress.carColor}
|
||||
onChange={formik.handleChange}
|
||||
/>
|
||||
<Input
|
||||
label='پلاک'
|
||||
name='carAddress.plateNumber'
|
||||
value={formik.values.carAddress.plateNumber}
|
||||
onChange={formik.handleChange}
|
||||
/>
|
||||
<Input
|
||||
label='شماره تماس'
|
||||
name='carAddress.phone'
|
||||
value={formik.values.carAddress.phone}
|
||||
onChange={formik.handleChange}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className='mt-6'>
|
||||
<Textarea
|
||||
label='توضیحات سفارش'
|
||||
name='description'
|
||||
placeholder='توضیحات اضافی...'
|
||||
value={formik.values.description}
|
||||
onChange={formik.handleChange}
|
||||
isNotRequired
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className='mt-6 flex justify-end gap-3 sticky bottom-0 bg-white pt-3'>
|
||||
<button
|
||||
type='button'
|
||||
onClick={onClose}
|
||||
className='h-10 px-6 rounded-xl border border-border text-sm hover:bg-[#F8F9FC] transition-colors'
|
||||
>
|
||||
انصراف
|
||||
</button>
|
||||
<Button type='button' className='w-fit px-6' onClick={handleConfirm}>
|
||||
تأیید
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</DefaulModal>
|
||||
|
||||
<DefaulModal
|
||||
open={isAddressModalOpen}
|
||||
close={() => setIsAddressModalOpen(false)}
|
||||
isHeader={true}
|
||||
title_header='آدرس تحویل'
|
||||
width={600}
|
||||
>
|
||||
<div className='p-2'>
|
||||
<CreateOrderAddressSelector
|
||||
addresses={customerAddresses}
|
||||
selectedAddressId={selectedAddressId}
|
||||
onSelectAddress={onSelectSavedAddress}
|
||||
onSelectManual={onSelectManualAddress}
|
||||
/>
|
||||
|
||||
<div className='grid grid-cols-2 gap-3 mt-4'>
|
||||
<Input
|
||||
label='عنوان آدرس'
|
||||
name='userAddress.title'
|
||||
placeholder='مثال: منزل'
|
||||
value={formik.values.userAddress.title}
|
||||
onChange={onAddressFieldChange}
|
||||
readOnly={isAddressReadOnly}
|
||||
/>
|
||||
<Input
|
||||
label='شماره تماس'
|
||||
name='userAddress.phone'
|
||||
value={formik.values.userAddress.phone}
|
||||
onChange={onAddressFieldChange}
|
||||
readOnly={isAddressReadOnly}
|
||||
/>
|
||||
<Input
|
||||
label='کد پستی'
|
||||
name='userAddress.postalCode'
|
||||
value={formik.values.userAddress.postalCode}
|
||||
onChange={onAddressFieldChange}
|
||||
readOnly={isAddressReadOnly}
|
||||
isNotRequired
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className={isAddressReadOnly ? 'pointer-events-none opacity-60' : ''}>
|
||||
<LocationInput
|
||||
label='موقعیت روی نقشه'
|
||||
latitude={latitude || undefined}
|
||||
longitude={longitude || undefined}
|
||||
onClick={() => setIsLocationModalOpen(true)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className='mt-4'>
|
||||
<Textarea
|
||||
label='آدرس کامل'
|
||||
name='userAddress.address'
|
||||
value={formik.values.userAddress.address}
|
||||
onChange={onAddressFieldChange}
|
||||
readOnly={isAddressReadOnly}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className='mt-4 flex justify-end'>
|
||||
<Button
|
||||
type='button'
|
||||
className='w-fit px-6'
|
||||
onClick={() => setIsAddressModalOpen(false)}
|
||||
>
|
||||
تأیید
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</DefaulModal>
|
||||
|
||||
<DefaulModal
|
||||
open={isLocationModalOpen}
|
||||
close={() => setIsLocationModalOpen(false)}
|
||||
isHeader={true}
|
||||
title_header='انتخاب موقعیت روی نقشه'
|
||||
width={800}
|
||||
>
|
||||
<div className='p-4'>
|
||||
<LocationPicker
|
||||
initialPosition={
|
||||
latitude && longitude ? [latitude, longitude] : undefined
|
||||
}
|
||||
onLocationSelect={handleMapLocationSelect}
|
||||
/>
|
||||
<div className='mt-4 text-xs text-gray-600 text-center'>
|
||||
روی نقشه کلیک کنید تا موقعیت را انتخاب کنید
|
||||
</div>
|
||||
</div>
|
||||
</DefaulModal>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default CreateOrderDeliveryModal
|
||||
Reference in New Issue
Block a user