import { useQuery, useQueries } from "@tanstack/react-query"; import { getMyUploadedFiles } from "@/external-portal/services/portalOutgoingService"; import { getDocumentRequirementsById } from "@/shared/services/organizationsService"; import { getUserById } from "@/super-admin/services/api/userService"; import { Card, CardHeader, CardTitle, CardContent, } from "@/shared/common/ui/card"; import { Button } from "@/shared/common/ui/button"; import { ScrollArea } from "@/shared/common/ui/scroll-area"; import { Skeleton } from "@/shared/common/ui/skeleton"; import { Alert, AlertDescription } from "@/shared/common/ui/alert"; import { FileText, RefreshCw, User, Mail, Phone, Building } from "lucide-react"; import { useLocalizedName } from "@/shared/common/localizedName"; import { DocumentRequirementResponseDto, DocumentResponseDto, } from "@/shared/dto/External-Portal/External-PortalDto"; import ActionModal from "./ResponseActions"; import { toast } from "sonner"; import { useGiveResponse } from "@/shared/hooks/useOrganizationReport"; import { useState } from "react"; import { useTranslation } from "react-i18next"; import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "@/shared/common/ui/tooltip"; type ViewDocumentProps = { userId: string; }; interface UploadsResponse { items: DocumentResponseDto[]; counts: number; } interface UserInfo { id: string; name: { am: string; en: string; }; email: string; phoneNumber: string; username: string; userType: string; status: string; } const ViewDocument: React.FC = ({ userId }) => { const localizedName = useLocalizedName(); const { t } = useTranslation(); const [status, setStatus] = useState<"APPROVED" | "REJECTED" | "PENDING">( "APPROVED" ); // Utility function to truncate email if too long const truncateEmail = (email: string, maxLength: number = 25) => { if (email.length <= maxLength) return email; const [localPart, domain] = email.split("@"); if (localPart.length > maxLength - 10) { return `${localPart.substring(0, maxLength - 10)}...@${domain}`; } return email; }; const { mutate, isLoading: isGiveResponseLoading } = useGiveResponse(); // 1️⃣ Fetch user information const { data: userInfo, isLoading: isUserLoading, isError: isUserError, } = useQuery({ queryKey: ["user-info", userId], queryFn: async () => { const res = await getUserById(userId); return res.data; }, }); // 2️⃣ Fetch uploaded documents const { data: uploadedDocuments, isLoading, isError, refetch, isRefetching, } = useQuery({ queryKey: ["external-letters", userId], queryFn: async () => { const res = await getMyUploadedFiles(userId); return { items: res.data.items, counts: res.data.counts, }; }, }); // 3️⃣ Fetch requirements for each uploaded document const documentRequirementsQueries = useQueries({ queries: uploadedDocuments?.items.map((doc) => ({ queryKey: ["document-requirements", doc.documentId], queryFn: async (): Promise => { const res = await getDocumentRequirementsById(doc.documentId); return res.data; }, enabled: !!uploadedDocuments && uploadedDocuments.items.length > 0, })) ?? [], }); // 4️⃣ Action submit handler const handleActionSubmit = async ( documentId: string, actionStatus: | "pending" | "submitted" | "approved" | "adjusted" | "rejected", remark?: string ) => { try { await mutate({ id: documentId, data: { status: actionStatus, remark } }); toast.success( t("viewDocument.actions.success", { action: actionStatus }) ); } catch (err: any) { toast.error( t("viewDocument.actions.error", { error: err.message || t("viewDocument.loading.failedToLoad"), }) ); } }; return (
{t("viewDocument.title")}
{/* User Information Section */} {isUserLoading ? (
) : isUserError ? ( {t("viewDocument.failedToLoadUserInfo")} ) : userInfo ? (

{t("viewDocument.userInformation")}

{t("viewDocument.organizationName")}

{localizedName(userInfo.name)}

{t("viewDocument.email")}

{truncateEmail(userInfo.email)}

{userInfo.email}

{t("viewDocument.phoneNumber")}

{userInfo.phoneNumber}

) : null} {/* Documents Section */} {isLoading ? (
{[...Array(3)].map((_, i) => ( ))}
) : isError ? ( {t("viewDocument.loading.failedToLoad")} ) : ( <>

{t("viewDocument.totalDocuments")}{" "} {uploadedDocuments?.counts ?? 0}

    {uploadedDocuments?.items.map((doc, index) => { const eachDocument = documentRequirementsQueries[index]?.data; const isEachLoading = documentRequirementsQueries[index]?.isLoading; const isEachError = documentRequirementsQueries[index]?.isError; const requirements = eachDocument ? [eachDocument] : []; // Translate status const getTranslatedStatus = (status: string) => { switch (status) { case "approved": return t("viewDocument.document.status.approved"); case "rejected": return t("viewDocument.document.status.rejected"); case "pending": default: return t("viewDocument.document.status.pending"); } }; return (
  • {doc.fileInfo.originalname}

    {getTranslatedStatus(doc.status)}
    {doc.status !== "approved" && ( )}
    {/* Document Requirements Section */}

    {t("viewDocument.document.requirements")}

    {isEachLoading ? (
    ) : isEachError ? (

    {t("viewDocument.loading.failedToLoadRequirements")}

    ) : requirements.length ? (
      {requirements.map((req) => (
    • {localizedName(req.title)} {req.isOptional ? t("viewDocument.document.optional") : t("viewDocument.document.required")}
    • ))}
    ) : (

    {t("viewDocument.document.noRequirements")}

    )}
  • ); })}
)}
); }; export default ViewDocument;