From 7956e9fa6772ab57a0794fb7cba7e9d9c0bd7878 Mon Sep 17 00:00:00 2001 From: Mohamed Bassem Date: Sat, 28 Dec 2024 12:30:24 +0000 Subject: feat: Implement the all highlights page. Fixes #620 --- .../dashboard/highlights/AllHighlights.tsx | 98 ++++++++++++++++++++++ .../dashboard/highlights/HighlightCard.tsx | 76 +++++++++++++++++ 2 files changed, 174 insertions(+) create mode 100644 apps/web/components/dashboard/highlights/AllHighlights.tsx create mode 100644 apps/web/components/dashboard/highlights/HighlightCard.tsx (limited to 'apps/web/components/dashboard/highlights') diff --git a/apps/web/components/dashboard/highlights/AllHighlights.tsx b/apps/web/components/dashboard/highlights/AllHighlights.tsx new file mode 100644 index 00000000..27dda6ff --- /dev/null +++ b/apps/web/components/dashboard/highlights/AllHighlights.tsx @@ -0,0 +1,98 @@ +"use client"; + +import { useEffect } from "react"; +import Link from "next/link"; +import { ActionButton } from "@/components/ui/action-button"; +import useRelativeTime from "@/lib/hooks/relative-time"; +import { api } from "@/lib/trpc"; +import { Separator } from "@radix-ui/react-dropdown-menu"; +import dayjs from "dayjs"; +import relativeTime from "dayjs/plugin/relativeTime"; +import { Dot, LinkIcon } from "lucide-react"; +import { useTranslation } from "react-i18next"; +import { useInView } from "react-intersection-observer"; + +import { + ZGetAllHighlightsResponse, + ZHighlight, +} from "@hoarder/shared/types/highlights"; + +import HighlightCard from "./HighlightCard"; + +dayjs.extend(relativeTime); + +function Highlight({ highlight }: { highlight: ZHighlight }) { + const { fromNow, localCreatedAt } = useRelativeTime(highlight.createdAt); + const { t } = useTranslation(); + return ( +
+ + + {fromNow} + + + + {t("common.source")} + + +
+ ); +} + +export default function AllHighlights({ + highlights: initialHighlights, +}: { + highlights: ZGetAllHighlightsResponse; +}) { + const { data, fetchNextPage, hasNextPage, isFetchingNextPage } = + api.highlights.getAll.useInfiniteQuery( + {}, + { + initialData: () => ({ + pages: [initialHighlights], + pageParams: [null], + }), + initialCursor: null, + getNextPageParam: (lastPage) => lastPage.nextCursor, + }, + ); + + const { ref: loadMoreRef, inView: loadMoreButtonInView } = useInView(); + useEffect(() => { + if (loadMoreButtonInView && hasNextPage && !isFetchingNextPage) { + fetchNextPage(); + } + }, [loadMoreButtonInView]); + + return ( +
+ {data?.pages + .flatMap((p) => p.highlights) + .map((h) => ( + <> + + + + ))} + {hasNextPage && ( +
+ fetchNextPage()} + variant="ghost" + > + Load More + +
+ )} +
+ ); +} diff --git a/apps/web/components/dashboard/highlights/HighlightCard.tsx b/apps/web/components/dashboard/highlights/HighlightCard.tsx new file mode 100644 index 00000000..63ff9423 --- /dev/null +++ b/apps/web/components/dashboard/highlights/HighlightCard.tsx @@ -0,0 +1,76 @@ +import { ActionButton } from "@/components/ui/action-button"; +import { toast } from "@/components/ui/use-toast"; +import { cn } from "@/lib/utils"; +import { Trash2 } from "lucide-react"; + +import { useDeleteHighlight } from "@hoarder/shared-react/hooks/highlights"; +import { ZHighlight } from "@hoarder/shared/types/highlights"; + +import { HIGHLIGHT_COLOR_MAP } from "../preview/highlights"; + +export default function HighlightCard({ + highlight, + clickable, + className, +}: { + highlight: ZHighlight; + clickable: boolean; + className?: string; +}) { + const { mutate: deleteHighlight, isPending: isDeleting } = useDeleteHighlight( + { + onSuccess: () => { + toast({ + description: "Highlight has been deleted!", + }); + }, + onError: () => { + toast({ + description: "Something went wrong", + variant: "destructive", + }); + }, + }, + ); + + const onBookmarkClick = () => { + document + .querySelector(`[data-highlight-id="${highlight.id}"]`) + ?.scrollIntoView({ + behavior: "smooth", + block: "center", + }); + }; + + const Wrapper = ({ children }: { children: React.ReactNode }) => + clickable ? ( + + ) : ( +
{children}
+ ); + + return ( +
+ +
+

{highlight.text}

+
+
+
+ deleteHighlight({ highlightId: highlight.id })} + > + + +
+
+ ); +} -- cgit v1.2.3-70-g09d2