Compare commits
3 Commits
6324cabb32
...
b92faa81a9
| Author | SHA1 | Date | |
|---|---|---|---|
| b92faa81a9 | |||
| a248064800 | |||
| 72ca39c284 |
@@ -11,6 +11,7 @@ import Select from '@/components/Select'
|
|||||||
import Switch from '@/components/Switch'
|
import Switch from '@/components/Switch'
|
||||||
import Textarea from '@/components/Textarea'
|
import Textarea from '@/components/Textarea'
|
||||||
import type { CreateRestaurantPaymentMethodType } from './types/Types'
|
import type { CreateRestaurantPaymentMethodType } from './types/Types'
|
||||||
|
import PaymentMethodCardsSection from './components/PaymentMethodCardsSection'
|
||||||
import { useCreateRestaurantPaymentMethod } from './hooks/usePaymentMethodData'
|
import { useCreateRestaurantPaymentMethod } from './hooks/usePaymentMethodData'
|
||||||
import { PaymentMethodEnum, PaymentGatewayEnum } from './enum/Enum'
|
import { PaymentMethodEnum, PaymentGatewayEnum } from './enum/Enum'
|
||||||
import { Pages } from '@/config/Pages'
|
import { Pages } from '@/config/Pages'
|
||||||
@@ -41,8 +42,7 @@ const CreatePaymentMethod: FC = () => {
|
|||||||
enabled: true,
|
enabled: true,
|
||||||
order: 0,
|
order: 0,
|
||||||
merchantId: '',
|
merchantId: '',
|
||||||
cardNumber: '',
|
cards: [{ cardNumber: '', owner: '' }],
|
||||||
cardOwner: '',
|
|
||||||
},
|
},
|
||||||
validationSchema: Yup.object().shape({
|
validationSchema: Yup.object().shape({
|
||||||
method: Yup.string().required('روش پرداخت الزامی است'),
|
method: Yup.string().required('روش پرداخت الزامی است'),
|
||||||
@@ -59,14 +59,17 @@ const CreatePaymentMethod: FC = () => {
|
|||||||
then: (schema) => schema.required('شناسه مرچنت الزامی است'),
|
then: (schema) => schema.required('شناسه مرچنت الزامی است'),
|
||||||
otherwise: (schema) => schema.notRequired(),
|
otherwise: (schema) => schema.notRequired(),
|
||||||
}),
|
}),
|
||||||
cardNumber: Yup.string().when('method', {
|
cards: Yup.array().when('method', {
|
||||||
is: PaymentMethodEnum.CreditCard,
|
is: PaymentMethodEnum.CreditCard,
|
||||||
then: (schema) => schema.required('شماره کارت الزامی است'),
|
then: (schema) =>
|
||||||
otherwise: (schema) => schema.notRequired(),
|
schema
|
||||||
}),
|
.min(1, 'حداقل یک کارت الزامی است')
|
||||||
cardOwner: Yup.string().when('method', {
|
.of(
|
||||||
is: PaymentMethodEnum.CreditCard,
|
Yup.object().shape({
|
||||||
then: (schema) => schema.required('نام صاحب کارت الزامی است'),
|
cardNumber: Yup.string().required('شماره کارت الزامی است'),
|
||||||
|
owner: Yup.string().required('نام صاحب کارت الزامی است'),
|
||||||
|
})
|
||||||
|
),
|
||||||
otherwise: (schema) => schema.notRequired(),
|
otherwise: (schema) => schema.notRequired(),
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
@@ -84,8 +87,7 @@ const CreatePaymentMethod: FC = () => {
|
|||||||
: {}),
|
: {}),
|
||||||
...(values.method === PaymentMethodEnum.CreditCard
|
...(values.method === PaymentMethodEnum.CreditCard
|
||||||
? {
|
? {
|
||||||
cardNumber: values.cardNumber,
|
cards: values.cards,
|
||||||
cardOwner: values.cardOwner,
|
|
||||||
}
|
}
|
||||||
: {}),
|
: {}),
|
||||||
}
|
}
|
||||||
@@ -160,26 +162,7 @@ const CreatePaymentMethod: FC = () => {
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{formik.values.method === PaymentMethodEnum.CreditCard && (
|
{formik.values.method === PaymentMethodEnum.CreditCard && (
|
||||||
<>
|
<PaymentMethodCardsSection formik={formik} />
|
||||||
<div className='mt-6'>
|
|
||||||
<Input
|
|
||||||
label='شماره کارت'
|
|
||||||
name='cardNumber'
|
|
||||||
value={formik.values.cardNumber}
|
|
||||||
onChange={formik.handleChange}
|
|
||||||
error_text={formik.touched.cardNumber && formik.errors.cardNumber ? formik.errors.cardNumber : ''}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className='mt-6'>
|
|
||||||
<Input
|
|
||||||
label='نام صاحب کارت'
|
|
||||||
name='cardOwner'
|
|
||||||
value={formik.values.cardOwner}
|
|
||||||
onChange={formik.handleChange}
|
|
||||||
error_text={formik.touched.cardOwner && formik.errors.cardOwner ? formik.errors.cardOwner : ''}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)}
|
)}
|
||||||
<div className='mt-6'>
|
<div className='mt-6'>
|
||||||
<Textarea
|
<Textarea
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import Select from '@/components/Select'
|
|||||||
import Switch from '@/components/Switch'
|
import Switch from '@/components/Switch'
|
||||||
import Textarea from '@/components/Textarea'
|
import Textarea from '@/components/Textarea'
|
||||||
import type { CreateRestaurantPaymentMethodType } from './types/Types'
|
import type { CreateRestaurantPaymentMethodType } from './types/Types'
|
||||||
|
import PaymentMethodCardsSection from './components/PaymentMethodCardsSection'
|
||||||
import { useGetRestaurantPaymentMethod, useUpdateRestaurantPaymentMethod } from './hooks/usePaymentMethodData'
|
import { useGetRestaurantPaymentMethod, useUpdateRestaurantPaymentMethod } from './hooks/usePaymentMethodData'
|
||||||
import { PaymentMethodEnum, PaymentGatewayEnum } from './enum/Enum'
|
import { PaymentMethodEnum, PaymentGatewayEnum } from './enum/Enum'
|
||||||
import { Pages } from '@/config/Pages'
|
import { Pages } from '@/config/Pages'
|
||||||
@@ -45,8 +46,7 @@ const UpdatePaymentMethod: FC = () => {
|
|||||||
enabled: data.enabled ?? true,
|
enabled: data.enabled ?? true,
|
||||||
order: data.order || 0,
|
order: data.order || 0,
|
||||||
merchantId: data.merchantId || '',
|
merchantId: data.merchantId || '',
|
||||||
cardNumber: data.cardNumber || '',
|
cards: data.cards?.length ? data.cards : [{ cardNumber: '', owner: '' }],
|
||||||
cardOwner: data.cardOwner || '',
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
@@ -56,8 +56,7 @@ const UpdatePaymentMethod: FC = () => {
|
|||||||
enabled: true,
|
enabled: true,
|
||||||
order: 0,
|
order: 0,
|
||||||
merchantId: '',
|
merchantId: '',
|
||||||
cardNumber: '',
|
cards: [{ cardNumber: '', owner: '' }],
|
||||||
cardOwner: '',
|
|
||||||
}
|
}
|
||||||
}, [paymentMethodData])
|
}, [paymentMethodData])
|
||||||
|
|
||||||
@@ -79,14 +78,17 @@ const UpdatePaymentMethod: FC = () => {
|
|||||||
then: (schema) => schema.required('شناسه مرچنت الزامی است'),
|
then: (schema) => schema.required('شناسه مرچنت الزامی است'),
|
||||||
otherwise: (schema) => schema.notRequired(),
|
otherwise: (schema) => schema.notRequired(),
|
||||||
}),
|
}),
|
||||||
cardNumber: Yup.string().when('method', {
|
cards: Yup.array().when('method', {
|
||||||
is: PaymentMethodEnum.CreditCard,
|
is: PaymentMethodEnum.CreditCard,
|
||||||
then: (schema) => schema.required('شماره کارت الزامی است'),
|
then: (schema) =>
|
||||||
otherwise: (schema) => schema.notRequired(),
|
schema
|
||||||
}),
|
.min(1, 'حداقل یک کارت الزامی است')
|
||||||
cardOwner: Yup.string().when('method', {
|
.of(
|
||||||
is: PaymentMethodEnum.CreditCard,
|
Yup.object().shape({
|
||||||
then: (schema) => schema.required('نام صاحب کارت الزامی است'),
|
cardNumber: Yup.string().required('شماره کارت الزامی است'),
|
||||||
|
owner: Yup.string().required('نام صاحب کارت الزامی است'),
|
||||||
|
})
|
||||||
|
),
|
||||||
otherwise: (schema) => schema.notRequired(),
|
otherwise: (schema) => schema.notRequired(),
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
@@ -106,8 +108,7 @@ const UpdatePaymentMethod: FC = () => {
|
|||||||
: {}),
|
: {}),
|
||||||
...(values.method === PaymentMethodEnum.CreditCard
|
...(values.method === PaymentMethodEnum.CreditCard
|
||||||
? {
|
? {
|
||||||
cardNumber: values.cardNumber,
|
cards: values.cards,
|
||||||
cardOwner: values.cardOwner,
|
|
||||||
}
|
}
|
||||||
: {}),
|
: {}),
|
||||||
}
|
}
|
||||||
@@ -201,26 +202,7 @@ const UpdatePaymentMethod: FC = () => {
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
{formik.values.method === PaymentMethodEnum.CreditCard && (
|
{formik.values.method === PaymentMethodEnum.CreditCard && (
|
||||||
<>
|
<PaymentMethodCardsSection formik={formik} />
|
||||||
<div className='mt-6'>
|
|
||||||
<Input
|
|
||||||
label='شماره کارت'
|
|
||||||
name='cardNumber'
|
|
||||||
value={formik.values.cardNumber}
|
|
||||||
onChange={formik.handleChange}
|
|
||||||
error_text={formik.touched.cardNumber && formik.errors.cardNumber ? formik.errors.cardNumber : ''}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div className='mt-6'>
|
|
||||||
<Input
|
|
||||||
label='نام صاحب کارت'
|
|
||||||
name='cardOwner'
|
|
||||||
value={formik.values.cardOwner}
|
|
||||||
onChange={formik.handleChange}
|
|
||||||
error_text={formik.touched.cardOwner && formik.errors.cardOwner ? formik.errors.cardOwner : ''}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
)}
|
)}
|
||||||
<div className='mt-6'>
|
<div className='mt-6'>
|
||||||
<Textarea
|
<Textarea
|
||||||
|
|||||||
@@ -0,0 +1,109 @@
|
|||||||
|
import { type FC } from 'react'
|
||||||
|
import type { FormikProps } from 'formik'
|
||||||
|
import { Add, Card, Trash } from 'iconsax-react'
|
||||||
|
import Input from '@/components/Input'
|
||||||
|
import type { CreateRestaurantPaymentMethodType } from '../types/Types'
|
||||||
|
|
||||||
|
type PaymentMethodCardsSectionProps = {
|
||||||
|
formik: FormikProps<CreateRestaurantPaymentMethodType>
|
||||||
|
}
|
||||||
|
|
||||||
|
const PaymentMethodCardsSection: FC<PaymentMethodCardsSectionProps> = ({ formik }) => {
|
||||||
|
const cards = formik.values.cards ?? []
|
||||||
|
const cardsError = formik.touched.cards && typeof formik.errors.cards === 'string' ? formik.errors.cards : ''
|
||||||
|
const cardErrors = Array.isArray(formik.errors.cards) ? formik.errors.cards : []
|
||||||
|
|
||||||
|
const getFieldError = (index: number, field: 'cardNumber' | 'owner') => {
|
||||||
|
const fieldErrors = cardErrors[index]
|
||||||
|
if (
|
||||||
|
!formik.touched.cards?.[index]?.[field] ||
|
||||||
|
!fieldErrors ||
|
||||||
|
typeof fieldErrors !== 'object' ||
|
||||||
|
!(field in fieldErrors)
|
||||||
|
) {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
return String(fieldErrors[field])
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='mt-6'>
|
||||||
|
<div className='flex items-center justify-between mb-3'>
|
||||||
|
<div className='text-sm'>کارتهای بانکی</div>
|
||||||
|
{cards.length > 0 && (
|
||||||
|
<span className='text-xs text-description'>{cards.length} کارت</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='space-y-3'>
|
||||||
|
{cards.map((card, index) => (
|
||||||
|
<div
|
||||||
|
key={index}
|
||||||
|
className='bg-gray-50 rounded-2xl p-4 border border-border'
|
||||||
|
>
|
||||||
|
<div className='flex items-center justify-between mb-3'>
|
||||||
|
<div className='flex items-center gap-2.5'>
|
||||||
|
<div className='w-9 h-9 rounded-xl bg-white border border-border flex items-center justify-center shrink-0'>
|
||||||
|
<Card size={18} color='#8C90A3' variant='Bold' />
|
||||||
|
</div>
|
||||||
|
<span className='text-sm text-gray-700'>کارت {index + 1}</span>
|
||||||
|
</div>
|
||||||
|
{cards.length > 1 && (
|
||||||
|
<button
|
||||||
|
type='button'
|
||||||
|
className='p-2 rounded-xl hover:bg-red-50 transition-colors'
|
||||||
|
onClick={() => {
|
||||||
|
formik.setFieldValue(
|
||||||
|
'cards',
|
||||||
|
cards.filter((_, i) => i !== index)
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
aria-label={`حذف کارت ${index + 1}`}
|
||||||
|
>
|
||||||
|
<Trash size={18} color='#EF4444' />
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='grid grid-cols-1 md:grid-cols-2 gap-3'>
|
||||||
|
<Input
|
||||||
|
label='شماره کارت'
|
||||||
|
name={`cards.${index}.cardNumber`}
|
||||||
|
value={card.cardNumber}
|
||||||
|
onChange={formik.handleChange}
|
||||||
|
onBlur={formik.handleBlur}
|
||||||
|
inputMode='numeric'
|
||||||
|
placeholder='مثال: ۶۲۱۹۸۶۱۹۲۸۹۴۸۵۹۵'
|
||||||
|
error_text={getFieldError(index, 'cardNumber')}
|
||||||
|
/>
|
||||||
|
<Input
|
||||||
|
label='نام صاحب کارت'
|
||||||
|
name={`cards.${index}.owner`}
|
||||||
|
value={card.owner}
|
||||||
|
onChange={formik.handleChange}
|
||||||
|
onBlur={formik.handleBlur}
|
||||||
|
placeholder='نام صاحب حساب'
|
||||||
|
error_text={getFieldError(index, 'owner')}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
|
||||||
|
<button
|
||||||
|
type='button'
|
||||||
|
className='w-full flex items-center justify-center gap-2 h-11 rounded-2xl border border-dashed border-border text-sm text-description hover:border-primary hover:text-primary hover:bg-primary/5 transition-colors'
|
||||||
|
onClick={() => {
|
||||||
|
formik.setFieldValue('cards', [...cards, { cardNumber: '', owner: '' }])
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Add size={20} />
|
||||||
|
افزودن کارت جدید
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{cardsError && <div className='text-xs text-red-500'>{cardsError}</div>}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PaymentMethodCardsSection
|
||||||
@@ -61,17 +61,19 @@ export const getPaymentMethodTableColumns = ({ onDelete, isDeleting }: GetPaymen
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'cardNumber',
|
key: 'cards',
|
||||||
title: 'شماره کارت',
|
title: 'شماره کارت',
|
||||||
render: (item: RestaurantPaymentMethod) => {
|
render: (item: RestaurantPaymentMethod) => {
|
||||||
return item.cardNumber || '-'
|
if (!item.cards?.length) return '-'
|
||||||
|
return item.cards.map((card) => card.cardNumber).join('، ')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'cardOwner',
|
key: 'cardOwners',
|
||||||
title: 'نام صاحب کارت',
|
title: 'نام صاحب کارت',
|
||||||
render: (item: RestaurantPaymentMethod) => {
|
render: (item: RestaurantPaymentMethod) => {
|
||||||
return item.cardOwner || '-'
|
if (!item.cards?.length) return '-'
|
||||||
|
return item.cards.map((card) => card.owner).join('، ')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -55,6 +55,11 @@ export type RestaurantPaymentMethodsResponse = IResponse<
|
|||||||
RestaurantPaymentMethod[]
|
RestaurantPaymentMethod[]
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
export type PaymentMethodCard = {
|
||||||
|
cardNumber: string;
|
||||||
|
owner: string;
|
||||||
|
};
|
||||||
|
|
||||||
export type RestaurantPaymentMethod = {
|
export type RestaurantPaymentMethod = {
|
||||||
id: string;
|
id: string;
|
||||||
createdAt: string;
|
createdAt: string;
|
||||||
@@ -67,8 +72,7 @@ export type RestaurantPaymentMethod = {
|
|||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
order: number;
|
order: number;
|
||||||
merchantId: string;
|
merchantId: string;
|
||||||
cardNumber?: string;
|
cards?: PaymentMethodCard[];
|
||||||
cardOwner?: string;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type RestaurantPaymentMethodResponse = IResponse<
|
export type RestaurantPaymentMethodResponse = IResponse<
|
||||||
@@ -82,8 +86,7 @@ export type CreateRestaurantPaymentMethodType = {
|
|||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
order: number;
|
order: number;
|
||||||
merchantId?: string;
|
merchantId?: string;
|
||||||
cardNumber?: string;
|
cards?: PaymentMethodCard[];
|
||||||
cardOwner?: string;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type GetRestaurantPaymentMethodsParams = {
|
export type GetRestaurantPaymentMethodsParams = {
|
||||||
|
|||||||
@@ -17,11 +17,15 @@ import * as yup from 'yup'
|
|||||||
import { toast } from 'react-toastify'
|
import { toast } from 'react-toastify'
|
||||||
import { extractErrorMessage } from '@/config/func'
|
import { extractErrorMessage } from '@/config/func'
|
||||||
import ServiceAreaPicker from './components/ServiceAreaPicker'
|
import ServiceAreaPicker from './components/ServiceAreaPicker'
|
||||||
|
import PhonesSection from './components/PhonesSection'
|
||||||
|
|
||||||
const validationSchema = yup.object({
|
const validationSchema = yup.object({
|
||||||
name: yup.string().required('نام رستوران الزامی است'),
|
name: yup.string().required('نام رستوران الزامی است'),
|
||||||
menuColor: yup.string().required('رنگ منو الزامی است'),
|
menuColor: yup.string().required('رنگ منو الزامی است'),
|
||||||
phone: yup.string().required('شماره تماس الزامی است'),
|
phones: yup
|
||||||
|
.array()
|
||||||
|
.min(1, 'حداقل یک شماره تماس الزامی است')
|
||||||
|
.of(yup.string().required('شماره تماس الزامی است')),
|
||||||
instagram: yup.string().url('لینک اینستاگرام معتبر نیست').nullable(),
|
instagram: yup.string().url('لینک اینستاگرام معتبر نیست').nullable(),
|
||||||
address: yup.string().required('آدرس الزامی است'),
|
address: yup.string().required('آدرس الزامی است'),
|
||||||
latitude: yup.number().required('انتخاب موقعیت روی نقشه الزامی است'),
|
latitude: yup.number().required('انتخاب موقعیت روی نقشه الزامی است'),
|
||||||
@@ -40,7 +44,7 @@ const GeneralSettings: FC = () => {
|
|||||||
initialValues: {
|
initialValues: {
|
||||||
name: '',
|
name: '',
|
||||||
menuColor: '#000000',
|
menuColor: '#000000',
|
||||||
phone: '',
|
phones: [''],
|
||||||
instagram: '',
|
instagram: '',
|
||||||
address: '',
|
address: '',
|
||||||
latitude: 0,
|
latitude: 0,
|
||||||
@@ -93,7 +97,12 @@ const GeneralSettings: FC = () => {
|
|||||||
formik.setValues({
|
formik.setValues({
|
||||||
name: restaurantData.name || '',
|
name: restaurantData.name || '',
|
||||||
menuColor: restaurantData.menuColor || '#000000',
|
menuColor: restaurantData.menuColor || '#000000',
|
||||||
phone: restaurantData.phone || '',
|
phones:
|
||||||
|
restaurantData.phones?.length
|
||||||
|
? restaurantData.phones
|
||||||
|
: restaurantData.phone
|
||||||
|
? [restaurantData.phone]
|
||||||
|
: [''],
|
||||||
instagram: restaurantData.instagram || '',
|
instagram: restaurantData.instagram || '',
|
||||||
address: restaurantData.address || '',
|
address: restaurantData.address || '',
|
||||||
latitude: restaurantData.latitude || 0,
|
latitude: restaurantData.latitude || 0,
|
||||||
@@ -155,16 +164,11 @@ const GeneralSettings: FC = () => {
|
|||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className='mt-8 rowTwoInput'>
|
<div className='mt-8'>
|
||||||
<Input
|
<PhonesSection formik={formik} />
|
||||||
label='شماره تماس'
|
</div>
|
||||||
name='phone'
|
|
||||||
value={formik.values.phone}
|
|
||||||
onChange={formik.handleChange}
|
|
||||||
onBlur={formik.handleBlur}
|
|
||||||
error_text={formik.touched.phone && formik.errors.phone ? formik.errors.phone : undefined}
|
|
||||||
/>
|
|
||||||
|
|
||||||
|
<div className='mt-8'>
|
||||||
<Input
|
<Input
|
||||||
label='اینستاگرام'
|
label='اینستاگرام'
|
||||||
name='instagram'
|
name='instagram'
|
||||||
|
|||||||
@@ -0,0 +1,92 @@
|
|||||||
|
import { type FC } from 'react'
|
||||||
|
import type { FormikProps } from 'formik'
|
||||||
|
import { Add, Call, Trash } from 'iconsax-react'
|
||||||
|
import Input from '@/components/Input'
|
||||||
|
import type { UpdateRestaurantType } from '../types/Types'
|
||||||
|
|
||||||
|
type PhonesSectionProps = {
|
||||||
|
formik: FormikProps<UpdateRestaurantType>
|
||||||
|
}
|
||||||
|
|
||||||
|
const PhonesSection: FC<PhonesSectionProps> = ({ formik }) => {
|
||||||
|
const phones = formik.values.phones ?? []
|
||||||
|
const phonesError = formik.touched.phones && typeof formik.errors.phones === 'string' ? formik.errors.phones : ''
|
||||||
|
const phoneErrors = Array.isArray(formik.errors.phones) ? formik.errors.phones : []
|
||||||
|
|
||||||
|
const getFieldError = (index: number) => {
|
||||||
|
if (!formik.touched.phones?.[index] || !phoneErrors[index]) {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
return String(phoneErrors[index])
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div className='flex items-center justify-between mb-3'>
|
||||||
|
<div className='text-sm'>شمارههای تماس</div>
|
||||||
|
{phones.length > 0 && (
|
||||||
|
<span className='text-xs text-description'>{phones.length} شماره</span>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className='space-y-3'>
|
||||||
|
{phones.map((phone, index) => (
|
||||||
|
<div
|
||||||
|
key={index}
|
||||||
|
className='bg-gray-50 rounded-2xl p-4 border border-border'
|
||||||
|
>
|
||||||
|
<div className='flex items-center justify-between mb-3'>
|
||||||
|
<div className='flex items-center gap-2.5'>
|
||||||
|
<div className='w-9 h-9 rounded-xl bg-white border border-border flex items-center justify-center shrink-0'>
|
||||||
|
<Call size={18} color='#8C90A3' variant='Bold' />
|
||||||
|
</div>
|
||||||
|
<span className='text-sm text-gray-700'>شماره {index + 1}</span>
|
||||||
|
</div>
|
||||||
|
{phones.length > 1 && (
|
||||||
|
<button
|
||||||
|
type='button'
|
||||||
|
className='p-2 rounded-xl hover:bg-red-50 transition-colors'
|
||||||
|
onClick={() => {
|
||||||
|
formik.setFieldValue(
|
||||||
|
'phones',
|
||||||
|
phones.filter((_, i) => i !== index)
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
aria-label={`حذف شماره ${index + 1}`}
|
||||||
|
>
|
||||||
|
<Trash size={18} color='#EF4444' />
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Input
|
||||||
|
label='شماره تماس'
|
||||||
|
name={`phones.${index}`}
|
||||||
|
value={phone}
|
||||||
|
onChange={formik.handleChange}
|
||||||
|
onBlur={formik.handleBlur}
|
||||||
|
inputMode='tel'
|
||||||
|
placeholder='مثال: ۰۹۱۲۳۴۵۶۷۸۹'
|
||||||
|
error_text={getFieldError(index)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
|
||||||
|
<button
|
||||||
|
type='button'
|
||||||
|
className='w-full flex items-center justify-center gap-2 h-11 rounded-2xl border border-dashed border-border text-sm text-description hover:border-primary hover:text-primary hover:bg-primary/5 transition-colors'
|
||||||
|
onClick={() => {
|
||||||
|
formik.setFieldValue('phones', [...phones, ''])
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Add size={20} />
|
||||||
|
افزودن شماره جدید
|
||||||
|
</button>
|
||||||
|
|
||||||
|
{phonesError && <div className='text-xs text-red-500'>{phonesError}</div>}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PhonesSection
|
||||||
@@ -10,7 +10,7 @@ export type GeoJSONPolygon = {
|
|||||||
export type UpdateRestaurantType = {
|
export type UpdateRestaurantType = {
|
||||||
name?: string;
|
name?: string;
|
||||||
menuColor?: string;
|
menuColor?: string;
|
||||||
phone?: string;
|
phones?: string[];
|
||||||
instagram?: string;
|
instagram?: string;
|
||||||
address?: string;
|
address?: string;
|
||||||
logo?: string;
|
logo?: string;
|
||||||
@@ -51,7 +51,8 @@ export type Restaurant = {
|
|||||||
isActive: boolean;
|
isActive: boolean;
|
||||||
establishedYear: number | null;
|
establishedYear: number | null;
|
||||||
phoneNumber: string | null;
|
phoneNumber: string | null;
|
||||||
phone: string;
|
phone?: string;
|
||||||
|
phones?: string[];
|
||||||
instagram: string | null;
|
instagram: string | null;
|
||||||
telegram: string | null;
|
telegram: string | null;
|
||||||
whatsapp: string | null;
|
whatsapp: string | null;
|
||||||
|
|||||||
Reference in New Issue
Block a user