1
0
mirror of https://github.com/kamranahmedse/developer-roadmap.git synced 2025-09-09 08:40:40 +02:00
This commit is contained in:
Arik Chakma
2025-06-09 10:57:01 +06:00
parent 6a413cdaef
commit 799f6eebbb
4 changed files with 64 additions and 26 deletions

View File

@@ -43,7 +43,6 @@ import { AIChatCourse } from './AIChatCouse';
import { showLoginPopup } from '../../lib/popup';
import { UpgradeAccountModal } from '../Billing/UpgradeAccountModal';
import { readChatStream } from '../../lib/chat';
import type { ChatHistoryDocument } from '../../queries/chat-history';
export const aiChatRenderer: Record<string, MessagePartRenderer> = {
'roadmap-recommendations': (options) => {
@@ -55,27 +54,20 @@ export const aiChatRenderer: Record<string, MessagePartRenderer> = {
};
type AIChatProps = {
chatHistory?: Pick<ChatHistoryDocument, '_id' | 'title'>;
messages?: RoadmapAIChatHistoryType[];
chatHistoryId?: string;
setChatHistoryId?: (chatHistoryId: string) => void;
};
export function AIChat(props: AIChatProps) {
const { chatHistory: defaultDetails, messages: defaultMessages } = props;
const {
messages: defaultMessages,
chatHistoryId: defaultChatHistoryId,
setChatHistoryId: setDefaultChatHistoryId,
} = props;
const toast = useToast();
const [chatDetails, setChatDetails] = useState<{
chatHistoryId: string;
title: string;
} | null>(
defaultDetails
? {
chatHistoryId: defaultDetails._id,
title: defaultDetails.title,
}
: null,
);
const [message, setMessage] = useState('');
const [isStreamingMessage, setIsStreamingMessage] = useState(false);
const [streamedMessage, setStreamedMessage] =
@@ -183,7 +175,7 @@ export function AIChat(props: AIChatProps) {
},
credentials: 'include',
body: JSON.stringify({
chatHistoryId: chatDetails?.chatHistoryId,
chatHistoryId: defaultChatHistoryId,
messages: messages.slice(-10),
force,
}),
@@ -252,7 +244,7 @@ export function AIChat(props: AIChatProps) {
return;
}
setChatDetails(detailsJson);
setDefaultChatHistoryId?.(chatHistoryId);
window.history.replaceState({}, '', `/ai/chat/${chatHistoryId}`);
},
});

View File

@@ -7,13 +7,17 @@ import { useEffect, useState } from 'react';
import { AIChatLayout } from './AIChatLayout';
type AIChatHistoryProps = {
chatHistoryId: string;
chatHistoryId?: string;
};
export function AIChatHistory(props: AIChatHistoryProps) {
const { chatHistoryId } = props;
const { chatHistoryId: defaultChatHistoryId } = props;
const [isLoading, setIsLoading] = useState(!!defaultChatHistoryId);
const [chatHistoryId, setChatHistoryId] = useState<string | undefined>(
defaultChatHistoryId || undefined,
);
const [isLoading, setIsLoading] = useState(true);
const { data } = useQuery(chatHistoryOptions(chatHistoryId), queryClient);
useEffect(() => {
@@ -31,7 +35,13 @@ export function AIChatHistory(props: AIChatHistoryProps) {
<Loader2Icon className="h-4 w-4 animate-spin" />
</div>
)}
{!isLoading && <AIChat messages={data?.messages} chatHistory={data} />}
{!isLoading && (
<AIChat
messages={data?.messages}
chatHistoryId={chatHistoryId}
setChatHistoryId={setChatHistoryId}
/>
)}
</AIChatLayout>
);
}

View File

@@ -1,7 +1,7 @@
---
import SkeletonLayout from '../../../layouts/SkeletonLayout.astro';
import { AIChat } from '../../../components/AIChat/AIChat';
import { AIChatLayout } from '../../../components/AIChatHistory/AIChatLayout';
import { AIChatHistory } from '../../../components/AIChatHistory/AIChatHistory';
---
<SkeletonLayout
@@ -9,7 +9,5 @@ import { AIChatLayout } from '../../../components/AIChatHistory/AIChatLayout';
noIndex={true}
description='Learn anything with AI Tutor. Pick a topic, choose a difficulty level and the AI will guide you through the learning process.'
>
<AIChatLayout client:load>
<AIChat client:load />
</AIChatLayout>
<AIChatHistory client:load />
</SkeletonLayout>

View File

@@ -23,7 +23,7 @@ export interface ChatHistoryDocument {
updatedAt: Date;
}
export function chatHistoryOptions(chatHistoryId: string) {
export function chatHistoryOptions(chatHistoryId?: string) {
return queryOptions({
queryKey: ['chat-history', chatHistoryId],
queryFn: async () => {
@@ -31,6 +31,10 @@ export function chatHistoryOptions(chatHistoryId: string) {
`/v1-chat-history/${chatHistoryId}`,
);
if (data.title) {
document.title = data.title;
}
const messages: RoadmapAIChatHistoryType[] = [];
for (const message of data.messages) {
messages.push({
@@ -52,6 +56,40 @@ export function chatHistoryOptions(chatHistoryId: string) {
messages,
};
},
enabled: !!isLoggedIn() && !!chatHistoryId,
});
}
type ListChatHistoryQuery = {
perPage?: string;
currPage?: string;
query?: string;
};
type ListChatHistoryResponse = {
data: Omit<ChatHistoryDocument, 'messages'>[];
totalCount: number;
totalPages: number;
currPage: number;
perPage: number;
};
export function listChatHistoryOptions(
query: ListChatHistoryQuery = {
perPage: '20',
currPage: '1',
query: '',
},
) {
return queryOptions({
queryKey: ['chat-history', query],
queryFn: () => {
return httpGet<ListChatHistoryResponse>('/v1-list-chat-history', {
...(query?.query ? { query: query.query } : {}),
...(query?.perPage ? { perPage: query.perPage } : {}),
...(query?.currPage ? { currPage: query.currPage } : {}),
});
},
enabled: !!isLoggedIn(),
});
}