diff --git a/web/components/custom/sidebar/partial/link-section.tsx b/web/components/custom/sidebar/partial/link-section.tsx
index e4639ccc..46a6e359 100644
--- a/web/components/custom/sidebar/partial/link-section.tsx
+++ b/web/components/custom/sidebar/partial/link-section.tsx
@@ -6,7 +6,6 @@ import { cn } from "@/lib/utils"
import { PersonalLinkLists } from "@/lib/schema/personal-link"
import { useQueryState, parseAsStringLiteral } from "nuqs"
import { LEARNING_STATES } from "@/lib/constants"
-import { useRouter } from "next/navigation"
export const LinkSection: React.FC<{ pathname: string }> = ({ pathname }) => {
const { me } = useAccount({
diff --git a/web/components/custom/sidebar/partial/profile-section.tsx b/web/components/custom/sidebar/partial/profile-section.tsx
index 68f6bc2c..2f0809eb 100644
--- a/web/components/custom/sidebar/partial/profile-section.tsx
+++ b/web/components/custom/sidebar/partial/profile-section.tsx
@@ -1,7 +1,6 @@
-import { useAccount } from "@/lib/providers/jazz-provider"
-import { LaIcon } from "../../la-icon"
+import { LaIcon } from "@/components/custom/la-icon"
import { useState } from "react"
-import { useAuth } from "@clerk/nextjs"
+import { SignInButton, useAuth, useUser } from "@clerk/nextjs"
import {
DropdownMenu,
DropdownMenuContent,
@@ -11,97 +10,68 @@ import {
} from "@/components/ui/dropdown-menu"
import { Avatar, AvatarImage } from "@/components/ui/avatar"
import Link from "next/link"
+import { cn } from "@/lib/utils"
+import { Button } from "@/components/ui/button"
+import { usePathname } from "next/navigation"
-const MenuItem = ({
- icon,
- text,
- href,
- onClick,
- onClose
-}: {
- icon: string
- text: string
- href?: string
- onClick?: () => void
- onClose: () => void
-}) => {
- const handleClick = () => {
- onClose()
- if (onClick) {
- onClick()
- }
+export const ProfileSection: React.FC = () => {
+ const { user, isSignedIn } = useUser()
+ const { signOut } = useAuth()
+ const [menuOpen, setMenuOpen] = useState(false)
+ const pathname = usePathname()
+
+ if (!isSignedIn) {
+ return (
+
+
+
+
+
+ )
}
return (
-
-
- {href ? (
-
- {text}
-
- ) : (
-
- {text}
-
- )}
-
- )
-}
-export const ProfileSection: React.FC = () => {
- const { me } = useAccount({
- profile: true
- })
- const { signOut, isSignedIn } = useAuth()
- const [menuOpen, setMenuOpen] = useState(false)
-
- const closeMenu = () => setMenuOpen(false)
-
- return (
-
+
-
+
- {isSignedIn ? (
- <>
-
-
-
-
-
-
-
-
-
-
-
- >
- ) : (
-
-
-
- )}
+
+
+
+
+ My profile
+
+
+
+
+ signOut()}>
+
+
+ Log out
+
+
@@ -109,7 +79,3 @@ export const ProfileSection: React.FC = () => {
)
}
-
-/*
-
- */
diff --git a/web/components/custom/sidebar/sidebar.tsx b/web/components/custom/sidebar/sidebar.tsx
index 54c4d1c7..3679128a 100644
--- a/web/components/custom/sidebar/sidebar.tsx
+++ b/web/components/custom/sidebar/sidebar.tsx
@@ -15,7 +15,6 @@ import { PageSection } from "./partial/page-section"
import { TopicSection } from "./partial/topic-section"
import { ProfileSection } from "./partial/profile-section"
import { useAccountOrGuest } from "@/lib/providers/jazz-provider"
-import { SignInButton } from "@clerk/nextjs"
interface SidebarContextType {
isCollapsed: boolean
@@ -126,15 +125,9 @@ const SidebarContent: React.FC = React.memo(() => {
{me._type === "Account" &&
}
{me._type === "Account" &&
}
-
- {me._type === "Account" ? (
- ) : (
-
- Fake profile section
-
- )}
+
>
)
})
diff --git a/web/components/routes/topics/detail/Header.tsx b/web/components/routes/topics/detail/Header.tsx
index 244dbc06..461f3176 100644
--- a/web/components/routes/topics/detail/Header.tsx
+++ b/web/components/routes/topics/detail/Header.tsx
@@ -6,13 +6,16 @@ import { ListOfTopics, Topic } from "@/lib/schema"
import { LearningStateSelector } from "@/components/custom/learning-state-selector"
import { useAccountOrGuest } from "@/lib/providers/jazz-provider"
import { LearningStateValue } from "@/lib/constants"
-import { toast } from "sonner"
+import { useClerk } from "@clerk/nextjs"
+import { usePathname } from "next/navigation"
interface TopicDetailHeaderProps {
topic: Topic
}
export const TopicDetailHeader = React.memo(function TopicDetailHeader({ topic }: TopicDetailHeaderProps) {
+ const clerk = useClerk()
+ const pathname = usePathname()
const { me } = useAccountOrGuest({
root: {
topicsWantToLearn: [],
@@ -32,7 +35,6 @@ export const TopicDetailHeader = React.memo(function TopicDetailHeader({ topic }
if (wantToLearnIndex !== -1) {
p = {
index: wantToLearnIndex,
- // TODO: fix this type error by doing better conditionals on both index and p
topic: me && me._type !== "Anonymous" ? me.root.topicsWantToLearn[wantToLearnIndex] : undefined,
learningState: "wantToLearn"
}
@@ -60,9 +62,9 @@ export const TopicDetailHeader = React.memo(function TopicDetailHeader({ topic }
const handleAddToProfile = (learningState: LearningStateValue) => {
if (me?._type === "Anonymous") {
- // TODO: handle better
- toast.error("You need to sign in to add links to your personal list.")
- return
+ return clerk.redirectToSignIn({
+ redirectUrl: pathname
+ })
}
const topicLists: Record
= {
diff --git a/web/components/routes/topics/detail/partials/link-item.tsx b/web/components/routes/topics/detail/partials/link-item.tsx
index 4758f01e..f6a80579 100644
--- a/web/components/routes/topics/detail/partials/link-item.tsx
+++ b/web/components/routes/topics/detail/partials/link-item.tsx
@@ -1,6 +1,6 @@
import React, { useCallback, useMemo, useState } from "react"
import Link from "next/link"
-import { useRouter } from "next/navigation"
+import { usePathname, useRouter } from "next/navigation"
import { useAtom } from "jotai"
import { toast } from "sonner"
@@ -10,10 +10,11 @@ import { Button } from "@/components/ui/button"
import { LearningStateSelectorContent } from "@/components/custom/learning-state-selector"
import { cn, ensureUrlProtocol, generateUniqueSlug } from "@/lib/utils"
-import { LaAccount, Link as LinkSchema, PersonalLink, PersonalLinkLists, Topic, UserRoot } from "@/lib/schema"
+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
@@ -24,185 +25,183 @@ interface LinkItemProps {
}
export const LinkItem = React.memo(
- React.forwardRef(
- ({ topic, link, isActive, index, setActiveIndex }, ref) => {
- const router = useRouter()
- const [, setOpenPopoverForId] = useAtom(openPopoverForIdAtom)
- const [isPopoverOpen, setIsPopoverOpen] = useState(false)
+ 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 { me } = useAccountOrGuest({ root: { personalLinks: [] } })
- const personalLinks = useMemo(() => {
- if (!me || me._type === "Anonymous") return undefined;
- return me?.root?.personalLinks || []
- }, [me])
+ 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 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 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 handleClick = useCallback(
+ (e: React.MouseEvent) => {
+ e.preventDefault()
+ setActiveIndex(index)
+ },
+ [index, setActiveIndex]
+ )
- const handleSelectLearningState = useCallback(
- (learningState: LearningStateValue) => {
- if (!personalLinks || !me || me?._type === "Anonymous") {
- if (me?._type === "Anonymous") {
- // TODO: handle better
- toast.error("You need to sign in to add links to your personal list.")
- }
- return
- };
+ 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("/")
- }
+ const defaultToast = {
+ duration: 5000,
+ position: "bottom-right" as const,
+ closeButton: true,
+ action: {
+ label: "Go to list",
+ onClick: () => router.push("/")
}
+ }
- 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)
- }
+ if (personalLink) {
+ if (personalLink.learningState === learningState) {
+ personalLink.learningState = undefined
+ toast.error("Link learning state removed", defaultToast)
} else {
- const slug = generateUniqueSlug(personalLinks.toJSON(), 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.`
- })
+ personalLink.learningState = learningState
+ toast.success("Link learning state updated", defaultToast)
}
+ } else {
+ const slug = generateUniqueSlug(personalLinks.toJSON(), 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 }
+ )
- setOpenPopoverForId(null)
- setIsPopoverOpen(false)
- },
- [personalLink, personalLinks, me, link, router, setOpenPopoverForId, topic]
- )
+ personalLinks.push(newPersonalLink)
- const handlePopoverOpenChange = useCallback(
- (open: boolean) => {
- setIsPopoverOpen(open)
- setOpenPopoverForId(open ? link.id : null)
- },
- [link.id, setOpenPopoverForId]
- )
+ toast.success("Link added.", {
+ ...defaultToast,
+ description: `${link.title} has been added to your personal link.`
+ })
+ }
- return (
-
-
-
-
-
-
-
- e.preventDefault()}
+ setOpenPopoverForId(null)
+ setIsPopoverOpen(false)
+ },
+ [personalLink, personalLinks, me, link, router, setOpenPopoverForId, topic]
+ )
+
+ const handlePopoverOpenChange = useCallback(
+ (open: boolean) => {
+ setIsPopoverOpen(open)
+ setOpenPopoverForId(open ? link.id : null)
+ },
+ [link.id, setOpenPopoverForId]
+ )
+
+ return (
+
+
+
+
+
+
+
+ e.preventDefault()}
+ >
+ handleSelectLearningState(value as LearningStateValue)}
+ />
+
+
+
+
+
+
+ {link.title}
+
+
+
+
-
-
-
-
-
e.stopPropagation()}
+ className="text-muted-foreground hover:text-primary text-xs"
>
- {link.title}
-
-
-
-
-
- e.stopPropagation()}
- className="text-muted-foreground hover:text-primary text-xs"
- >
- {link.url}
-
-
+
{link.url}
+
-
-
- )
- }
- )
+
+
+
+ )
+ })
)
LinkItem.displayName = "LinkItem"