144 lines
4.6 KiB
TypeScript
144 lines
4.6 KiB
TypeScript
import {Box, TextField, Button, Typography, Autocomplete} from '@mui/material'
|
|
import {Edit} from '@refinedev/mui'
|
|
import {useForm} from '@refinedev/react-hook-form'
|
|
import {useEffect} from 'react'
|
|
import {useShow} from '@refinedev/core'
|
|
import {Controller} from 'react-hook-form'
|
|
|
|
import {MEDIA_TYPES} from '../../lib/constants'
|
|
import {ALLOWED_IMAGE_TYPES, ALLOWED_VIDEO_TYPES, useMediaFileUpload} from '../../components/media/MediaFormUtils'
|
|
|
|
type MediaFormValues = {
|
|
media_name: string
|
|
media_type: number
|
|
file?: File
|
|
}
|
|
|
|
export const MediaEdit = () => {
|
|
const {
|
|
saveButtonProps,
|
|
refineCore: {onFinish},
|
|
register,
|
|
formState: {errors},
|
|
setValue,
|
|
handleSubmit,
|
|
watch,
|
|
setError,
|
|
clearErrors,
|
|
control,
|
|
} = useForm<MediaFormValues>({
|
|
defaultValues: {
|
|
media_name: '',
|
|
media_type: '',
|
|
file: undefined,
|
|
},
|
|
})
|
|
|
|
const {query} = useShow()
|
|
const {data} = query
|
|
const record = data?.data
|
|
|
|
const selectedMediaType = watch('media_type')
|
|
|
|
const {selectedFile, previewUrl, setPreviewUrl, handleFileChange, handleMediaTypeChange} = useMediaFileUpload({
|
|
selectedMediaType,
|
|
setError,
|
|
clearErrors,
|
|
setValue,
|
|
})
|
|
|
|
useEffect(() => {
|
|
if (record?.id) {
|
|
setPreviewUrl(`https://wn.krbl.ru/media/${record.id}/download`)
|
|
setValue('media_name', record?.media_name || '')
|
|
setValue('media_type', record?.media_type)
|
|
}
|
|
}, [record, setValue, setPreviewUrl])
|
|
|
|
return (
|
|
<Edit
|
|
saveButtonProps={{
|
|
...saveButtonProps,
|
|
disabled: !!errors.file,
|
|
onClick: handleSubmit((data) => {
|
|
const formData = {
|
|
media_name: data.media_name,
|
|
filename: selectedFile?.name || record?.filename,
|
|
type: Number(data.media_type),
|
|
}
|
|
onFinish(formData)
|
|
}),
|
|
}}
|
|
>
|
|
<Box component="form" sx={{display: 'flex', flexDirection: 'column'}} autoComplete="off">
|
|
<Controller
|
|
control={control}
|
|
name="media_type"
|
|
rules={{
|
|
required: 'Это поле является обязательным',
|
|
}}
|
|
defaultValue={null}
|
|
render={({field}) => (
|
|
<Autocomplete
|
|
options={MEDIA_TYPES}
|
|
value={MEDIA_TYPES.find((option) => option.value === field.value) || null}
|
|
onChange={(_, value) => {
|
|
field.onChange(value?.value || null)
|
|
handleMediaTypeChange(value?.value || null)
|
|
}}
|
|
getOptionLabel={(item) => {
|
|
return item ? item.label : ''
|
|
}}
|
|
isOptionEqualToValue={(option, value) => {
|
|
return option.value === value?.value
|
|
}}
|
|
renderInput={(params) => <TextField {...params} label="Тип" margin="normal" variant="outlined" error={!!errors.media_type} helperText={(errors as any)?.media_type?.message} required />}
|
|
/>
|
|
)}
|
|
/>
|
|
|
|
<TextField
|
|
{...register('media_name', {
|
|
required: 'Это поле является обязательным',
|
|
})}
|
|
error={!!(errors as any)?.media_name}
|
|
helperText={(errors as any)?.media_name?.message}
|
|
margin="normal"
|
|
fullWidth
|
|
InputLabelProps={{shrink: true}}
|
|
type="text"
|
|
label="Название *"
|
|
name="media_name"
|
|
/>
|
|
|
|
<Box display="flex" flexDirection="column-reverse" alignItems="center" gap={4} style={{marginTop: 10}}>
|
|
<Box display="flex" flexDirection="column" alignItems="center" gap={2}>
|
|
<Button variant="contained" component="label" disabled={!selectedMediaType}>
|
|
{selectedFile ? 'Изменить файл' : 'Загрузить файл'}
|
|
<input type="file" hidden onChange={handleFileChange} accept={selectedMediaType === 1 ? ALLOWED_IMAGE_TYPES.join(',') : ALLOWED_VIDEO_TYPES.join(',')} />
|
|
</Button>
|
|
|
|
{selectedFile && (
|
|
<Typography variant="body2" color="text.secondary">
|
|
{selectedFile.name}
|
|
</Typography>
|
|
)}
|
|
|
|
{errors.file && (
|
|
<Typography variant="caption" color="error">
|
|
{(errors as any)?.file?.message}
|
|
</Typography>
|
|
)}
|
|
</Box>
|
|
|
|
{previewUrl && selectedMediaType === 1 && (
|
|
<Box mt={2} display="flex" justifyContent="center">
|
|
<img src={previewUrl} alt="Preview" style={{maxWidth: '200px', borderRadius: 8}} />
|
|
</Box>
|
|
)}
|
|
</Box>
|
|
</Box>
|
|
</Edit>
|
|
)
|
|
}
|