+
+
= 90
+ ? 'bg-red-500'
+ : percentageUsed >= 70
+ ? 'bg-yellow-500'
+ : 'bg-green-500',
+ )}
+ style={{ width: `${Math.min(percentageUsed, 100)}%` }}
+ />
+
+
{percentageUsed}% used
+
+
+ Upgrade
+
+
+ );
+}
+
type RoadmapChatProps = {
roadmapId: string;
};
@@ -111,6 +179,19 @@ export function RoadmapFloatingChat(props: RoadmapChatProps) {
queryClient,
);
+ const { data: tokenUsage, isLoading: isTokenUsageLoading } = useQuery(
+ getAiCourseLimitOptions(),
+ queryClient,
+ );
+ const isLimitExceeded = (tokenUsage?.used || 0) >= (tokenUsage?.limit || 0);
+ const percentageUsed = Math.round(
+ ((tokenUsage?.used || 0) / (tokenUsage?.limit || 0)) * 100,
+ );
+
+ const { data: userBillingDetails, isLoading: isBillingDetailsLoading } =
+ useQuery(billingDetailsOptions(), queryClient);
+ const isPaidUser = userBillingDetails?.status === 'active';
+
const totalTopicCount = useMemo(() => {
const allowedTypes = ['topic', 'subtopic', 'todo'];
return (
@@ -222,174 +303,205 @@ export function RoadmapFloatingChat(props: RoadmapChatProps) {
{isOpen && (
-
- {/* Messages area */}
-
-
-
}
- >
- AI Tutor
-
-
{
- setIsPersonalizeOpen(true);
- }}
- icon={}
- className="rounded-md bg-gray-200 py-1 pr-2 pl-1.5 text-gray-500 hover:bg-gray-300"
- >
- Personalize
-
-
-
-
- {hasMessages && (
+ <>
+
+ {/* Messages area */}
+
+
{
- setInputValue('');
- clearChat();
- }}
- icon={}
- className="mr-2 text-gray-500"
+ icon={}
+ className="mr-2 hidden text-sm sm:flex"
>
- Clear
+ AI Tutor
- )}
+ {!isPaidUser && (
+ {
+ window.open('/premium', '_blank');
+ }}
+ />
+ )}
+
-
}
- className="rounded-md hidden sm:flex bg-gray-200 py-1 pr-2 pl-1.5 text-gray-500 hover:bg-gray-300"
- >
- Open in new tab
-
+
+ }
+ className="hidden rounded-md bg-gray-200 py-1 pr-2 pl-1.5 text-gray-500 hover:bg-gray-300 sm:flex"
+ >
+ Open in new tab
+
- setIsOpen(false)}
- icon={}
- className="rounded-md bg-red-100 px-1 py-1 text-red-500 hover:bg-red-200"
- />
+ setIsOpen(false)}
+ icon={}
+ className="rounded-md bg-red-100 px-1 py-1 text-red-500 hover:bg-red-200"
+ />
+
-
-
-
-
- Hey, I am your AI tutor. How can I help you today? 👋
-
- }
- isIntro
- />
+
+
+
+ Hey, I am your AI tutor. How can I help you today? 👋
+
+ }
+ isIntro
+ />
- {/* Show default questions only when there's no chat history */}
- {aiChatHistory.length === 0 && defaultQuestions.length > 0 && (
-
-
- Some questions you might have about this roadmap:
-
-
- {defaultQuestions.map((question, index) => (
-
- ))}
-
-
- )}
+ {/* Show default questions only when there's no chat history */}
+ {aiChatHistory.length === 0 &&
+ defaultQuestions.length > 0 && (
+
+
+ Some questions you might have about this roadmap:
+
+
+ {defaultQuestions.map((question, index) => (
+
+ ))}
+
+
+ )}
- {aiChatHistory.map(
- (chat: RoadmapAIChatHistoryType, index: number) => (
-
-
-
- ),
- )}
+ {aiChatHistory.map(
+ (chat: RoadmapAIChatHistoryType, index: number) => (
+
+
+
+ ),
+ )}
- {isStreamingMessage && !streamedMessage && (
-
- )}
+ {isStreamingMessage && !streamedMessage && (
+
+ )}
- {streamedMessage && (
-
+ {streamedMessage && (
+
+ )}
+
+
+ {/* Scroll to bottom button */}
+ {showScrollToBottom && (
+
)}
- {/* Scroll to bottom button */}
- {showScrollToBottom && (
-
+ />
+ )}
+ {!isLimitExceeded && (
+ <>
+
+
{
+ setIsPersonalizeOpen(true);
+ }}
+ icon={}
+ className="rounded-md bg-gray-200 py-1 pr-2 pl-1.5 text-gray-500 hover:bg-gray-300"
+ >
+ Personalize
+
+ {hasMessages && (
+
{
+ setInputValue('');
+ clearChat();
+ }}
+ icon={}
+ className="rounded-md bg-gray-200 py-1 pr-2 pl-1.5 text-gray-500 hover:bg-gray-300"
+ >
+ Clear
+
+ )}
+
+
+
setInputValue(e.target.value)}
+ autoFocus
+ disabled={isLimitExceeded}
+ onKeyDown={(e) => {
+ if (e.key === 'Enter') {
+ e.preventDefault();
+ if (isStreamingMessage) {
+ return;
+ }
+ submitInput();
+ }
+ }}
+ placeholder={
+ isLimitExceeded
+ ? 'You have reached the usage limit for today..'
+ : 'Ask me anything about this roadmap...'
+ }
+ className={cn(
+ 'w-full resize-none px-3 py-4 outline-none',
+ isLimitExceeded && 'bg-gray-100 text-gray-400',
+ )}
+ />
+
+
+
+ >
)}
-
- {/* Input area */}
-
-
setInputValue(e.target.value)}
- autoFocus
- onKeyDown={(e) => {
- if (e.key === 'Enter') {
- e.preventDefault();
- if (isStreamingMessage) {
- return;
- }
- submitInput();
- }
- }}
- placeholder="Ask me anything about this roadmap..."
- className="w-full resize-none p-3 outline-none"
- />
-
-
-
-
+ >
)}
{!isOpen && (