Initialize ZUJ OL Apps website with React + TypeScript + Vite
This commit is contained in:
@@ -0,0 +1,94 @@
|
||||
import type { ComponentType } from 'react';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { ExternalLink, Download, BookOpen, Star, NotebookPen, Terminal, MapPin, Smartphone, Monitor, Brain, KeyRound } from 'lucide-react';
|
||||
import { useI18n } from '../hooks/useI18n';
|
||||
import { siteData } from '../data/siteData';
|
||||
import type { Project } from '../types';
|
||||
|
||||
const iconMap: Record<string, ComponentType<{ size?: number }>> = {
|
||||
NotebookPen,
|
||||
Terminal,
|
||||
MapPin,
|
||||
Smartphone,
|
||||
BookOpen,
|
||||
Monitor,
|
||||
Brain,
|
||||
KeyRound,
|
||||
};
|
||||
|
||||
interface ProjectCardProps {
|
||||
project: Project;
|
||||
}
|
||||
|
||||
export default function ProjectCard({ project }: ProjectCardProps) {
|
||||
const { t, bi } = useI18n();
|
||||
const status = siteData.statuses[project.status];
|
||||
const IconComponent = iconMap[project.icon];
|
||||
|
||||
return (
|
||||
<div className="project-card">
|
||||
<div className="project-card-header">
|
||||
<div className="project-icon">
|
||||
{IconComponent && <IconComponent size={22} />}
|
||||
</div>
|
||||
<div className="project-card-info">
|
||||
<div className="project-name">
|
||||
<Link to={`/projects/${project.id}`}>{project.name}</Link>
|
||||
{status && (
|
||||
<span
|
||||
className="badge badge-status"
|
||||
style={{ color: status.color }}
|
||||
>
|
||||
{bi(status.label)}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<div className="project-slogan">{bi(project.slogan)}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="project-card-meta">
|
||||
{project.techStack.slice(0, 4).map((tech) => (
|
||||
<span key={tech} className="badge">{tech}</span>
|
||||
))}
|
||||
{project.platforms.slice(0, 3).map((platform) => (
|
||||
<span key={platform} className="badge">
|
||||
{siteData.platforms[platform] || platform}
|
||||
</span>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="project-card-meta">
|
||||
<span className="badge badge-accent">
|
||||
<Star size={12} /> {project.stars}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="project-card-actions">
|
||||
<a
|
||||
href={project.repoUrl}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="btn btn-sm"
|
||||
>
|
||||
<ExternalLink size={14} /> GitHub
|
||||
</a>
|
||||
{project.downloads.length > 0 && (
|
||||
<Link to={`/projects/${project.id}`} className="btn btn-sm">
|
||||
<Download size={14} /> {t('common.download')}
|
||||
</Link>
|
||||
)}
|
||||
{project.docsUrl && (
|
||||
<a
|
||||
href={project.docsUrl}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="btn btn-sm"
|
||||
>
|
||||
<BookOpen size={14} /> {t('common.docs')}
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user