import { useCallback, useEffect, useMemo, useRef, useState } from "react"; import { ActionIcon, Anchor, Center, Group, Loader, Modal, ScrollArea, Text, Tooltip, } from "@mantine/core"; import { IconDownload } from "@tabler/icons-react"; import { useTranslation } from "react-i18next"; import { SearchInput } from "@/components/common/search-input.tsx"; import { CustomAvatar } from "@/components/ui/custom-avatar.tsx"; import { usePageAttachmentsQuery } from "@/features/attachments/queries/attachment-query.ts"; import { IPageAttachment } from "@/features/attachments/types/attachment.types.ts"; import { AttachmentFileIcon } from "@/features/attachments/components/attachment-file-icon.tsx"; import { formatBytes } from "@/lib"; import { getFileUrl } from "@/lib/config.ts"; import { formattedDate } from "@/lib/time.ts"; interface PageAttachmentsModalProps { pageId: string; open: boolean; onClose: () => void; } export default function PageAttachmentsModal({ pageId, open, onClose, }: PageAttachmentsModalProps) { const { t } = useTranslation(); return ( ); } function PageAttachmentsList({ pageId }: { pageId: string }) { const { t } = useTranslation(); const [search, setSearch] = useState(""); const { data, isLoading, isError, isFetching, fetchNextPage, hasNextPage, isFetchingNextPage, } = usePageAttachmentsQuery(pageId, search); const attachments = useMemo( () => data?.pages.flatMap((page) => page.items) ?? [], [data], ); const loadMoreRef = useRef(null); useEffect(() => { const sentinel = loadMoreRef.current; if (!sentinel || !hasNextPage) return; const observer = new IntersectionObserver( (entries) => { if (entries[0].isIntersecting && !isFetching) { fetchNextPage(); } }, { threshold: 0.1 }, ); observer.observe(sentinel); return () => observer.disconnect(); }, [fetchNextPage, hasNextPage, isFetching]); const handleSearch = useCallback((value: string) => setSearch(value), []); return ( <> {isLoading ? (
) : isError ? (
{t("Error loading attachments.")}
) : attachments.length === 0 ? (
{search ? t("No results found") : t("No attachments on this page yet.")}
) : ( {attachments.map((attachment) => ( ))} {hasNextPage &&
} {isFetchingNextPage && (
)} )} ); } function AttachmentRow({ attachment }: { attachment: IPageAttachment }) { const { t } = useTranslation(); const fileUrl = getFileUrl(attachment.url); return (
{attachment.fileName} {formatBytes(Number(attachment.fileSize))} {" ยท "} {formattedDate(new Date(attachment.createdAt))}
{attachment.creator && ( )}
); }