From 56b327177b399c09ca96f53ca8c9d21acacf94c7 Mon Sep 17 00:00:00 2001 From: Arik Chakma Date: Thu, 7 Mar 2024 02:04:58 +0600 Subject: [PATCH] feat: explore ai roadmaps --- .../ExploreAIRoadmap/ExploreAIRoadmap.tsx | 183 ++++++++++++++++++ src/pages/ai/explore.astro | 10 + 2 files changed, 193 insertions(+) create mode 100644 src/components/ExploreAIRoadmap/ExploreAIRoadmap.tsx create mode 100644 src/pages/ai/explore.astro diff --git a/src/components/ExploreAIRoadmap/ExploreAIRoadmap.tsx b/src/components/ExploreAIRoadmap/ExploreAIRoadmap.tsx new file mode 100644 index 000000000..fccaa4b1e --- /dev/null +++ b/src/components/ExploreAIRoadmap/ExploreAIRoadmap.tsx @@ -0,0 +1,183 @@ +import { useEffect, useState, useCallback } from 'react'; +import { useToast } from '../../hooks/use-toast'; +import { httpGet } from '../../lib/http'; +import { getRelativeTimeString } from '../../lib/date'; +import { + BadgeCheck, + CalendarCheck, + Eye, + Loader2, + RefreshCcw, + Sparkles, +} from 'lucide-react'; + +export interface AIRoadmapDocument { + _id?: string; + topic: string; + data: string; + viewCount: number; + createdAt: Date; + updatedAt: Date; +} + +type ExploreRoadmapsResponse = { + data: AIRoadmapDocument[]; + totalCount: number; + totalPages: number; + currPage: number; + perPage: number; +}; + +export function ExploreAIRoadmap() { + const toast = useToast(); + + const [isLoading, setIsLoading] = useState(true); + const [isLoadingMore, setIsLoadingMore] = useState(false); + const [roadmaps, setRoadmaps] = useState([]); + const [currPage, setCurrPage] = useState(1); + const [totalPages, setTotalPages] = useState(1); + + const loadAIRoadamps = useCallback( + async (currPage: number) => { + const { response, error } = await httpGet( + `${import.meta.env.PUBLIC_API_URL}/v1-explore-roadmaps`, + { + currPage, + }, + ); + + if (error || !response) { + toast.error(error?.message || 'Something went wrong'); + return; + } + + const newRoadmaps = [...roadmaps, ...response.data]; + if ( + JSON.stringify(roadmaps) === JSON.stringify(response.data) || + JSON.stringify(roadmaps) === JSON.stringify(newRoadmaps) + ) { + return; + } + + setRoadmaps(newRoadmaps); + setCurrPage(response.currPage); + setTotalPages(response.totalPages); + }, + [currPage, roadmaps], + ); + + useEffect(() => { + loadAIRoadamps(currPage).finally(() => { + setIsLoading(false); + }); + }, []); + + const hasMorePages = currPage < totalPages; + + return ( +
+
+

+ Explore AI Generated Roadmaps +

+

+ These roadmaps are generated by AI based on the data and the topic + community has provided. You can also create your own roadmap and share + it with the community. +

+ +
+ {isLoading ? ( +
    + {new Array(6).fill(0).map((_, index) => ( +
  • +
    +
    + + + {index} views + + + + {index}h ago + +
    +
  • + ))} +
+ ) : ( +
+ {roadmaps?.length === 0 ? ( +
No roadmaps found
+ ) : ( +
    + {roadmaps.map((roadmap) => ( +
  • +

    + {roadmap.topic} +

    +
    + + + {roadmap?.viewCount || 0} views + + + + + {getRelativeTimeString(String(roadmap?.createdAt))} + + +
    +
  • + ))} + {hasMorePages && ( +
  • + +
  • + )} +
+ )} +
+ )} +
+ ); +} diff --git a/src/pages/ai/explore.astro b/src/pages/ai/explore.astro new file mode 100644 index 000000000..8d8461f69 --- /dev/null +++ b/src/pages/ai/explore.astro @@ -0,0 +1,10 @@ +--- +import LoginPopup from '../../components/AuthenticationFlow/LoginPopup.astro'; +import { ExploreAIRoadmap } from '../../components/ExploreAIRoadmap/ExploreAIRoadmap'; +import AccountLayout from '../../layouts/AccountLayout.astro'; +--- + + + + +