import React, { useCallback, useEffect, useMemo } from "react" import { Primitive } from "@radix-ui/react-primitive" import { useAccount } from "@/lib/providers/jazz-provider" import { atom, useAtom } from "jotai" import { commandPaletteOpenAtom } from "@/components/custom/command-palette/command-palette" import { TopicItem } from "./partials/topic-item" import { useMedia } from "react-use" import { useRouter } from "next/navigation" import { useActiveItemScroll } from "@/hooks/use-active-item-scroll" import { Column } from "@/components/custom/column" import { useColumnStyles } from "./hooks/use-column-styles" import { LaAccount, ListOfTopics, Topic, UserRoot } from "@/lib/schema" import { LearningStateValue } from "@/lib/constants" interface TopicListProps { activeItemIndex: number | null setActiveItemIndex: React.Dispatch> disableEnterKey: boolean } interface MainTopicListProps extends TopicListProps { me: { root: { topicsWantToLearn: ListOfTopics topicsLearning: ListOfTopics topicsLearned: ListOfTopics } & UserRoot } & LaAccount } export interface PersonalTopic { topic: Topic | null learningState: LearningStateValue } export const topicOpenPopoverForIdAtom = atom(null) export const TopicList: React.FC = ({ activeItemIndex, setActiveItemIndex, disableEnterKey }) => { const { me } = useAccount({ root: { topicsWantToLearn: [], topicsLearning: [], topicsLearned: [] } }) if (!me) return null return ( ) } export const MainTopicList: React.FC = ({ me, activeItemIndex, setActiveItemIndex, disableEnterKey }) => { const isTablet = useMedia("(max-width: 640px)") const [isCommandPaletteOpen] = useAtom(commandPaletteOpenAtom) const router = useRouter() const personalTopics = useMemo( () => [ ...me.root.topicsWantToLearn.map(topic => ({ topic, learningState: "wantToLearn" as const })), ...me.root.topicsLearning.map(topic => ({ topic, learningState: "learning" as const })), ...me.root.topicsLearned.map(topic => ({ topic, learningState: "learned" as const })) ], [me.root.topicsWantToLearn, me.root.topicsLearning, me.root.topicsLearned] ) const itemCount = personalTopics.length const handleEnter = useCallback( (selectedTopic: Topic) => { router.push(`/${selectedTopic.name}`) }, [router] ) const handleKeyDown = useCallback( (e: KeyboardEvent) => { if (isCommandPaletteOpen) return if (e.key === "ArrowUp" || e.key === "ArrowDown") { e.preventDefault() setActiveItemIndex(prevIndex => { if (prevIndex === null) return 0 const newIndex = e.key === "ArrowUp" ? (prevIndex - 1 + itemCount) % itemCount : (prevIndex + 1) % itemCount return newIndex }) } else if (e.key === "Enter" && !disableEnterKey && activeItemIndex !== null && personalTopics) { e.preventDefault() const selectedTopic = personalTopics[activeItemIndex] if (selectedTopic?.topic) handleEnter?.(selectedTopic.topic) } }, [itemCount, isCommandPaletteOpen, activeItemIndex, setActiveItemIndex, disableEnterKey, personalTopics, handleEnter] ) useEffect(() => { window.addEventListener("keydown", handleKeyDown) return () => window.removeEventListener("keydown", handleKeyDown) }, [handleKeyDown]) return (
{!isTablet && }
) } export const ColumnHeader: React.FC = () => { const columnStyles = useColumnStyles() return (
Name State
) } interface TopicListItemsProps { personalTopics: PersonalTopic[] | null activeItemIndex: number | null } const TopicListItems: React.FC = ({ personalTopics, activeItemIndex }) => { const { setElementRef } = useActiveItemScroll({ activeIndex: activeItemIndex }) return ( {personalTopics?.map( (pt, index) => pt.topic?.id && ( setElementRef(el, index)} topic={pt.topic} learningState={pt.learningState} isActive={index === activeItemIndex} /> ) )} ) }