Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion src/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -803,7 +803,6 @@
"__PLAN_PAGE_EXPERT_REVIEW_TOOLTIP_CONTENT": "An expert will contact you within 3-5 business days with a custom quote",
"__PLAN_PAGE_EXPERT_REVIEW_WARNING": "Requires expert review",
"__PLAN_PAGE_GROUP_TITLE_ACTIVITY_SCOPE": "Activity Scope",
"__PLAN_PAGE_GROUP_TITLE_ADDITIONAL_DETAILS": "Additional Details",
"__PLAN_PAGE_GROUP_TITLE_ADVANCED_CRITERIA": "Other",
"__PLAN_PAGE_GROUP_TITLE_BEFORE_STARTING": " ",
"__PLAN_PAGE_GROUP_TITLE_BEHAVIOURAL_DATA": "Behavioural Data",
Expand Down
1 change: 0 additions & 1 deletion src/locales/it/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -833,7 +833,6 @@
"__PLAN_PAGE_EXPERT_REVIEW_TOOLTIP_CONTENT": "",
"__PLAN_PAGE_EXPERT_REVIEW_WARNING": "",
"__PLAN_PAGE_GROUP_TITLE_ACTIVITY_SCOPE": "",
"__PLAN_PAGE_GROUP_TITLE_ADDITIONAL_DETAILS": "",
"__PLAN_PAGE_GROUP_TITLE_ADVANCED_CRITERIA": "",
"__PLAN_PAGE_GROUP_TITLE_BEFORE_STARTING": "",
"__PLAN_PAGE_GROUP_TITLE_BEHAVIOURAL_DATA": "",
Expand Down
8 changes: 1 addition & 7 deletions src/pages/Plan/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export const MODULE_GROUPS: Record<PlanTabName, ModuleGroup[]> = {
{
id: 'essentials',
title: '__PLAN_PAGE_GROUP_TITLE_ESSENTIALS',
modules: ['goal'],
modules: ['goal', 'out_of_scope'],
},
{
id: 'technicalRequirements',
Expand Down Expand Up @@ -75,11 +75,6 @@ export const MODULE_GROUPS: Record<PlanTabName, ModuleGroup[]> = {
title: '__PLAN_PAGE_GROUP_TITLE_ACTIVITY_SCOPE',
modules: ['tasks'],
},
{
id: 'additionalDetails',
title: '__PLAN_PAGE_GROUP_TITLE_ADDITIONAL_DETAILS',
modules: ['out_of_scope'],
},
],
summary: [],
};
Expand All @@ -99,7 +94,6 @@ const i18nPlanTitles = () => {
t('__PLAN_PAGE_GROUP_TITLE_BEHAVIOURAL_DATA');
t('__PLAN_PAGE_GROUP_TITLE_ADVANCED_CRITERIA');
t('__PLAN_PAGE_GROUP_TITLE_ACTIVITY_SCOPE');
t('__PLAN_PAGE_GROUP_TITLE_ADDITIONAL_DETAILS');
// Tab titles
t('__PLAN_PAGE_TAB_SETUP_TAB_TITLE');
t('__PLAN_PAGE_TAB_TARGET_TAB_TITLE');
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,33 @@
import {
AccordionNew,
Button,
Textarea,
FormField,
Label,
Message,
Input,
AccordionNew,
Label,
LG,
Message,
Textarea,
} from '@appquality/unguess-design-system';
import { useEffect, useMemo, useState } from 'react';
import { useParams } from 'react-router-dom';
import { useAppSelector } from 'src/app/hooks';
import { appTheme } from 'src/app/theme';
import {
useGetServicesApiKJobsByJobIdQuery,
usePostServicesApiKUsecasesMutation,
} from 'src/features/api';
import { processItemOutput } from './processItemOutput';

// constants
const MODULES_TO_PROMPT = [
'title',
'goal',
'out_of_scope',
'tasks',
'language',
'touchpoints',
];
const MAX_PROMPT_LENGTH = 102300;

export const CreateTaskListsWithAI = () => {
const { planId } = useParams();
Expand All @@ -23,9 +36,12 @@ export const CreateTaskListsWithAI = () => {
const [taskCount, setTaskCount] = useState(3);
const [isCreating, setIsCreating] = useState(false);
const [pollingInterval, setPollingInterval] = useState(0);

const { records } = useAppSelector((state) => state.planModules);

// API hooks
const [postServicesApiKUsecases, { data: jobData, error: postError }] =
usePostServicesApiKUsecasesMutation();

const { data: useCasesData, error: useCasesError } =
useGetServicesApiKJobsByJobIdQuery(
{ jobId: jobData?.jobId || '' },
Expand All @@ -35,24 +51,35 @@ export const CreateTaskListsWithAI = () => {
}
);

// Form inputs and button are disabled while creating the task lists or while polling for results
const isFormDisabled = useMemo(
() => isCreating || pollingInterval > 0,
[isCreating, pollingInterval]
);

// Button is disabled if form is disabled or if user prompt is too short
const isButtonDisabled = useMemo(
() => userPrompt.length < MIN_LENGTH || isFormDisabled,
[userPrompt, isFormDisabled]
);

const handleClick = async () => {
setIsCreating(true);
console.log('Button clicked', userPrompt);
// gather modules info to prepend to the user prompt
const modulesInfo = Object.entries(records)
.filter(([key]) => MODULES_TO_PROMPT.includes(key))
.map(
([key, item]) =>
`Module: ${key}, Config: ${JSON.stringify(processItemOutput(item))}`
)
.join('\n');
const fullPrompt = `User prompt:\n${userPrompt}\nModules info:\n${modulesInfo}`;

await postServicesApiKUsecases({
body: {
planId: planId || '',
count: taskCount,
requirements: userPrompt,
requirements: fullPrompt.slice(0, MAX_PROMPT_LENGTH),
},
});
setIsCreating(false);
Expand All @@ -61,15 +88,13 @@ export const CreateTaskListsWithAI = () => {
// Polling for job status every 5 seconds when jobId becomes available or changes
useEffect(() => {
if (jobData?.jobId) {
console.log('Job ID received:', jobData.jobId);
setPollingInterval(5000);
}
}, [jobData?.jobId]);

// Stop polling when job is completed
useEffect(() => {
if (useCasesData?.status === 'completed' && useCasesData?.result) {
console.log('Use cases data received:', useCasesData);
setPollingInterval(0);
}
}, [useCasesData]);
Expand Down Expand Up @@ -127,7 +152,7 @@ export const CreateTaskListsWithAI = () => {
<LG style={{ marginBottom: appTheme.space.sm }}>
Generated Task Lists:
</LG>
{useCasesData.result.useCases.map((useCase: any, index: number) => (
{useCasesData.result.useCases.map((useCase: any) => (
<AccordionNew level={3} id={useCase.id} key={useCase.id}>
<AccordionNew.Section>
<AccordionNew.Header icon="🤖">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Helper function to process module item output for better readability in the AI prompt
export const processItemOutput = (item: any): any => {
if (Array.isArray(item)) {
// If it's an array, process each item in the array
return item.map((subItem) => processItemOutput(subItem));
}
if (typeof item === 'object' && item !== null) {
// recursively process nested values
return Object.fromEntries(
Object.entries(item)
// here we can filter out any keys we don't want to include in the prompt, for example 'id'
.filter(([key]) => key !== 'id')
.map(([key, value]) => [key, processItemOutput(value)])
);
}
return item;
};
Loading