Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 96 additions & 0 deletions src/components/ActionButtons/ActionButtons.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import React, { useState } from 'react';
import { useCart } from '../../context/context';
import './ActionButtons.scss';

const ActionButtons = ({
onPlay,
onAddToCart,
onBuyNow,
movie,
variant = 'primary' // primary, secondary, compact
}) => {
const { cart } = useCart();
const [isAdding, setIsAdding] = useState(false);

const isInCart = cart.some(item => item.id === movie?.id);

const handleAddToCart = async () => {
if (isInCart || isAdding) return;

setIsAdding(true);
await onAddToCart();

setTimeout(() => {
setIsAdding(false);
}, 1000);
};

const getAddToCartText = () => {
if (isAdding) return '✓ Adding...';
if (isInCart) return '✓ In Cart';
return '+ My List';
};

const getAddToCartClass = () => {
let baseClass = `action-buttons__btn action-buttons__btn--${variant}`;
if (isInCart) baseClass += ' action-buttons__btn--added';
if (isAdding) baseClass += ' action-buttons__btn--adding';
return baseClass;
};

return (
<div className={`action-buttons action-buttons--${variant}`}>
{onPlay && (
<button
onClick={onPlay}
className="action-buttons__btn action-buttons__btn--play"
aria-label="Play trailer"
>
<svg className="play-icon" viewBox="0 0 24 24" fill="currentColor">
<path d="M8 5v14l11-7z"/>
</svg>
Play
</button>
)}

<button
onClick={handleAddToCart}
className={getAddToCartClass()}
disabled={isInCart || isAdding}
aria-label={isInCart ? 'Already in list' : 'Add to my list'}
>
{variant === 'compact' ? (
<svg className="list-icon" viewBox="0 0 24 24" fill="currentColor">
<path d="M19 13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
</svg>
) : (
getAddToCartText()
)}
</button>

{onBuyNow && (
<button
onClick={onBuyNow}
className="action-buttons__btn action-buttons__btn--buy"
aria-label="Buy now"
>
<svg className="buy-icon" viewBox="0 0 24 24" fill="currentColor">
<path d="M7 18c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zM1 2v2h2l3.6 7.59-1.35 2.45c-.16.28-.25.61-.25.96 0 1.1.9 2 2 2h12v-2H7.42c-.14 0-.25-.11-.25-.25l.03-.12L8.1 13h7.45c.75 0 1.41-.41 1.75-1.03L21.7 4H5.21l-.94-2H1zm16 16c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"/>
</svg>
Buy ${movie?.price || 9.99}
</button>
)}

<button
className="action-buttons__btn action-buttons__btn--more"
aria-label="More options"
>
<svg className="more-icon" viewBox="0 0 24 24" fill="currentColor">
<path d="M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"/>
</svg>
</button>
</div>
);
};

export default ActionButtons;
234 changes: 234 additions & 0 deletions src/components/ActionButtons/ActionButtons.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
@use '../../styles/variables' as *;

.action-buttons {
display: flex;
align-items: center;
gap: $spacing-md;
flex-wrap: wrap;

&__btn {
display: flex;
align-items: center;
gap: $spacing-sm;
padding: $spacing-md $spacing-xl;
border: none;
border-radius: $radius-md;
font-size: $font-size-base;
font-weight: $font-weight-semibold;
font-family: $font-family-primary;
cursor: pointer;
transition: $transition-all;
position: relative;
overflow: hidden;

// Icon sizing
svg {
width: 20px;
height: 20px;
transition: $transition-all;
}

// Hover effect
&::before {
content: '';
position: absolute;
top: 0;
left: -100%;
width: 100%;
height: 100%;
background: linear-gradient(
90deg,
transparent,
rgba(255, 255, 255, 0.2),
transparent
);
transition: left 0.5s;
}

&:hover::before {
left: 100%;
}

&:hover {
transform: translateY(-2px);
box-shadow: $shadow-lg;
}

&:active {
transform: translateY(0);
}

&:disabled {
opacity: 0.6;
cursor: not-allowed;
transform: none;

&:hover::before {
left: -100%;
}
}

// Play button - primary CTA
&--play {
background: $text-primary;
color: #000;
font-weight: $font-weight-bold;
padding: $spacing-md $spacing-2xl;

.play-icon {
width: 24px;
height: 24px;
}

&:hover {
background: rgba(255, 255, 255, 0.8);
box-shadow: 0 8px 25px rgba(255, 255, 255, 0.3);
}
}

// Add to list button
&--primary {
background: rgba(109, 109, 110, 0.7);
color: $text-primary;
border: 1px solid rgba(255, 255, 255, 0.3);
backdrop-filter: blur(10px);

&:hover {
background: rgba(109, 109, 110, 0.9);
border-color: rgba(255, 255, 255, 0.5);
}

&--added {
background: rgba(76, 175, 80, 0.7);
border-color: rgba(76, 175, 80, 0.8);

&:hover {
background: rgba(76, 175, 80, 0.8);
}
}

&--adding {
background: rgba(255, 193, 7, 0.7);
border-color: rgba(255, 193, 7, 0.8);
}
}

// Buy button
&--buy {
background: $netflix-red;
color: $text-primary;

.buy-icon {
width: 18px;
height: 18px;
}

&:hover {
background: $netflix-red-dark;
box-shadow: 0 8px 25px rgba(229, 9, 20, 0.4);
}
}

// More options button
&--more {
background: transparent;
color: $text-secondary;
border: 1px solid rgba(255, 255, 255, 0.3);
padding: $spacing-md;
border-radius: $radius-full;

.more-icon {
width: 20px;
height: 20px;
}

&:hover {
background: rgba(255, 255, 255, 0.1);
color: $text-primary;
border-color: rgba(255, 255, 255, 0.5);
}
}
}

// Compact variant for smaller spaces
&--compact {
gap: $spacing-sm;

.action-buttons__btn {
padding: $spacing-sm;
border-radius: $radius-full;

&--play {
padding: $spacing-sm $spacing-lg;
border-radius: $radius-md;
}

svg {
width: 18px;
height: 18px;
}
}
}

// Secondary variant with different styling
&--secondary {
.action-buttons__btn {
background: transparent;
border: 1px solid $border-primary;
color: $text-secondary;

&:hover {
background: $surface-primary;
color: $text-primary;
border-color: $border-secondary;
}

&--play {
background: $text-primary;
color: #000;
border: none;

&:hover {
background: rgba(255, 255, 255, 0.8);
}
}
}
}
}

// Responsive design
@media (max-width: $breakpoint-md) {
.action-buttons {
flex-direction: column;
align-items: stretch;
gap: $spacing-sm;

&__btn {
justify-content: center;
padding: $spacing-md;

&--play {
order: -1; // Play button first on mobile
}
}

&--compact {
flex-direction: row;
justify-content: center;
}
}
}

// Animation keyframes
@keyframes pulse {
0%, 100% {
transform: scale(1);
}
50% {
transform: scale(1.05);
}
}

.action-buttons__btn--adding {
animation: pulse 1s ease-in-out infinite;
}
Loading