This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { type FC } from 'react'
|
||||
import { memo, useCallback, useRef, type FC } from 'react'
|
||||
import type { AttributeType, RequestType } from '../type/Types'
|
||||
import { clx } from '@/helpers/utils'
|
||||
import { FieldTypeEnum } from '../enum/RequestEnum'
|
||||
@@ -15,25 +15,57 @@ type Props = {
|
||||
formik: FormikProps<RequestType>
|
||||
}
|
||||
|
||||
type AttributeFieldProps = {
|
||||
item: AttributeType
|
||||
value: string
|
||||
onChange: (attributeId: string, value: string) => void
|
||||
}
|
||||
|
||||
const AttributeTextField = memo<AttributeFieldProps>(({ item, value, onChange }) => (
|
||||
<div className='mt-6'>
|
||||
<Input
|
||||
label={item.name}
|
||||
type={item.type}
|
||||
value={value}
|
||||
onChange={(e) => onChange(item.id, e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
))
|
||||
AttributeTextField.displayName = 'AttributeTextField'
|
||||
|
||||
const AttributeTextareaField = memo<AttributeFieldProps>(({ item, value, onChange }) => (
|
||||
<div className='mt-6'>
|
||||
<Textarea
|
||||
label={item.name}
|
||||
value={value}
|
||||
onChange={(e) => onChange(item.id, e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
))
|
||||
AttributeTextareaField.displayName = 'AttributeTextareaField'
|
||||
|
||||
const ManageAttribute: FC<Props> = (props) => {
|
||||
|
||||
const { attributes, formik } = props
|
||||
const formikRef = useRef(formik)
|
||||
formikRef.current = formik
|
||||
|
||||
const getAttributeValue = (fieldId: string) => {
|
||||
const attr = formik.values.attributes.find((o) => o.fieldId === fieldId)
|
||||
const getAttributeValue = useCallback((fieldId: string) => {
|
||||
const attr = formikRef.current.values.attributes.find((o) => o.fieldId === fieldId)
|
||||
return attr?.value != null ? String(attr.value) : ''
|
||||
}
|
||||
}, [])
|
||||
|
||||
const handleChange = (attributeId: string, value: string) => {
|
||||
const next = [...formik.values.attributes]
|
||||
const handleChange = useCallback((attributeId: string, value: string) => {
|
||||
const current = formikRef.current
|
||||
const next = [...current.values.attributes]
|
||||
const index = next.findIndex((o) => o.fieldId === attributeId)
|
||||
if (index > -1) {
|
||||
next[index] = { ...next[index], value }
|
||||
} else {
|
||||
next.push({ fieldId: attributeId, value })
|
||||
}
|
||||
formik.setFieldValue('attributes', next)
|
||||
}
|
||||
current.setFieldValue('attributes', next)
|
||||
}, [])
|
||||
|
||||
|
||||
return (
|
||||
@@ -115,24 +147,21 @@ const ManageAttribute: FC<Props> = (props) => {
|
||||
)
|
||||
else if (item.type === FieldTypeEnum.number || item.type === FieldTypeEnum.text)
|
||||
return (
|
||||
<div key={item.id} className='mt-6'>
|
||||
<Input
|
||||
label={item.name}
|
||||
type={item.type}
|
||||
value={getAttributeValue(item.id)}
|
||||
onChange={(e) => handleChange(item.id, e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<AttributeTextField
|
||||
key={item.id}
|
||||
item={item}
|
||||
value={getAttributeValue(item.id)}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
)
|
||||
else if (item.type === FieldTypeEnum.textarea)
|
||||
return (
|
||||
<div key={item.id} className='mt-6'>
|
||||
<Textarea
|
||||
label={item.name}
|
||||
value={getAttributeValue(item.id)}
|
||||
onChange={(e) => handleChange(item.id, e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
<AttributeTextareaField
|
||||
key={item.id}
|
||||
item={item}
|
||||
value={getAttributeValue(item.id)}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
)
|
||||
|
||||
})
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { useEffect, useMemo, useState, type ChangeEvent, type FC } from 'react'
|
||||
import { useCallback, useEffect, useMemo, useState, type ChangeEvent, type FC } from 'react'
|
||||
import Button from '@/components/Button'
|
||||
import UploadBox from '@/components/UploadBox'
|
||||
import VoiceRecorder from '@/components/VoiceRecorder'
|
||||
@@ -32,7 +32,7 @@ const Request: FC<Props> = ({ editIndex, initialItem, onSaved, onCancelEdit }) =
|
||||
const isEditing = editIndex !== null
|
||||
|
||||
const { data } = useGetProducts()
|
||||
const { setItems, items } = useRequestStore()
|
||||
const setItems = useRequestStore((state) => state.setItems)
|
||||
const [productSelected, setProductSelected] = useState<ProductType>()
|
||||
const [voiceFile, setVoiceFile] = useState<File>()
|
||||
const [files, setFiles] = useState<File[]>([])
|
||||
@@ -74,10 +74,12 @@ const Request: FC<Props> = ({ editIndex, initialItem, onSaved, onCancelEdit }) =
|
||||
const payload: RequestType = { ...values, attachments }
|
||||
|
||||
if (isEditing && editIndex !== null) {
|
||||
const items = useRequestStore.getState().items
|
||||
const updated = [...items]
|
||||
updated[editIndex] = payload
|
||||
setItems(updated)
|
||||
} else {
|
||||
const items = useRequestStore.getState().items
|
||||
setItems([...items, payload])
|
||||
}
|
||||
|
||||
@@ -119,6 +121,18 @@ const Request: FC<Props> = ({ editIndex, initialItem, onSaved, onCancelEdit }) =
|
||||
|
||||
const isUploading = singleUpload.isPending || multiUpload.isPending
|
||||
|
||||
const handleDescriptionChange = useCallback(
|
||||
(value: string) => {
|
||||
formik.setFieldValue('description', value)
|
||||
},
|
||||
[formik.setFieldValue]
|
||||
)
|
||||
|
||||
const handleRecordingComplete = useCallback((blob: Blob) => {
|
||||
const file = new File([blob], 'recording.wav', { type: blob.type })
|
||||
setVoiceFile(file)
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className='bg-white rounded-3xl p-6'>
|
||||
<div className='flex items-center justify-between'>
|
||||
@@ -160,12 +174,9 @@ const Request: FC<Props> = ({ editIndex, initialItem, onSaved, onCancelEdit }) =
|
||||
<div className='mt-6'>
|
||||
<VoiceRecorder
|
||||
value={formik.values.description ?? ''}
|
||||
onChange={(value) => formik.setFieldValue('description', value)}
|
||||
onChange={handleDescriptionChange}
|
||||
label='پیام صوتی'
|
||||
onRecordingComplete={(blob) => {
|
||||
const file = new File([blob], 'recording.wav', { type: blob.type })
|
||||
setVoiceFile(file)
|
||||
}}
|
||||
onRecordingComplete={handleRecordingComplete}
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user