Skip to content

Commit 43e2de1

Browse files
committed
refactor(security-questionnaire): normalize results and update button states
1 parent ab3a576 commit 43e2de1

File tree

6 files changed

+57
-21
lines changed

6 files changed

+57
-21
lines changed

apps/app/src/app/(app)/[orgId]/security-questionnaire/components/QuestionnaireParser.tsx

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,23 @@ export function QuestionnaireParser() {
4040
handleToggleSource,
4141
} = useQuestionnaireParser();
4242

43+
const normalizedResults =
44+
results?.map((result) => ({
45+
...result,
46+
sources: result.sources ?? [],
47+
})) ?? null;
48+
49+
const normalizedFilteredResults =
50+
filteredResults?.map((result) => ({
51+
...result,
52+
sources: result.sources ?? [],
53+
})) ?? null;
54+
4355
return (
4456
<QuestionnaireView
4557
orgId={orgId}
46-
results={results}
47-
filteredResults={filteredResults}
58+
results={normalizedResults}
59+
filteredResults={normalizedFilteredResults}
4860
searchQuery={searchQuery}
4961
setSearchQuery={setSearchQuery}
5062
editingIndex={editingIndex}

apps/app/src/app/(app)/[orgId]/security-questionnaire/components/QuestionnaireResultsHeader.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ export function QuestionnaireResultsHeader({
154154
</Button>
155155
<DropdownMenu>
156156
<DropdownMenuTrigger asChild>
157-
<Button variant="outline" size="default" disabled={isExporting || isLoading} suppressHydrationWarning>
157+
<Button variant="outline" size="default" disabled={isExporting} suppressHydrationWarning>
158158
<Download className="size-4" />
159159
Export
160160
<ChevronDown className="size-4" />
@@ -163,21 +163,21 @@ export function QuestionnaireResultsHeader({
163163
<DropdownMenuContent align="end" suppressHydrationWarning>
164164
<DropdownMenuItem
165165
onClick={() => onExport('xlsx')}
166-
disabled={isExporting || isLoading}
166+
disabled={isExporting}
167167
>
168168
<FileSpreadsheet className="mr-2 h-4 w-4" />
169169
Excel
170170
</DropdownMenuItem>
171171
<DropdownMenuItem
172172
onClick={() => onExport('csv')}
173-
disabled={isExporting || isLoading}
173+
disabled={isExporting}
174174
>
175175
<FileTextIcon className="mr-2 h-4 w-4" />
176176
CSV
177177
</DropdownMenuItem>
178178
<DropdownMenuItem
179179
onClick={() => onExport('pdf')}
180-
disabled={isExporting || isLoading}
180+
disabled={isExporting}
181181
>
182182
<File className="mr-2 h-4 w-4" />
183183
PDF

apps/app/src/app/(app)/[orgId]/security-questionnaire/components/QuestionnaireUpload.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ interface QuestionnaireUploadProps {
1919
isLoading: boolean;
2020
parseStatus: 'uploading' | 'starting' | 'queued' | 'analyzing' | 'processing' | null;
2121
orgId: string;
22+
hasResults?: boolean;
2223
}
2324

2425
export function QuestionnaireUpload({
@@ -28,6 +29,7 @@ export function QuestionnaireUpload({
2829
onParse,
2930
isLoading,
3031
parseStatus,
32+
hasResults = false,
3133
}: QuestionnaireUploadProps) {
3234
return (
3335
<div className="flex flex-col gap-6">
@@ -99,7 +101,7 @@ export function QuestionnaireUpload({
99101
<div className="flex items-center justify-end">
100102
<Button
101103
onClick={onParse}
102-
disabled={isLoading || !selectedFile}
104+
disabled={isLoading || !selectedFile || hasResults}
103105
className="h-11 lg:h-12 px-6 lg:px-8 w-full sm:w-auto"
104106
size="lg"
105107
>

apps/app/src/app/(app)/[orgId]/security-questionnaire/hooks/useQuestionnaireAutoAnswer.ts

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -299,17 +299,30 @@ export function useQuestionnaireAutoAnswer({
299299

300300
answers.forEach((answer) => {
301301
if (answer.sources && answer.sources.length > 0) {
302-
const targetIndex = updatedResults.findIndex(
303-
(r) => r.originalIndex === answer.questionIndex
304-
);
305-
306-
if (targetIndex >= 0 && targetIndex < updatedResults.length) {
307-
const currentSources = updatedResults[targetIndex]?.sources || [];
308-
const sourcesChanged = JSON.stringify(currentSources) !== JSON.stringify(answer.sources);
302+
const directIndex =
303+
answer.questionIndex >= 0 && answer.questionIndex < updatedResults.length
304+
? answer.questionIndex
305+
: -1;
306+
307+
const fallbackIndex =
308+
directIndex === -1
309+
? updatedResults.findIndex((r, idx) => {
310+
const candidate =
311+
(r as { originalIndex?: number; _originalIndex?: number }).originalIndex ??
312+
(r as { originalIndex?: number; _originalIndex?: number })._originalIndex ??
313+
idx;
314+
return candidate === answer.questionIndex;
315+
})
316+
: directIndex;
317+
318+
if (fallbackIndex >= 0 && fallbackIndex < updatedResults.length) {
319+
const currentSources = updatedResults[fallbackIndex]?.sources || [];
320+
const sourcesChanged =
321+
JSON.stringify(currentSources) !== JSON.stringify(answer.sources);
309322

310323
if (sourcesChanged) {
311-
updatedResults[targetIndex] = {
312-
...updatedResults[targetIndex],
324+
updatedResults[fallbackIndex] = {
325+
...updatedResults[fallbackIndex],
313326
sources: answer.sources,
314327
};
315328
hasChanges = true;

apps/app/src/app/(app)/[orgId]/security-questionnaire/hooks/useQuestionnaireDetail/useQuestionnaireDetailHandlers.ts

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ interface UseQuestionnaireDetailHandlersProps {
3232
}) => void;
3333
};
3434
deleteAnswerAction: {
35-
execute: (payload: { questionnaireId: string; questionAnswerId: string }) => Promise<any>;
35+
execute: (
36+
payload: { questionnaireId: string; questionAnswerId: string }
37+
) => Promise<any> | void;
3638
};
3739
router: { refresh: () => void };
3840
triggerAutoAnswer: (payload: {
@@ -242,10 +244,12 @@ export function useQuestionnaireDetailHandlers({
242244

243245
const handleDeleteAnswer = async (questionAnswerId: string, questionIndex: number) => {
244246
try {
245-
await deleteAnswerAction.execute({
246-
questionnaireId,
247-
questionAnswerId,
248-
});
247+
await Promise.resolve(
248+
deleteAnswerAction.execute({
249+
questionnaireId,
250+
questionAnswerId,
251+
})
252+
);
249253

250254
setResults((prev) =>
251255
prev.map((r) =>

apps/app/src/lib/vector/core/upsert-embedding.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ export interface EmbeddingMetadata {
1717
vendorName?: string;
1818
questionnaireQuestion?: string;
1919
documentName?: string;
20+
manualAnswerQuestion?: string;
2021
updatedAt?: string; // ISO timestamp for incremental sync comparison
2122
}
2223

@@ -62,6 +63,7 @@ export async function upsertEmbedding(
6263
...(metadata.vendorId && { vendorId: metadata.vendorId }),
6364
...(metadata.vendorName && { vendorName: metadata.vendorName }),
6465
...(metadata.questionnaireQuestion && { questionnaireQuestion: metadata.questionnaireQuestion }),
66+
...(metadata.manualAnswerQuestion && { manualAnswerQuestion: metadata.manualAnswerQuestion }),
6567
...(metadata.documentName && { documentName: metadata.documentName }),
6668
...(metadata.updatedAt && { updatedAt: metadata.updatedAt }),
6769
};
@@ -171,6 +173,9 @@ export async function batchUpsertEmbeddings(
171173
...(item.metadata.questionnaireQuestion && {
172174
questionnaireQuestion: item.metadata.questionnaireQuestion,
173175
}),
176+
...(item.metadata.manualAnswerQuestion && {
177+
manualAnswerQuestion: item.metadata.manualAnswerQuestion,
178+
}),
174179
...(item.metadata.documentName && { documentName: item.metadata.documentName }),
175180
...(item.metadata.updatedAt && { updatedAt: item.metadata.updatedAt }),
176181
},

0 commit comments

Comments
 (0)