import { CalendarDaysIcon, HomeIcon, ListIcon, MessageSquareTextIcon, PhoneIcon, PresentationIcon, Rows3Icon, StarIcon, } from "lucide-react"; import { RefObject, useEffect, useMemo, useState } from "react"; import { getLocalizedValue } from "@formbricks/lib/i18n/utils"; import { replaceRecallInfoWithUnderline } from "@formbricks/lib/utils/recall"; import { TSurvey, TSurveyQuestion } from "@formbricks/types/surveys"; const questionIconMapping = { openText: MessageSquareTextIcon, multipleChoiceSingle: Rows3Icon, multipleChoiceMulti: ListIcon, rating: StarIcon, nps: PresentationIcon, date: CalendarDaysIcon, cal: PhoneIcon, address: HomeIcon, }; interface RecallQuestionSelectProps { localSurvey: TSurvey; questionId: string; addRecallQuestion: (question: TSurveyQuestion) => void; setShowQuestionSelect: (show: boolean) => void; showQuestionSelect: boolean; inputRef: RefObject; recallQuestions: TSurveyQuestion[]; selectedLanguageCode: string; } export default function RecallQuestionSelect({ localSurvey, questionId, addRecallQuestion, setShowQuestionSelect, showQuestionSelect, inputRef, recallQuestions, selectedLanguageCode, }: RecallQuestionSelectProps) { const [focusedQuestionIdx, setFocusedQuestionIdx] = useState(0); // New state for managing focus const isNotAllowedQuestionType = (question: TSurveyQuestion) => { return ( question.type === "fileUpload" || question.type === "cta" || question.type === "consent" || question.type === "pictureSelection" || question.type === "cal" || question.type === "matrix" ); }; const recallQuestionIds = useMemo(() => { return recallQuestions.map((recallQuestion) => recallQuestion.id); }, [recallQuestions]); // function to remove some specific type of questions (fileUpload, imageSelect etc) from the list of questions to recall from and few other checks const filteredRecallQuestions = useMemo(() => { const idx = questionId === "end" ? localSurvey.questions.length : localSurvey.questions.findIndex((recallQuestion) => recallQuestion.id === questionId); const filteredQuestions = localSurvey.questions.filter((question, index) => { const notAllowed = isNotAllowedQuestionType(question); return ( !recallQuestionIds.includes(question.id) && !notAllowed && question.id !== questionId && idx > index ); }); return filteredQuestions; }, [localSurvey.questions, questionId, recallQuestionIds]); // function to modify headline (recallInfo to corresponding headline) const getRecallHeadline = (question: TSurveyQuestion): TSurveyQuestion => { let questionTemp = structuredClone(question); questionTemp = replaceRecallInfoWithUnderline(questionTemp, selectedLanguageCode); return questionTemp; }; // function to handle key press useEffect(() => { const handleKeyPress = (event: KeyboardEvent) => { if (showQuestionSelect) { if (event.key === "ArrowDown") { event.preventDefault(); setFocusedQuestionIdx((prevIdx) => (prevIdx + 1) % filteredRecallQuestions.length); } else if (event.key === "ArrowUp") { event.preventDefault(); setFocusedQuestionIdx((prevIdx) => prevIdx === 0 ? filteredRecallQuestions.length - 1 : prevIdx - 1 ); } else if (event.key === "Enter") { event.preventDefault(); event.stopPropagation(); const selectedQuestion = filteredRecallQuestions[focusedQuestionIdx]; setShowQuestionSelect(false); if (!selectedQuestion) return; addRecallQuestion(selectedQuestion); } } }; const inputElement = inputRef.current; inputElement?.addEventListener("keydown", handleKeyPress); return () => { inputElement?.removeEventListener("keydown", handleKeyPress); }; }, [showQuestionSelect, localSurvey.questions, focusedQuestionIdx]); return (
{filteredRecallQuestions.length === 0 ? (

There is no information to recall yet 🤷

) : (

Recall Information from...

)}
{filteredRecallQuestions.map((q, idx) => { const isFocused = idx === focusedQuestionIdx; const IconComponent = questionIconMapping[q.type as keyof typeof questionIconMapping]; return (
{ addRecallQuestion(q); setShowQuestionSelect(false); }}>
{IconComponent && }
{getLocalizedValue(getRecallHeadline(q).headline, selectedLanguageCode)}
); })}
); }