overview / js /cards /ResourceCard.js
yjernite's picture
yjernite HF Staff
Upload 3 files
aeeb334 verified
raw
history blame
6.82 kB
// cards/ResourceCard.js - Resource card component for SPA
import { areasData } from '../data/areas.js';
export function createResourceCard(resource) {
// Get the primary area for this resource
const primaryArea = areasData[resource.areaTags[0]];
const primaryColor = primaryArea?.primaryColor || 'gray';
// Format date
const formattedDate = new Date(resource.date).toLocaleDateString('en-US', {
year: 'numeric',
month: 'short',
day: 'numeric'
});
// Generate area tags
const areaTagsHtml = resource.areaTags.map(areaId => {
const area = areasData[areaId];
if (!area) return '';
return `<span class="px-2 py-1 rounded-full text-xs font-medium ${area.colors.medium}">${area.name}</span>`;
}).join('');
// Generate sub-area tags
const subAreaTagsHtml = resource.subAreaTags.map(subAreaKey => {
// Find the sub-area name and color by looking through all areas
let subAreaName = subAreaKey; // fallback to key if not found
let textColor = 'text-gray-700'; // fallback color
for (const areaKey in areasData) {
const area = areasData[areaKey];
if (area.subAreas && area.subAreas[subAreaKey]) {
const subArea = area.subAreas[subAreaKey];
subAreaName = typeof subArea === 'string' ? subArea : subArea.name;
// Extract just the text color from the sub-area color
if (typeof subArea === 'object' && subArea.color) {
const colorMatch = subArea.color.match(/text-(\w+)-(\d+)/);
if (colorMatch) {
textColor = `text-${colorMatch[1]}-700`; // Use consistent 700 shade
}
}
break;
}
}
return `<span class="inline-block px-2 py-0.5 text-xs bg-gray-200 ${textColor} rounded">${subAreaName}</span>`;
}).join('');
// Type badge
const typeBadge = resource.type === 'dataset' ? 'Dataset' : 'Tool';
const typeColor = resource.type === 'dataset' ? 'bg-blue-100 text-blue-800' : 'bg-green-100 text-green-800';
return `
<div class="resource-card bg-white rounded-lg shadow-sm border border-gray-200 overflow-hidden flex-shrink-0 relative" style="height: 600px; width: 600px;">
<!-- Top Section - Single view with all information -->
<div class="resource-card-top h-48 bg-gradient-to-br from-${primaryColor}-50 to-${primaryColor}-100 relative overflow-hidden">
<!-- Background image for top section -->
<div class="absolute inset-0 opacity-10">
<img src="images/${primaryArea?.image || 'ai.png'}" alt="" class="w-full h-full object-cover">
</div>
<div class="relative z-10 p-4 h-full flex flex-col">
<!-- Header with type, link, and date -->
<div class="flex items-center justify-between mb-3">
<div class="flex items-center gap-2">
<span class="px-2 py-1 rounded-full text-xs font-medium ${typeColor}">${typeBadge}</span>
<a href="${resource.url}" target="_blank" class="text-xs text-blue-600 hover:text-blue-800 flex items-center">
<svg class="w-3 h-3 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"></path>
</svg>
View Resource
</a>
</div>
<span class="text-xs text-gray-600">${formattedDate}</span>
</div>
<!-- Title -->
<h3 class="text-lg font-semibold text-gray-900 mb-3 leading-tight">${resource.title}</h3>
<!-- Description -->
<p class="text-sm text-gray-700 mb-3 flex-1 overflow-hidden" style="display: -webkit-box; -webkit-line-clamp: 4; -webkit-box-orient: vertical;">
${resource.description}
</p>
<!-- Footer with tags and area image -->
<div class="flex items-center justify-between">
<div class="flex flex-wrap gap-1 flex-1">
${areaTagsHtml}
${subAreaTagsHtml}
</div>
<div class="w-8 h-8 rounded-full bg-white bg-opacity-50 flex items-center justify-center ml-3 flex-shrink-0">
<img src="images/${primaryArea?.image || 'ai.png'}" alt="" class="w-6 h-6 rounded-full object-cover">
</div>
</div>
</div>
</div>
<!-- Bottom Section - 70% of height -->
<div class="resource-card-bottom relative" style="height: 420px;">
${resource.embedUrl ? `
<!-- Iframe embed -->
<iframe
src="${resource.embedUrl}"
class="w-full h-full border-0"
loading="lazy"
title="${resource.title}"
></iframe>
` : `
<!-- Fallback with background image and text -->
<div class="w-full h-full relative overflow-hidden">
<div class="absolute inset-0 opacity-50">
<img src="images/${primaryArea?.image || 'ai.png'}" alt="" class="w-full h-full object-cover">
</div>
<div class="absolute inset-0 bg-black bg-opacity-20 flex items-center justify-center">
<div class="text-center text-white">
<div class="text-lg font-semibold mb-2">Iframe not available</div>
<a href="${resource.url}" target="_blank" class="text-sm text-blue-200 hover:text-blue-100 underline">
View on external site
</a>
</div>
</div>
</div>
`}
</div>
</div>
`;
}
export function initializeResourceCards() {
// Resource cards now have a single view, no toggle functionality needed
// This function is kept for consistency with the calling code
}