Files
WhiteNightsAdminPanel/src/pages/media/edit.tsx
2025-05-19 21:53:34 +03:00

232 lines
6.3 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 { TOKEN_KEY } from "@providers";
import { MEDIA_TYPES } from "@lib";
import {
ALLOWED_IMAGE_TYPES,
ALLOWED_VIDEO_TYPES,
ALLOWED_ICON_TYPES,
ALLOWED_WATERMARK_TYPES,
ALLOWED_PANORAMA_TYPES,
ALLOWED_3D_MODEL_TYPES,
useMediaFileUpload,
} from "../../components/media/MediaFormUtils";
import { languageStore, META_LANGUAGE } from "@stores";
import { observer } from "mobx-react-lite";
import { LanguageSelector, MediaData, MediaView } from "@ui";
type MediaFormValues = {
media_name: string;
media_type: number;
file?: File;
};
export const MediaEdit = observer(() => {
const { language } = languageStore;
const {
saveButtonProps,
refineCore: { onFinish },
register,
formState: { errors },
setValue,
handleSubmit,
watch,
setError,
clearErrors,
control,
} = useForm<MediaFormValues>({
defaultValues: {
media_name: "",
media_type: "",
file: undefined,
},
refineCoreProps: META_LANGUAGE(language)
});
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(
`${import.meta.env.VITE_KRBL_MEDIA}${
record.id
}/download?token=${localStorage.getItem(TOKEN_KEY)}`
);
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"
>
<LanguageSelector />
<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
slotProps={{inputLabel: {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(",")
: selectedMediaType === 2
? ALLOWED_VIDEO_TYPES.join(",")
: selectedMediaType === 3
? ALLOWED_ICON_TYPES.join(",")
: selectedMediaType === 4
? ALLOWED_WATERMARK_TYPES.join(",")
: selectedMediaType === 5
? ALLOWED_PANORAMA_TYPES.join(",")
: selectedMediaType === 6
? ALLOWED_3D_MODEL_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>
<MediaView media={record as MediaData} />
{/* {previewUrl && selectedMediaType === 1 && (
<Box mt={2} display="flex" justifyContent="center">
<img
src={previewUrl}
alt="Preview"
style={{ maxWidth: "200px", borderRadius: 8 }}
/>
</Box>
)} */}
</Box>
</Box>
</Edit>
);
});