ui: fetch suggestions for kai prompts
* update display logic * don't copy array when unnecessary * only update prompt ideas when array size changes --------- Co-authored-by: Jonathan Griffin <jonathangriffin@Jonathans-MacBook-Air.local>
This commit is contained in:
parent
7fc744c273
commit
59c10cdbea
4 changed files with 45 additions and 7 deletions
|
|
@ -119,7 +119,7 @@ function KaiChat() {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{section === 'intro' ? (
|
{section === 'intro' ? (
|
||||||
<IntroSection onAsk={onCreate} />
|
<IntroSection onAsk={onCreate} projectId={activeSiteId} />
|
||||||
) : (
|
) : (
|
||||||
<ChatLog
|
<ChatLog
|
||||||
threadId={threadId}
|
threadId={threadId}
|
||||||
|
|
|
||||||
|
|
@ -123,4 +123,15 @@ export default class KaiService extends AiService {
|
||||||
const data = await r.json();
|
const data = await r.json();
|
||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
getPromptSuggestions = async (
|
||||||
|
projectId: string,
|
||||||
|
): Promise<string[]> => {
|
||||||
|
const r = await this.client.get(`/kai/${projectId}/prompt-suggestions`);
|
||||||
|
if (!r.ok) {
|
||||||
|
throw new Error('Failed to fetch prompt suggestions');
|
||||||
|
}
|
||||||
|
const data = await r.json();
|
||||||
|
return data;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,43 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Lightbulb, MoveRight } from 'lucide-react';
|
import { Lightbulb, MoveRight } from 'lucide-react';
|
||||||
|
import { useQuery } from '@tanstack/react-query';
|
||||||
|
import { kaiService } from 'App/services';
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
function Ideas({ onClick }: { onClick: (query: string) => void }) {
|
function Ideas({ onClick, projectId }: { onClick: (query: string) => void, projectId: string }) {
|
||||||
|
const { t } = useTranslation();
|
||||||
|
const {
|
||||||
|
data: suggestedPromptIdeas = [],
|
||||||
|
isPending,
|
||||||
|
} = useQuery({
|
||||||
|
queryKey: ['kai', 'prompt-suggestions', projectId],
|
||||||
|
queryFn: () => kaiService.getPromptSuggestions(projectId),
|
||||||
|
staleTime: 1000 * 60,
|
||||||
|
});
|
||||||
|
const ideas = React.useMemo(() => {
|
||||||
|
const defaultPromptIdeas = [
|
||||||
|
'Top user journeys',
|
||||||
|
'Where do users drop off',
|
||||||
|
'Failed network requests today',
|
||||||
|
];
|
||||||
|
const result = suggestedPromptIdeas;
|
||||||
|
const targetSize = 3;
|
||||||
|
while (result.length < targetSize && defaultPromptIdeas.length) {
|
||||||
|
result.push(defaultPromptIdeas.pop())
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}, [suggestedPromptIdeas.length]);
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className={'flex items-center gap-2 mb-1 text-gray-dark'}>
|
<div className={'flex items-center gap-2 mb-1 text-gray-dark'}>
|
||||||
<Lightbulb size={16} />
|
<Lightbulb size={16} />
|
||||||
<b>Ideas:</b>
|
<b>Ideas:</b>
|
||||||
</div>
|
</div>
|
||||||
<IdeaItem onClick={onClick} title={'Top user journeys'} />
|
{
|
||||||
<IdeaItem onClick={onClick} title={'Where do users drop off'} />
|
isPending ?
|
||||||
<IdeaItem onClick={onClick} title={'Failed network requests today'} />
|
(<div className="animate-pulse text-disabled-text">{t('Generating ideas')}...</div>) :
|
||||||
|
(<div>{ideas.map(title => (<IdeaItem key={title} onClick={onClick} title={title} />))}</div>)
|
||||||
|
}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import React from 'react';
|
||||||
import ChatInput from './ChatInput';
|
import ChatInput from './ChatInput';
|
||||||
import Ideas from './Ideas';
|
import Ideas from './Ideas';
|
||||||
|
|
||||||
function IntroSection({ onAsk }: { onAsk: (query: string) => void }) {
|
function IntroSection({ onAsk, projectId }: { onAsk: (query: string) => void, projectId: string }) {
|
||||||
const isLoading = false;
|
const isLoading = false;
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
|
@ -14,7 +14,7 @@ function IntroSection({ onAsk }: { onAsk: (query: string) => void }) {
|
||||||
{/*<GradientBorderInput placeholder={'Ask anything about your product and users...'} onButtonClick={() => null} />*/}
|
{/*<GradientBorderInput placeholder={'Ask anything about your product and users...'} onButtonClick={() => null} />*/}
|
||||||
<ChatInput isLoading={isLoading} onSubmit={onAsk} />
|
<ChatInput isLoading={isLoading} onSubmit={onAsk} />
|
||||||
<div className={'absolute top-full flex flex-col gap-2 mt-4'}>
|
<div className={'absolute top-full flex flex-col gap-2 mt-4'}>
|
||||||
<Ideas onClick={(query) => onAsk(query)} />
|
<Ideas onClick={(query) => onAsk(query)} projectId={projectId} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={'text-disabled-text absolute bottom-4'}>
|
<div className={'text-disabled-text absolute bottom-4'}>
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue