create order without scoll
deploy to danak / build_and_deploy (push) Has been cancelled

This commit is contained in:
hamid zarghami
2026-07-01 10:10:15 +03:30
parent 0539d4bc48
commit 3c6d3f009a
6 changed files with 824 additions and 561 deletions
@@ -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