Files
leaudit-platform-frontend/app/components/contract-template/TemplateCard.tsx
T
2025-05-29 18:17:14 +08:00

118 lines
3.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { useState } from 'react';
import { useNavigate } from '@remix-run/react';
interface Template {
id: string;
title: string;
type: string;
description: string;
updateTime: string;
useCount: number;
rating: number;
category: string;
}
interface TemplateCardProps {
template: Template;
onClick: () => void;
}
export function TemplateCard({ template, onClick }: TemplateCardProps) {
const [isFavorited, setIsFavorited] = useState(false);
const navigate = useNavigate();
const handleFavoriteClick = (e: React.MouseEvent) => {
e.stopPropagation();
setIsFavorited(!isFavorited);
};
const handleActionClick = (e: React.MouseEvent, action: string) => {
e.stopPropagation();
switch (action) {
case '立即使用':
console.log('下载并使用模板:', template.id);
// 这里应该触发下载逻辑
break;
case '预览':
// 导航到模板详情页面
navigate(`/contract-template/detail/${template.id}`);
break;
default:
console.log(`执行操作: ${action}`, template.id);
}
};
const renderStars = (rating: number) => {
const stars = [];
const fullStars = Math.floor(rating);
const hasHalfStar = rating % 1 !== 0;
for (let i = 0; i < 5; i++) {
if (i < fullStars) {
stars.push(<i key={i} className="ri-star-fill text-xs"></i>);
} else if (i === fullStars && hasHalfStar) {
stars.push(<i key={i} className="ri-star-half-fill text-xs"></i>);
} else {
stars.push(<i key={i} className="ri-star-line text-xs"></i>);
}
}
return stars;
};
const handleKeyDown = (e: React.KeyboardEvent) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
onClick();
}
};
return (
<div
className="template-card"
onClick={onClick}
onKeyDown={handleKeyDown}
role="button"
tabIndex={0}
aria-label={`查看${template.title}详情`}
>
<div className="template-header">
<div className="template-type">{template.type}</div>
<div className="flex items-center gap-1 text-yellow-500">
{renderStars(template.rating)}
<span className="text-xs ml-1">{template.rating}</span>
</div>
</div>
<h3 className="template-title">{template.title}</h3>
<p className="template-desc">{template.description}</p>
<div className="template-meta">
<span>{template.updateTime}</span>
<span>使{template.useCount.toLocaleString()}</span>
</div>
<div className="template-actions mt-3">
<button
className="action-btn primary"
onClick={(e) => handleActionClick(e, '立即使用')}
>
使
</button>
<button
className="action-btn"
onClick={(e) => handleActionClick(e, '预览')}
>
</button>
<button
className="action-btn"
onClick={handleFavoriteClick}
title={isFavorited ? '取消收藏' : '收藏'}
>
<i className={isFavorited ? 'ri-star-fill text-yellow-500' : 'ri-star-line'}></i>
</button>
</div>
</div>
);
}