Skip to content

Commit 7f49841

Browse files
committed
feat: tags in blog
1 parent 2c4c17a commit 7f49841

2 files changed

Lines changed: 63 additions & 5 deletions

File tree

src/app/blog/page.tsx

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,19 @@ interface Gist {
2121
cleanTitle: string;
2222
cleanDescription: string;
2323
imageUrl: string;
24+
tags: string[];
2425
}
2526

27+
const technologyKeywords = [
28+
'aws', 'sns', 'sqs', 's3', 'lambda', 'architecture', 'arquitetura', 'clean', 'design', 'adr',
29+
'java', 'spring', 'jvm', 'performance', 'rabbitmq', 'kafka', 'message', 'mensageria',
30+
'go', 'golang', 'cloud', 'docker', 'kubernetes', 'test', 'teste', 'quality', 'qualidade',
31+
'code', 'código', 'desenvolvimento', 'api', 'rest', 'graphql', 'security', 'segurança',
32+
'typescript', 'javascript', 'python', 'php', 'ruby', 'csharp', 'c++', 'c', 'dart', 'rust', 'scala', 'elixir',
33+
'backstage', 'mysql', 'mongodb', 'mongo', 'postgres', 'postgresql', 'android', 'sql'
34+
];
35+
36+
2637
// Mapeamento de palavras-chave para imagens temáticas
2738
const getImageForTitle = (title: string): string => {
2839
const titleLower = title.toLowerCase();
@@ -98,6 +109,12 @@ const getImageForTitle = (title: string): string => {
98109
return imageMap.default;
99110
};
100111

112+
const extractTagsFromText = (text: string): string[] => {
113+
const words = text.toLowerCase().match(/\b\w+\b/g) || [];
114+
const wordSet = new Set(words);
115+
return technologyKeywords.filter(keyword => wordSet.has(keyword));
116+
};
117+
101118
export default function Blog() {
102119
const [gists, setGists] = useState<Gist[]>([]);
103120
const [loading, setLoading] = useState(true);
@@ -122,12 +139,14 @@ export default function Blog() {
122139
const language = firstFile?.language || 'default';
123140
const fileName = firstFile?.filename.split('.')[0].replace(/-/g, ' ');
124141
const description = `${fileName} - ${language}`;
142+
const tags = extractTagsFromText(gist.description);
125143

126144
return {
127145
...gist,
128146
cleanTitle: rawTitle,
129147
cleanDescription: description,
130-
imageUrl: getImageForTitle(rawTitle)
148+
imageUrl: getImageForTitle(rawTitle),
149+
tags: tags
131150
};
132151
});
133152

@@ -243,6 +262,7 @@ export default function Blog() {
243262
date={new Date(gist.created_at).toLocaleDateString('pt-BR')}
244263
link={gist.html_url}
245264
imageUrl={gist.imageUrl}
265+
tags={gist.tags}
246266
/>
247267
))}
248268
</div>

src/app/components/BlogCard/index.tsx

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,43 @@ interface BlogCardProps {
88
date: string;
99
link: string;
1010
imageUrl: string;
11+
tags: string[];
1112
}
1213

13-
export const BlogCard = ({ title, description, date, link, imageUrl }: BlogCardProps) => {
14+
export const BlogCard = ({ title, description, date, link, imageUrl, tags }: BlogCardProps) => {
15+
16+
const getTagColor = (tag: string) => {
17+
const colors: { [key: string]: string } = {
18+
'java': 'bg-red-100 text-red-800',
19+
'python': 'bg-blue-100 text-blue-800',
20+
'c++': 'bg-purple-100 text-purple-800',
21+
'javascript': 'bg-yellow-100 text-yellow-800',
22+
'typescript': 'bg-blue-100 text-blue-800',
23+
'kotlin': 'bg-purple-100 text-purple-800',
24+
'c': 'bg-gray-100 text-gray-800',
25+
'html': 'bg-orange-100 text-orange-800',
26+
'css': 'bg-pink-100 text-pink-800',
27+
'shell': 'bg-green-100 text-green-800',
28+
'ruby': 'bg-red-100 text-red-800',
29+
'swift': 'bg-orange-100 text-orange-800',
30+
'go': 'bg-cyan-100 text-cyan-800',
31+
'rust': 'bg-orange-100 text-orange-800',
32+
'arduino': 'bg-teal-100 text-teal-800',
33+
'android': 'bg-green-100 text-green-800',
34+
'aws': 'bg-blue-100 text-blue-800',
35+
'sns': 'bg-green-100 text-green-800',
36+
'sqs': 'bg-yellow-100 text-yellow-800',
37+
's3': 'bg-orange-100 text-orange-800',
38+
'lambda': 'bg-purple-100 text-purple-800',
39+
'architecture': 'bg-gray-100 text-gray-800',
40+
'clean': 'bg-teal-100 text-teal-800',
41+
'design': 'bg-pink-100 text-pink-800',
42+
'adr': 'bg-red-100 text-red-800'
43+
};
44+
45+
return colors[tag] || 'bg-gray-100 text-gray-800';
46+
}
47+
1448
return (
1549
<div className="bg-white rounded-lg shadow-[0_3px_10px_rgb(0,0,0,0.2)] overflow-hidden hover:shadow-[0_8px_30px_rgb(0,0,0,0.12)] transition-all duration-300 transform hover:-translate-y-1">
1650
<a
@@ -34,9 +68,13 @@ export const BlogCard = ({ title, description, date, link, imageUrl }: BlogCardP
3468
<div className="p-6">
3569
<div className="flex items-center justify-between mb-4">
3670
<span className="text-sm text-gray-500">{date}</span>
37-
<span className="px-3 py-1 text-xs font-medium text-blue-600 bg-blue-100 rounded-full">
38-
Gist
39-
</span>
71+
<div className="flex flex-wrap gap-2">
72+
{tags.map((tag: string) => (
73+
<span key={tag} className={`px-2 py-1 rounded-full text-xs font-medium ${getTagColor(tag)}`}>
74+
{tag}
75+
</span>
76+
))}
77+
</div>
4078
</div>
4179
<h3 className="text-xl font-bold text-gray-900 mb-2 group-hover:text-blue-600 transition-colors duration-300">
4280
{title}

0 commit comments

Comments
 (0)