feat(client): add resize button and status badge to GalleryGrid
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
import AutoFixHighOutlinedIcon from '@mui/icons-material/AutoFixHighOutlined'
|
||||
import CheckCircleOutlineOutlinedIcon from '@mui/icons-material/CheckCircleOutlineOutlined'
|
||||
import DeleteOutlineOutlinedIcon from '@mui/icons-material/DeleteOutlineOutlined'
|
||||
import Box from '@mui/material/Box'
|
||||
import Chip from '@mui/material/Chip'
|
||||
import IconButton from '@mui/material/IconButton'
|
||||
import Tooltip from '@mui/material/Tooltip'
|
||||
import { OptimizedImage } from '@/shared/ui/OptimizedImage'
|
||||
@@ -8,10 +11,12 @@ import type { GalleryImageItem } from '../model/types'
|
||||
type Props = {
|
||||
items: GalleryImageItem[]
|
||||
deleting?: boolean
|
||||
resizing?: string | null
|
||||
onDelete: (id: string) => void
|
||||
onResize: (id: string) => void
|
||||
}
|
||||
|
||||
export function GalleryGrid({ items, deleting, onDelete }: Props) {
|
||||
export function GalleryGrid({ items, deleting, resizing, onDelete, onResize }: Props) {
|
||||
return (
|
||||
<Box
|
||||
sx={{
|
||||
@@ -38,23 +43,56 @@ export function GalleryGrid({ items, deleting, onDelete }: Props) {
|
||||
sizes="140px"
|
||||
sx={{ width: '100%', height: '100%', objectFit: 'cover', display: 'block' }}
|
||||
/>
|
||||
<Tooltip title="Удалить из галереи">
|
||||
<IconButton
|
||||
size="small"
|
||||
color="error"
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
top: 4,
|
||||
right: 4,
|
||||
bgcolor: 'background.paper',
|
||||
'&:hover': { bgcolor: 'error.light', color: 'error.contrastText' },
|
||||
}}
|
||||
disabled={deleting}
|
||||
onClick={() => onDelete(item.id)}
|
||||
>
|
||||
<DeleteOutlineOutlinedIcon fontSize="small" />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<Box sx={{ position: 'absolute', top: 4, left: 4 }}>
|
||||
{item.isResized ? (
|
||||
<Chip
|
||||
label="Готово"
|
||||
size="small"
|
||||
color="success"
|
||||
icon={<CheckCircleOutlineOutlinedIcon fontSize="small" />}
|
||||
sx={{ height: 24, '& .MuiChip-label': { px: 0.75 }, '& .MuiChip-icon': { fontSize: 14, ml: 0.5 } }}
|
||||
/>
|
||||
) : (
|
||||
<Chip
|
||||
label="Не обработано"
|
||||
size="small"
|
||||
color="warning"
|
||||
sx={{ height: 24, '& .MuiChip-label': { px: 0.75 } }}
|
||||
/>
|
||||
)}
|
||||
</Box>
|
||||
<Box sx={{ position: 'absolute', top: 4, right: 4, display: 'flex', gap: 0.5 }}>
|
||||
{!item.isResized && (
|
||||
<Tooltip title="Обработать (resize)">
|
||||
<IconButton
|
||||
size="small"
|
||||
color="primary"
|
||||
sx={{
|
||||
bgcolor: 'background.paper',
|
||||
'&:hover': { bgcolor: 'primary.light', color: 'primary.contrastText' },
|
||||
}}
|
||||
disabled={resizing === item.id}
|
||||
onClick={() => onResize(item.id)}
|
||||
>
|
||||
<AutoFixHighOutlinedIcon fontSize="small" />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
)}
|
||||
<Tooltip title="Удалить из галереи">
|
||||
<IconButton
|
||||
size="small"
|
||||
color="error"
|
||||
sx={{
|
||||
bgcolor: 'background.paper',
|
||||
'&:hover': { bgcolor: 'error.light', color: 'error.contrastText' },
|
||||
}}
|
||||
disabled={deleting}
|
||||
onClick={() => onDelete(item.id)}
|
||||
>
|
||||
<DeleteOutlineOutlinedIcon fontSize="small" />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
</Box>
|
||||
</Box>
|
||||
))}
|
||||
</Box>
|
||||
|
||||
@@ -6,7 +6,7 @@ import Stack from '@mui/material/Stack'
|
||||
import Typography from '@mui/material/Typography'
|
||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
|
||||
import { fetchAdminCatalogSlider } from '@/entities/catalog-slider'
|
||||
import { deleteGalleryImage, fetchAdminGallery, GalleryGrid } from '@/entities/gallery'
|
||||
import { deleteGalleryImage, fetchAdminGallery, GalleryGrid, resizeGalleryImage } from '@/entities/gallery'
|
||||
import { uploadAdminProductImages } from '@/entities/product/api/product-api'
|
||||
import { formatAdminImageMaxSizeHint } from '@/shared/constants/upload-limits'
|
||||
import { invalidateQueryKeys } from '@/shared/lib/invalidate-query-keys'
|
||||
@@ -50,6 +50,13 @@ export function AdminGalleryPage() {
|
||||
},
|
||||
})
|
||||
|
||||
const resizeMut = useMutation({
|
||||
mutationFn: (id: string) => resizeGalleryImage(id),
|
||||
onSuccess: () => {
|
||||
void invalidateQueryKeys(queryClient, [['admin', 'gallery'], ['admin', 'catalog-slider'], ['catalog-slider']])
|
||||
},
|
||||
})
|
||||
|
||||
const items = galleryQuery.data?.items ?? []
|
||||
|
||||
return (
|
||||
@@ -122,7 +129,13 @@ export function AdminGalleryPage() {
|
||||
</Typography>
|
||||
)}
|
||||
|
||||
<GalleryGrid items={items} deleting={deleteMut.isPending} onDelete={(id) => deleteMut.mutate(id)} />
|
||||
<GalleryGrid
|
||||
items={items}
|
||||
deleting={deleteMut.isPending}
|
||||
resizing={resizeMut.isPending ? (resizeMut.variables ?? null) : null}
|
||||
onDelete={(id) => deleteMut.mutate(id)}
|
||||
onResize={(id) => resizeMut.mutate(id)}
|
||||
/>
|
||||
|
||||
{!galleryQuery.isLoading && items.length === 0 && (
|
||||
<Typography color="text.secondary">Пока нет загруженных изображений.</Typography>
|
||||
|
||||
Reference in New Issue
Block a user