/
viktorphp
/
front-socket
Обзор
Документация
Войти
/
viktorphp
/
front-socket
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
src/features/diary/entryEditor/ui/DiaryFileIcon.tsx
161 строка
5 KB
Иванов Виктор Евгеньевич
[feature-diary]: поправить баги и верстку, добавить README.md
12 апр 2026, 20:01
12 апр 2026, 20:01
0d63759
Код
Авторство
О чём код?
'use client'; import CheckCircleIcon from '@mui/icons-material/CheckCircle'; import CloseIcon from '@mui/icons-material/Close'; import DescriptionIcon from '@mui/icons-material/Description'; import ErrorIcon from '@mui/icons-material/Error'; import HourglassEmptyIcon from '@mui/icons-material/HourglassEmpty'; import ImageIcon from '@mui/icons-material/Image'; import InsertDriveFileIcon from '@mui/icons-material/InsertDriveFile'; import PictureAsPdfIcon from '@mui/icons-material/PictureAsPdf'; import { Box, IconButton, Tooltip, Typography } from '@mui/material'; import { EOcrStatus, IDiaryFile } from '@shared/types'; interface IDiaryFileIconProps { file: IDiaryFile; /** Клик по иконке файла — открывает просмотрщик */ onClick: (file: IDiaryFile) => void; /** Удаление файла */ onDelete: (fileId: string) => void; } /** Возвращает MUI-иконку по MIME-типу файла */ const getFileIcon = (mimeType: string) => { if (mimeType.startsWith('image/')) return <ImageIcon fontSize="large" color="action" />; if (mimeType === 'application/pdf') return <PictureAsPdfIcon fontSize="large" color="error" />; if (mimeType.startsWith('text/')) return <DescriptionIcon fontSize="large" color="info" />; return <InsertDriveFileIcon fontSize="large" color="action" />; }; /** Индикатор статуса OCR в углу иконки */ const OcrStatusBadge = ({ status, error, }: { status: EOcrStatus; error?: string; }) => { if (status === EOcrStatus.PENDING) { return ( <Tooltip title="Идёт распознавание..."> <HourglassEmptyIcon sx={{ fontSize: 14, color: 'warning.main', position: 'absolute', bottom: 2, right: 2, }} /> </Tooltip> ); } if (status === EOcrStatus.DONE) { return ( <Tooltip title="Текст распознан"> <CheckCircleIcon sx={{ fontSize: 14, color: 'success.main', position: 'absolute', bottom: 2, right: 2, }} /> </Tooltip> ); } if (status === EOcrStatus.ERROR) { return ( <Tooltip title={error || 'Ошибка распознавания'}> <ErrorIcon sx={{ fontSize: 14, color: 'error.main', position: 'absolute', bottom: 2, right: 2, }} /> </Tooltip> ); } return null; }; /** * Иконка прикреплённого файла с кнопкой удаления и индикатором OCR. * При клике открывает модальное окно просмотра файла. */ export const DiaryFileIcon = ({ file, onClick, onDelete, }: IDiaryFileIconProps) => { return ( <Box sx={{ position: 'relative', display: 'inline-flex' }}> <Tooltip title={file.originalName}> <Box sx={{ display: 'inline-flex', flexDirection: 'column', alignItems: 'center', width: 72, cursor: 'pointer', borderRadius: '8px', p: 0.5, '&:hover': { bgcolor: 'rgba(0,0,0,0.05)' }, }} onClick={() => onClick(file)} > {/* Иконка файла */} {getFileIcon(file.mimeType)} {/* Имя файла (обрезанное) */} <Typography variant="caption" sx={{ fontSize: '0.75rem', textAlign: 'center', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', width: '100%', }} > {file.originalName} </Typography> </Box> </Tooltip> {/* Индикатор статуса OCR — вне Tooltip с именем файла, чтобы тултипы не перекрывались */} <OcrStatusBadge status={file.ocrStatus} error={file.ocrError} /> {/* Кнопка удаления */} <IconButton size="small" sx={{ position: 'absolute', top: -6, right: -6, width: 22, height: 22, bgcolor: 'background.paper', border: '1px solid', borderColor: 'divider', '&:hover': { bgcolor: 'error.light', color: 'white' }, }} onClick={(e) => { e.stopPropagation(); // не открывать просмотрщик onDelete(file.id); }} > <CloseIcon sx={{ fontSize: 14 }} /> </IconButton> </Box> ); };