Files
znakovni.hr/packages/frontend/src/components/dictionary/WordCard.tsx
johnny2211 85ae57b95b Refactor word type colors into centralized utility
- Extract word type color logic into shared wordTypeColors.ts utility
- Update TokenTray to use centralized color utility
- Remove duplicate color logic from WordCard and SortableToken
- Add color legend to Layout header for better UX
- Simplify Znakopis page component
2026-01-17 19:11:45 +01:00

95 lines
3.0 KiB
TypeScript

import { Info, Plus } from 'lucide-react';
import { Term, CefrLevel } from '../../types/term';
import { Button } from '../ui/button';
import { wordTypeColors, wordTypeLabels } from '../../lib/wordTypeColors';
interface WordCardProps {
term: Term;
onInfo: (term: Term) => void;
onAddToSentence?: (term: Term) => void;
}
const cefrColors: Record<CefrLevel, string> = {
[CefrLevel.A1]: 'bg-green-500',
[CefrLevel.A2]: 'bg-green-400',
[CefrLevel.B1]: 'bg-yellow-500',
[CefrLevel.B2]: 'bg-yellow-400',
[CefrLevel.C1]: 'bg-orange-500',
[CefrLevel.C2]: 'bg-red-500',
};
export function WordCard({ term, onInfo, onAddToSentence }: WordCardProps) {
const videoMedia = term.media?.find(m => m.kind === 'VIDEO');
const imageMedia = term.media?.find(m => m.kind === 'IMAGE' || m.kind === 'ILLUSTRATION');
return (
<div className="bg-white rounded-lg shadow hover:shadow-lg transition-shadow p-4 flex flex-col">
{/* CEFR Level Indicator */}
<div className="flex justify-between items-start mb-3">
<span className={`${cefrColors[term.cefrLevel]} text-white text-xs font-bold px-2 py-1 rounded`}>
{term.cefrLevel}
</span>
<span className="text-xs text-gray-500">
{wordTypeLabels[term.wordType] || term.wordType}
</span>
</div>
{/* Icon/Image */}
<div className="flex-1 flex items-center justify-center mb-4 min-h-[120px]">
{imageMedia ? (
<img
src={imageMedia.url}
alt={term.wordText}
className="max-h-[120px] max-w-full object-contain"
/>
) : videoMedia ? (
<div className="w-full h-[120px] bg-gray-100 rounded flex items-center justify-center">
<span className="text-gray-400 text-sm">Video</span>
</div>
) : (
<div className="w-full h-[120px] bg-gray-100 rounded flex items-center justify-center">
<span className="text-4xl">📝</span>
</div>
)}
</div>
{/* Word Text with colored background based on word type */}
<div className={`${wordTypeColors[term.wordType] || 'bg-gray-600'} text-white text-lg font-semibold px-4 py-2 rounded text-center mb-3`}>
{term.wordText}
</div>
{/* Short Description */}
{term.shortDescription && (
<p className="text-sm text-gray-600 text-center mb-4 line-clamp-2">
{term.shortDescription}
</p>
)}
{/* Actions - Dodaj on left, Info on right */}
<div className="flex gap-2 mt-auto">
{onAddToSentence && (
<Button
variant="default"
size="sm"
className="flex-1"
onClick={() => onAddToSentence(term)}
>
<Plus className="h-4 w-4 mr-1" />
Dodaj
</Button>
)}
<Button
variant="outline"
size="sm"
className="flex-1"
onClick={() => onInfo(term)}
>
<Info className="h-4 w-4 mr-1" />
Info
</Button>
</div>
</div>
);
}