|
|
@@ -1,4 +1,3 @@
|
|
|
-
|
|
|
import { NewsItem } from '@/types/news';
|
|
|
import { Card, CardContent, CardHeader } from '@/components/ui/card';
|
|
|
import { Badge } from '@/components/ui/badge';
|
|
|
@@ -6,7 +5,6 @@ import { Button } from '@/components/ui/button';
|
|
|
import { Clock, Pin, ExternalLink, Eye, Trash2 } from 'lucide-react';
|
|
|
import { cn } from '@/lib/utils';
|
|
|
import { useAuth } from '@/hooks/useAuth';
|
|
|
-
|
|
|
interface NewsCardProps {
|
|
|
news: NewsItem;
|
|
|
onTogglePin: (id: string) => void;
|
|
|
@@ -14,7 +12,6 @@ interface NewsCardProps {
|
|
|
onDelete: (id: string) => void;
|
|
|
onOpenArticle: (article: NewsItem) => void;
|
|
|
}
|
|
|
-
|
|
|
const NewsCard = ({
|
|
|
news,
|
|
|
onTogglePin,
|
|
|
@@ -22,7 +19,9 @@ const NewsCard = ({
|
|
|
onDelete,
|
|
|
onOpenArticle
|
|
|
}: NewsCardProps) => {
|
|
|
- const { user } = useAuth();
|
|
|
+ const {
|
|
|
+ user
|
|
|
+ } = useAuth();
|
|
|
|
|
|
// Function to decode HTML entities
|
|
|
const decodeHtmlEntities = (text: string) => {
|
|
|
@@ -30,7 +29,6 @@ const NewsCard = ({
|
|
|
textarea.innerHTML = text;
|
|
|
return textarea.value;
|
|
|
};
|
|
|
-
|
|
|
const getSourceColor = (category: string) => {
|
|
|
switch (category) {
|
|
|
case 'rss':
|
|
|
@@ -45,21 +43,13 @@ const NewsCard = ({
|
|
|
return 'bg-muted text-muted-foreground';
|
|
|
}
|
|
|
};
|
|
|
-
|
|
|
const handleCardClick = () => {
|
|
|
onOpenArticle(news);
|
|
|
if (!news.isRead) {
|
|
|
onMarkAsRead(news.id);
|
|
|
}
|
|
|
};
|
|
|
-
|
|
|
- return (
|
|
|
- <Card className={cn(
|
|
|
- "group hover:shadow-lg transition-all duration-300 border-l-4 cursor-pointer",
|
|
|
- news.isPinned && "border-l-yellow-500",
|
|
|
- news.isRead && "opacity-75",
|
|
|
- !news.isRead && "border-l-primary"
|
|
|
- )}>
|
|
|
+ return <Card className={cn("group hover:shadow-lg transition-all duration-300 border-l-4 cursor-pointer", news.isPinned && "border-l-yellow-500", news.isRead && "opacity-75", !news.isRead && "border-l-primary")}>
|
|
|
<CardHeader className="space-y-3">
|
|
|
<div className="flex items-start justify-between gap-4">
|
|
|
<div className="flex-1 space-y-2" onClick={handleCardClick}>
|
|
|
@@ -67,35 +57,19 @@ const NewsCard = ({
|
|
|
<Badge variant="outline" className={getSourceColor(news.category)}>
|
|
|
{news.source}
|
|
|
</Badge>
|
|
|
- <div className="flex items-center gap-1 text-xs text-muted-foreground">
|
|
|
- <Clock className="h-3 w-3" />
|
|
|
- {news.readTime} min
|
|
|
- </div>
|
|
|
+
|
|
|
</div>
|
|
|
|
|
|
- <h3 className={cn(
|
|
|
- "font-semibold leading-tight group-hover:text-primary transition-colors",
|
|
|
- news.isRead && "text-muted-foreground"
|
|
|
- )}>
|
|
|
+ <h3 className={cn("font-semibold leading-tight group-hover:text-primary transition-colors", news.isRead && "text-muted-foreground")}>
|
|
|
{decodeHtmlEntities(news.title)}
|
|
|
</h3>
|
|
|
</div>
|
|
|
|
|
|
<div className="flex items-center gap-1 opacity-0 group-hover:opacity-100 transition-opacity">
|
|
|
- <Button
|
|
|
- variant="ghost"
|
|
|
- size="sm"
|
|
|
- onClick={e => {
|
|
|
- e.stopPropagation();
|
|
|
- onTogglePin(news.id);
|
|
|
- }}
|
|
|
- disabled={!user}
|
|
|
- className={cn(
|
|
|
- "h-8 w-8 p-0",
|
|
|
- news.isPinned && "text-yellow-600",
|
|
|
- !user && "opacity-50 cursor-not-allowed"
|
|
|
- )}
|
|
|
- >
|
|
|
+ <Button variant="ghost" size="sm" onClick={e => {
|
|
|
+ e.stopPropagation();
|
|
|
+ onTogglePin(news.id);
|
|
|
+ }} disabled={!user} className={cn("h-8 w-8 p-0", news.isPinned && "text-yellow-600", !user && "opacity-50 cursor-not-allowed")}>
|
|
|
<Pin className={cn("h-4 w-4", news.isPinned && "fill-current")} />
|
|
|
</Button>
|
|
|
</div>
|
|
|
@@ -110,49 +84,32 @@ const NewsCard = ({
|
|
|
<div className="flex items-center justify-between">
|
|
|
<span className="text-xs text-muted-foreground">
|
|
|
{new Date(news.publishedAt).toLocaleDateString('fr-FR', {
|
|
|
- day: 'numeric',
|
|
|
- month: 'long',
|
|
|
- hour: '2-digit',
|
|
|
- minute: '2-digit'
|
|
|
- })}
|
|
|
+ day: 'numeric',
|
|
|
+ month: 'long',
|
|
|
+ hour: '2-digit',
|
|
|
+ minute: '2-digit'
|
|
|
+ })}
|
|
|
</span>
|
|
|
|
|
|
<div className="flex items-center gap-2">
|
|
|
- {!news.isRead && (
|
|
|
- <Button
|
|
|
- variant="outline"
|
|
|
- size="sm"
|
|
|
- onClick={e => {
|
|
|
- e.stopPropagation();
|
|
|
- onMarkAsRead(news.id);
|
|
|
- }}
|
|
|
- disabled={!user}
|
|
|
- className={cn("gap-1", !user && "opacity-50 cursor-not-allowed")}
|
|
|
- >
|
|
|
+ {!news.isRead && <Button variant="outline" size="sm" onClick={e => {
|
|
|
+ e.stopPropagation();
|
|
|
+ onMarkAsRead(news.id);
|
|
|
+ }} disabled={!user} className={cn("gap-1", !user && "opacity-50 cursor-not-allowed")}>
|
|
|
<Eye className="h-3 w-3" />
|
|
|
Marquer lu
|
|
|
- </Button>
|
|
|
- )}
|
|
|
+ </Button>}
|
|
|
|
|
|
- {news.url && (
|
|
|
- <Button
|
|
|
- variant="default"
|
|
|
- size="sm"
|
|
|
- className="gap-1"
|
|
|
- onClick={e => {
|
|
|
- e.stopPropagation();
|
|
|
- window.open(news.url, '_blank');
|
|
|
- }}
|
|
|
- >
|
|
|
+ {news.url && <Button variant="default" size="sm" className="gap-1" onClick={e => {
|
|
|
+ e.stopPropagation();
|
|
|
+ window.open(news.url, '_blank');
|
|
|
+ }}>
|
|
|
<ExternalLink className="h-3 w-3" />
|
|
|
Lire
|
|
|
- </Button>
|
|
|
- )}
|
|
|
+ </Button>}
|
|
|
</div>
|
|
|
</div>
|
|
|
</CardContent>
|
|
|
- </Card>
|
|
|
- );
|
|
|
+ </Card>;
|
|
|
};
|
|
|
-
|
|
|
-export default NewsCard;
|
|
|
+export default NewsCard;
|