fix: add load more button and pagination to attachments page (#5258)

pull/5263/merge
gitkeniwo 3 days ago committed by GitHub
parent edfbd6b073
commit a533ba02dc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -3,16 +3,17 @@ import { includes } from "lodash-es";
import { PaperclipIcon, SearchIcon } from "lucide-react";
import { observer } from "mobx-react-lite";
import { useEffect, useState } from "react";
import { toast } from "react-hot-toast";
import AttachmentIcon from "@/components/AttachmentIcon";
import Empty from "@/components/Empty";
import MobileHeader from "@/components/MobileHeader";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Separator } from "@/components/ui/separator";
import { attachmentServiceClient } from "@/grpcweb";
import useLoading from "@/hooks/useLoading";
import useResponsiveWidth from "@/hooks/useResponsiveWidth";
import i18n from "@/i18n";
import { memoStore } from "@/store";
import { Attachment } from "@/types/proto/api/v1/attachment_service";
import { useTranslate } from "@/utils/i18n";
@ -42,18 +43,51 @@ const Attachments = observer(() => {
searchQuery: "",
});
const [attachments, setAttachments] = useState<Attachment[]>([]);
const [nextPageToken, setNextPageToken] = useState("");
const [isLoadingMore, setIsLoadingMore] = useState(false);
const filteredAttachments = attachments.filter((attachment) => includes(attachment.filename, state.searchQuery));
const groupedAttachments = groupAttachmentsByDate(filteredAttachments.filter((attachment) => attachment.memo));
const unusedAttachments = filteredAttachments.filter((attachment) => !attachment.memo);
useEffect(() => {
attachmentServiceClient.listAttachments({}).then(({ attachments }) => {
setAttachments(attachments);
loadingState.setFinish();
Promise.all(attachments.map((attachment) => (attachment.memo ? memoStore.getOrFetchMemoByName(attachment.memo) : null)));
const fetchInitialAttachments = async () => {
try {
const { attachments: fetchedAttachments, nextPageToken } = await attachmentServiceClient.listAttachments({
pageSize: 50,
});
setAttachments(fetchedAttachments);
setNextPageToken(nextPageToken ?? "");
} catch (error) {
console.error("Failed to fetch attachments:", error);
toast.error("Failed to load attachments. Please try again.");
} finally {
loadingState.setFinish();
}
};
fetchInitialAttachments();
}, []);
const handleLoadMore = async () => {
if (!nextPageToken || isLoadingMore) {
return;
}
setIsLoadingMore(true);
try {
const { attachments: fetchedAttachments, nextPageToken: newPageToken } = await attachmentServiceClient.listAttachments({
pageSize: 50,
pageToken: nextPageToken,
});
setAttachments((prevAttachments) => [...prevAttachments, ...fetchedAttachments]);
setNextPageToken(newPageToken ?? "");
} catch (error) {
console.error("Failed to load more attachments:", error);
toast.error("Failed to load more attachments. Please try again.");
} finally {
setIsLoadingMore(false);
}
};
return (
<section className="@container w-full max-w-5xl min-h-full flex flex-col justify-start items-center sm:pt-3 md:pt-6 pb-8">
{!md && <MobileHeader />}
@ -89,6 +123,7 @@ const Attachments = observer(() => {
<p className="mt-4 text-muted-foreground">{t("message.no-data")}</p>
</div>
) : (
<>
<div className={"w-full h-auto px-2 flex flex-col justify-start items-start gap-y-8"}>
{Array.from(groupedAttachments.entries()).map(([monthStr, attachments]) => {
return (
@ -144,6 +179,14 @@ const Attachments = observer(() => {
</>
)}
</div>
{nextPageToken && (
<div className="w-full flex flex-row justify-center items-center mt-4">
<Button variant="outline" size="sm" onClick={handleLoadMore} disabled={isLoadingMore}>
{isLoadingMore ? t("resource.fetching-data") : t("memo.load-more")}
</Button>
</div>
)}
</>
)}
</>
)}

Loading…
Cancel
Save