From f173a4723c59e4ee48312440c21a27900991502e Mon Sep 17 00:00:00 2001 From: Kamran Ahmed Date: Fri, 2 May 2025 20:19:35 +0100 Subject: [PATCH] Refactor actions logic --- ...ageGroup.tsx => PredefinedActionGroup.tsx} | 16 +-- .../TopicDetail/PredefinedActions.tsx | 115 +++++++++++++++++ .../TopicDetail/PredefinedMessages.tsx | 120 ------------------ src/components/TopicDetail/TopicDetailAI.tsx | 39 ++---- 4 files changed, 133 insertions(+), 157 deletions(-) rename src/components/TopicDetail/{PredefinedMessageGroup.tsx => PredefinedActionGroup.tsx} (77%) create mode 100644 src/components/TopicDetail/PredefinedActions.tsx delete mode 100644 src/components/TopicDetail/PredefinedMessages.tsx diff --git a/src/components/TopicDetail/PredefinedMessageGroup.tsx b/src/components/TopicDetail/PredefinedActionGroup.tsx similarity index 77% rename from src/components/TopicDetail/PredefinedMessageGroup.tsx rename to src/components/TopicDetail/PredefinedActionGroup.tsx index c65e06f8d..0b95d476c 100644 --- a/src/components/TopicDetail/PredefinedMessageGroup.tsx +++ b/src/components/TopicDetail/PredefinedActionGroup.tsx @@ -2,18 +2,18 @@ import type { LucideIcon } from 'lucide-react'; import { useState, useRef } from 'react'; import { useOutsideClick } from '../../hooks/use-outside-click'; import { - type PredefinedMessage, - PredefinedMessageButton, -} from './PredefinedMessages'; + type PredefinedMessageType, + PredefinedActionButton, +} from './PredefinedActions'; type PredefinedMessageGroupProps = { label: string; icon: LucideIcon; - messages: Omit[]; - onSelect: (message: Omit) => void; + messages: PredefinedMessageType[]; + onSelect: (message: PredefinedMessageType) => void; }; -export function PredefinedMessageGroup(props: PredefinedMessageGroupProps) { +export function PredefinedActionGroup(props: PredefinedMessageGroupProps) { const { label, icon: Icon, messages, onSelect } = props; const [isOpen, setIsOpen] = useState(false); @@ -25,7 +25,7 @@ export function PredefinedMessageGroup(props: PredefinedMessageGroupProps) { return (
- setIsOpen(!isOpen)} @@ -36,7 +36,7 @@ export function PredefinedMessageGroup(props: PredefinedMessageGroupProps) {
{messages.map((m) => { return ( - { + if (action.prompt) { + acc[action.prompt] = action.label; + } + return acc; + }, + {} as Record, +); + +type PredefinedActionsProps = { + onSelect: (action: PredefinedActionType) => void; +}; + +export function PredefinedActions(props: PredefinedActionsProps) { + const { onSelect } = props; + + return ( +
+ {actions.map((action) => { + if (!action.children) { + return ( + { + onSelect(action); + }} + /> + ); + } + + return ( + + ); + })} +
+ ); +} + +type PredefinedActionButtonProps = { + label: string; + icon?: LucideIcon; + onClick: () => void; + isGroup?: boolean; + className?: string; +}; + +export function PredefinedActionButton(props: PredefinedActionButtonProps) { + const { label, icon: Icon, onClick, isGroup = false, className } = props; + + return ( + + ); +} diff --git a/src/components/TopicDetail/PredefinedMessages.tsx b/src/components/TopicDetail/PredefinedMessages.tsx deleted file mode 100644 index ba3d5dc44..000000000 --- a/src/components/TopicDetail/PredefinedMessages.tsx +++ /dev/null @@ -1,120 +0,0 @@ -import { - BabyIcon, - BookOpenTextIcon, - BrainIcon, - ChevronDownIcon, - NotebookPenIcon, - type LucideIcon, -} from 'lucide-react'; -import { useMemo } from 'react'; -import { cn } from '../../lib/classname'; -import { PredefinedMessageGroup } from './PredefinedMessageGroup'; - -export const testMyKnowledgePrompt = - 'Act as an interviewer and test my understanding of this topic'; -export const explainTopicPrompt = 'Explain this topic in detail'; - -export type PredefinedMessage = { - icon: LucideIcon; - label: string; -} & ( - | { - message?: never; - messages: PredefinedMessage[]; - } - | { - message: string; - messages?: never; - } -); - -type PredefinedMessagesProps = { - onSelect: (message: Omit) => void; -}; - -export function PredefinedMessages(props: PredefinedMessagesProps) { - const { onSelect } = props; - - const predefinedMessages: PredefinedMessage[] = useMemo( - () => [ - { - icon: BookOpenTextIcon, - label: 'Explain', - messages: [ - { - icon: NotebookPenIcon, - label: 'Explain Topic', - message: 'Explain this topic in detail and include examples', - }, - { - icon: BabyIcon, - label: 'Explain like I am five', - message: 'Explain this topic like I am a 5 years old', - }, - ], - }, - { - icon: BrainIcon, - label: 'Test my Knowledge', - message: testMyKnowledgePrompt, - }, - ], - [], - ); - - return ( -
- {predefinedMessages.map((m) => { - const isGroup = 'messages' in m && Array.isArray(m?.messages); - if (!isGroup) { - return ( - { - onSelect(m); - }} - /> - ); - } - - return ( - - ); - })} -
- ); -} - -type PredefinedMessageButtonProps = { - label: string; - icon?: LucideIcon; - onClick: () => void; - isGroup?: boolean; - className?: string; -}; - -export function PredefinedMessageButton(props: PredefinedMessageButtonProps) { - const { label, icon: Icon, onClick, isGroup = false, className } = props; - - return ( - - ); -} diff --git a/src/components/TopicDetail/TopicDetailAI.tsx b/src/components/TopicDetail/TopicDetailAI.tsx index 79e340163..f9862b974 100644 --- a/src/components/TopicDetail/TopicDetailAI.tsx +++ b/src/components/TopicDetail/TopicDetailAI.tsx @@ -1,14 +1,6 @@ import '../GenerateCourse/AICourseLessonChat.css'; import { useQuery } from '@tanstack/react-query'; -import { - useState, - type FormEvent, - useRef, - Fragment, - useCallback, - useEffect, - useMemo, -} from 'react'; +import { useState, useRef, Fragment, useCallback, useEffect } from 'react'; import { billingDetailsOptions } from '../../queries/billing'; import { getAiCourseLimitOptions } from '../../queries/ai-course'; import { queryClient } from '../../stores/query-client'; @@ -37,11 +29,7 @@ import { getPercentage } from '../../lib/number'; import { roadmapTreeMappingOptions } from '../../queries/roadmap-tree'; import { defaultChatHistory } from './TopicDetail'; import { AILimitsPopup } from '../GenerateCourse/AILimitsPopup'; -import { - explainTopicPrompt, - PredefinedMessages, - testMyKnowledgePrompt, -} from './PredefinedMessages'; +import { PredefinedActions, promptLabelMapping } from './PredefinedActions'; type TopicDetailAIProps = { resourceId: string; @@ -338,15 +326,15 @@ export function TopicDetailAI(props: TopicDetailAIProps) { )}
- { - if (!m?.message) { + { + if (!action?.prompt) { toast.error('Something went wrong'); return; } - setMessage(m.message); - handleChatSubmit(m.message); + setMessage(action.prompt); + handleChatSubmit(action.prompt); }} /> @@ -358,17 +346,10 @@ export function TopicDetailAI(props: TopicDetailAIProps) {
{aiChatHistory.map((chat, index) => { - const isTextMyKnowledgePrompt = - chat.role === 'user' && - chat.content === testMyKnowledgePrompt; - const isTextExplainTopicPrompt = - chat.role === 'user' && chat.content === explainTopicPrompt; - let content = chat.content; - if (isTextMyKnowledgePrompt) { - content = 'Starting Interview'; - } else if (isTextExplainTopicPrompt) { - content = 'Explain Topic'; + + if (chat.role === 'user' && promptLabelMapping[chat.content]) { + content = promptLabelMapping[chat.content]; } return (