58 lines
2.0 KiB
TypeScript
58 lines
2.0 KiB
TypeScript
// src/components/AchievementsList.tsx
|
|
import React from 'react';
|
|
import { Achievement, UserAchievement } from '../types';
|
|
|
|
/**
|
|
* A simple component to render an icon based on its name.
|
|
* In a real app, this would map to an icon library like Feather or FontAwesome.
|
|
*/
|
|
const Icon: React.FC<{ name: string | null | undefined }> = ({ name }) => {
|
|
if (!name) return <span className="icon-placeholder">🏆</span>;
|
|
// For now, just return the name as text or a default emoji.
|
|
// Example: if name is 'chef-hat', you could return a chef hat icon.
|
|
const iconMap: { [key: string]: string } = {
|
|
'chef-hat': '🧑🍳',
|
|
'share-2': '🤝',
|
|
list: '📋',
|
|
heart: '❤️',
|
|
'git-fork': '🍴',
|
|
'piggy-bank': '🐷',
|
|
};
|
|
return <span className="text-2xl">{iconMap[name] || '🏆'}</span>;
|
|
};
|
|
|
|
interface AchievementsListProps {
|
|
achievements: (UserAchievement & Achievement)[];
|
|
}
|
|
|
|
export const AchievementsList: React.FC<AchievementsListProps> = ({ achievements }) => {
|
|
return (
|
|
<div>
|
|
<h2 className="text-2xl font-semibold mb-4 border-b pb-2">Achievements</h2>
|
|
{achievements.length > 0 ? (
|
|
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
|
{achievements.map((ach) => (
|
|
<div
|
|
key={ach.achievement_id}
|
|
className="bg-white dark:bg-gray-800 p-4 rounded-lg shadow-md flex items-start space-x-4"
|
|
>
|
|
<div className="shrink-0">
|
|
<Icon name={ach.icon} />
|
|
</div>
|
|
<div>
|
|
<h3 className="font-bold">{ach.name}</h3>
|
|
<p className="text-sm text-gray-600 dark:text-gray-300">{ach.description}</p>
|
|
<p className="text-xs text-yellow-500 font-semibold mt-1">
|
|
+{ach.points_value} Points
|
|
</p>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
) : (
|
|
<p className="text-gray-500">No achievements earned yet. Keep exploring to unlock them!</p>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|