From 2a61e6aab654c281e0caa43d337115510c48602f Mon Sep 17 00:00:00 2001 From: Kamran Ahmed Date: Wed, 18 Jun 2025 23:39:01 +0100 Subject: [PATCH] Guide listing UI update --- .../GenerateGuide/ListUserAIGuides.tsx | 150 ------------------ .../GenerateGuide/UserGuidesList.tsx | 146 +++++++++++++++++ src/pages/ai/guides.astro | 4 +- 3 files changed, 148 insertions(+), 152 deletions(-) delete mode 100644 src/components/GenerateGuide/ListUserAIGuides.tsx create mode 100644 src/components/GenerateGuide/UserGuidesList.tsx diff --git a/src/components/GenerateGuide/ListUserAIGuides.tsx b/src/components/GenerateGuide/ListUserAIGuides.tsx deleted file mode 100644 index 3debe38a8..000000000 --- a/src/components/GenerateGuide/ListUserAIGuides.tsx +++ /dev/null @@ -1,150 +0,0 @@ -import { useQuery } from '@tanstack/react-query'; -import { BookOpen } from 'lucide-react'; -import { useEffect, useState } from 'react'; -import { deleteUrlParam, getUrlParams, setUrlParams } from '../../lib/browser'; -import { isLoggedIn } from '../../lib/jwt'; -import { showLoginPopup } from '../../lib/popup'; -import { - listUserAIGuidesOptions, - type ListUserAIGuidesQuery, -} from '../../queries/ai-guide'; -import { queryClient } from '../../stores/query-client'; -import { AITutorHeader } from '../AITutor/AITutorHeader'; -import { AITutorTallMessage } from '../AITutor/AITutorTallMessage'; -import { UpgradeAccountModal } from '../Billing/UpgradeAccountModal'; -import { Pagination } from '../Pagination/Pagination'; -import { AILoadingState } from '../AITutor/AILoadingState'; -import { AICourseSearch } from '../GenerateCourse/AICourseSearch'; -import { AIGuideCard } from '../AIGuide/AIGuideCard'; - -export function ListUserAIGuides() { - const [isInitialLoading, setIsInitialLoading] = useState(true); - const [showUpgradePopup, setShowUpgradePopup] = useState(false); - - const [pageState, setPageState] = useState({ - perPage: '21', - currPage: '1', - query: '', - }); - - const { data: userAiGuides, isFetching: isUserAiGuidesLoading } = useQuery( - listUserAIGuidesOptions(pageState), - queryClient, - ); - - useEffect(() => { - setIsInitialLoading(false); - }, [userAiGuides]); - - const guides = userAiGuides?.data ?? []; - - useEffect(() => { - const queryParams = getUrlParams(); - - setPageState({ - ...pageState, - currPage: queryParams?.p || '1', - query: queryParams?.q || '', - }); - }, []); - - useEffect(() => { - if (pageState?.currPage !== '1' || pageState?.query !== '') { - setUrlParams({ - p: pageState?.currPage || '1', - q: pageState?.query || '', - }); - } else { - deleteUrlParam('p'); - deleteUrlParam('q'); - } - }, [pageState]); - - if (isUserAiGuidesLoading || isInitialLoading) { - return ( - - ); - } - - if (!isLoggedIn()) { - return ( - { - showLoginPopup(); - }} - /> - ); - } - - return ( - <> - {showUpgradePopup && ( - setShowUpgradePopup(false)} /> - )} - - setShowUpgradePopup(true)} - > - { - setPageState({ - ...pageState, - query: value, - currPage: '1', - }); - }} - placeholder="Search guides..." - /> - - - {(isUserAiGuidesLoading || isInitialLoading) && ( - - )} - - {!isUserAiGuidesLoading && !isInitialLoading && guides.length > 0 && ( -
-
- {guides.map((guide) => ( - - ))} -
- - { - setPageState({ ...pageState, currPage: String(page) }); - }} - className="rounded-lg border border-gray-200 bg-white p-4" - /> -
- )} - - {!isUserAiGuidesLoading && !isInitialLoading && guides.length === 0 && ( - { - window.location.href = '/ai'; - }} - /> - )} - - ); -} diff --git a/src/components/GenerateGuide/UserGuidesList.tsx b/src/components/GenerateGuide/UserGuidesList.tsx new file mode 100644 index 000000000..14c8c7268 --- /dev/null +++ b/src/components/GenerateGuide/UserGuidesList.tsx @@ -0,0 +1,146 @@ +import { useQuery } from '@tanstack/react-query'; +import { BookOpen, Loader2 } from 'lucide-react'; +import { useEffect, useState } from 'react'; +import { deleteUrlParam, getUrlParams, setUrlParams } from '../../lib/browser'; +import { isLoggedIn } from '../../lib/jwt'; +import { showLoginPopup } from '../../lib/popup'; +import { + listUserAIGuidesOptions, + type ListUserAIGuidesQuery, +} from '../../queries/ai-guide'; +import { queryClient } from '../../stores/query-client'; +import { AITutorTallMessage } from '../AITutor/AITutorTallMessage'; +import { UpgradeAccountModal } from '../Billing/UpgradeAccountModal'; +import { Pagination } from '../Pagination/Pagination'; +import { AICourseSearch } from '../GenerateCourse/AICourseSearch'; +import { AIGuideCard } from '../AIGuide/AIGuideCard'; + +export function UserGuidesList() { + const [isInitialLoading, setIsInitialLoading] = useState(true); + const [showUpgradePopup, setShowUpgradePopup] = useState(false); + + const [pageState, setPageState] = useState({ + perPage: '21', + currPage: '1', + query: '', + }); + + const { data: userAiGuides, isFetching: isUserAiGuidesLoading } = useQuery( + listUserAIGuidesOptions(pageState), + queryClient, + ); + + useEffect(() => { + setIsInitialLoading(false); + }, [userAiGuides]); + + const guides = userAiGuides?.data ?? []; + + useEffect(() => { + const queryParams = getUrlParams(); + + setPageState({ + ...pageState, + currPage: queryParams?.p || '1', + query: queryParams?.q || '', + }); + }, []); + + useEffect(() => { + if (pageState?.currPage !== '1' || pageState?.query !== '') { + setUrlParams({ + p: pageState?.currPage || '1', + q: pageState?.query || '', + }); + } else { + deleteUrlParam('p'); + deleteUrlParam('q'); + } + }, [pageState]); + + const isUserAuthenticated = isLoggedIn(); + const isAnyLoading = isUserAiGuidesLoading || isInitialLoading; + + return ( + <> + {showUpgradePopup && ( + setShowUpgradePopup(false)} /> + )} + + { + setPageState({ + ...pageState, + query: value, + currPage: '1', + }); + }} + disabled={isAnyLoading} + placeholder="Search guides..." + /> + + {isAnyLoading && ( +

+ + Loading your guides... +

+ )} + + {!isAnyLoading && ( + <> +

+ You have generated {userAiGuides?.totalCount} guides so far. +

+ + {isUserAuthenticated && !isAnyLoading && guides.length > 0 && ( +
+
+ {guides.map((guide) => ( + + ))} +
+ + { + setPageState({ ...pageState, currPage: String(page) }); + }} + className="rounded-lg border border-gray-200 bg-white p-4" + /> +
+ )} + + {!isAnyLoading && guides.length === 0 && ( + { + if (isUserAuthenticated) { + window.location.href = '/ai'; + } else { + showLoginPopup(); + } + }} + /> + )} + + )} + + ); +} diff --git a/src/pages/ai/guides.astro b/src/pages/ai/guides.astro index 19614acaf..72d52f8c6 100644 --- a/src/pages/ai/guides.astro +++ b/src/pages/ai/guides.astro @@ -1,5 +1,5 @@ --- -import { ListUserAIGuides } from '../../components/GenerateGuide/ListUserAIGuides'; +import { UserGuidesList } from '../../components/GenerateGuide/UserGuidesList'; import SkeletonLayout from '../../layouts/SkeletonLayout.astro'; import { AILibraryLayout } from '../../components/AIGuide/AILibraryLayout'; const ogImage = 'https://roadmap.sh/og-images/ai-tutor.png'; @@ -12,6 +12,6 @@ const ogImage = 'https://roadmap.sh/og-images/ai-tutor.png'; description='Learn anything with AI Tutor. Pick a topic, choose a difficulty level and the AI will guide you through the learning process.' > - +