"use client"; import React, { use, useCallback, useEffect, useState } from "react"; import Link from "next/link"; import { motion, AnimatePresence } from "framer-motion"; import { Search, Paperclip, Reply, Forward, ShieldAlert, Inbox, Filter, CheckCircle2, Image as ImageIcon, Mail, Clock, User, ExternalLink, } from "lucide-react"; import { useTranslations } from "../../../../../i18n/provider"; import { useMailEvents } from "../../../../../lib/useMailEvents"; import { sanitizeEmailHtml, blockRemoteImages, unblockRemoteImages } from "../../../../../lib/sanitizer"; import { Badge } from "../../../../../components/ui/Badge"; import { Button } from "../../../../../components/ui/Button"; interface MessageSummary { uid: number; subject: string; sender_address: string; from_display_name: string; snippet: string; size_bytes: number; received_at: string; has_attachments: boolean; seen: boolean; spam_verdict: string; dmarc_result: string; } interface RenderedMessage { uid: number; subject: string; from: string; to: string[]; cc: string[]; date: string; text: string; html: string; attachments: string[]; } export default function MailFolderPage({ params }: { params: Promise<{ folder: string }> }) { const { folder } = use(params); const t = useTranslations(); const [messages, setMessages] = useState([]); const [selected, setSelected] = useState(null); const [loadRemoteImages, setLoadRemoteImages] = useState(false); const [searchQuery, setSearchQuery] = useState(""); const [activeFilter, setActiveFilter] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const loadMessages = useCallback( async (search: string) => { setLoading(true); setError(null); try { const query = new URLSearchParams({ folder, ...(search ? { q: search } : {}) }); const res = await fetch(`/api/v1/mail/messages?${query}`); if (res.status === 401) { window.location.href = "/user/login"; return; } if (!res.ok) throw new Error(t("errors.serverError")); setMessages(await res.json()); } catch (err) { setError(err instanceof Error ? err.message : t("errors.serverError")); } finally { setLoading(false); } }, [folder, t] ); useEffect(() => { void loadMessages(""); }, [loadMessages]); useMailEvents( useCallback( (event) => { if (event.type === "resync" || event.type === "EmailReceived") { void loadMessages(searchQuery); } }, [loadMessages, searchQuery] ) ); useEffect(() => { const handle = setTimeout(() => void loadMessages(searchQuery), 250); return () => clearTimeout(handle); }, [searchQuery, loadMessages]); const openMessage = async (uid: number) => { setLoadRemoteImages(false); try { const res = await fetch(`/api/v1/mail/message/${uid}?folder=${encodeURIComponent(folder)}`); if (!res.ok) throw new Error(t("errors.serverError")); const data = await res.json(); setSelected(data); setMessages((current) => current.map((m) => (m.uid === uid ? { ...m, seen: true } : m))); } catch (err) { setError(err instanceof Error ? err.message : t("errors.serverError")); } }; const filteredMessages = messages.filter((msg) => { if (activeFilter === "unread") return !msg.seen; if (activeFilter === "attachment") return msg.has_attachments; return true; }); const sanitizedHtml = selected?.html ? sanitizeEmailHtml(selected.html) : null; const bodyHtml = sanitizedHtml ? loadRemoteImages ? unblockRemoteImages(sanitizedHtml) : blockRemoteImages(sanitizedHtml) : null; return (
{/* Messages List Column */}
{/* Search Bar & Filter Chips */}
setSearchQuery(e.target.value)} placeholder={`${t("common.search")} (from:, subject:)...`} className="w-full pl-9 pr-3 py-2 text-xs rounded-xl bg-slate-900/90 border border-slate-800 text-white placeholder-slate-500 focus:outline-none focus:border-indigo-500 transition-colors" />
{/* Message Items List */}
{loading ? (
{t("common.loading")}
) : error ? (
{error}
) : filteredMessages.length === 0 ? (
{t("mail.noMessages")}
) : ( filteredMessages.map((msg) => { const isSelected = selected?.uid === msg.uid; return ( ); }) )}
{/* Message Reader Column */}
{selected && ( )} {selected ? ( {/* Header & Reply/Forward Actions */}

{selected.subject || "(Sem assunto)"}

{/* Action Buttons */}
{selected.from}
{selected.to.length > 0 && (
Para: {selected.to.join(", ")}
)}
{selected.date ? new Date(selected.date).toLocaleString() : ""}
{/* Attachment Download Chips */} {selected.attachments.length > 0 && (
{selected.attachments.map((filename, idx) => ( {filename} ))}
)}
{/* Remote Images Privacy Banner */} {selected.html && (
{t("mail.loadImages")} (sanitised)
)} {/* Message Body Container */} {bodyHtml ? (