Skip to content
Merged
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
Original file line number Diff line number Diff line change
Expand Up @@ -27,25 +27,27 @@ interface UseQuestionnaireActionsProps {
setQuestionStatuses: React.Dispatch<
React.SetStateAction<Map<number, 'pending' | 'processing' | 'completed'>>
>;
uploadFileAction: {
execute: (payload: any) => void;
status: 'idle' | 'executing' | 'hasSucceeded' | 'hasErrored' | 'transitioning' | 'hasNavigated';
};
parseAction: {
execute: (payload: any) => void;
status: 'idle' | 'executing' | 'hasSucceeded' | 'hasErrored' | 'transitioning' | 'hasNavigated';
};
triggerAutoAnswer: (payload: {
vendorId: string;
organizationId: string;
questionsAndAnswers: QuestionAnswer[];
}) => void;
triggerSingleAnswer: (payload: {
question: string;
organizationId: string;
questionIndex: number;
totalQuestions: number;
}) => void;
setParseTaskId: (id: string | null) => void;
setParseToken: (token: string | null) => void;
uploadFileAction: {
execute: (payload: any) => void;
status: 'idle' | 'executing' | 'hasSucceeded' | 'hasErrored' | 'transitioning' | 'hasNavigated';
};
parseAction: {
execute: (payload: any) => void;
status: 'idle' | 'executing' | 'hasSucceeded' | 'hasErrored' | 'transitioning' | 'hasNavigated';
};
triggerAutoAnswer: (payload: {
vendorId: string;
organizationId: string;
questionsAndAnswers: QuestionAnswer[];
}) => void;
triggerSingleAnswer: (payload: {
question: string;
organizationId: string;
questionIndex: number;
totalQuestions: number;
}) => void;
}

export function useQuestionnaireActions({
Expand All @@ -66,11 +68,13 @@ export function useQuestionnaireActions({
answeringQuestionIndex,
setAnsweringQuestionIndex,
setQuestionStatuses,
uploadFileAction,
parseAction,
triggerAutoAnswer,
triggerSingleAnswer,
}: UseQuestionnaireActionsProps) {
setParseTaskId,
setParseToken,
uploadFileAction,
parseAction,
triggerAutoAnswer,
triggerSingleAnswer,
}: UseQuestionnaireActionsProps) {
const exportAction = useAction(exportQuestionnaire, {
onSuccess: ({ data }: { data: any }) => {
const responseData = data?.data || data;
Expand Down Expand Up @@ -106,6 +110,9 @@ export function useQuestionnaireActions({
}, [setSelectedFile]);

const handleParse = async () => {
// Clear old parse state before starting new parse to prevent token mismatch
setParseTaskId(null);
setParseToken(null);
setIsParseProcessStarted(true);

if (selectedFile) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
'use client';

import { useRealtimeRun } from '@trigger.dev/react-hooks';
import type { parseQuestionnaireTask } from '@/jobs/tasks/vendors/parse-questionnaire';
import { useRealtimeRun } from '@trigger.dev/react-hooks';
import { useAction } from 'next-safe-action/hooks';
import { useEffect } from 'react';
import { toast } from 'sonner';
Expand Down Expand Up @@ -96,7 +96,9 @@ export function useQuestionnaireParse({
setExtractedContent(extractedContent || null);
setQuestionStatuses(new Map());
setHasClickedAutoAnswer(false);
toast.success(`Successfully parsed ${questionsAndAnswers.length} question-answer pairs`);
toast.success(
`Successfully parsed ${questionsAndAnswers.length} question-answer pairs`,
);
} else {
toast.error('Parsed data is missing questions');
}
Expand Down Expand Up @@ -137,6 +139,8 @@ export function useQuestionnaireParse({
return;
}

// Clear old token before setting new task ID to prevent using wrong token with new run
setParseToken(null);
setParseTaskId(taskId);

const tokenResult = await createRunReadToken(taskId);
Expand Down Expand Up @@ -185,4 +189,3 @@ export function useQuestionnaireParse({
uploadFileAction,
};
}

Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use client';

import { useMemo, useState, useEffect, useRef } from 'react';
import { useEffect, useMemo, useRef, useState } from 'react';
import { useQuestionnaireActions } from './useQuestionnaireActions';
import { useQuestionnaireAutoAnswer } from './useQuestionnaireAutoAnswer';
import { useQuestionnaireParse } from './useQuestionnaireParse';
Expand Down Expand Up @@ -65,11 +65,13 @@ export function useQuestionnaireParser() {
answeringQuestionIndex: state.answeringQuestionIndex,
setAnsweringQuestionIndex: state.setAnsweringQuestionIndex,
setQuestionStatuses: state.setQuestionStatuses,
uploadFileAction: parse.uploadFileAction,
parseAction: parse.parseAction,
triggerAutoAnswer: autoAnswer.triggerAutoAnswer,
triggerSingleAnswer: singleAnswer.triggerSingleAnswer,
});
setParseTaskId: state.setParseTaskId,
setParseToken: state.setParseToken,
uploadFileAction: parse.uploadFileAction,
parseAction: parse.parseAction,
triggerAutoAnswer: autoAnswer.triggerAutoAnswer,
triggerSingleAnswer: singleAnswer.triggerSingleAnswer,
});

const isLoading = useMemo(() => {
const isUploading = parse.uploadFileAction.status === 'executing';
Expand Down Expand Up @@ -167,7 +169,9 @@ export function useQuestionnaireParser() {
]);

// Throttled status for smooth transitions
const [parseStatus, setParseStatus] = useState<'uploading' | 'starting' | 'queued' | 'analyzing' | 'processing' | null>(null);
const [parseStatus, setParseStatus] = useState<
'uploading' | 'starting' | 'queued' | 'analyzing' | 'processing' | null
>(null);
const statusTimeoutRef = useRef<NodeJS.Timeout | null>(null);
const lastStatusRef = useRef<string | null>(null);
const statusStartTimeRef = useRef<number | null>(null);
Expand Down Expand Up @@ -207,12 +211,17 @@ export function useQuestionnaireParser() {
statusStartTimeRef.current = Date.now();
} else {
// Check if current status has been visible for minimum duration
const isEarlyStage = lastStatusRef.current === 'uploading' || lastStatusRef.current === 'starting' || lastStatusRef.current === 'queued';
const isEarlyStage =
lastStatusRef.current === 'uploading' ||
lastStatusRef.current === 'starting' ||
lastStatusRef.current === 'queued';
const minDisplayTime = isEarlyStage ? 3000 : 1500; // 3s minimum for early stages, 1.5s for later

const timeSinceStatusStart = statusStartTimeRef.current ? Date.now() - statusStartTimeRef.current : 0;

const timeSinceStatusStart = statusStartTimeRef.current
? Date.now() - statusStartTimeRef.current
: 0;
const remainingTime = Math.max(0, minDisplayTime - timeSinceStatusStart);

statusTimeoutRef.current = setTimeout(() => {
setParseStatus(rawParseStatus);
lastStatusRef.current = rawParseStatus;
Expand Down
Loading