Skip to content

Commit 5de620c

Browse files
authored
Merge pull request #353 from Richajaishwal0/main
Updated Discussion page.
2 parents 758530d + 90b3a71 commit 5de620c

File tree

7 files changed

+1937
-289
lines changed

7 files changed

+1937
-289
lines changed
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
import React from "react";
2+
import { motion } from "framer-motion";
3+
import { MessageCircle, ThumbsUp, Calendar, Tag, User } from "lucide-react";
4+
5+
export interface Discussion {
6+
id: string;
7+
title: string;
8+
body: string;
9+
author: {
10+
login: string;
11+
avatar_url: string;
12+
html_url: string;
13+
};
14+
category: {
15+
name: string;
16+
emoji: string;
17+
};
18+
created_at: string;
19+
updated_at: string;
20+
comments: number;
21+
reactions: {
22+
total_count: number;
23+
};
24+
html_url: string;
25+
labels: Array<{
26+
name: string;
27+
color: string;
28+
}>;
29+
}
30+
31+
interface DiscussionCardProps {
32+
discussion: Discussion;
33+
index: number;
34+
}
35+
36+
export default function DiscussionCard({
37+
discussion,
38+
index,
39+
}: DiscussionCardProps): JSX.Element {
40+
const formatDate = (dateString: string) => {
41+
const date = new Date(dateString);
42+
return date.toLocaleDateString("en-US", {
43+
year: "numeric",
44+
month: "short",
45+
day: "numeric",
46+
});
47+
};
48+
49+
const truncateText = (text: string, maxLength: number) => {
50+
if (!text || text.length <= maxLength) return text;
51+
return text.substring(0, maxLength).trim() + "...";
52+
};
53+
54+
const formatCount = (count: number) => {
55+
if (count >= 1000) {
56+
return (count / 1000).toFixed(1) + "k";
57+
}
58+
return count.toString();
59+
};
60+
61+
return (
62+
<motion.div
63+
className="discussion-card-new"
64+
initial={{ opacity: 0, y: 20 }}
65+
animate={{ opacity: 1, y: 0 }}
66+
transition={{ duration: 0.5, delay: index * 0.1 }}
67+
whileHover={{ boxShadow: "0 4px 20px rgba(0,0,0,0.08)" }}
68+
>
69+
<div className="discussion-card-header">
70+
<div className="discussion-category-badge">
71+
<Tag size={14} />
72+
<span>{discussion.category.name}</span>
73+
</div>
74+
<div className="discussion-date-badge">
75+
<Calendar size={14} />
76+
<span>{formatDate(discussion.created_at)}</span>
77+
</div>
78+
</div>
79+
80+
<div className="discussion-main-content">
81+
<h3 className="discussion-title-new">
82+
<a
83+
href={discussion.html_url}
84+
target="_blank"
85+
rel="noopener noreferrer"
86+
>
87+
{discussion.title}
88+
</a>
89+
</h3>
90+
91+
{discussion.body && (
92+
<p className="discussion-excerpt">
93+
{truncateText(
94+
discussion.body.replace(/[#*`\[\]]/g, "").replace(/\n/g, " "),
95+
150
96+
)}
97+
</p>
98+
)}
99+
100+
{discussion.labels.length > 0 && (
101+
<div className="discussion-keywords">
102+
{discussion.labels.slice(0, 4).map((label, idx) => (
103+
<span key={idx} className="keyword-tag">
104+
{label.name}
105+
</span>
106+
))}
107+
</div>
108+
)}
109+
</div>
110+
111+
<div className="discussion-card-footer">
112+
<div className="discussion-author-info">
113+
{discussion.author.avatar_url ? (
114+
<img
115+
src={discussion.author.avatar_url}
116+
alt={discussion.author.login}
117+
className="author-avatar-small"
118+
onError={(e) => {
119+
const target = e.currentTarget;
120+
target.style.display = 'none';
121+
const fallback = target.nextElementSibling;
122+
if (fallback) fallback.style.display = 'flex';
123+
}}
124+
/>
125+
) : null}
126+
<div
127+
className="author-avatar-fallback"
128+
style={{ display: discussion.author.avatar_url ? 'none' : 'flex' }}
129+
>
130+
{discussion.author.login.charAt(0).toUpperCase()}
131+
</div>
132+
<span className="author-name-new">{discussion.author.login}</span>
133+
</div>
134+
135+
<div className="discussion-engagement">
136+
<div className="engagement-item">
137+
<MessageCircle size={16} />
138+
<span>{formatCount(discussion.comments)}</span>
139+
</div>
140+
<div className="engagement-item">
141+
<ThumbsUp size={16} />
142+
<span>{formatCount(discussion.reactions.total_count)}</span>
143+
</div>
144+
</div>
145+
</div>
146+
</motion.div>
147+
);
148+
}

0 commit comments

Comments
 (0)