fix: eager loading for nested topic

This commit is contained in:
Aslam H
2024-11-09 15:14:23 +07:00
parent 60846a4c42
commit 6475855e2f
5 changed files with 60 additions and 210 deletions

View File

@@ -7,8 +7,8 @@ import { Link } from "@tanstack/react-router"
import { getFeatureFlag } from "~/actions"
export const JournalSection: React.FC = () => {
const { me } = useAccount()
const journalEntries = me?.root?.journalEntries
const { me } = useAccount({ root: { journalEntries: [{}] } })
const journalEntries = me?.root.journalEntries
const [, setIsFetching] = useState(false)
const [isFeatureActive, setIsFeatureActive] = useState(false)

View File

@@ -3,25 +3,16 @@ import { useAccount } from "@/lib/providers/jazz-provider"
import { NavItem } from "~/components/custom/nav-item"
export const LinkCollection: React.FC = () => {
const { me } = useAccount({
root: {
personalLinks: [],
personalPages: [],
topicsWantToLearn: [],
topicsLearning: [],
topicsLearned: [],
tasks: [],
},
})
const { me } = useAccount()
const linkCount = me?.root.personalLinks?.length || 0
const pageCount = me?.root.personalPages?.length || 0
const taskCount = me?.root.tasks?.length || 0
const linkCount = me?.root?.personalLinks?.length || 0
const pageCount = me?.root?.personalPages?.length || 0
const taskCount = me?.root?.tasks?.length || 0
const topicCount =
(me?.root.topicsWantToLearn?.length || 0) +
(me?.root.topicsLearning?.length || 0) +
(me?.root.topicsLearned?.length || 0)
(me?.root?.topicsWantToLearn?.length || 0) +
(me?.root?.topicsLearning?.length || 0) +
(me?.root?.topicsLearned?.length || 0)
return (
<div className="flex flex-col gap-px py-2">

View File

@@ -1,140 +0,0 @@
import * as React from "react"
import { Link } from "@tanstack/react-router"
import { useAccount } from "@/lib/providers/jazz-provider"
import { cn } from "@/lib/utils"
import { PersonalLinkLists } from "@/lib/schema/personal-link"
import { LearningStateValue } from "~/lib/constants"
import { LaIcon } from "~/components/custom/la-icon"
export const LinkSection: React.FC = () => {
const { me } = useAccount({ root: { personalLinks: [] } })
if (!me) return null
const linkCount = me.root.personalLinks?.length || 0
return (
<div className="flex flex-col gap-px">
<LinkSectionHeader linkCount={linkCount} />
<LinkList personalLinks={me.root.personalLinks} />
</div>
)
}
interface LinkSectionHeaderProps {
linkCount: number
}
const LinkSectionHeader: React.FC<LinkSectionHeaderProps> = ({ linkCount }) => {
return (
<Link
to="/links"
className={cn(
"flex h-[30px] items-center gap-px rounded-md px-2 text-sm font-medium hover:bg-[var(--item-hover)] focus-visible:outline-none focus-visible:ring-0",
)}
activeProps={{
className:
"bg-[var(--item-active)] data-[status='active']:hover:bg-[var(--item-active)]",
}}
>
{({ isActive }) => {
return (
<>
<div className="flex items-center gap-1.5">
<LaIcon name="Link" className="" />
<span>Links</span>
</div>
<span className="flex flex-auto"></span>
{linkCount > 0 && (
<span
className={cn("font-mono text-muted-foreground", {
"text-foreground": isActive,
})}
>
{linkCount}
</span>
)}
</>
)
}}
</Link>
)
}
interface LinkListProps {
personalLinks: PersonalLinkLists
}
const LinkList: React.FC<LinkListProps> = ({ personalLinks }) => {
const linkStates: LearningStateValue[] = [
"wantToLearn",
"learning",
"learned",
]
const linkLabels: Record<LearningStateValue, string> = {
wantToLearn: "To Learn",
learning: "Learning",
learned: "Learned",
}
const linkCounts = linkStates.reduce(
(acc, state) => ({
...acc,
[state]: personalLinks.filter((link) => link?.learningState === state)
.length,
}),
{} as Record<LearningStateValue, number>,
)
return (
<div className="flex flex-col gap-px">
{linkStates.map((state) => (
<LinkListItem
key={state}
label={linkLabels[state]}
state={state}
count={linkCounts[state]}
/>
))}
</div>
)
}
interface LinkListItemProps {
label: string
state: LearningStateValue
count: number
}
const LinkListItem: React.FC<LinkListItemProps> = ({ label, state, count }) => (
<div className="relative flex min-w-0 flex-1">
<Link
to="/links"
search={{ state }}
className={cn(
"relative flex h-[30px] w-full items-center gap-2 rounded-md px-1.5 text-sm font-medium hover:bg-[var(--item-hover)]",
)}
activeProps={{
className:
"bg-[var(--item-active)] data-[status='active']:hover:bg-[var(--item-active)]",
}}
>
{({ isActive }) => (
<>
<div className="flex max-w-full flex-1 items-center gap-1.5 truncate">
<p className="truncate">{label}</p>
</div>
{count > 0 && (
<span
className={cn("font-mono text-muted-foreground", {
"text-foreground": isActive,
})}
>
{count}
</span>
)}
</>
)}
</Link>
</div>
)

View File

@@ -1,7 +1,7 @@
import * as React from "react"
import { useAtom } from "jotai"
import { atomWithStorage } from "jotai/utils"
import { Link, useNavigate } from "@tanstack/react-router"
import { Link } from "@tanstack/react-router"
import { useAccount } from "@/lib/providers/jazz-provider"
import { cn } from "@/lib/utils"
import { Button } from "@/components/ui/button"
@@ -49,9 +49,14 @@ const isExpandedAtom = atomWithStorage("isPageSectionExpanded", true)
export const PageSection: React.FC = () => {
const { me } = useAccount({
root: {
personalPages: [{}],
personalPages: [
{
topic: {},
},
],
},
})
const [sort] = useAtom(pageSortAtom)
const [show] = useAtom(pageShowAtom)
const [isExpanded, setIsExpanded] = useAtom(isExpandedAtom)
@@ -163,23 +168,13 @@ const PageSectionHeader: React.FC<PageSectionHeaderProps> = ({
)
const NewPageButton: React.FC = () => {
const { me } = useAccount()
const navigate = useNavigate()
const { newPage } = usePageActions()
const handleClick = async (e: React.MouseEvent<HTMLButtonElement>) => {
e.preventDefault()
e.stopPropagation()
const page = newPage(me)
if (page.id) {
navigate({
to: "/pages/$pageId",
params: { pageId: page.id },
replace: true,
})
}
newPage()
}
return (

View File

@@ -38,44 +38,48 @@ const useSidebarCollapse = (
return [isCollapsed, setIsCollapsed]
}
const SidebarItem: React.FC<SidebarItemProps> = React.memo(
({ label, url, icon, onClick, children }) => {
const { pathname } = useLocation()
const isActive = pathname === url
const SidebarItem: React.FC<SidebarItemProps> = ({
label,
url,
icon,
onClick,
children,
}) => {
const { pathname } = useLocation()
const isActive = pathname === url
return (
<div
className={cn(
"group relative my-0.5 rounded-md",
isActive ? "bg-secondary/80" : "hover:bg-secondary/40",
)}
return (
<div
className={cn(
"group relative my-0.5 rounded-md",
isActive ? "bg-secondary/80" : "hover:bg-secondary/40",
)}
>
<Link
className="flex h-8 grow items-center truncate rounded-md pl-1.5 pr-1 text-sm font-medium text-secondary-foreground"
to={url}
onClick={onClick}
>
<Link
className="flex h-8 grow items-center truncate rounded-md pl-1.5 pr-1 text-sm font-medium text-secondary-foreground"
to={url}
onClick={onClick}
>
{icon && (
<span
className={cn(
"mr-2 size-4 text-primary/60 group-hover:text-primary",
{ "text-primary": isActive },
)}
>
{icon}
</span>
)}
<span>{label}</span>
{children}
</Link>
</div>
)
},
)
{icon && (
<span
className={cn(
"mr-2 size-4 text-primary/60 group-hover:text-primary",
{ "text-primary": isActive },
)}
>
{icon}
</span>
)}
<span>{label}</span>
{children}
</Link>
</div>
)
}
SidebarItem.displayName = "SidebarItem"
const LogoAndSearch: React.FC = React.memo(() => {
const LogoAndSearch: React.FC = () => {
const { pathname } = useLocation()
return (
@@ -105,11 +109,11 @@ const LogoAndSearch: React.FC = React.memo(() => {
</div>
</div>
)
})
}
LogoAndSearch.displayName = "LogoAndSearch"
const SidebarContent: React.FC = React.memo(() => {
const SidebarContent: React.FC = () => {
const { me } = useAccountOrGuest()
return (
@@ -119,15 +123,15 @@ const SidebarContent: React.FC = React.memo(() => {
</div>
<div className="relative mt-1.5 flex grow flex-col overflow-y-auto rounded-md px-3 outline-none">
<div className="h-2 shrink-0" />
{me._type === "Account" && <LinkCollection />}
{me._type === "Account" && <JournalSection />}
{me._type === "Account" && <PageSection />}
{me?._type === "Account" && <LinkCollection />}
{me?._type === "Account" && <JournalSection />}
{me?._type === "Account" && <PageSection />}
</div>
<ProfileSection />
</nav>
)
})
}
SidebarContent.displayName = "SidebarContent"