WhiteNightsAdminPanel/src/pages/media/edit.tsx
2025-03-31 20:06:48 +03:00

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>
)
}