270 lines
12 KiB
TypeScript
270 lines
12 KiB
TypeScript
import { type FC, useState } from 'react'
|
||
import type { FormikProps } from 'formik'
|
||
import { useTranslation } from 'react-i18next'
|
||
import Input from '@/components/Input'
|
||
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 CreateOrderDeliverySectionProps {
|
||
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 CreateOrderDeliverySection: FC<CreateOrderDeliverySectionProps> = ({
|
||
formik,
|
||
deliveryMethods,
|
||
cashPaymentMethod,
|
||
isCourierDelivery,
|
||
isCarDelivery,
|
||
isDineIn,
|
||
customerAddresses,
|
||
selectedAddressId,
|
||
onSelectSavedAddress,
|
||
onSelectManualAddress,
|
||
onAddressFieldChange,
|
||
onLocationSelect,
|
||
}) => {
|
||
const { t } = useTranslation('global')
|
||
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
|
||
|
||
return (
|
||
<div className='flex flex-col gap-8'>
|
||
<div className='w-full bg-white rounded-4xl p-8'>
|
||
<div className='text-lg font-light'>تحویل و پرداخت</div>
|
||
|
||
<div className='mt-6'>
|
||
<div className='text-sm mb-3'>روش تحویل</div>
|
||
<div className='grid grid-cols-1 sm:grid-cols-2 gap-3'>
|
||
{deliveryMethods.map((method) => {
|
||
const isSelected = formik.values.deliveryMethodId === method.id
|
||
return (
|
||
<button
|
||
key={method.id}
|
||
type='button'
|
||
onClick={() => formik.setFieldValue('deliveryMethodId', method.id)}
|
||
className={`text-right p-4 rounded-xl border transition-colors ${
|
||
isSelected
|
||
? 'border-primary bg-primary/5'
|
||
: 'border-border hover:border-primary/40'
|
||
}`}
|
||
>
|
||
<div className='text-sm font-medium'>
|
||
{getDeliveryLabel(method.method)}
|
||
</div>
|
||
{method.description && (
|
||
<div className='text-xs text-description mt-1 line-clamp-2'>
|
||
{method.description}
|
||
</div>
|
||
)}
|
||
{method.deliveryFee > 0 && (
|
||
<div className='text-xs mt-2 text-primary'>
|
||
{formatPrice(method.deliveryFee)}
|
||
</div>
|
||
)}
|
||
</button>
|
||
)
|
||
})}
|
||
</div>
|
||
{formik.touched.deliveryMethodId && formik.errors.deliveryMethodId && (
|
||
<div className='text-xs text-red-500 mt-2'>
|
||
{formik.errors.deliveryMethodId}
|
||
</div>
|
||
)}
|
||
</div>
|
||
|
||
<div className='mt-8'>
|
||
<div className='text-sm mb-3'>روش پرداخت</div>
|
||
<div className='p-4 rounded-xl border border-primary bg-primary/5'>
|
||
<div className='text-sm font-medium'>پرداخت نقدی</div>
|
||
{cashPaymentMethod?.description && (
|
||
<div className='text-xs text-description mt-1'>
|
||
{cashPaymentMethod.description}
|
||
</div>
|
||
)}
|
||
</div>
|
||
{!cashPaymentMethod && (
|
||
<div className='text-xs text-red-500 mt-2'>
|
||
روش پرداخت نقدی فعال یافت نشد
|
||
</div>
|
||
)}
|
||
</div>
|
||
|
||
{isDineIn && (
|
||
<div className='mt-8'>
|
||
<Input
|
||
label='شماره میز'
|
||
name='tableNumber'
|
||
placeholder='مثال: ۱۲'
|
||
value={formik.values.tableNumber}
|
||
onChange={formik.handleChange}
|
||
/>
|
||
</div>
|
||
)}
|
||
</div>
|
||
|
||
{isCourierDelivery && (
|
||
<div className='w-full bg-white rounded-4xl p-8'>
|
||
<div className='text-lg font-light'>آدرس تحویل</div>
|
||
|
||
<CreateOrderAddressSelector
|
||
addresses={customerAddresses}
|
||
selectedAddressId={selectedAddressId}
|
||
onSelectAddress={onSelectSavedAddress}
|
||
onSelectManual={onSelectManualAddress}
|
||
/>
|
||
|
||
<div className='grid grid-cols-1 sm:grid-cols-2 gap-4 mt-6'>
|
||
<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-5'>
|
||
<Textarea
|
||
label='آدرس کامل'
|
||
name='userAddress.address'
|
||
value={formik.values.userAddress.address}
|
||
onChange={onAddressFieldChange}
|
||
readOnly={isAddressReadOnly}
|
||
/>
|
||
</div>
|
||
|
||
<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>
|
||
</div>
|
||
)}
|
||
|
||
{isCarDelivery && (
|
||
<div className='w-full bg-white rounded-4xl p-8'>
|
||
<div className='text-lg font-light'>اطلاعات خودرو</div>
|
||
|
||
<div className='grid grid-cols-1 sm:grid-cols-2 gap-4 mt-6'>
|
||
<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='w-full bg-white rounded-4xl p-8'>
|
||
<div className='text-lg font-light'>توضیحات سفارش</div>
|
||
<div className='mt-6'>
|
||
<Textarea
|
||
label='توضیحات'
|
||
name='description'
|
||
placeholder='توضیحات اضافی برای سفارش...'
|
||
value={formik.values.description}
|
||
onChange={formik.handleChange}
|
||
isNotRequired
|
||
/>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
)
|
||
}
|
||
|
||
export default CreateOrderDeliverySection
|