From 8826d252cde81049fc8226af806c00e5a911c1a2 Mon Sep 17 00:00:00 2001 From: iacopolea Date: Thu, 19 Feb 2026 15:12:40 +0100 Subject: [PATCH 1/3] feat: enhance task list creation by incorporating module information into user prompts --- .../Component/parts/CreateTaskListsWithAI.tsx | 57 ++++++++++++++++--- 1 file changed, 50 insertions(+), 7 deletions(-) diff --git a/src/pages/Plan/modules/Factory/modules/Tasks/Component/parts/CreateTaskListsWithAI.tsx b/src/pages/Plan/modules/Factory/modules/Tasks/Component/parts/CreateTaskListsWithAI.tsx index 83d80347a..a54efb268 100644 --- a/src/pages/Plan/modules/Factory/modules/Tasks/Component/parts/CreateTaskListsWithAI.tsx +++ b/src/pages/Plan/modules/Factory/modules/Tasks/Component/parts/CreateTaskListsWithAI.tsx @@ -1,21 +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'; +// constants +const MODULES_TO_PROMPT = [ + 'title', + 'goal', + 'out_of_scope', + 'tasks', + 'language', + 'touchpoints', +]; +const MAX_PROMPT_LENGTH = 102300; + export const CreateTaskListsWithAI = () => { const { planId } = useParams(); const MIN_LENGTH = 1; @@ -23,9 +35,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 || '' }, @@ -35,11 +50,13 @@ 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] @@ -47,12 +64,21 @@ export const CreateTaskListsWithAI = () => { 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); @@ -156,3 +182,20 @@ export const CreateTaskListsWithAI = () => { ); }; + +// Helper function to process module item output for better readability in the prompt +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)); + } else if (typeof item === 'object' && item !== null) { + // Process object: strip out id and recursively process nested values + const { id, ...rest } = item; + const processedRest: any = {}; + for (const [key, value] of Object.entries(rest)) { + processedRest[key] = processItemOutput(value); + } + return processedRest; + } + return item; +}; From 548f9e7a70e73a2aa0fe128fee3866ee3b7ca9d5 Mon Sep 17 00:00:00 2001 From: iacopolea Date: Thu, 19 Feb 2026 16:04:45 +0100 Subject: [PATCH 2/3] feat: change out of scope module position. UN-2337 --- src/locales/en/translation.json | 1 - src/locales/it/translation.json | 1 - src/pages/Plan/common/constants.ts | 8 +------- 3 files changed, 1 insertion(+), 9 deletions(-) diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index 962dea062..247f984c7 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -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", diff --git a/src/locales/it/translation.json b/src/locales/it/translation.json index f3dbda73c..bc2913b6d 100644 --- a/src/locales/it/translation.json +++ b/src/locales/it/translation.json @@ -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": "", diff --git a/src/pages/Plan/common/constants.ts b/src/pages/Plan/common/constants.ts index ec1f8ebb4..131200246 100644 --- a/src/pages/Plan/common/constants.ts +++ b/src/pages/Plan/common/constants.ts @@ -15,7 +15,7 @@ export const MODULE_GROUPS: Record = { { id: 'essentials', title: '__PLAN_PAGE_GROUP_TITLE_ESSENTIALS', - modules: ['goal'], + modules: ['goal', 'out_of_scope'], }, { id: 'technicalRequirements', @@ -75,11 +75,6 @@ export const MODULE_GROUPS: Record = { title: '__PLAN_PAGE_GROUP_TITLE_ACTIVITY_SCOPE', modules: ['tasks'], }, - { - id: 'additionalDetails', - title: '__PLAN_PAGE_GROUP_TITLE_ADDITIONAL_DETAILS', - modules: ['out_of_scope'], - }, ], summary: [], }; @@ -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'); From f49c1b3cd5b76b238f7f2ca94ea5ce155f68151a Mon Sep 17 00:00:00 2001 From: iacopolea Date: Thu, 19 Feb 2026 16:17:40 +0100 Subject: [PATCH 3/3] validation --- .../Component/parts/CreateTaskListsWithAI.tsx | 22 ++----------------- .../Component/parts/processItemOutput.ts | 17 ++++++++++++++ 2 files changed, 19 insertions(+), 20 deletions(-) create mode 100644 src/pages/Plan/modules/Factory/modules/Tasks/Component/parts/processItemOutput.ts diff --git a/src/pages/Plan/modules/Factory/modules/Tasks/Component/parts/CreateTaskListsWithAI.tsx b/src/pages/Plan/modules/Factory/modules/Tasks/Component/parts/CreateTaskListsWithAI.tsx index a54efb268..53ed73e09 100644 --- a/src/pages/Plan/modules/Factory/modules/Tasks/Component/parts/CreateTaskListsWithAI.tsx +++ b/src/pages/Plan/modules/Factory/modules/Tasks/Component/parts/CreateTaskListsWithAI.tsx @@ -16,6 +16,7 @@ import { useGetServicesApiKJobsByJobIdQuery, usePostServicesApiKUsecasesMutation, } from 'src/features/api'; +import { processItemOutput } from './processItemOutput'; // constants const MODULES_TO_PROMPT = [ @@ -87,7 +88,6 @@ 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]); @@ -95,7 +95,6 @@ export const CreateTaskListsWithAI = () => { // Stop polling when job is completed useEffect(() => { if (useCasesData?.status === 'completed' && useCasesData?.result) { - console.log('Use cases data received:', useCasesData); setPollingInterval(0); } }, [useCasesData]); @@ -153,7 +152,7 @@ export const CreateTaskListsWithAI = () => { Generated Task Lists: - {useCasesData.result.useCases.map((useCase: any, index: number) => ( + {useCasesData.result.useCases.map((useCase: any) => ( @@ -182,20 +181,3 @@ export const CreateTaskListsWithAI = () => { ); }; - -// Helper function to process module item output for better readability in the prompt -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)); - } else if (typeof item === 'object' && item !== null) { - // Process object: strip out id and recursively process nested values - const { id, ...rest } = item; - const processedRest: any = {}; - for (const [key, value] of Object.entries(rest)) { - processedRest[key] = processItemOutput(value); - } - return processedRest; - } - return item; -}; diff --git a/src/pages/Plan/modules/Factory/modules/Tasks/Component/parts/processItemOutput.ts b/src/pages/Plan/modules/Factory/modules/Tasks/Component/parts/processItemOutput.ts new file mode 100644 index 000000000..1a3596fd0 --- /dev/null +++ b/src/pages/Plan/modules/Factory/modules/Tasks/Component/parts/processItemOutput.ts @@ -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; +};