138 lines
4.6 KiB
TypeScript
138 lines
4.6 KiB
TypeScript
"use client";
|
|
|
|
import { useEffect, useState } from "react";
|
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
|
import { Button } from "@/components/ui/button";
|
|
import { RefreshCw, Mail } from "lucide-react";
|
|
import { useRouter } from "next/navigation";
|
|
import { useSession } from "next-auth/react";
|
|
|
|
interface Email {
|
|
id: string;
|
|
subject: string;
|
|
from: string;
|
|
fromName: string;
|
|
date: string;
|
|
read: boolean;
|
|
starred: boolean;
|
|
hasAttachments: boolean;
|
|
}
|
|
|
|
export function CourrierWidget() {
|
|
const [emails, setEmails] = useState<Email[]>([]);
|
|
const [error, setError] = useState<string | null>(null);
|
|
const [loading, setLoading] = useState(true);
|
|
const [refreshing, setRefreshing] = useState(false);
|
|
const router = useRouter();
|
|
const { status } = useSession();
|
|
|
|
const fetchEmails = async (isRefresh = false) => {
|
|
try {
|
|
if (isRefresh) {
|
|
setRefreshing(true);
|
|
}
|
|
|
|
const response = await fetch('/api/courrier');
|
|
if (!response.ok) {
|
|
throw new Error('Failed to fetch emails');
|
|
}
|
|
|
|
const data = await response.json();
|
|
if (Array.isArray(data.emails)) {
|
|
setEmails(data.emails.slice(0, 5));
|
|
} else {
|
|
console.warn('Unexpected data format:', data);
|
|
setEmails([]);
|
|
}
|
|
setError(null);
|
|
} catch (err) {
|
|
console.error('Error fetching emails:', err);
|
|
const errorMessage = err instanceof Error ? err.message : 'Failed to fetch emails';
|
|
setError(errorMessage);
|
|
} finally {
|
|
setLoading(false);
|
|
setRefreshing(false);
|
|
}
|
|
};
|
|
|
|
useEffect(() => {
|
|
if (status === 'authenticated') {
|
|
fetchEmails();
|
|
}
|
|
}, [status]);
|
|
|
|
const formatDate = (dateString: string) => {
|
|
const date = new Date(dateString);
|
|
const now = new Date();
|
|
const diff = now.getTime() - date.getTime();
|
|
const days = Math.floor(diff / (1000 * 60 * 60 * 24));
|
|
|
|
if (days === 0) {
|
|
return date.toLocaleTimeString('fr-FR', { hour: '2-digit', minute: '2-digit' });
|
|
} else if (days === 1) {
|
|
return 'Hier';
|
|
} else if (days < 7) {
|
|
return date.toLocaleDateString('fr-FR', { weekday: 'long' });
|
|
} else {
|
|
return date.toLocaleDateString('fr-FR', { day: '2-digit', month: '2-digit', year: '2-digit' });
|
|
}
|
|
};
|
|
|
|
return (
|
|
<Card
|
|
className="transition-transform duration-500 ease-in-out transform hover:scale-105 bg-white/95 backdrop-blur-sm border-0 shadow-lg cursor-pointer"
|
|
onClick={() => router.push('/courrier')}
|
|
>
|
|
<CardHeader className="flex flex-row items-center justify-between pb-2 border-b border-gray-100">
|
|
<CardTitle className="text-lg font-semibold text-gray-800 flex items-center gap-2">
|
|
<Mail className="h-5 w-5 text-gray-600" />
|
|
Courrier
|
|
</CardTitle>
|
|
<Button
|
|
variant="ghost"
|
|
size="icon"
|
|
onClick={(e) => {
|
|
e.stopPropagation();
|
|
fetchEmails(true);
|
|
}}
|
|
disabled={refreshing}
|
|
className="h-7 w-7 p-0 hover:bg-gray-100/50 rounded-full"
|
|
>
|
|
<RefreshCw className="h-3.5 w-3.5 text-gray-600" />
|
|
</Button>
|
|
</CardHeader>
|
|
<CardContent className="p-3">
|
|
{loading ? (
|
|
<div className="flex items-center justify-center py-6">
|
|
<div className="h-4 w-4 animate-spin rounded-full border-2 border-blue-500 border-t-transparent" />
|
|
</div>
|
|
) : error ? (
|
|
<div className="text-xs text-red-500 text-center py-3">{error}</div>
|
|
) : emails.length === 0 ? (
|
|
<div className="text-xs text-gray-500 text-center py-6">No emails found</div>
|
|
) : (
|
|
<div className="space-y-2 max-h-[400px] overflow-y-auto pr-1 scrollbar-thin scrollbar-thumb-gray-200 scrollbar-track-transparent">
|
|
{emails.map((email) => (
|
|
<div
|
|
key={email.id}
|
|
className="p-2 rounded-lg bg-white shadow-sm hover:shadow-md transition-all duration-200 border border-gray-100"
|
|
>
|
|
<div className="flex flex-col gap-1">
|
|
<div className="flex items-center justify-between text-xs">
|
|
<span className="text-gray-500">{formatDate(email.date)}</span>
|
|
</div>
|
|
<h3 className="text-sm font-medium text-gray-800 line-clamp-2" title={email.subject}>
|
|
{email.subject}
|
|
</h3>
|
|
<p className="text-xs text-gray-500 line-clamp-1" title={email.fromName}>
|
|
{email.fromName}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
)}
|
|
</CardContent>
|
|
</Card>
|
|
);
|
|
}
|