@@ -1,53 +1,167 @@
import { LoadingLis t} from "../components/LoadingList.tsx " ;
import { Survey } from "../types/survey.ts ";
import { Link , useParams } from "react-router-dom" ;
import React from "react" ;
import { useData , useDataPage } from "../API/common.ts" ;
import { LoadingData } from "../components/LoadingData.tsx" ;
import React , { useState , useEffec t } from "react " ;
import { Navigate , useNavigate , useParams } from "react-router-dom " ;
import {
Survey ,
Question ,
QuestionPair ,
AgreementQuestion ,
QuestionType ,
ScoreVariable ,
} from "../types/survey" ;
import { useData , useDataPage } from "../API/common" ;
import { LoadingData } from "../components/LoadingData" ;
import { LoadingList } from "../components/LoadingList" ;
export function SurveyPage() {
const { surveyId } = useParams < { surveyId : string } > ( ) ;
const navigate = useNavigate ( ) ;
const { surveyId } = useParams ( ) ;
// Загрузка теста
const survey = useData < Survey > ( "surveys" , "surveys" , surveyId || 0 ) ;
const survey = useData < Survey > ( "surveys" , "surveys" , surveyId ) ;
// Загрузка вопросов
const [ questions , setQuestions ] = useState < Question [ ] | null > ( null ) ;
const questionsPairs = useDataPage < QuestionPair > ( "surveys" , "question-pairs" , { survey : surveyId || 0 } ) ;
const questionsAgreement = useDataPage < AgreementQuestion > ( "surveys" , "agreement-questions" , { survey : surveyId || 0 } ) ;
// Загрузка score variables
const scoreVariables = useDataPage < ScoreVariable > ( "surveys" , "score-variables" ) ;
// Состояние для ответов
const [ answers , setAnswers ] = useState < Record < string , number > > ( { } ) ;
const [ isCompleted , setIsCompleted ] = useState ( false ) ;
// Объединение вопросов после загрузки
useEffect ( ( ) = > {
if (
questions === null &&
questionsPairs . items !== null &&
questionsAgreement . items !== null
) {
const mergedQuestions = [
. . . questionsPairs . items . map ( ( q :Question ) = > ( { . . . q , questionType : QuestionType.QuestionPair } ) ) ,
. . . questionsAgreement . items . map ( ( q :Question ) = > ( { . . . q , questionType : QuestionType.AgreementQuestion } ) ) ,
] ;
mergedQuestions . sort ( ( ) = > Math . random ( ) - 0.5 ) ; // Перемешивание
setQuestions ( mergedQuestions ) ;
}
} , [ questions , questionsPairs . items , questionsAgreement . items ] ) ;
// Проверка завершения теста
useEffect ( ( ) = > {
if ( questions && Object . keys ( answers ) . length === questions . length ) {
setIsCompleted ( true ) ;
} else {
setIsCompleted ( false ) ;
}
} , [ questions , answers ] ) ;
// Обработка ответов
const handleAnswer = ( questionKey : string , answerValue : number ) = > {
setAnswers ( ( prev ) = > ( { . . . prev , [ questionKey ] : answerValue } ) ) ;
} ;
// Вычисление итогового score_variable
const calculateResults = ( ) = > {
if ( ! questions || ! scoreVariables . items ) return ;
const scoreCounts : Record < string , number > = { } ;
questions . forEach ( ( question ) = > {
const questionKey = ` ${ question . questionType } _ ${ question . id } ` ;
const answer = answers [ questionKey ] ;
if ( answer !== undefined ) {
if ( question . questionType === QuestionType . QuestionPair ) {
const selectedStatement = ( question as QuestionPair ) . statements . find (
( s ) = > s . id === answer
) ;
if ( selectedStatement ) {
scoreCounts [ selectedStatement . score_variable ] =
( scoreCounts [ selectedStatement . score_variable ] || 0 ) + 1 ;
}
} else if ( question . questionType === QuestionType . AgreementQuestion ) {
const scoreVariable = ( question as AgreementQuestion ) . score_variable ;
scoreCounts [ scoreVariable ] = ( scoreCounts [ scoreVariable ] || 0 ) + answer ;
}
}
} ) ;
const maxScoreVariable = Object . keys ( scoreCounts ) . reduce ( ( a , b ) = >
scoreCounts [ a ] > scoreCounts [ b ] ? a : b
) ;
navigate ( ` /surveys/results/ ${ maxScoreVariable } ` ) ;
} ;
return (
< div className = "survey-page" >
< LoadingData data = { survey } >
< h1 >
{ survey ? . title }
< / h1 >
< div >
{ survey ? . description }
< / div >
< h1 > { survey ? . title } < / h1 >
< div > { survey ? . description } < / div >
< SurveyQuestions survey = { survey } / >
< LoadingList data = { questions } listElement = { ( question : Question ) = > (
< QuestionBlock
key = { ` ${ question . questionType } _ ${ question . id } ` } // Используем тип вопроса и id для уникальности
question = { question }
onAnswer = { handleAnswer }
answered = { answers [ ` ${ question . questionType } _ ${ question . id } ` ] } // Учитываем тип вопроса в ключе
/ >
) } / >
{ isCompleted && (
< button onClick = { calculateResults } > З а в е р ш и т ь т е с т < / button >
) }
< / LoadingData >
< / div >
) ;
}
function SurveyQ uestions ( { survey } : { survey : Survey | null | undefined } ) {
const _survey = survey as Survey ;
const questionsPairs = useDataPage ( "surveys" , "question-pairs" , { survey :_survey.id } ) ;
const questionsAgreement = useDataPage ( "surveys" , "question-pairs" , { survey :_survey.id } ) ;
//const questions =
function QuestionBlock ( {
q uestion ,
onAnswer ,
answered ,
} : {
question : Question ;
onAnswer : ( questionId : string , answerValue : number ) = > void ;
answered? : number ;
} ) {
switch ( question . questionType ) {
case QuestionType.AgreementQuestion :
const agreementQuestion = question as AgreementQuestion ;
return (
< >
< div className = { ` question agreement ${ answered !== undefined ? "answered" : "unanswered" } ` } >
{ agreementQuestion . question }
< button
className = { answered === 1 ? "selected" : "" }
disabled = { answered === 1 }
onClick = { ( ) = > onAnswer ( ` ${ question . questionType } _ ${ question . id } ` , 1 ) } > С о г л а с е н < / button >
< button
className = { answered === 0 ? "selected" : "" }
disabled = { answered === 0 }
onClick = { ( ) = > onAnswer ( ` ${ question . questionType } _ ${ question . id } ` , 0 ) } > Н е с о г л а с е н < / button >
< / >
< / div >
) ;
case QuestionType.QuestionPair :
const pairQuestion = question as QuestionPair ;
return (
< div className = { ` question pair ${ answered !== undefined ? "answered" : "unanswered" } ` } >
{ pairQuestion . statements . map ( ( statement ) = > (
< button
className = { answered === statement . id ? "selected" : "" }
disabled = { answered === statement . id }
key = { statement . id }
onClick = { ( ) = > onAnswer ( ` ${ question . questionType } _ ${ question . id } ` , statement . id ) }
>
{ statement . text }
< / button >
) ) }
< / div >
) ;
default :
return null ;
}
}