197 lines
4.9 KiB
TypeScript
197 lines
4.9 KiB
TypeScript
import {useEffect, useState} from 'react';
|
||
import styled from 'styled-components';
|
||
import {getProductAmount} from '../../utils/product';
|
||
import type {Product} from '../../types/cart';
|
||
import {reachGoal} from "../../hooks/useYM";
|
||
|
||
interface CartItemProps {
|
||
product: Product;
|
||
isProcessing: boolean;
|
||
onOpen: () => void;
|
||
onReplace: () => void;
|
||
onDelete: () => void;
|
||
}
|
||
|
||
export function CartItem({
|
||
product,
|
||
isProcessing,
|
||
onOpen,
|
||
onReplace,
|
||
onDelete,
|
||
}: CartItemProps) {
|
||
const [isMenuOpen, setIsMenuOpen] = useState(false);
|
||
useEffect(() => {
|
||
if (isMenuOpen) {
|
||
reachGoal('ac_product_replacement_menu_' + product.name);
|
||
}
|
||
}, [product.name, isMenuOpen])
|
||
|
||
return (
|
||
<Item $processing={isProcessing}>
|
||
<ItemImage type="button" onClick={onOpen}>
|
||
<img src={product.image} alt=""/>
|
||
</ItemImage>
|
||
|
||
<ItemDetails>
|
||
<ItemName>{product.name}</ItemName>
|
||
<ItemPrice>
|
||
{getProductAmount(product)} × {Math.round(product.price * 100) / 100} ₽
|
||
</ItemPrice>
|
||
</ItemDetails>
|
||
|
||
<MenuWrapper>
|
||
<MenuButton
|
||
type="button"
|
||
onClick={() => setIsMenuOpen(value => !value)}
|
||
>
|
||
⋮
|
||
</MenuButton>
|
||
|
||
{isMenuOpen && (
|
||
<>
|
||
<Overlay onClick={() => setIsMenuOpen(false)}>
|
||
</Overlay>
|
||
<Dropdown>
|
||
<ul>
|
||
<li>
|
||
<button type="button" onClick={onReplace}>
|
||
Заменить
|
||
</button>
|
||
</li>
|
||
<li>
|
||
<button type="button" onClick={onDelete}>
|
||
Удалить
|
||
</button>
|
||
</li>
|
||
</ul>
|
||
</Dropdown>
|
||
</>
|
||
)}
|
||
</MenuWrapper>
|
||
</Item>
|
||
);
|
||
}
|
||
|
||
const Item = styled.li<{ $processing: boolean }>`
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: stretch;
|
||
padding: 16px 0;
|
||
border-bottom: 1px solid #E7EDE7;
|
||
position: relative;
|
||
transition: opacity 0.4s, transform 0.4s;
|
||
opacity: ${({$processing}) => ($processing ? 0.5 : 1)};
|
||
pointer-events: ${({$processing}) => ($processing ? 'none' : 'auto')};
|
||
`;
|
||
|
||
const ItemImage = styled.button`
|
||
width: 72px;
|
||
height: 65px;
|
||
border-radius: 8px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin-right: 16px;
|
||
flex-shrink: 0;
|
||
position: relative;
|
||
overflow: hidden;
|
||
border: 0;
|
||
background: transparent;
|
||
cursor: pointer;
|
||
|
||
img {
|
||
max-width: 100%;
|
||
max-height: 100%;
|
||
}
|
||
`;
|
||
|
||
const ItemDetails = styled.div`
|
||
flex: 1 1 100%;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
flex-direction: column;
|
||
`;
|
||
|
||
const ItemName = styled.div`
|
||
font-size: 15px;
|
||
color: ${({theme}) => theme.colors.darkGreen};
|
||
margin-bottom: 4px;
|
||
`;
|
||
|
||
const ItemPrice = styled.div`
|
||
font-size: 14px;
|
||
color: ${({theme}) => theme.colors.darkGreen};
|
||
`;
|
||
|
||
const MenuWrapper = styled.div`
|
||
position: relative;
|
||
width: 26px;
|
||
display: flex;
|
||
align-self: flex-start;
|
||
`;
|
||
|
||
const MenuButton = styled.button`
|
||
background: none;
|
||
border: none;
|
||
color: #CEDFD0;
|
||
cursor: pointer;
|
||
padding: 4px 8px;
|
||
font-size: 20px;
|
||
letter-spacing: 2px;
|
||
border-radius: 4px;
|
||
transition: 0.2s;
|
||
position: absolute;
|
||
top: 0; right: 0;
|
||
|
||
&:hover {
|
||
background: #f3f4f6;
|
||
color: ${({theme}) => theme.colors.darkGreen};
|
||
}
|
||
`;
|
||
|
||
const Overlay = styled.div`
|
||
height: 100svh;
|
||
position: fixed;
|
||
display: flex;
|
||
inset: 0;
|
||
background-color: rgba(0, 0, 0, 0);
|
||
justify-content: center;
|
||
align-items: center;
|
||
z-index: 9;
|
||
overflow: auto;
|
||
`;
|
||
|
||
const Dropdown = styled.div`
|
||
position: absolute;
|
||
right: 0;
|
||
top: 100%;
|
||
background: #ffffff;
|
||
border-radius: 8px;
|
||
box-shadow: 0 11px 29px rgba(0, 0, 0, 0.06);
|
||
min-width: 150px;
|
||
padding: 10px;
|
||
z-index: 10;
|
||
margin-top: 4px;
|
||
|
||
ul {
|
||
list-style: none;
|
||
}
|
||
|
||
button {
|
||
width: 100%;
|
||
padding: 10px 16px;
|
||
font-size: 14px;
|
||
color: ${({theme}) => theme.colors.darkGreen};
|
||
cursor: pointer;
|
||
transition: 0.2s;
|
||
background: transparent;
|
||
border: 0;
|
||
border-radius: 8px;
|
||
text-align: center;
|
||
|
||
&:hover {
|
||
background: #5EA12D;
|
||
color: #fff;
|
||
}
|
||
}
|
||
`; |