This commit is contained in:
89
frontend/src/components/competition/CompetitionCard.jsx
Normal file
89
frontend/src/components/competition/CompetitionCard.jsx
Normal file
@@ -0,0 +1,89 @@
|
||||
import React from 'react';
|
||||
import { Card, Tag, Typography, Space, Divider } from 'antd';
|
||||
import { CalendarOutlined } from '@ant-design/icons';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
import dayjs from 'dayjs';
|
||||
import ReactMarkdown from 'react-markdown';
|
||||
import remarkGfm from 'remark-gfm';
|
||||
|
||||
const { Title } = Typography;
|
||||
|
||||
const CompetitionCard = ({ competition }) => {
|
||||
const navigate = useNavigate();
|
||||
|
||||
const getStatusColor = (status) => {
|
||||
switch(status) {
|
||||
case 'published': return 'cyan';
|
||||
case 'registration': return 'green';
|
||||
case 'submission': return 'blue';
|
||||
case 'judging': return 'orange';
|
||||
case 'ended': return 'red';
|
||||
default: return 'default';
|
||||
}
|
||||
};
|
||||
|
||||
const getStatusText = (status) => {
|
||||
switch(status) {
|
||||
case 'published': return '即将开始';
|
||||
case 'registration': return '报名中';
|
||||
case 'submission': return '作品提交中';
|
||||
case 'judging': return '评审中';
|
||||
case 'ended': return '已结束';
|
||||
default: return '草稿';
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<Card
|
||||
hoverable
|
||||
cover={
|
||||
<div style={{ height: 200, overflow: 'hidden', position: 'relative' }}>
|
||||
<img
|
||||
alt={competition.title}
|
||||
src={competition.display_cover_image || 'https://via.placeholder.com/400x200'}
|
||||
style={{ width: '100%', height: '100%', objectFit: 'cover' }}
|
||||
/>
|
||||
<div style={{ position: 'absolute', top: 10, right: 10 }}>
|
||||
<Tag color={getStatusColor(competition.status)} style={{ marginRight: 0 }}>
|
||||
{getStatusText(competition.status)}
|
||||
</Tag>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
style={{ height: '100%', display: 'flex', flexDirection: 'column' }}
|
||||
bodyStyle={{ flex: 1, display: 'flex', flexDirection: 'column' }}
|
||||
onClick={() => navigate(`/competitions/${competition.id}`)}
|
||||
>
|
||||
<Title level={4} ellipsis={{ rows: 2 }} style={{ marginBottom: 8, height: 54 }}>
|
||||
{competition.title}
|
||||
</Title>
|
||||
|
||||
<div style={{
|
||||
flex: 1,
|
||||
color: 'rgba(255,255,255,0.65)',
|
||||
overflow: 'hidden',
|
||||
display: '-webkit-box',
|
||||
WebkitLineClamp: 3,
|
||||
WebkitBoxOrient: 'vertical',
|
||||
marginBottom: 0
|
||||
}}>
|
||||
<ReactMarkdown remarkPlugins={[remarkGfm]}>
|
||||
{competition.description}
|
||||
</ReactMarkdown>
|
||||
</div>
|
||||
|
||||
<Divider style={{ margin: '12px 0' }} />
|
||||
|
||||
<Space direction="vertical" style={{ width: '100%' }} size={4}>
|
||||
<Space>
|
||||
<CalendarOutlined style={{ color: '#00b96b' }} />
|
||||
<span style={{ fontSize: 12 }}>
|
||||
{dayjs(competition.start_time).format('YYYY-MM-DD')} ~ {dayjs(competition.end_time).format('YYYY-MM-DD')}
|
||||
</span>
|
||||
</Space>
|
||||
</Space>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
|
||||
export default CompetitionCard;
|
||||
Reference in New Issue
Block a user