| // components/article/ArticleHeader.tsx | |
| import { Link } from "react-router-dom"; | |
| import { Article } from "@/types"; | |
| import { Calendar, Eye, Heart, MessageCircle, Clock, User, Tag } from "lucide-react"; | |
| interface ArticleHeaderProps { | |
| article: Article; | |
| } | |
| export function ArticleHeader({ article }: ArticleHeaderProps) { | |
| const formatDate = (dateStr?: string | null) => { | |
| if (!dateStr) return "Draft"; | |
| return new Date(dateStr).toLocaleDateString(undefined, { | |
| year: "numeric", | |
| month: "long", | |
| day: "numeric", | |
| }); | |
| }; | |
| return ( | |
| <div className="bg-white dark:bg-gray-800 rounded-2xl shadow-lg overflow-hidden border border-gray-100 dark:border-gray-700"> | |
| {/* Optional cover image placeholder – you can replace with a real image if available */} | |
| <div className="h-48 sm:h-60 bg-linear-to-br from-primary/20 to-secondary/20 relative flex items-end p-6 sm:p-8"> | |
| <h1 className="text-3xl sm:text-4xl font-bold text-gray-900 dark:text-white leading-tight drop-shadow-sm"> | |
| {article.title} | |
| </h1> | |
| </div> | |
| <div className="p-6 sm:p-8 space-y-6"> | |
| {/* Meta row */} | |
| <div className="flex flex-wrap items-center gap-4 text-sm text-gray-600 dark:text-gray-300"> | |
| <div className="flex items-center gap-1.5"> | |
| <User className="w-4 h-4 text-gray-400" /> | |
| <span>{article.authorUsername}</span> | |
| </div> | |
| <div className="flex items-center gap-1.5"> | |
| <Calendar className="w-4 h-4 text-gray-400" /> | |
| <span>{formatDate(article.publishedDate)}</span> | |
| </div> | |
| <div className="flex items-center gap-1.5"> | |
| <Eye className="w-4 h-4 text-gray-400" /> | |
| <span>{article.views} views</span> | |
| </div> | |
| <div className="flex items-center gap-1.5"> | |
| <Heart className="w-4 h-4 text-gray-400" /> | |
| <span>{article.likesCount} likes</span> | |
| </div> | |
| <div className="flex items-center gap-1.5"> | |
| <MessageCircle className="w-4 h-4 text-gray-400" /> | |
| <span>{article.commentsCount} comments</span> | |
| </div> | |
| <div className="flex items-center gap-1.5"> | |
| <Clock className="w-4 h-4 text-gray-400" /> | |
| <span>{article.readingTime} min read</span> | |
| </div> | |
| </div> | |
| {/* Tags */} | |
| {article.tags && article.tags.length > 0 && ( | |
| <div className="flex flex-wrap gap-2"> | |
| {article.tags.map((tag) => ( | |
| <Link | |
| key={tag} | |
| to={`/search?tag=${tag}`} | |
| className="inline-flex items-center gap-1 bg-blue-50 dark:bg-blue-900/20 text-blue-700 dark:text-blue-300 px-3 py-1 rounded-full text-xs font-medium hover:bg-blue-100 dark:hover:bg-blue-900/40 transition" | |
| > | |
| <Tag className="w-3 h-3" /> | |
| {tag} | |
| </Link> | |
| ))} | |
| </div> | |
| )} | |
| </div> | |
| </div> | |
| ); | |
| } | |
Xet Storage Details
- Size:
- 3.01 kB
- Xet hash:
- 9b0f8db4cd3899ba8587cecc3057c7983d6b69062a59ff88706cf9ce1ae378af
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.