import React, { useCallback, useMemo, useState } from "react" import Link from "next/link" import { usePathname, useRouter } from "next/navigation" import { useAtom } from "jotai" import { toast } from "sonner" import { LaIcon } from "@/components/custom/la-icon" import { Popover, PopoverTrigger, PopoverContent } from "@/components/ui/popover" import { Button } from "@/components/ui/button" import { LearningStateSelectorContent } from "@/components/custom/learning-state-selector" import { cn, ensureUrlProtocol, generateUniqueSlug } from "@/lib/utils" import { Link as LinkSchema, PersonalLink, Topic } from "@/lib/schema" import { openPopoverForIdAtom } from "../TopicDetailRoute" import { LEARNING_STATES, LearningStateValue } from "@/lib/constants" import { useAccountOrGuest } from "@/lib/providers/jazz-provider" import { useClerk } from "@clerk/nextjs" interface LinkItemProps { topic: Topic link: LinkSchema isActive: boolean index: number setActiveIndex: (index: number) => void } export const LinkItem = React.memo( React.forwardRef(({ topic, link, isActive, index, setActiveIndex }, ref) => { const clerk = useClerk() const pathname = usePathname() const router = useRouter() const [, setOpenPopoverForId] = useAtom(openPopoverForIdAtom) const [isPopoverOpen, setIsPopoverOpen] = useState(false) const { me } = useAccountOrGuest({ root: { personalLinks: [] } }) const personalLinks = useMemo(() => { if (!me || me._type === "Anonymous") return undefined return me?.root?.personalLinks || [] }, [me]) const personalLink = useMemo(() => { return personalLinks?.find(pl => pl?.link?.id === link.id) }, [personalLinks, link.id]) const selectedLearningState = useMemo(() => { return LEARNING_STATES.find(ls => ls.value === personalLink?.learningState) }, [personalLink?.learningState]) const handleClick = useCallback( (e: React.MouseEvent) => { e.preventDefault() setActiveIndex(index) }, [index, setActiveIndex] ) const handleSelectLearningState = useCallback( (learningState: LearningStateValue) => { if (!personalLinks || !me || me?._type === "Anonymous") { return clerk.redirectToSignIn({ redirectUrl: pathname }) } const defaultToast = { duration: 5000, position: "bottom-right" as const, closeButton: true, action: { label: "Go to list", onClick: () => router.push("/links") } } if (personalLink) { if (personalLink.learningState === learningState) { personalLink.learningState = undefined toast.error("Link learning state removed", defaultToast) } else { personalLink.learningState = learningState toast.success("Link learning state updated", defaultToast) } } else { const slug = generateUniqueSlug(link.title) const newPersonalLink = PersonalLink.create( { url: link.url, title: link.title, slug, link, learningState, sequence: personalLinks.length + 1, completed: false, topic, createdAt: new Date(), updatedAt: new Date() }, { owner: me } ) personalLinks.push(newPersonalLink) toast.success("Link added.", { ...defaultToast, description: `${link.title} has been added to your personal link.` }) } setOpenPopoverForId(null) setIsPopoverOpen(false) }, [personalLink, personalLinks, me, link, router, setOpenPopoverForId, topic, clerk, pathname] ) const handlePopoverOpenChange = useCallback( (open: boolean) => { setIsPopoverOpen(open) setOpenPopoverForId(open ? link.id : null) }, [link.id, setOpenPopoverForId] ) return (
  • e.preventDefault()} > handleSelectLearningState(value as LearningStateValue)} />

    {link.title}

  • ) }) ) LinkItem.displayName = "LinkItem"