diff --git a/web/app/components/DefaultCatchBoundary.tsx b/web/app/components/DefaultCatchBoundary.tsx index 3ed2e4a8..3cf88627 100644 --- a/web/app/components/DefaultCatchBoundary.tsx +++ b/web/app/components/DefaultCatchBoundary.tsx @@ -14,8 +14,6 @@ export function DefaultCatchBoundary({ error }: ErrorComponentProps) { select: (state) => state.id === rootRouteId, }) - console.error(error) - return (
diff --git a/web/app/components/GlobalKeyboardHandler.tsx b/web/app/components/GlobalKeyboardHandler.tsx index ec76f762..41308409 100644 --- a/web/app/components/GlobalKeyboardHandler.tsx +++ b/web/app/components/GlobalKeyboardHandler.tsx @@ -45,7 +45,7 @@ export function KeyboardHandlerContent() { const { signOut } = useAuth() const navigate = useNavigate() const { me } = useAccountOrGuest() - const { newPage } = usePageActions() + const { createNewPage } = usePageActions() const resetSequence = React.useCallback(() => { setSequence([]) @@ -81,9 +81,9 @@ export function KeyboardHandlerContent() { return } - newPage() + createNewPage() }, - [newPage], + [createNewPage], ) useKeyDown( diff --git a/web/app/components/sidebar/partials/link-collection.tsx b/web/app/components/sidebar/partials/link-collection.tsx index c22bc80f..d4c710a7 100644 --- a/web/app/components/sidebar/partials/link-collection.tsx +++ b/web/app/components/sidebar/partials/link-collection.tsx @@ -3,7 +3,16 @@ import { useAccount } from "@/lib/providers/jazz-provider" import { NavItem } from "~/components/custom/nav-item" export const LinkCollection: React.FC = () => { - const { me } = useAccount() + const { me } = useAccount({ + root: { + personalLinks: [{}], + personalPages: [{}], + tasks: [{}], + topicsWantToLearn: [{}], + topicsLearning: [{}], + topicsLearned: [{}], + }, + }) const linkCount = me?.root?.personalLinks?.length || 0 const pageCount = me?.root?.personalPages?.length || 0 diff --git a/web/app/components/sidebar/partials/page-section.tsx b/web/app/components/sidebar/partials/page-section.tsx index 1e5d32fc..5876ec8f 100644 --- a/web/app/components/sidebar/partials/page-section.tsx +++ b/web/app/components/sidebar/partials/page-section.tsx @@ -49,11 +49,7 @@ const isExpandedAtom = atomWithStorage("isPageSectionExpanded", true) export const PageSection: React.FC = () => { const { me } = useAccount({ root: { - personalPages: [ - { - topic: {}, - }, - ], + personalPages: [{}], }, }) @@ -81,9 +77,9 @@ export const PageSection: React.FC = () => { /> {isExpanded && (
- {sortedPages.map((page) => ( + {sortedPages.map((page, index) => ( = ({ ) const NewPageButton: React.FC = () => { - const { newPage } = usePageActions() + const { createNewPage } = usePageActions() const handleClick = async (e: React.MouseEvent) => { e.preventDefault() e.stopPropagation() - newPage() + createNewPage() } return ( diff --git a/web/app/components/sidebar/partials/profile-section.tsx b/web/app/components/sidebar/partials/profile-section.tsx index 97d06ffb..b425240b 100644 --- a/web/app/components/sidebar/partials/profile-section.tsx +++ b/web/app/components/sidebar/partials/profile-section.tsx @@ -19,22 +19,16 @@ import { SignInButton, useAuth, useUser } from "@clerk/tanstack-start" import { Link, useLocation } from "@tanstack/react-router" import { ShortcutKey } from "@shared/minimal-tiptap/components/shortcut-key" import { Feedback } from "./feedback" +import { useAccount } from "~/lib/providers/jazz-provider" export const ProfileSection: React.FC = () => { const { user, isSignedIn } = useUser() - const { signOut } = useAuth() const [menuOpen, setMenuOpen] = React.useState(false) const { pathname } = useLocation() const [, setShowShortcut] = useAtom(showShortcutAtom) const { disableKeydown } = useKeyboardManager("profileSection") - const handleSignOut = () => { - signOut(() => { - window.location.replace("/") - }) - } - React.useEffect(() => { disableKeydown(menuOpen) }, [menuOpen, disableKeydown]) @@ -59,7 +53,6 @@ export const ProfileSection: React.FC = () => { user={user} menuOpen={menuOpen} setMenuOpen={setMenuOpen} - signOut={handleSignOut} setShowShortcut={setShowShortcut} /> @@ -73,7 +66,6 @@ interface ProfileDropdownProps { user: any menuOpen: boolean setMenuOpen: (open: boolean) => void - signOut: () => void setShowShortcut: (show: boolean) => void } @@ -81,7 +73,6 @@ const ProfileDropdown: React.FC = ({ user, menuOpen, setMenuOpen, - signOut, setShowShortcut, }) => (
@@ -107,60 +98,71 @@ const ProfileDropdown: React.FC = ({ - +
) interface DropdownMenuItemsProps { - signOut: () => void setShowShortcut: (show: boolean) => void } const DropdownMenuItems: React.FC = ({ - signOut, setShowShortcut, -}) => ( - <> - - setShowShortcut(true)}> - - Shortcut - - - - - - - - -
- - Log out -
- +}) => { + const { signOut } = useAuth() + const { logOut } = useAccount() + + const handleSignOut = React.useCallback(async () => { + try { + logOut() + signOut(() => { + window.location.href = "/" + }) + } catch (error) { + console.error("Error signing out:", error) + } + }, [logOut, signOut]) + + return ( + <> + + setShowShortcut(true)}> + + Shortcut + + + + + + + + +
+ + Log out +
+ +
-
- - -) + + + ) +} interface MenuLinkProps { href: string diff --git a/web/app/hooks/actions/use-command-actions.ts b/web/app/hooks/actions/use-command-actions.ts index 248a5012..1220ce15 100644 --- a/web/app/hooks/actions/use-command-actions.ts +++ b/web/app/hooks/actions/use-command-actions.ts @@ -8,7 +8,7 @@ import { useNavigate } from "@tanstack/react-router" export const useCommandActions = () => { const { setTheme } = useTheme() const navigate = useNavigate() - const { newPage } = usePageActions() + const { createNewPage } = usePageActions() const changeTheme = React.useCallback( (theme: string) => { @@ -39,6 +39,6 @@ export const useCommandActions = () => { navigateTo, openLinkInNewTab, copyCurrentURL, - createNewPage: newPage, + createNewPage, } } diff --git a/web/app/hooks/actions/use-page-actions.ts b/web/app/hooks/actions/use-page-actions.ts index 49b09340..66a71eda 100644 --- a/web/app/hooks/actions/use-page-actions.ts +++ b/web/app/hooks/actions/use-page-actions.ts @@ -1,60 +1,60 @@ import * as React from "react" import { toast } from "sonner" -import { LaAccount, PersonalPage } from "@/lib/schema" +import { PersonalPage } from "@/lib/schema" import { ID } from "jazz-tools" import { useNavigate } from "@tanstack/react-router" import { useAccountOrGuest } from "~/lib/providers/jazz-provider" export const usePageActions = () => { - const { me } = useAccountOrGuest() + const { me: account } = useAccountOrGuest() const navigate = useNavigate() - const newPage = React.useCallback(() => { - if (!me) return - if (me._type !== "Account") return + const createNewPage = React.useCallback(async () => { + try { + const isValidAccount = account && account._type === "Account" + if (!isValidAccount) return - const page = PersonalPage.create( - { public: false, createdAt: new Date(), updatedAt: new Date() }, - { owner: me }, - ) + const page = PersonalPage.create( + { + public: false, + topic: null, + createdAt: new Date(), + updatedAt: new Date(), + }, + { owner: account }, + ) - me.root?.personalPages?.push(page) + account.root?.personalPages?.push(page) - navigate({ to: "/pages/$pageId", params: { pageId: page.id } }) - }, [me, navigate]) + navigate({ + to: "/pages/$pageId", + params: { pageId: page.id }, + replace: true, + }) + } catch (error) { + console.error(error) + } + }, [account, navigate]) const deletePage = React.useCallback( - (me: LaAccount, pageId: ID): void => { - if (!me.root?.personalPages) return + (pageId: ID): void => { + const isValidAccount = account && account._type === "Account" + if (!isValidAccount) return - const index = me.root.personalPages.findIndex( + const found = account.root?.personalPages?.findIndex( (item) => item?.id === pageId, ) - if (index === -1) { - toast.error("Page not found") - return - } - const page = me.root.personalPages[index] - if (!page) { - toast.error("Page data is invalid") - return - } - - try { - me.root.personalPages.splice(index, 1) + if (found !== undefined && found > -1) { + account.root?.personalPages?.splice(found, 1) toast.success("Page deleted", { - position: "bottom-right", - description: `${page.title} has been deleted.`, + description: "The page has been deleted", }) - } catch (error) { - console.error("Failed to delete page", error) - toast.error("Failed to delete page") } }, - [], + [account], ) - return { newPage, deletePage } + return { createNewPage, deletePage } } diff --git a/web/app/router.tsx b/web/app/router.tsx index 959bf8b5..65975701 100644 --- a/web/app/router.tsx +++ b/web/app/router.tsx @@ -2,21 +2,17 @@ import { createRouter as createTanStackRouter } from "@tanstack/react-router" import { routeTree } from "./routeTree.gen" import { DefaultCatchBoundary } from "./components/DefaultCatchBoundary" import { NotFound } from "./components/NotFound" -import { QueryClient } from "@tanstack/react-query" -import { routerWithQueryClient } from "@tanstack/react-router-with-query" export function createRouter() { - const queryClient = new QueryClient() - const router = routerWithQueryClient( - createTanStackRouter({ - routeTree, - defaultPreload: "intent", - defaultErrorComponent: DefaultCatchBoundary, - defaultNotFoundComponent: () => , - context: { queryClient, auth: undefined! }, - }), - queryClient, - ) + const router = createTanStackRouter({ + routeTree, + defaultPreload: "intent", + defaultErrorComponent: DefaultCatchBoundary, + defaultNotFoundComponent: () => , + context: { + auth: undefined, + }, + }) return router } diff --git a/web/app/routes/__root.tsx b/web/app/routes/__root.tsx index 2ed4809c..985eaa0e 100644 --- a/web/app/routes/__root.tsx +++ b/web/app/routes/__root.tsx @@ -1,6 +1,5 @@ /// import { getAuth } from "@clerk/tanstack-start/server" -import type { QueryClient } from "@tanstack/react-query" import { Outlet, ScrollRestoration, @@ -29,15 +28,6 @@ export const TanStackRouterDevtools = })), ) -export const ReactQueryDevtools = - process.env.NODE_ENV === "production" - ? () => null - : React.lazy(() => - import("@tanstack/react-query-devtools").then((d) => ({ - default: d.ReactQueryDevtools, - })), - ) - export const fetchClerkAuth = createServerFn("GET", async (_, ctx) => { const auth = await getAuth(ctx.request) @@ -45,8 +35,7 @@ export const fetchClerkAuth = createServerFn("GET", async (_, ctx) => { }) export const Route = createRootRouteWithContext<{ - auth: { userId: string } - queryClient: QueryClient + auth?: ReturnType | null }>()({ meta: () => [ { @@ -86,13 +75,25 @@ export const Route = createRootRouteWithContext<{ { rel: "manifest", href: "/site.webmanifest", color: "#fffff" }, { rel: "icon", href: "/favicon.ico" }, ], - beforeLoad: async ({ context }) => { - if (context.auth) { - return { auth: context.auth } - } + beforeLoad: async (ctx) => { + try { + // Handle explicit null auth (logged out state) + if (ctx.context.auth === null) { + return { auth: null } + } - const auth = await fetchClerkAuth() - return { auth } + // Use existing auth if available + if (ctx.context.auth) { + return { auth: ctx.context.auth } + } + + // Fetch new auth state + const auth = await fetchClerkAuth() + return { auth } + } catch (error) { + console.error("Error in beforeLoad:", error) + return { auth: null } + } }, errorComponent: (props) => { return ( @@ -101,6 +102,11 @@ export const Route = createRootRouteWithContext<{ ) }, + pendingComponent: () => ( + +
Loading...
+
+ ), notFoundComponent: () => , component: RootComponent, }) @@ -124,7 +130,6 @@ function RootDocument({ children }: { children: React.ReactNode }) { - diff --git a/web/app/routes/_layout/_pages/(topic)/$.tsx b/web/app/routes/_layout/_pages/(topic)/$.tsx index b34a8aad..ba13cdbc 100644 --- a/web/app/routes/_layout/_pages/(topic)/$.tsx +++ b/web/app/routes/_layout/_pages/(topic)/$.tsx @@ -17,7 +17,7 @@ export const openPopoverForIdAtom = atom(null) export function TopicDetailComponent() { const params = useParams({ from: "/_layout/_pages/(topic)/$" }) - const { me } = useAccountOrGuest({ root: { personalLinks: [] } }) + const { me } = useAccountOrGuest({ root: { personalLinks: [{}] } }) const topicID = React.useMemo( () => diff --git a/web/app/routes/_layout/_pages/(topic)/-header.tsx b/web/app/routes/_layout/_pages/(topic)/-header.tsx index 506a0ad3..56037083 100644 --- a/web/app/routes/_layout/_pages/(topic)/-header.tsx +++ b/web/app/routes/_layout/_pages/(topic)/-header.tsx @@ -29,9 +29,9 @@ export const TopicDetailHeader = function TopicDetailHeader({ const isMobile = useMedia("(max-width: 770px)") const { me } = useAccountOrGuest({ root: { - topicsWantToLearn: [], - topicsLearning: [], - topicsLearned: [], + topicsWantToLearn: [{}], + topicsLearning: [{}], + topicsLearned: [{}], }, }) diff --git a/web/app/routes/_layout/_pages/(topic)/-list.tsx b/web/app/routes/_layout/_pages/(topic)/-list.tsx index 35d6b875..b6d43e6b 100644 --- a/web/app/routes/_layout/_pages/(topic)/-list.tsx +++ b/web/app/routes/_layout/_pages/(topic)/-list.tsx @@ -25,7 +25,7 @@ export function TopicDetailList({ activeIndex, setActiveIndex, }: TopicDetailListProps) { - const { me } = useAccountOrGuest({ root: { personalLinks: [] } }) + const { me } = useAccountOrGuest({ root: { personalLinks: [{}] } }) const personalLinks = !me || me._type === "Anonymous" ? undefined : me.root.personalLinks diff --git a/web/app/routes/_layout/_pages/_protected.tsx b/web/app/routes/_layout/_pages/_protected.tsx index e52efd3b..e6d63beb 100644 --- a/web/app/routes/_layout/_pages/_protected.tsx +++ b/web/app/routes/_layout/_pages/_protected.tsx @@ -2,12 +2,24 @@ import { createFileRoute, Outlet, redirect } from "@tanstack/react-router" export const Route = createFileRoute("/_layout/_pages/_protected")({ beforeLoad: async ({ context, location }) => { - if (!context?.auth?.userId) { + // Add extra validation + if (!context || !context.auth) { throw redirect({ to: "/sign-in/$", search: { redirect_url: location.pathname }, }) } + + const auth = await context.auth + + if (!auth?.userId) { + throw redirect({ + to: "/sign-in/$", + search: { redirect_url: location.pathname }, + }) + } + + return context }, component: () => , }) diff --git a/web/app/routes/_layout/_pages/_protected/community/$topicName/index.tsx b/web/app/routes/_layout/_pages/_protected/community/$topicName/index.tsx index 186e9354..44d58e06 100644 --- a/web/app/routes/_layout/_pages/_protected/community/$topicName/index.tsx +++ b/web/app/routes/_layout/_pages/_protected/community/$topicName/index.tsx @@ -26,7 +26,7 @@ interface Question { function CommunityTopicComponent() { const { topicName } = Route.useParams() - const { me } = useAccountOrGuest({ root: { personalLinks: [] } }) + const { me } = useAccountOrGuest() const topicID = useMemo( () => me && Topic.findUnique({ topicName }, JAZZ_GLOBAL_GROUP_ID, me), [topicName, me], diff --git a/web/app/routes/_layout/_pages/_protected/links/-link-form.tsx b/web/app/routes/_layout/_pages/_protected/links/-link-form.tsx index 4150bc33..487d16bb 100644 --- a/web/app/routes/_layout/_pages/_protected/links/-link-form.tsx +++ b/web/app/routes/_layout/_pages/_protected/links/-link-form.tsx @@ -143,7 +143,7 @@ export const LinkForm: React.FC = ({ const [isFetching, setIsFetching] = React.useState(false) const [urlFetched, setUrlFetched] = React.useState(null) - const { me } = useAccount() + const { me } = useAccount({ root: { personalLinks: [{}] } }) const selectedLink = useCoState(PersonalLink, personalLink?.id) const form = useForm({ diff --git a/web/app/routes/_layout/_pages/_protected/onboarding/index.tsx b/web/app/routes/_layout/_pages/_protected/onboarding/index.tsx index ea4371a1..865c74cc 100644 --- a/web/app/routes/_layout/_pages/_protected/onboarding/index.tsx +++ b/web/app/routes/_layout/_pages/_protected/onboarding/index.tsx @@ -80,9 +80,9 @@ const StepItem = ({ function OnboardingComponent() { const { me } = useAccount({ root: { - personalPages: [], - personalLinks: [], - topicsWantToLearn: [], + personalPages: [{}], + personalLinks: [{}], + topicsWantToLearn: [{}], }, }) diff --git a/web/app/routes/_layout/_pages/_protected/pages/$pageId/index.tsx b/web/app/routes/_layout/_pages/_protected/pages/$pageId/index.tsx index bed1bba7..1b2a000b 100644 --- a/web/app/routes/_layout/_pages/_protected/pages/$pageId/index.tsx +++ b/web/app/routes/_layout/_pages/_protected/pages/$pageId/index.tsx @@ -1,9 +1,9 @@ import * as React from "react" import { createFileRoute, useNavigate } from "@tanstack/react-router" import { ID } from "jazz-tools" -import { LaAccount, PersonalPage } from "@/lib/schema" +import { PersonalPage } from "@/lib/schema" import { Content, EditorContent, useEditor } from "@tiptap/react" -import { useAccount, useCoState } from "@/lib/providers/jazz-provider" +import { useCoState } from "@/lib/providers/jazz-provider" import { EditorView } from "@tiptap/pm/view" import { Editor } from "@tiptap/core" import { generateUniqueSlug } from "@/lib/utils" @@ -29,17 +29,10 @@ const TITLE_PLACEHOLDER = "Untitled" function PageDetailComponent() { const { pageId } = Route.useParams() - const { me } = useAccount({ - root: { - personalPages: [ - { - topic: {}, - }, - ], - }, - }) const isMobile = useMedia("(max-width: 770px)") - const page = useCoState(PersonalPage, pageId as ID) + const page = useCoState(PersonalPage, pageId as ID, { + topic: {}, + }) const navigate = useNavigate() const { deletePage } = usePageActions() @@ -55,13 +48,13 @@ function PageDetailComponent() { confirmButton: { variant: "destructive" }, }) - if (result && me?.root.personalPages) { - deletePage(me, pageId as ID) + if (result) { + deletePage(pageId as ID) navigate({ to: "/pages" }) } - }, [confirm, deletePage, me, pageId, navigate]) + }, [confirm, deletePage, pageId, navigate]) - if (!page || !me) return null + if (!page) return null return (
@@ -72,7 +65,7 @@ function PageDetailComponent() { handleDelete={handleDelete} isMobile={isMobile} /> - +
{!isMobile && ( @@ -132,29 +125,11 @@ const SidebarActions = ({ SidebarActions.displayName = "SidebarActions" -const DetailPageForm = ({ - page, - me, -}: { - page: PersonalPage - me: LaAccount -}) => { +const DetailPageForm = ({ page }: { page: PersonalPage }) => { const titleEditorRef = React.useRef(null) const contentEditorRef = React.useRef(null) const [isInitialSync, setIsInitialSync] = React.useState(true) - // const { id: pageId, title: pageTitle } = page - - // React.useEffect(() => { - // if (!pageId) return - - // if (!pageTitle && titleEditorRef.current) { - // titleEditorRef.current.commands.focus() - // } else if (contentEditorRef.current) { - // contentEditorRef.current.commands.focus() - // } - // }, [pageId, pageTitle]) - React.useEffect(() => { if (!page) return @@ -293,17 +268,25 @@ const DetailPageForm = ({ onUpdate: ({ editor }) => handleUpdateTitle(editor), }) + const { content: pageContent, title: pageTitle } = page + const handleCreate = React.useCallback( ({ editor }: { editor: Editor }) => { contentEditorRef.current = editor - if (page.content) { - editor.commands.setContent(page.content as Content) + if (pageContent) { + editor.commands.setContent(pageContent as Content) } setIsInitialSync(false) + + if (!pageTitle && titleEditorRef.current) { + titleEditorRef.current.commands.focus() + } else if (contentEditorRef.current) { + contentEditorRef.current.commands.focus() + } }, - [page.content], + [pageContent, pageTitle], ) return ( @@ -312,6 +295,7 @@ const DetailPageForm = ({
@@ -319,8 +303,7 @@ const DetailPageForm = ({
= () => { - const { me } = useAccount() - const { newPage } = usePageActions() - - if (!me) return null + const { createNewPage } = usePageActions() return ( @@ -28,7 +24,7 @@ export const PageHeader: React.FC = () => { type="button" variant="secondary" className="gap-x-2" - onClick={newPage} + onClick={createNewPage} > New page diff --git a/web/app/routes/_layout/_pages/_protected/profile/index.tsx b/web/app/routes/_layout/_pages/_protected/profile/index.tsx index b4e0fa13..96de905c 100644 --- a/web/app/routes/_layout/_pages/_protected/profile/index.tsx +++ b/web/app/routes/_layout/_pages/_protected/profile/index.tsx @@ -26,7 +26,14 @@ const ProfileStats: React.FC = ({ number, label }) => { } function ProfileComponent() { - const account = useAccount() + const account = useAccount({ + profile: {}, + root: { + topicsLearning: [{}], + topicsWantToLearn: [{}], + topicsLearned: [{}], + }, + }) const username = "" const { user } = useUser() const avatarInputRef = React.useRef(null) diff --git a/web/app/routes/_layout/_pages/_protected/tasks/index.tsx b/web/app/routes/_layout/_pages/_protected/tasks/index.tsx index 2f102b72..028fb146 100644 --- a/web/app/routes/_layout/_pages/_protected/tasks/index.tsx +++ b/web/app/routes/_layout/_pages/_protected/tasks/index.tsx @@ -82,7 +82,7 @@ export const Route = createFileRoute("/_layout/_pages/_protected/tasks/")({ function TaskComponent() { const { filter } = Route.useSearch() - const { me } = useAccount({ root: { tasks: [] } }) + const { me } = useAccount({ root: { tasks: [{}] } }) const tasks = me?.root.tasks const { deleteTask } = useTaskActions() diff --git a/web/app/routes/_layout/_pages/_protected/topics/-item.tsx b/web/app/routes/_layout/_pages/_protected/topics/-item.tsx index 37bcb07b..7ec63b60 100644 --- a/web/app/routes/_layout/_pages/_protected/topics/-item.tsx +++ b/web/app/routes/_layout/_pages/_protected/topics/-item.tsx @@ -30,7 +30,11 @@ export const TopicItem = React.forwardRef( ) const navigate = useNavigate() const { me } = useAccount({ - root: { topicsWantToLearn: [], topicsLearning: [], topicsLearned: [] }, + root: { + topicsWantToLearn: [{}], + topicsLearning: [{}], + topicsLearned: [{}], + }, }) let p: { diff --git a/web/app/routes/_layout/_pages/_protected/topics/-list.tsx b/web/app/routes/_layout/_pages/_protected/topics/-list.tsx index 3833c2c3..4d15e7f0 100644 --- a/web/app/routes/_layout/_pages/_protected/topics/-list.tsx +++ b/web/app/routes/_layout/_pages/_protected/topics/-list.tsx @@ -5,23 +5,13 @@ import { atom } from "jotai" import { useMedia } from "@/hooks/use-media" import { useActiveItemScroll } from "@/hooks/use-active-item-scroll" import { Column } from "@/components/custom/column" -import { LaAccount, ListOfTopics, Topic, UserRoot } from "@/lib/schema" +import { Topic } from "@/lib/schema" import { LearningStateValue } from "@/lib/constants" import { useKeyDown } from "@/hooks/use-key-down" import { TopicItem } from "./-item" interface TopicListProps {} -interface MainTopicListProps extends TopicListProps { - me: { - root: { - topicsWantToLearn: ListOfTopics - topicsLearning: ListOfTopics - topicsLearned: ListOfTopics - } & UserRoot - } & LaAccount -} - export interface PersonalTopic { topic: Topic | null learningState: LearningStateValue @@ -31,15 +21,13 @@ export const topicOpenPopoverForIdAtom = atom(null) export const TopicList: React.FC = () => { const { me } = useAccount({ - root: { topicsWantToLearn: [], topicsLearning: [], topicsLearned: [] }, + root: { + topicsWantToLearn: [{}], + topicsLearning: [{}], + topicsLearned: [{}], + }, }) - if (!me) return null - - return -} - -export const MainTopicList: React.FC = ({ me }) => { const isTablet = useMedia("(max-width: 640px)") const [activeItemIndex, setActiveItemIndex] = React.useState( null, @@ -49,21 +37,24 @@ export const MainTopicList: React.FC = ({ me }) => { >(null) const personalTopics = React.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], + () => + me + ? [ + ...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], ) const next = () => diff --git a/web/app/routes/_layout/_pages/search/index.tsx b/web/app/routes/_layout/_pages/search/index.tsx index a3c5271a..d927da2b 100644 --- a/web/app/routes/_layout/_pages/search/index.tsx +++ b/web/app/routes/_layout/_pages/search/index.tsx @@ -85,9 +85,7 @@ const SearchComponent = () => { pages: PersonalPage[] }>({ topics: [], links: [], pages: [] }) - const { me } = useAccountOrGuest({ - root: { personalLinks: [{}], personalPages: [{}] }, - }) + const { me } = useAccountOrGuest() const globalGroup = useCoState(PublicGlobalGroup, JAZZ_GLOBAL_GROUP_ID, { root: { @@ -112,14 +110,14 @@ const SearchComponent = () => { links: me?._type === "Anonymous" ? [] - : me?.root.personalLinks?.filter( + : me?.root?.personalLinks?.filter( (link: PersonalLink | null): link is PersonalLink => link !== null && link.title.toLowerCase().startsWith(value), ) || [], pages: me?._type === "Anonymous" ? [] - : me?.root.personalPages.filter( + : me?.root?.personalPages?.filter( (page): page is PersonalPage => page !== null && page.title !== undefined &&