mirror of
https://github.com/linsa-io/linsa.git
synced 2026-04-25 01:38:35 +02:00
fix: detail topic (#117)
* feat: keyboard nav * fix: link update * feat: reusable learning state * chore: use new learning state * feat: add to my profile * . * . * feat: on enter open the link * fix: lint * fix: use eslint v8 instead of v9 * fix: add to my profile * chore: update personal link schema * chore: update personal page schema * fix: update detail wrapper * fix: update page section * removing option for learning status * removing option for learning status for topic * feat: add createdAt and updatedAt for personal Page * chore: update page section component * chore: remove chevron from sub menu * fix: sidebar * chore: add focus and disable toast * feat: la editor add execption for no command class * fix: la editor style and fix page detail * fix: title * fix: topic learning state * chore: add showSearch for learning state * fix: bunch stuff * chore: link list and item handle learning state * chore: set expand to false * feat: personal link for topic detail * chore: hook use topic data * chore: go to list * fix: link and topic * feat(utils): new keyboard utils * feat(store): add linkOpenPopoverForIdAtom for link * chore: using memo for use topic data * fix: remove duplicate component * chore: performance for topic detail lint item * refactor: remove LinkOptions component * chore: improve performance for list * feat: added LinkRoute copmonent * chore: link manage * feat: bottom bar * fix: link * fix: page wrapper * fix: import thing * chore: added a displayname * refactor: page detail * refactor: page detail * fix: add topic to personal link form link * fix: only show page count if more than zero * fix: sidebar topic section --------- Co-authored-by: Nikita <github@nikiv.dev> Co-authored-by: marshennikovaolga <marshennikova@gmail.com>
This commit is contained in:
@@ -1,108 +1,41 @@
|
||||
"use client"
|
||||
|
||||
import React from "react"
|
||||
import Link from "next/link"
|
||||
import { useCoState } from "@/lib/providers/jazz-provider"
|
||||
import { PublicGlobalGroup } from "@/lib/schema/master/public-group"
|
||||
import { ID } from "jazz-tools"
|
||||
import { TopicDetailHeader } from "./Header"
|
||||
import { LaIcon } from "@/components/custom/la-icon"
|
||||
import { cn, ensureUrlProtocol } from "@/lib/utils"
|
||||
import { Section as SectionSchema, Link as LinkSchema } from "@/lib/schema"
|
||||
import { TopicSections } from "./partials/topic-sections"
|
||||
import { useLinkNavigation } from "./use-link-navigation"
|
||||
import { useTopicData } from "@/hooks/use-topic-data"
|
||||
import { atom } from "jotai"
|
||||
import { useAccount } from "@/lib/providers/jazz-provider"
|
||||
|
||||
interface TopicDetailRouteProps {
|
||||
topicName: string
|
||||
}
|
||||
|
||||
export const openPopoverForIdAtom = atom<string | null>(null)
|
||||
|
||||
export function TopicDetailRoute({ topicName }: TopicDetailRouteProps) {
|
||||
const topics = useCoState(PublicGlobalGroup, process.env.NEXT_PUBLIC_JAZZ_GLOBAL_GROUP as ID<PublicGlobalGroup>, {
|
||||
root: {
|
||||
topics: []
|
||||
}
|
||||
})
|
||||
const { me } = useAccount({ root: { personalLinks: [] } })
|
||||
const { topic, allLinks } = useTopicData(topicName)
|
||||
const { activeIndex, setActiveIndex, containerRef, linkRefs } = useLinkNavigation(allLinks)
|
||||
|
||||
const topic = topics?.root.topics.find(topic => topic?.name === topicName)
|
||||
|
||||
if (!topic) {
|
||||
if (!topic || !me) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex h-full flex-auto flex-col">
|
||||
<TopicDetailHeader topic={topic} />
|
||||
<div className="flex w-full flex-1 flex-col gap-4 focus-visible:outline-none">
|
||||
<div tabIndex={-1} className="outline-none">
|
||||
<div className="flex flex-1 flex-col gap-4" role="listbox" aria-label="Topic sections">
|
||||
{topic.latestGlobalGuide?.sections?.map(
|
||||
(section, index) => section?.id && <Section key={index} section={section} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<TopicSections
|
||||
topic={topic}
|
||||
sections={topic.latestGlobalGuide?.sections}
|
||||
activeIndex={activeIndex}
|
||||
setActiveIndex={setActiveIndex}
|
||||
linkRefs={linkRefs}
|
||||
containerRef={containerRef}
|
||||
me={me}
|
||||
personalLinks={me.root.personalLinks}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
interface SectionProps {
|
||||
section: SectionSchema
|
||||
}
|
||||
|
||||
function Section({ section }: SectionProps) {
|
||||
return (
|
||||
<div className="flex flex-col">
|
||||
<div className="flex items-center gap-4 px-4 py-2">
|
||||
<p className="text-foreground text-sm font-medium">{section.title}</p>
|
||||
<div className="border-b-secondary flex-1 border-b"></div>
|
||||
</div>
|
||||
|
||||
<div className="flex flex-col gap-px py-2">
|
||||
{section.links?.map((link, index) => link?.url && <LinkItem key={index} link={link} />)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
interface LinkItemProps {
|
||||
link: LinkSchema
|
||||
}
|
||||
|
||||
function LinkItem({ link }: LinkItemProps) {
|
||||
return (
|
||||
<li
|
||||
tabIndex={0}
|
||||
className={cn("hover:bg-muted/50 relative flex h-14 cursor-default items-center outline-none xl:h-11")}
|
||||
>
|
||||
<div className="flex grow justify-between gap-x-6 px-6 max-lg:px-4">
|
||||
<div className="flex min-w-0 items-center gap-x-4">
|
||||
<LaIcon name="GraduationCap" className="size-5" />
|
||||
<div className="w-full min-w-0 flex-auto">
|
||||
<div className="gap-x-2 space-y-0.5 xl:flex xl:flex-row">
|
||||
<p className="text-primary hover:text-primary line-clamp-1 text-sm font-medium xl:truncate">
|
||||
{link.title}
|
||||
</p>
|
||||
|
||||
<div className="group flex items-center gap-x-1">
|
||||
<LaIcon
|
||||
name="Link"
|
||||
aria-hidden="true"
|
||||
className="text-muted-foreground group-hover:text-primary size-3 flex-none"
|
||||
/>
|
||||
<Link
|
||||
href={ensureUrlProtocol(link.url)}
|
||||
passHref
|
||||
prefetch={false}
|
||||
target="_blank"
|
||||
onClick={e => e.stopPropagation()}
|
||||
className="text-muted-foreground hover:text-primary text-xs"
|
||||
>
|
||||
<span className="xl:truncate">{link.url}</span>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex shrink-0 items-center gap-x-4"></div>
|
||||
</div>
|
||||
</li>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user