import React from 'react'; import { motion, AnimatePresence } from 'framer-motion'; import { FileText, File, Eye, MoreVertical, Edit3, Share2, Trash2, Lock, ExternalLink, Download, Clock, AlertCircle } from 'lucide-react'; import type { Asset } from '../../../types/assets'; import type { User } from '../../../types/auth'; import { axiosInstance } from '../../../services/axios'; interface AssetCardProps { asset: Asset; user: User | null; activeMenuId: string | null; setActiveMenuId: (id: string | null) => void; onViewDetails: (asset: Asset) => void; onEdit: (asset: Asset) => void; onShare: (asset: Asset) => void; onDelete: (assetId: string) => void; onOpenViewer: (asset: Asset) => void; onDownload: (asset: Asset) => void; onRequestDownload: (asset: Asset) => void; isSelected?: boolean; onToggleSelect?: (assetId: string) => void; isExpanded?: boolean; onToggleExpand?: () => void; } export const AssetCard: React.FC = ({ asset, user, activeMenuId, setActiveMenuId, onViewDetails, onEdit, onShare, onDelete, onOpenViewer, onDownload, onRequestDownload, isSelected = false, onToggleSelect, isExpanded = false, onToggleExpand }) => { const isMenuOpen = activeMenuId === asset.id; const canDirectDownload = user?.role === 'ADMIN' || asset.isDownloadable || asset.downloadRequests?.[0]?.status === 'APPROVED'; const requestStatus = asset.downloadRequests?.[0]?.status; const formatBytes = (bytes: number, decimals = 2) => { if (bytes === 0) return '0 Bytes'; const k = 1024; const dm = decimals < 0 ? 0 : decimals; const sizes = ['Bytes', 'KB', 'MB', 'GB']; const i = Math.floor(Math.log(bytes) / Math.log(k)); return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i]; }; const isRenderable = (type: string, url: string) => { const isOffice = type.includes('word') || type.includes('presentation') || type.includes('sheet') || url.toLowerCase().endsWith('.docx') || url.toLowerCase().endsWith('.doc') || url.toLowerCase().endsWith('.pptx') || url.toLowerCase().endsWith('.ppt') || url.toLowerCase().endsWith('.xlsx') || url.toLowerCase().endsWith('.xls'); return type === 'url' || type.includes('pdf') || type.includes('image') || type.includes('png') || type.includes('jpg') || isOffice; }; const getFullAssetUrl = (url: string) => { let resolvedUrl = url; if (!url.startsWith('http')) { const backendBase = axiosInstance.defaults.baseURL || '/api/v1'; const relativeHost = backendBase.replace('/api/v1', ''); resolvedUrl = relativeHost.startsWith('/') || relativeHost === '' ? `${window.location.origin}${relativeHost}${url}` : `${relativeHost}${url}`; } const currentOrigin = window.location.origin; const isCurrentOriginLocal = currentOrigin.includes('localhost') || currentOrigin.includes('127.0.0.1'); if (!isCurrentOriginLocal && (resolvedUrl.includes('localhost') || resolvedUrl.includes('127.0.0.1'))) { resolvedUrl = resolvedUrl.replace(/https?:\/\/(localhost|127\.0\.0\.1)(:\d+)?/, currentOrigin); } return resolvedUrl; }; const isImage = asset.type.includes('image') || asset.type.includes('png') || asset.type.includes('jpg') || asset.url.match(/\.(png|jpe?g|gif|svg|webp)$/i); const isPdf = asset.type.includes('pdf') || asset.url.toLowerCase().endsWith('.pdf'); const isWord = asset.type.includes('word') || asset.url.toLowerCase().endsWith('.docx') || asset.url.toLowerCase().endsWith('.doc'); const isPresentation = asset.type.includes('presentation') || asset.url.toLowerCase().endsWith('.pptx') || asset.url.toLowerCase().endsWith('.ppt'); const isSpreadsheet = asset.type.includes('sheet') || asset.url.toLowerCase().endsWith('.xlsx') || asset.url.toLowerCase().endsWith('.xls') || asset.url.toLowerCase().endsWith('.csv'); const hasBanner = isImage || !!asset.thumbnailUrl; const bannerSrc = asset.thumbnailUrl ? asset.thumbnailUrl : asset.url; return ( { const target = e.target as HTMLElement; if (target.closest('button') || target.closest('a') || target.closest('input') || target.closest('.toggle-expand-btn')) { return; } onViewDetails(asset); }} className={`group bg-ink-0 border rounded-xl p-4 transition-all duration-300 flex flex-col justify-between cursor-pointer min-h-[410px] ${ isExpanded ? 'absolute z-20 top-0 left-0 right-0 h-auto shadow-2xl border-ink-300 bg-ink-0' : 'relative w-full h-full border-ink-200 hover:border-ink-300 hover:shadow-md hover:-translate-y-0.5' } ${isSelected ? 'border-ink-900 ring-1 ring-ink-900 bg-ink-50/30' : ''}`} >
{/* Visual Thumbnail Area */}
{/* Absolute overlays for controls */}
{user?.role === 'ADMIN' && onToggleSelect && ( onToggleSelect(asset.id)} className="w-3.5 h-3.5 rounded border-ink-300 bg-ink-0 text-ink-900 focus:ring-ink-900/10 cursor-pointer shadow-sm" /> )}
{isRenderable(asset.type, asset.url) && ( )}
{isMenuOpen && ( <>
setActiveMenuId(null)} />
{user?.role === 'ADMIN' && ( <> )}
)}
{/* Thumbnail Preview Area Content */} {hasBanner ? ( {asset.title} { e.currentTarget.style.display = 'none'; const placeholder = document.getElementById(`fallback-${asset.id}`); if (placeholder) placeholder.style.display = 'flex'; }} /> ) : null}
{isPdf ? (
PDF Document
PDF RESOURCE
) : isPresentation ? (
PRESENTATION PPTX
) : isWord ? (
Word Doc
DOCX RESOURCE
) : isSpreadsheet ? (
Spreadsheet
XLSX SHEET EXCEL
) : (
Resource File
BINARY {asset.type.split('/').pop() || 'FILE'}
)}
{asset.categoryId || 'General'}
{!asset.isDownloadable && (
Strict View Only
)}

{asset.title}

{asset.description && (

{asset.description}

)}

{asset.type === 'case_study' ? 'Case Study' : asset.type === 'url' ? 'External Link' : formatBytes(asset.size)} • {new Date(asset.createdAt).toLocaleDateString()}

{asset.type === 'case_study' && (asset.problemStatement || asset.solution) && ( )}
{asset.type === 'case_study' && isExpanded && (asset.problemStatement || asset.solution) && ( {asset.problemStatement && (
Problem / Challenge

{asset.problemStatement}

)} {asset.solution && (
Our Approach

{asset.solution}

)}
)}
{asset.type === 'url' || asset.type === 'case_study' ? 'Type' : 'Downloads'} {asset.type === 'case_study' ? 'Case Study' : asset.type === 'url' ? 'URL Link' : asset.downloadsCount}
{asset.type === 'url' || asset.type === 'case_study' ? ( ) : canDirectDownload ? ( ) : requestStatus === 'PENDING' ? (
Pending Access
) : requestStatus === 'REJECTED' ? ( ) : ( )}
); };