Add src/components/ProductCard.tsx
This commit is contained in:
73
src/components/ProductCard.tsx
Normal file
73
src/components/ProductCard.tsx
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
'use client';
|
||||||
|
|
||||||
|
import Image from 'next/image';
|
||||||
|
import { Button } from '@/components/ui/button';
|
||||||
|
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@/components/ui/card';
|
||||||
|
|
||||||
|
interface StripeProduct {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
description: string | null;
|
||||||
|
images: string[];
|
||||||
|
default_price: {
|
||||||
|
id: string;
|
||||||
|
unit_amount: number;
|
||||||
|
currency: string;
|
||||||
|
} | null;
|
||||||
|
metadata: Record<string, string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ProductCardProps {
|
||||||
|
product: StripeProduct;
|
||||||
|
onCheckout: (productId: string, priceId: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function ProductCard({ product, onCheckout }: ProductCardProps) {
|
||||||
|
const formatPrice = (amount: number, currency: string) => {
|
||||||
|
return new Intl.NumberFormat('en-US', {
|
||||||
|
style: 'currency',
|
||||||
|
currency: currency.toUpperCase(),
|
||||||
|
}).format(amount / 100);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Card className="flex flex-col h-full overflow-hidden hover:shadow-lg transition-shadow">
|
||||||
|
{product.images[0] && (
|
||||||
|
<div className="relative aspect-square overflow-hidden">
|
||||||
|
<Image
|
||||||
|
src={product.images[0]}
|
||||||
|
alt={product.name}
|
||||||
|
fill
|
||||||
|
className="object-cover hover:scale-105 transition-transform duration-300"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<CardHeader className="flex-none">
|
||||||
|
<CardTitle className="line-clamp-1">{product.name}</CardTitle>
|
||||||
|
{product.default_price && (
|
||||||
|
<p className="text-2xl font-bold text-primary">
|
||||||
|
{formatPrice(product.default_price.unit_amount, product.default_price.currency)}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</CardHeader>
|
||||||
|
<CardContent className="flex-1">
|
||||||
|
{product.description && (
|
||||||
|
<CardDescription className="line-clamp-3">{product.description}</CardDescription>
|
||||||
|
)}
|
||||||
|
</CardContent>
|
||||||
|
<CardFooter>
|
||||||
|
<Button
|
||||||
|
className="w-full"
|
||||||
|
onClick={() => {
|
||||||
|
if (product.default_price) {
|
||||||
|
onCheckout(product.id, product.default_price.id);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
disabled={!product.default_price}
|
||||||
|
>
|
||||||
|
{product.default_price ? 'Buy Now' : 'Unavailable'}
|
||||||
|
</Button>
|
||||||
|
</CardFooter>
|
||||||
|
</Card>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user