'use client'; import React, { ReactNode, HTMLAttributes, forwardRef } from 'react'; import Link from 'next/link'; import { cn } from '@/lib/utils'; import { Card } from '@/components/ui'; // Base card sizes export type CardSize = 'sm' | 'md' | 'lg'; // Base card layouts export type CardLayout = 'vertical' | 'horizontal'; // Base card props interface export interface BaseCardProps extends Omit, 'title'> { /** Card title */ title?: ReactNode; /** Card description/excerpt */ description?: ReactNode; /** Card image URL */ image?: string; /** Card image alt text */ imageAlt?: string; /** Card size */ size?: CardSize; /** Card layout */ layout?: CardLayout; /** Card href/link */ href?: string; /** Card badge/badges */ badge?: ReactNode; /** Card footer content */ footer?: ReactNode; /** Card header content */ header?: ReactNode; /** Loading state */ loading?: boolean; /** Hover effect */ hoverable?: boolean; /** Card variant */ variant?: 'elevated' | 'flat' | 'bordered'; /** Image height */ imageHeight?: 'sm' | 'md' | 'lg' | 'xl'; /** Children content */ children?: ReactNode; } // Helper function to get size styles const getSizeStyles = (size: CardSize, layout: CardLayout) => { const sizeMap = { vertical: { sm: { container: 'max-w-xs', image: 'h-32', padding: 'p-3' }, md: { container: 'max-w-sm', image: 'h-48', padding: 'p-4' }, lg: { container: 'max-w-md', image: 'h-64', padding: 'p-6' }, }, horizontal: { sm: { container: 'max-w-sm', image: 'h-24 w-24', padding: 'p-3' }, md: { container: 'max-w-lg', image: 'h-32 w-32', padding: 'p-4' }, lg: { container: 'max-w-xl', image: 'h-40 w-40', padding: 'p-6' }, }, }; return sizeMap[layout][size]; }; // Helper function to get image height const getImageHeight = (height: CardSize | 'sm' | 'md' | 'lg' | 'xl') => { const heightMap = { sm: 'h-32', md: 'h-48', lg: 'h-64', xl: 'h-80', }; return heightMap[height] || heightMap['md']; }; // Skeleton loader component const CardSkeleton = ({ layout, size }: { layout: CardLayout; size: CardSize }) => { const sizeStyles = getSizeStyles(size, layout); return (
); }; // Main BaseCard Component export const BaseCard = forwardRef( ( { title, description, image, imageAlt = '', size = 'md', layout = 'vertical', href, badge, footer, header, loading = false, hoverable = true, variant = 'elevated', imageHeight, className = '', children, ...props }, ref ) => { const sizeStyles = getSizeStyles(size, layout); // Loading state if (loading) { return ; } // Content sections const renderImage = () => { if (!image) return null; const imageClasses = layout === 'horizontal' ? cn('flex-shrink-0 overflow-hidden rounded-lg', sizeStyles.image) : cn('w-full overflow-hidden rounded-t-lg', imageHeight ? getImageHeight(imageHeight) : sizeStyles.image); return (
{/* eslint-disable-next-line @next/next/no-img-element */} {imageAlt}
); }; const renderHeader = () => { if (!header && !badge) return null; return (
{header} {badge}
); }; const renderTitle = () => { if (!title) return null; return (

{title}

); }; const renderDescription = () => { if (!description) return null; return (
{description}
); }; const renderFooter = () => { if (!footer) return null; return (
{footer}
); }; // Card content const cardContent = (
{layout === 'horizontal' && renderImage()}
{renderHeader()} {renderTitle()} {renderDescription()} {children} {renderFooter()}
{layout === 'vertical' && renderImage()}
); // If href is provided, wrap in a Next.js Link if (href) { return ( {cardContent} ); } // Otherwise, just return the card return ( {cardContent} ); } ); BaseCard.displayName = 'BaseCard';