168 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			168 lines
		
	
	
		
			4.8 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| import { DataGrid, GridColDef, GridRenderCellParams } from "@mui/x-data-grid";
 | ||
| import { ruRU } from "@mui/x-data-grid/locales";
 | ||
| import { languageStore, MEDIA_TYPE_LABELS, mediaStore } from "@shared";
 | ||
| import { useEffect, useState } from "react";
 | ||
| import { observer } from "mobx-react-lite";
 | ||
| import { Eye, Trash2, Minus } from "lucide-react";
 | ||
| import { useNavigate } from "react-router-dom";
 | ||
| import { DeleteModal } from "@widgets";
 | ||
| import { Box, CircularProgress } from "@mui/material";
 | ||
| 
 | ||
| export const MediaListPage = observer(() => {
 | ||
|   const { media, getMedia, deleteMedia } = mediaStore;
 | ||
|   const navigate = useNavigate();
 | ||
|   const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
 | ||
|   const [isBulkDeleteModalOpen, setIsBulkDeleteModalOpen] = useState(false);
 | ||
|   const [rowId, setRowId] = useState<string | null>(null);
 | ||
|   const [ids, setIds] = useState<string[]>([]);
 | ||
|   const [isLoading, setIsLoading] = useState(false);
 | ||
|   const { language } = languageStore;
 | ||
| 
 | ||
|   useEffect(() => {
 | ||
|     const fetchMedia = async () => {
 | ||
|       setIsLoading(true);
 | ||
|       await getMedia();
 | ||
|       setIsLoading(false);
 | ||
|     };
 | ||
|     fetchMedia();
 | ||
|   }, [language]);
 | ||
| 
 | ||
|   const columns: GridColDef[] = [
 | ||
|     {
 | ||
|       field: "media_name",
 | ||
|       headerName: "Название",
 | ||
|       flex: 1,
 | ||
|       renderCell: (params: GridRenderCellParams) => {
 | ||
|         return (
 | ||
|           <div className="w-full h-full flex items-center">
 | ||
|             {params.value ? (
 | ||
|               params.value
 | ||
|             ) : (
 | ||
|               <Minus size={20} className="text-red-500" />
 | ||
|             )}
 | ||
|           </div>
 | ||
|         );
 | ||
|       },
 | ||
|     },
 | ||
|     {
 | ||
|       field: "media_type",
 | ||
|       headerName: "Тип",
 | ||
|       width: 200,
 | ||
|       flex: 1,
 | ||
|       renderCell: (params: GridRenderCellParams) => {
 | ||
|         return (
 | ||
|           <div className="w-full h-full flex items-center">
 | ||
|             {params.value ? (
 | ||
|               MEDIA_TYPE_LABELS[
 | ||
|                 params.row.media_type as keyof typeof MEDIA_TYPE_LABELS
 | ||
|               ]
 | ||
|             ) : (
 | ||
|               <Minus size={20} className="text-red-500" />
 | ||
|             )}
 | ||
|           </div>
 | ||
|         );
 | ||
|       },
 | ||
|     },
 | ||
|     {
 | ||
|       field: "actions",
 | ||
|       headerName: "Действия",
 | ||
|       width: 200,
 | ||
|       align: "center",
 | ||
|       headerAlign: "center",
 | ||
|       sortable: false,
 | ||
| 
 | ||
|       renderCell: (params: GridRenderCellParams) => {
 | ||
|         return (
 | ||
|           <div className="flex h-full gap-7 justify-center items-center">
 | ||
|             <button onClick={() => navigate(`/media/${params.row.id}`)}>
 | ||
|               <Eye size={20} className="text-green-500" />
 | ||
|             </button>
 | ||
|             <button
 | ||
|               onClick={() => {
 | ||
|                 setIsDeleteModalOpen(true);
 | ||
|                 setRowId(params.row.id);
 | ||
|               }}
 | ||
|             >
 | ||
|               <Trash2 size={20} className="text-red-500" />
 | ||
|             </button>
 | ||
|           </div>
 | ||
|         );
 | ||
|       },
 | ||
|     },
 | ||
|   ];
 | ||
| 
 | ||
|   const rows = media.map((media) => ({
 | ||
|     id: media.id,
 | ||
|     media_name: media.media_name,
 | ||
|     media_type: media.media_type,
 | ||
|   }));
 | ||
| 
 | ||
|   return (
 | ||
|     <>
 | ||
|       <div className="w-full">
 | ||
|         <div
 | ||
|           className="flex justify-end mb-5 duration-300"
 | ||
|           style={{ opacity: ids.length > 0 ? 1 : 0 }}
 | ||
|         >
 | ||
|           <button
 | ||
|             className="px-4 py-2 bg-red-500 text-white rounded flex gap-2 items-center"
 | ||
|             onClick={() => setIsBulkDeleteModalOpen(true)}
 | ||
|           >
 | ||
|             <Trash2 size={20} className="text-white" /> Удалить выбранные (
 | ||
|             {ids.length})
 | ||
|           </button>
 | ||
|         </div>
 | ||
| 
 | ||
|         <DataGrid
 | ||
|           rows={rows}
 | ||
|           columns={columns}
 | ||
|           hideFooterPagination
 | ||
|           checkboxSelection
 | ||
|           loading={isLoading}
 | ||
|           onRowSelectionModelChange={(newSelection) => {
 | ||
|             setIds(Array.from(newSelection.ids) as string[]);
 | ||
|           }}
 | ||
|           hideFooter
 | ||
|           localeText={ruRU.components.MuiDataGrid.defaultProps.localeText}
 | ||
|           slots={{
 | ||
|             noRowsOverlay: () => (
 | ||
|               <Box sx={{ mt: 5, textAlign: "center", color: "text.secondary" }}>
 | ||
|                 {isLoading ? <CircularProgress size={20} /> : "Нет медиафайлов"}
 | ||
|               </Box>
 | ||
|             ),
 | ||
|           }}
 | ||
|         />
 | ||
|       </div>
 | ||
| 
 | ||
|       <DeleteModal
 | ||
|         open={isDeleteModalOpen}
 | ||
|         onDelete={async () => {
 | ||
|           if (rowId) {
 | ||
|             deleteMedia(rowId.toString());
 | ||
|             getMedia();
 | ||
|           }
 | ||
|           setIsDeleteModalOpen(false);
 | ||
|           setRowId(null);
 | ||
|         }}
 | ||
|         onCancel={() => {
 | ||
|           setIsDeleteModalOpen(false);
 | ||
|           setRowId(null);
 | ||
|         }}
 | ||
|       />
 | ||
| 
 | ||
|       <DeleteModal
 | ||
|         open={isBulkDeleteModalOpen}
 | ||
|         onDelete={async () => {
 | ||
|           await Promise.all(ids.map((id) => deleteMedia(id)));
 | ||
|           getMedia();
 | ||
|           setIsBulkDeleteModalOpen(false);
 | ||
|           setIds([]);
 | ||
|         }}
 | ||
|         onCancel={() => {
 | ||
|           setIsBulkDeleteModalOpen(false);
 | ||
|         }}
 | ||
|       />
 | ||
|     </>
 | ||
|   );
 | ||
| });
 |