mirror of
https://github.com/kamranahmedse/developer-roadmap.git
synced 2025-09-03 14:22:41 +02:00
Handle error screen
This commit is contained in:
@@ -2,8 +2,7 @@ import './RoadmapAIChat.css';
|
||||
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import {
|
||||
roadmapDetailsOptions,
|
||||
roadmapJSONOptions,
|
||||
roadmapJSONOptions
|
||||
} from '../../queries/roadmap';
|
||||
import { queryClient } from '../../stores/query-client';
|
||||
import {
|
||||
@@ -14,7 +13,7 @@ import {
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react';
|
||||
import { BotIcon, Loader2Icon, PauseCircleIcon, SendIcon } from 'lucide-react';
|
||||
import { BotIcon, Frown, Loader2Icon, PauseCircleIcon, SendIcon } from 'lucide-react';
|
||||
import { ChatEditor } from '../ChatEditor/ChatEditor';
|
||||
import { roadmapTreeMappingOptions } from '../../queries/roadmap-tree';
|
||||
import { type AllowedAIChatRole } from '../GenerateCourse/AICourseLessonChat';
|
||||
@@ -72,12 +71,7 @@ export function RoadmapAIChat(props: RoadmapAIChatProps) {
|
||||
const [streamedMessage, setStreamedMessage] =
|
||||
useState<React.ReactNode | null>(null);
|
||||
|
||||
const { data: roadmapDetailsData } = useQuery(
|
||||
roadmapDetailsOptions(roadmapId),
|
||||
queryClient,
|
||||
);
|
||||
|
||||
const { data: roadmapJSONData } = useQuery(
|
||||
const { data: roadmapDetail, error: roadmapDetailError } = useQuery(
|
||||
roadmapJSONOptions(roadmapId),
|
||||
queryClient,
|
||||
);
|
||||
@@ -94,20 +88,20 @@ export function RoadmapAIChat(props: RoadmapAIChatProps) {
|
||||
const roadmapContainerRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!roadmapJSONData || !roadmapContainerRef.current) {
|
||||
if (!roadmapDetail || !roadmapContainerRef.current) {
|
||||
return;
|
||||
}
|
||||
|
||||
roadmapContainerRef.current.replaceChildren(roadmapJSONData.svg);
|
||||
}, [roadmapJSONData]);
|
||||
roadmapContainerRef.current.replaceChildren(roadmapDetail.svg);
|
||||
}, [roadmapDetail]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!roadmapTreeData || !roadmapJSONData || !roadmapDetailsData) {
|
||||
if (!roadmapTreeData || !roadmapDetail) {
|
||||
return;
|
||||
}
|
||||
|
||||
setIsLoading(false);
|
||||
}, [roadmapTreeData, roadmapJSONData, roadmapDetailsData]);
|
||||
}, [roadmapTreeData, roadmapDetail]);
|
||||
|
||||
const abortControllerRef = useRef<AbortController | null>(null);
|
||||
const handleChatSubmit = (json: JSONContent) => {
|
||||
@@ -282,6 +276,18 @@ export function RoadmapAIChat(props: RoadmapAIChatProps) {
|
||||
scrollToBottom();
|
||||
}, []);
|
||||
|
||||
if (roadmapDetailError) {
|
||||
return (
|
||||
<div className="flex flex-grow flex-col items-center justify-center">
|
||||
<Frown className="mb-4 size-16" />
|
||||
<h1 className="mb-2 text-2xl font-bold">There was an error</h1>
|
||||
<p className="max-w-sm text-balance text-gray-500">
|
||||
{roadmapDetailError.message}
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex flex-grow flex-row">
|
||||
<div className="relative h-full flex-grow overflow-y-scroll">
|
||||
@@ -290,13 +296,15 @@ export function RoadmapAIChat(props: RoadmapAIChatProps) {
|
||||
<Loader2Icon className="size-6 animate-spin stroke-[2.5]" />
|
||||
</div>
|
||||
)}
|
||||
{roadmapJSONData?.json && !isLoading && (
|
||||
<div className="mx-auto max-w-[968px] px-4">
|
||||
<ChatRoadmapRenderer
|
||||
roadmapId={roadmapId}
|
||||
nodes={roadmapJSONData?.json.nodes}
|
||||
edges={roadmapJSONData?.json.edges}
|
||||
/>
|
||||
{roadmapDetail?.json && !isLoading && (
|
||||
<div>
|
||||
<div className="mx-auto max-w-[968px] px-4">
|
||||
<ChatRoadmapRenderer
|
||||
roadmapId={roadmapId}
|
||||
nodes={roadmapDetail?.json.nodes}
|
||||
edges={roadmapDetail?.json.edges}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
@@ -80,6 +80,8 @@ export async function httpCall<ResponseType = AppResponse>(
|
||||
if (!response.ok) {
|
||||
if (data.errors) {
|
||||
throw new FetchError(response?.status, data.message);
|
||||
} else if (data.message) {
|
||||
throw new FetchError(response?.status, data.message);
|
||||
} else {
|
||||
throw new Error('An unexpected error occurred');
|
||||
}
|
||||
|
@@ -59,7 +59,7 @@ export const GET: APIRoute = async function ({ params, request, props }) {
|
||||
);
|
||||
|
||||
if (!fs.existsSync(roadmapFilePath)) {
|
||||
return new Response(JSON.stringify({ error: 'Roadmap file not found' }), {
|
||||
return new Response(JSON.stringify({ message: 'Roadmap not found' }), {
|
||||
status: 404,
|
||||
});
|
||||
}
|
||||
|
@@ -21,8 +21,7 @@ const { roadmapId } = Astro.params as Props;
|
||||
wrapperClassName='flex-row p-0 lg:p-0 overflow-hidden'
|
||||
client:load
|
||||
>
|
||||
<!-- Make it client:load please -->
|
||||
<RoadmapAIChat roadmapId={roadmapId} client:only='react' />
|
||||
<RoadmapAIChat roadmapId={roadmapId} client:load />
|
||||
<CheckSubscriptionVerification client:load />
|
||||
</AITutorLayout>
|
||||
</SkeletonLayout>
|
||||
|
@@ -2,15 +2,25 @@ import { queryOptions } from '@tanstack/react-query';
|
||||
import { httpGet } from '../lib/query-http';
|
||||
import { type Node, type Edge, renderFlowJSON } from '@roadmapsh/editor';
|
||||
|
||||
type RoadmapJSON = {
|
||||
_id: string;
|
||||
title: string;
|
||||
description: string;
|
||||
slug: string;
|
||||
nodes: Node[];
|
||||
edges: Edge[];
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
};
|
||||
|
||||
export function roadmapJSONOptions(roadmapId: string) {
|
||||
return queryOptions({
|
||||
queryKey: ['roadmap-json', roadmapId],
|
||||
queryFn: async () => {
|
||||
const baseUrl = import.meta.env.PUBLIC_APP_URL;
|
||||
const roadmapJSON = await httpGet<{
|
||||
nodes: Node[];
|
||||
edges: Edge[];
|
||||
}>(`${baseUrl}/${roadmapId}.json`);
|
||||
const roadmapJSON = await httpGet<RoadmapJSON>(
|
||||
`${baseUrl}/${roadmapId}.json`,
|
||||
);
|
||||
|
||||
const svg = await renderFlowJSON(roadmapJSON);
|
||||
|
||||
|
Reference in New Issue
Block a user