1
0
mirror of https://github.com/kamranahmedse/developer-roadmap.git synced 2025-09-03 06:12:53 +02:00
This commit is contained in:
Arik Chakma
2025-06-13 17:50:09 +06:00
parent ac923a3cd9
commit c382177277
2 changed files with 27 additions and 9 deletions

View File

@@ -35,13 +35,17 @@ export function AIGuideChat(props: AIGuideChatProps) {
const [inputValue, setInputValue] = useState('');
const [showScrollToBottom, setShowScrollToBottom] = useState(false);
const { data: tokenUsage, isLoading: isTokenUsageLoading } = useQuery(
getAiCourseLimitOptions(),
queryClient,
);
const {
data: tokenUsage,
isLoading: isTokenUsageLoading,
refetch: refetchTokenUsage,
} = useQuery(getAiCourseLimitOptions(), queryClient);
const { data: userBillingDetails, isLoading: isBillingDetailsLoading } =
useQuery(billingDetailsOptions(), queryClient);
const {
data: userBillingDetails,
isLoading: isBillingDetailsLoading,
refetch: refetchBillingDetails,
} = useQuery(billingDetailsOptions(), queryClient);
const isLimitExceeded = (tokenUsage?.used || 0) >= (tokenUsage?.limit || 0);
const isPaidUser = userBillingDetails?.status === 'active';
@@ -61,6 +65,9 @@ export function AIGuideChat(props: AIGuideChatProps) {
data: {
guideSlug,
},
onFinish: () => {
refetchTokenUsage();
},
});
const scrollToBottom = useCallback(
@@ -122,6 +129,9 @@ export function AIGuideChat(props: AIGuideChatProps) {
return () => scrollArea.removeEventListener('scroll', checkScrollPosition);
}, [checkScrollPosition]);
const isLoading =
isGuideLoading || isTokenUsageLoading || isBillingDetailsLoading;
return (
<div className="relative flex h-full w-full max-w-[40%] flex-col overflow-hidden border-l border-gray-200">
<div className="border-b border-gray-200 bg-white p-2">
@@ -131,13 +141,13 @@ export function AIGuideChat(props: AIGuideChatProps) {
</h2>
</div>
{isGuideLoading && (
{isLoading && (
<div className="absolute inset-0 flex items-center justify-center">
<Loader2Icon className="h-4 w-4 animate-spin" />
</div>
)}
{!isGuideLoading && (
{!isLoading && (
<>
<div className="relative grow overflow-y-auto" ref={scrollareaRef}>
<div className="absolute inset-0 flex flex-col">

View File

@@ -15,10 +15,11 @@ type UseChatOptions = {
initialMessages?: ChatMessage[];
onError?: (error: Error) => void;
data?: Record<string, any>;
onFinish?: () => void;
};
export function useChat(options: UseChatOptions) {
const { endpoint, initialMessages, onError, data = {} } = options;
const { endpoint, initialMessages, onError, data = {}, onFinish } = options;
const abortControllerRef = useRef<AbortController | null>(null);
const [messages, setMessages] = useState<ChatMessage[]>(
@@ -100,7 +101,14 @@ export function useChat(options: UseChatOptions) {
});
abortControllerRef.current = null;
onFinish?.();
} catch (error) {
if (abortControllerRef.current?.signal.aborted) {
// we don't want to show error if the user stops the chat
// so we just return
return;
}
onError?.(error as Error);
}
},