From a19d0f947878bd2e6b091a2273fc236141b0a6dd Mon Sep 17 00:00:00 2001 From: maxim Date: Mon, 3 Feb 2025 18:20:53 +0300 Subject: [PATCH] init `/media` route --- src/App.tsx | 18 +++++++ src/pages/media/create.tsx | 108 +++++++++++++++++++++++++++++++++++++ src/pages/media/edit.tsx | 96 +++++++++++++++++++++++++++++++++ src/pages/media/index.ts | 4 ++ src/pages/media/list.tsx | 64 ++++++++++++++++++++++ src/pages/media/show.tsx | 39 ++++++++++++++ 6 files changed, 329 insertions(+) create mode 100644 src/pages/media/create.tsx create mode 100644 src/pages/media/edit.tsx create mode 100644 src/pages/media/index.ts create mode 100644 src/pages/media/list.tsx create mode 100644 src/pages/media/show.tsx diff --git a/src/App.tsx b/src/App.tsx index bde900f..4f02261 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -22,6 +22,7 @@ import {authProvider} from './authProvider' import {CountryList, CountryCreate, CountryEdit} from './pages/country' import {CityList, CityCreate, CityEdit} from './pages/city' import {CarrierList, CarrierCreate, CarrierEdit} from './pages/carrier' +import {MediaList, MediaCreate, MediaEdit, MediaShow} from './pages/media' function App() { return ( @@ -86,6 +87,16 @@ function App() { canDelete: true, }, }, + { + name: 'media', + list: '/media', + create: '/media/create', + edit: '/media/edit/:id', + show: '/media/show/:id', + meta: { + canDelete: true, + }, + }, ]} options={{ syncWithLocation: true, @@ -136,6 +147,13 @@ function App() { } /> + + } /> + } /> + } /> + } /> + + } /> { + const { + saveButtonProps, + refineCore: {formLoading, onFinish}, + register, + formState: {errors}, + setValue, + handleSubmit, + watch, + } = useForm({}) + + const [selectedFile, setSelectedFile] = useState(null) + const [previewUrl, setPreviewUrl] = useState(null) + + const handleFileChange = (event: React.ChangeEvent) => { + const file = event.target.files?.[0] + if (file) { + setValue('file', file) + setSelectedFile(file) + + if (file.type.startsWith('image/')) { + const url = URL.createObjectURL(file) + setPreviewUrl(url) + } else { + setPreviewUrl(null) + } + } + } + + return ( + { + const formData = new FormData() + + formData.append('filename', data.filename) + formData.append('type', String(data.media_type)) + + const file = watch('file') + if (file) { + formData.append('file', file) + } + + onFinish(formData) + }), + }} + > + + + + + + {selectedFile && ( + + {selectedFile.name} + + )} + + + {previewUrl && ( + + Preview + + )} + + + + + + + + ) +} diff --git a/src/pages/media/edit.tsx b/src/pages/media/edit.tsx new file mode 100644 index 0000000..562e63c --- /dev/null +++ b/src/pages/media/edit.tsx @@ -0,0 +1,96 @@ +import {Box, TextField, Button, Typography} from '@mui/material' +import {Edit} from '@refinedev/mui' +import {useForm} from '@refinedev/react-hook-form' +import {useState, useEffect} from 'react' +import {useShow} from '@refinedev/core' + +export const MediaEdit = () => { + const { + saveButtonProps, + register, + formState: {errors}, + setValue, + } = useForm({}) + + const {query} = useShow() + const {data} = query + const record = data?.data + + const [selectedFile, setSelectedFile] = useState(null) + const [previewUrl, setPreviewUrl] = useState(null) + + useEffect(() => { + if (record?.id) { + setPreviewUrl(`https://wn.krbl.ru/media/${record.id}/download`) + } + }, [record]) + + const handleFileChange = (event: React.ChangeEvent) => { + const file = event.target.files?.[0] + if (file) { + setValue('file', file) + setSelectedFile(file) + + if (file.type.startsWith('image/')) { + const url = URL.createObjectURL(file) + setPreviewUrl(url) + } + } + } + + return ( + + + + + + + {selectedFile && ( + + {selectedFile.name} + + )} + + + {previewUrl && ( + + Preview + + )} + + + + + + + + ) +} diff --git a/src/pages/media/index.ts b/src/pages/media/index.ts new file mode 100644 index 0000000..0f886cc --- /dev/null +++ b/src/pages/media/index.ts @@ -0,0 +1,4 @@ +export * from './create' +export * from './edit' +export * from './list' +export * from './show' diff --git a/src/pages/media/list.tsx b/src/pages/media/list.tsx new file mode 100644 index 0000000..e68df8c --- /dev/null +++ b/src/pages/media/list.tsx @@ -0,0 +1,64 @@ +import {DataGrid, type GridColDef} from '@mui/x-data-grid' +import {DeleteButton, EditButton, List, ShowButton, useDataGrid} from '@refinedev/mui' +import React from 'react' + +export const MediaList = () => { + const {dataGridProps} = useDataGrid({}) + + const columns = React.useMemo( + () => [ + { + field: 'filename', + headerName: 'File name', + type: 'string', + minWidth: 250, + display: 'flex', + align: 'left', + headerAlign: 'left', + }, + { + field: 'media_type', + headerName: 'Media Type', + type: 'number', + minWidth: 150, + display: 'flex', + align: 'left', + headerAlign: 'left', + }, + { + field: 'id', + headerName: 'ID', + type: 'number', + display: 'flex', + align: 'left', + headerAlign: 'left', + flex: 1, + }, + { + field: 'actions', + headerName: 'Actions', + align: 'right', + headerAlign: 'center', + minWidth: 130, + sortable: false, + display: 'flex', + renderCell: function render({row}) { + return ( + <> + + + + + ) + }, + }, + ], + [], + ) + + return ( + + row.id} /> + + ) +} diff --git a/src/pages/media/show.tsx b/src/pages/media/show.tsx new file mode 100644 index 0000000..fdf8c09 --- /dev/null +++ b/src/pages/media/show.tsx @@ -0,0 +1,39 @@ +import {Stack, Typography} from '@mui/material' +import {useShow} from '@refinedev/core' +import {Show, TextFieldComponent as TextField} from '@refinedev/mui' + +export const MediaShow = () => { + const {query} = useShow({}) + const {data, isLoading} = query + + const record = data?.data + + return ( + + + {record && {record?.filename}} + + + + {'File name'} + + + + + + + {'Media Type'} + + + + + + + {'ID'} + + + + + + ) +}