149 lines
3.8 KiB
TypeScript
149 lines
3.8 KiB
TypeScript
import { QuestionVariant } from "@/api/types";
|
|
import { FontAwesome5 } from "@expo/vector-icons";
|
|
import { useMemo } from "react";
|
|
import { Pressable, StyleSheet, View } from "react-native";
|
|
import Panel from "./panel";
|
|
import { Skeleton } from "./skeleton";
|
|
import { ThemedText } from "./themed-text";
|
|
|
|
interface AnswerProps {
|
|
answer?: QuestionVariant;
|
|
isTextType?: boolean;
|
|
|
|
userAnswers?: string[] | number[];
|
|
correctAnswers?: string[] | number[];
|
|
|
|
isCorrectUserAnswer?: boolean;
|
|
|
|
displayCorrect?: boolean;
|
|
displayUserAnswer?: boolean;
|
|
|
|
onPress?: () => void;
|
|
}
|
|
type UserAnsweredType = "correct"|"incorrect"|"non_answered";
|
|
|
|
const Answer = ({
|
|
answer,
|
|
onPress,
|
|
userAnswers,
|
|
correctAnswers,
|
|
|
|
isTextType = false,
|
|
isCorrectUserAnswer = false,
|
|
displayCorrect = false,
|
|
displayUserAnswer = false
|
|
}: AnswerProps) => {
|
|
// Check if user answered on this answer variation
|
|
const isAnsweredByUser = useMemo(() => {
|
|
if(!userAnswers || !answer) return false;
|
|
|
|
if(isTextType) {
|
|
return (userAnswers[0] as string).length > 0;
|
|
}
|
|
return (userAnswers as number[]).includes(answer.id);
|
|
}, [userAnswers, answer, isTextType]);
|
|
|
|
// Check if this answer variation is correct
|
|
const isCorrectAnswer = useMemo(() => {
|
|
if(!correctAnswers || !answer) return false;
|
|
|
|
if(isTextType) {
|
|
return true;
|
|
}
|
|
|
|
return (correctAnswers as number[]).includes(answer.id);
|
|
}, [correctAnswers, isTextType, answer]);
|
|
|
|
// Check if user answered correct on this answer variation
|
|
const userAnsweredCorrectly = useMemo<UserAnsweredType>(() => {
|
|
if(isTextType) return isCorrectUserAnswer ? "correct" : "incorrect";
|
|
|
|
if(!isAnsweredByUser && isCorrectAnswer)
|
|
return "non_answered";
|
|
|
|
return isCorrectUserAnswer ? "correct" : "incorrect";
|
|
}, [isTextType, isAnsweredByUser, isCorrectAnswer, isCorrectUserAnswer]);
|
|
|
|
const stylePanel = useMemo(() => {
|
|
let style = undefined;
|
|
|
|
if(displayCorrect && isCorrectAnswer && !isTextType)
|
|
style = styles.correctAnswer;
|
|
|
|
if(displayUserAnswer && isAnsweredByUser && !isTextType)
|
|
style = styles.userAnsweredAnswer;
|
|
|
|
if(displayUserAnswer && displayCorrect) {
|
|
switch (userAnsweredCorrectly) {
|
|
case 'correct':
|
|
if(isAnsweredByUser)
|
|
style = styles.correctAnswer;
|
|
break;
|
|
case 'incorrect':
|
|
style = styles.incorrectAnswer;
|
|
break;
|
|
case 'non_answered':
|
|
style = styles.nonAnsweredAnswer;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return style;
|
|
}, [displayCorrect, displayUserAnswer, isAnsweredByUser, isCorrectAnswer, isTextType, userAnsweredCorrectly]);
|
|
const textColor = useMemo(() => {
|
|
if(stylePanel)
|
|
return "#ffffff";
|
|
else
|
|
return undefined;
|
|
}, [stylePanel]);
|
|
|
|
if (!answer) return <Skeleton className="w-full h-16" />;
|
|
|
|
return (
|
|
<Pressable onPress={onPress}>
|
|
<Panel style={stylePanel} className="flex-row">
|
|
<View style={styles.answerNumberation}>
|
|
{isTextType ? (
|
|
<FontAwesome5 name="quote-left" />
|
|
) : (
|
|
<ThemedText darkColor="#fff" lightColor="#fff">
|
|
{answer.id}
|
|
</ThemedText>
|
|
)}
|
|
</View>
|
|
<ThemedText lightColor={textColor} darkColor={textColor}>{answer.text}</ThemedText>
|
|
</Panel>
|
|
</Pressable>
|
|
);
|
|
};
|
|
|
|
const styles = StyleSheet.create({
|
|
answerNumberation: {
|
|
width: 25,
|
|
height: 25,
|
|
alignItems: "center",
|
|
justifyContent: "center",
|
|
borderRadius: 5,
|
|
marginRight: 10,
|
|
backgroundColor: "#bdbdbd",
|
|
},
|
|
correctAnswer: {
|
|
backgroundColor: "#2ab300"
|
|
},
|
|
incorrectAnswer: {
|
|
backgroundColor: "#c40404"
|
|
},
|
|
nonAnsweredAnswer: {
|
|
borderWidth: 1,
|
|
borderStyle: "solid",
|
|
borderColor: "#2ab300"
|
|
},
|
|
userAnsweredAnswer: {
|
|
borderWidth: 1,
|
|
borderStyle: "solid",
|
|
borderColor: "#2cb3f2"
|
|
}
|
|
});
|
|
|
|
export default Answer;
|