widget email 18
This commit is contained in:
parent
c83784ab44
commit
a48573c137
@ -5,101 +5,20 @@ import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { RefreshCw, Mail } from "lucide-react";
|
||||
import { useSession, signIn } from "next-auth/react";
|
||||
import { formatDistance } from 'date-fns/formatDistance';
|
||||
import { fr } from 'date-fns/locale/fr';
|
||||
|
||||
interface Email {
|
||||
id: string;
|
||||
subject: string;
|
||||
sender: {
|
||||
name: string;
|
||||
email: string;
|
||||
};
|
||||
date: string;
|
||||
isUnread: boolean;
|
||||
}
|
||||
|
||||
interface EmailResponse {
|
||||
emails: Email[];
|
||||
mailUrl: string;
|
||||
error?: string;
|
||||
}
|
||||
|
||||
export function Email() {
|
||||
const [emails, setEmails] = useState<Email[]>([]);
|
||||
const [mailUrl, setMailUrl] = useState<string | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [refreshing, setRefreshing] = useState(false);
|
||||
const { status } = useSession();
|
||||
|
||||
const fetchEmails = async (isRefresh = false) => {
|
||||
if (isRefresh) setRefreshing(true);
|
||||
if (!isRefresh) setLoading(true);
|
||||
|
||||
try {
|
||||
const response = await fetch('/api/emails');
|
||||
const data: EmailResponse = await response.json();
|
||||
|
||||
if (!response.ok) {
|
||||
// Handle session expiration
|
||||
if (response.status === 401) {
|
||||
signIn(); // Redirect to login
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle specific error messages
|
||||
if (response.status === 404) {
|
||||
setError("L'application Mail n'est pas disponible sur Nextcloud. Veuillez contacter votre administrateur.");
|
||||
return;
|
||||
}
|
||||
|
||||
throw new Error(data.error || 'Failed to fetch emails');
|
||||
}
|
||||
|
||||
setEmails(data.emails || []);
|
||||
setMailUrl(data.mailUrl);
|
||||
setError(null);
|
||||
} catch (err) {
|
||||
console.error('Error fetching emails:', err);
|
||||
setError(err instanceof Error ? err.message : 'Erreur lors de la récupération des emails');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
setRefreshing(false);
|
||||
}
|
||||
};
|
||||
|
||||
// Initial fetch
|
||||
useEffect(() => {
|
||||
if (status === 'authenticated') {
|
||||
fetchEmails();
|
||||
setLoading(false);
|
||||
} else if (status === 'unauthenticated') {
|
||||
signIn();
|
||||
}
|
||||
}, [status]);
|
||||
|
||||
// Auto-refresh every 5 minutes
|
||||
useEffect(() => {
|
||||
if (status !== 'authenticated') return;
|
||||
|
||||
const interval = setInterval(() => {
|
||||
fetchEmails(true);
|
||||
}, 5 * 60 * 1000);
|
||||
|
||||
return () => clearInterval(interval);
|
||||
}, [status]);
|
||||
|
||||
const formatDate = (dateString: string) => {
|
||||
try {
|
||||
const date = new Date(dateString);
|
||||
return formatDistance(date, new Date(), {
|
||||
addSuffix: true,
|
||||
locale: fr
|
||||
});
|
||||
} catch (err) {
|
||||
console.error('Error formatting date:', err);
|
||||
return dateString;
|
||||
}
|
||||
};
|
||||
|
||||
if (status === 'loading' || loading) {
|
||||
return (
|
||||
<Card className="transition-transform duration-500 ease-in-out transform hover:scale-105 bg-white/95 backdrop-blur-sm border-0 shadow-lg h-full">
|
||||
@ -107,7 +26,7 @@ export function Email() {
|
||||
<CardTitle className="text-lg font-semibold text-gray-800">
|
||||
<div className="flex items-center gap-2">
|
||||
<Mail className="h-5 w-5" />
|
||||
<span>Emails non lus</span>
|
||||
<span>Emails</span>
|
||||
</div>
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
@ -126,50 +45,16 @@ export function Email() {
|
||||
<CardTitle className="text-lg font-semibold text-gray-800">
|
||||
<div className="flex items-center gap-2">
|
||||
<Mail className="h-5 w-5" />
|
||||
<span>Emails non lus</span>
|
||||
<span>Emails</span>
|
||||
</div>
|
||||
</CardTitle>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
onClick={() => fetchEmails(true)}
|
||||
disabled={refreshing}
|
||||
className={`${refreshing ? 'animate-spin' : ''} text-gray-600 hover:text-gray-900`}
|
||||
>
|
||||
<RefreshCw className="h-4 w-4" />
|
||||
</Button>
|
||||
</CardHeader>
|
||||
<CardContent className="p-3">
|
||||
{error ? (
|
||||
<p className="text-center text-red-500">{error}</p>
|
||||
) : (
|
||||
<div className="space-y-2 max-h-[220px] overflow-y-auto">
|
||||
{emails.length === 0 ? (
|
||||
<p className="text-center text-gray-500">Aucun email non lu</p>
|
||||
) : (
|
||||
emails.map((email) => (
|
||||
<div
|
||||
key={email.id}
|
||||
className="p-2 hover:bg-gray-50/50 rounded-lg transition-colors cursor-pointer"
|
||||
onClick={() => mailUrl && window.open(mailUrl, '_blank')}
|
||||
>
|
||||
<div className="flex items-center justify-between mb-1">
|
||||
<span className="text-sm text-gray-600 truncate max-w-[60%]" title={email.sender.name}>
|
||||
{email.sender.name}
|
||||
</span>
|
||||
<div className="flex items-center space-x-2">
|
||||
<span className="w-1.5 h-1.5 bg-blue-600 rounded-full"></span>
|
||||
<span className="text-xs text-gray-500">{formatDate(email.date)}</span>
|
||||
</div>
|
||||
</div>
|
||||
<h3 className="text-sm font-semibold text-gray-800 line-clamp-2" title={email.subject}>
|
||||
{email.subject}
|
||||
</h3>
|
||||
</div>
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<CardContent className="p-0 h-[calc(100%-3.5rem)]">
|
||||
<iframe
|
||||
src="https://lab.slm-lab.net/email"
|
||||
className="w-full h-full border-0"
|
||||
title="Email Inbox"
|
||||
/>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user