Files
sam-sales/ref/components/SalesCard.tsx
2025-12-17 13:25:40 +09:00

125 lines
5.5 KiB
TypeScript

import React from 'react';
import { SalesAsset, AssetType } from '../types';
import { Play, ArrowUpRight, BarChart3, Image as ImageIcon } from 'lucide-react';
interface SalesCardProps {
asset: SalesAsset;
onClick: (asset: SalesAsset) => void;
}
const SalesCard: React.FC<SalesCardProps> = ({ asset, onClick }) => {
const baseClasses = `
group relative overflow-hidden rounded-2xl bg-white border border-slate-100 shadow-sm hover:shadow-xl hover:-translate-y-1 transition-all duration-300 ease-out cursor-pointer
${asset.gridSpan === 'col-span-2' ? 'md:col-span-2' : 'md:col-span-1'}
${asset.rowSpan === 'row-span-2' ? 'md:row-span-2' : 'md:row-span-1'}
flex flex-col
`;
// Handle click properly
const handleClick = (e: React.MouseEvent) => {
// Prevent triggering if clicking specific action buttons if needed,
// but generally the whole card should open the modal.
onClick(asset);
};
// Render Video Card
if (asset.type === AssetType.VIDEO) {
return (
<div className={`${baseClasses} bg-slate-900 text-white min-h-[300px]`} onClick={handleClick}>
<div className="absolute inset-0 w-full h-full pointer-events-none">
{/* Pointer events none on iframe to allow card click, or use a cover div */}
<iframe
src={`https://player.vimeo.com/video/${asset.src}?background=1&autoplay=0&loop=0&byline=0&title=0`}
className="w-full h-full object-cover opacity-60 group-hover:opacity-40 transition-opacity duration-500"
frameBorder="0"
allow="autoplay; fullscreen; picture-in-picture"
title={asset.videoTitle}
></iframe>
</div>
<div className="relative z-10 p-6 flex flex-col h-full justify-between pointer-events-none">
<div className="flex justify-between items-start">
<span className="bg-red-600 text-white text-xs font-bold px-2 py-1 rounded-full uppercase tracking-wider flex items-center gap-1">
<Play size={10} fill="currentColor" /> Video
</span>
</div>
<div>
<h3 className="text-2xl font-bold mb-2 leading-tight">{asset.title}</h3>
<p className="text-slate-300 text-sm line-clamp-2">{asset.description}</p>
</div>
<div className="mt-4 inline-flex items-center gap-2 text-sm font-medium text-white/80 group-hover:text-red-400 transition-colors">
<ArrowUpRight size={16} />
</div>
</div>
</div>
);
}
// Render Image Card
if (asset.type === AssetType.IMAGE) {
return (
<div className={`${baseClasses} min-h-[250px]`} onClick={handleClick}>
<div className="absolute inset-0">
<img
src={asset.src}
alt={asset.title}
className="w-full h-full object-cover transition-transform duration-700 group-hover:scale-110"
/>
<div className="absolute inset-0 bg-gradient-to-t from-black/80 via-transparent to-transparent opacity-80" />
</div>
<div className="relative z-10 p-6 mt-auto text-white h-full flex flex-col justify-end">
<div className="mb-auto">
<span className="bg-white/20 backdrop-blur-md text-white text-xs font-bold px-2 py-1 rounded-full uppercase tracking-wider inline-flex items-center gap-1">
<ImageIcon size={10} /> Image
</span>
</div>
<h3 className="text-xl font-bold mb-1">{asset.title}</h3>
<p className="text-slate-200 text-sm">{asset.description}</p>
</div>
</div>
);
}
// Render Stat Card
if (asset.type === AssetType.STAT) {
return (
<div className={`${baseClasses} bg-brand-600 text-white p-6 flex flex-col justify-between min-h-[200px]`} onClick={handleClick}>
<div className="flex justify-between items-start opacity-80">
<BarChart3 size={24} />
<span className="text-xs font-medium bg-white/10 px-2 py-1 rounded-lg">{asset.tags[0]}</span>
</div>
<div className="mt-4">
<div className="text-5xl font-extrabold tracking-tight mb-1">{asset.statValue}</div>
<div className="text-brand-100 font-medium">{asset.statLabel}</div>
</div>
<div className="mt-4 text-xs text-brand-100 opacity-60 flex items-center justify-between">
<span>* </span>
<ArrowUpRight size={16} />
</div>
</div>
);
}
// Render Text Card (Default)
return (
<div className={`${baseClasses} p-6 flex flex-col justify-between min-h-[200px] hover:border-brand-200`} onClick={handleClick}>
<div>
<div className="flex flex-wrap gap-2 mb-4">
{asset.tags.map(tag => (
<span key={tag} className="text-[10px] uppercase font-bold text-slate-500 bg-slate-100 px-2 py-1 rounded-md">
{tag}
</span>
))}
</div>
<h3 className="text-xl font-bold text-slate-900 mb-3">{asset.title}</h3>
<p className="text-slate-600 text-sm leading-relaxed line-clamp-4">{asset.content}</p>
</div>
<div className="mt-6 pt-4 border-t border-slate-100 flex items-center justify-between">
<span className="text-xs text-slate-400 font-medium group-hover:text-brand-600 transition-colors"> </span>
<ArrowUpRight size={16} className="text-slate-400 group-hover:text-brand-600 transition-colors" />
</div>
</div>
);
};
export default SalesCard;