This commit is contained in:
@kirill.komarov
2026-05-13 12:33:46 +05:00
parent c6228dfaab
commit 40483679de
3 changed files with 150 additions and 27 deletions
+13 -14
View File
@@ -1,14 +1,13 @@
import type { ReactNode } from 'react'
import { useMemo, useRef } from 'react'
import { useCallback, useMemo, useRef } from 'react'
import Box from '@mui/material/Box'
import Card from '@mui/material/Card'
import CardContent from '@mui/material/CardContent'
import CardMedia from '@mui/material/CardMedia'
import Chip from '@mui/material/Chip'
import Link from '@mui/material/Link'
import Stack from '@mui/material/Stack'
import Typography from '@mui/material/Typography'
import { Link as RouterLink } from 'react-router-dom'
import { useNavigate } from 'react-router-dom'
import { Swiper, SwiperSlide } from 'swiper/react'
import 'swiper/css'
import type { Product } from '@/entities/product/model/types'
@@ -18,6 +17,7 @@ import type { Swiper as SwiperType } from 'swiper/types'
type Props = { product: Product; mediaHeight?: number; actions?: ReactNode }
export function ProductCard({ product, mediaHeight = 200, actions }: Props) {
const navigate = useNavigate()
const swiperRef = useRef<SwiperType | null>(null)
const imageUrls = useMemo(() => {
const fromImages = (product.images ?? [])
@@ -40,6 +40,10 @@ export function ProductCard({ product, mediaHeight = 200, actions }: Props) {
swiperRef.current.slideTo(idx, 0)
}
const goToProduct = useCallback(() => {
navigate(`/products/${product.id}`)
}, [navigate, product.id])
const stockLabel =
product.inStock && product.quantity === 0
? { label: 'Нет в наличии', color: 'default' as const }
@@ -49,7 +53,9 @@ export function ProductCard({ product, mediaHeight = 200, actions }: Props) {
return (
<Card
onClick={goToProduct}
sx={{
cursor: 'pointer',
height: '100%',
display: 'flex',
flexDirection: 'column',
@@ -64,6 +70,7 @@ export function ProductCard({ product, mediaHeight = 200, actions }: Props) {
boxShadow: '0 8px 30px rgba(0,0,0,0.10)',
},
'&:hover .product-card__media': { transform: 'scale(1.06)' },
'&:hover .product-card__title': { color: 'primary.main' },
'@media (prefers-reduced-motion: reduce)': {
transition: 'none',
'&:hover': { transform: 'none' },
@@ -71,13 +78,7 @@ export function ProductCard({ product, mediaHeight = 200, actions }: Props) {
},
}}
>
<Link
component={RouterLink}
to={`/products/${product.id}`}
underline="none"
color="inherit"
sx={{ display: 'block', position: 'relative' }}
>
<Box sx={{ position: 'relative' }}>
{imageUrls.length ? (
<Box onMouseMove={onMouseMove} sx={{ height: mediaHeight, overflow: 'hidden' }}>
<Swiper
@@ -144,7 +145,7 @@ export function ProductCard({ product, mediaHeight = 200, actions }: Props) {
}}
/>
)}
</Link>
</Box>
<CardContent sx={{ flexGrow: 1, p: 2, '&:last-child': { pb: 2 } }}>
<Stack spacing={1.25}>
@@ -159,15 +160,13 @@ export function ProductCard({ product, mediaHeight = 200, actions }: Props) {
<Typography
variant="subtitle1"
component={RouterLink}
to={`/products/${product.id}`}
className="product-card__title"
sx={{
textDecoration: 'none',
color: 'text.primary',
fontWeight: 600,
lineHeight: 1.3,
transition: 'color 150ms ease',
'&:hover': { color: 'primary.main' },
}}
>
{product.title}