Files
dmenu-admin/src/pages/orders/components/CreateOrderDeliveryModal.tsx
T
hamid zarghami 3c6d3f009a
deploy to danak / build_and_deploy (push) Has been cancelled
create order without scoll
2026-07-01 10:10:15 +03:30

336 lines
15 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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