/**
* @typedef {Object} QuizVM
* @property {Boolean} showCategoryScore Returns `true` if category score should be shown
* @property {Boolean} hideResultQuizTime Returns `true` if result quiz time should be hidden
* @property {Boolean} hideResultPoints Returns `true` if result points should be hidden
* @property {Boolean} showAverageResult Returns `true` if average result should be shown
* @property {Boolean} toplistActivated Returns `true` if top list is activated
* @property {Boolean} hideResultCorrectQuestion Returns `true` if result correct question should be hidden
* @property {Boolean} btnRestartQuizHidden Returns `true` if restart quiz button should be hidden
* @property {Object} toplistData Contains top list data used for showing quiz leader board
* @property {Boolean} resultGradeEnabled Returns `true` if result grade is enabled
* @property {Object} resultText Contains result message which can also be displayed in Quiz Details screen
*/
/**
* @typedef {Object} CircleProgressResultProps
* @property {Number} progress Percentage of the score
* @property {String} progressColor Filled color according to progress
* @property {Number} width Line width of circle
* @property {Number} size Size of circle
* @property {String} unfilledColor Default color used for the unfilled portion of the circle
* @property {React.ComponentType} children Component that contains the content of the circle
*/
/**
* @typedef {Object} ArcContentProps
* @property {Object} config App configuration object
* @property {TranslationFunction} t
* @property {Object} result Quiz result details
* @property {QuizVM} quizVM
* @property {Number} size Size of circle
* @property {Number} progress Percentage of the score
* @property {String} arcColor Default color depending on the value of the average score
*/
/**
* @typedef {Object} ResultCorrectCountProps
* @property {QuizVM} quizVM
* @property {Object} global App global style
* @property {Object} labels Learndash labels
* @property {Number} correctAnswers Total count of correct answers
* @property {Object} result Quiz result details
*/
/**
* @typedef {Object} AverageResultProps
* @property {QuizVM} quizVM
* @property {Object} global App global style
* @property {Object} styles
* @property {String} progressColor
* @property {TranslationFunction} t
* @property {Object} result Quiz result details
*/
/**
* @typedef {Object} ResultQuizTimeProps
* @property {QuizVM} quizVM
* @property {Object} global App global style
* @property {Object} colors App colors
* @property {TranslationFunction} t
* @property {Object} result Quiz result details
*/
/**
* @typedef {Object} RestartQuizButtonProps
* @property {QuizVM} quizVM
* @property {Object} global App global style
* @property {Object} colors App colors
* @property {Object} styles
* @property {Function} onAgainClick Allows users to take the quiz again
*/
/**
* @typedef {Object} ViewDetailsQuizButtonProps
* @property {Object} global App global style
* @property {Object} colors App colors
* @property {Object} styles
* @property {Function} onDetailsClick Allows users to redirect to Quiz Details screen
*/
/**
* @typedef {Object} ViewCertificateButtonProps
* @property {Object} result Quiz result details
* @property {Object} styles
* @property {TranslationFunction} t
* @property {Function} setIsDownloadingState Sets the `downloading` state to `true`
* @property {Function} setIsNotDownloadingState Sets the `downloading` state to `false`
* @property {Boolean} downloading Returns `true` if certificate is currently downloading
*/
/**
* @typedef {Object} QuizCompleteButtonProps
* @property {Boolean} showContinue Returns `true` if the continue button should be shown
* @property {Object} global App global style
* @property {Object} colors App colors
* @property {Function} onCompleteButtonClick Function to execute when the continue button is pressed
* @property {TranslationFunction} t
*/
/**
* @class
* Quiz Result Screen Hooks.
* Instance name: quizResultApi
You can use these hooks to customize the quiz result information for your app such as customizing the average score display, buttons in the screen, and the result time.
* @example
* externalCodeSetup.quizResultApi.METHOD_NAME
*/
export class QuizResultApi {
CircleProgressResult = null;
/**
* You can use this hook to customize the CircleProgressResult component.
* For example, you can change its color, animation, thickness, etc.
* @method
* @param {React.ComponentType<CircleProgressResultProps>} CircleProgressResult
* @example
*
* //In custom_code/components/CircleProgressResult.js...
*
* import React from "react";
* import {View} from "react-native";
* import ProgressCircle from "react-native-progress/Circle";
* const CircleProgressResult = ({
* progress,
* progressColor,
* width,
* size,
* unfilledColor,
* children
* }) => (
* <>
* <View>
* <ProgressCircle
* size={size}
* progress={progress / 100}
* thickness={width}
* unfilledColor={unfilledColor}
* animated={true}
* borderWidth={0}
* color={progressColor}
* strokeCap="round"
* />
* </View>
* <View
* style={{
* width: "100%",
* height: "100%",
* position: "absolute",
* top: 0,
* left: 0
* }}
* >
* {children}
* </View>
* </>
* );
* export default CircleProgressResult
*
* //In custom_code/index.js...
*
* ...
*
* import CircleProgressResult from "./components/CircleProgressResult";
*
* export const applyCustomCode = (externalCodeSetup) => {
* externalCodeSetup.quizResultApi.setCircleProgressResult(props => <CircleProgressResult {...props} />)
* }
*
*/
setCircleProgressResult = CircleProgressResult => {
this.CircleProgressResult = CircleProgressResult;
};
ArcContent = null;
/**
* You can use this hook to customize the content inside the CircleProgressResult component.
* For example, you can change the result percentage or replace the CircleProgressResult component for the average score.
* @method
* @param {React.ComponentType<ArcContentProps>} ArcContent
* @example
*
* //In custom_code/components/ArcContent.js...
*
* import React from "react";
* import {View, Text} from "react-native";
* import {globalStyle, FontWeights} from "@src/styles/global";
* import CircleProgressResult from "./CircleProgressResult"; //See sample code from setCircleProgressResult hook
*
* const ArcContent = props => {
* const {config, result, size, quizVM} = props;
* const {global, colors, calcFontSize} = globalStyle(config.styles);
*
* const percent = Math.round((result.result || 0) * 100) / 100;
* return <>
* <View
* style={{
* width: "100%",
* height: "100%",
* position: "absolute",
* top: 0,
* left: 0,
* alignItems: "center",
* justifyContent: "center"
* }}
* >
* <Text>
* <Text
* key="progress"
* style={{
* ...global.text,
* fontSize: calcFontSize(50),
* fontWeight: FontWeights.semiBold,
* color: colors.textColor
* }}
* >
* {Math.floor(percent)}
* </Text>
* <Text
* key="progress"
* style={{
* ...global.text,
* fontSize: calcFontSize(24),
* fontWeight: FontWeights.semiBold,
* color: colors.textColor
* }}
* >
* {(percent % 1).toString().substring(1, 4)}
* </Text>
* <Text
* style={{
* ...global.text,
* fontSize: calcFontSize(24),
* fontWeight: FontWeights.semiBold,
* color: colors.textColor
* }}
* >
* %
* </Text>
* </Text>
* </View>
* <View
* style={{
* opacity: 0.19,
* width: size - 16,
* height: size - 16,
* position: "absolute",
* top: 8,
* left: 8,
* backgroundColor: "transparent"
* }}
* >
* {quizVM.showAverageResult && (
* <View>
* <CircleProgressResult
* unfilledColor="#ffffff"
* size={size - 16}
* width={6}
* progress={result.average_result}
* progressColor={rgb(26, 193, 60)}
* />
* </View>
* )}
* </View>
* </>
* };
*
* export default ArcContent;
*
* //In custom_code/index.js...
*
* ...
*
* import ArcContent from "./components/ArcContent";
* export const applyCustomCode = (externalCodeSetup) => {
* externalCodeSetup.quizResultApi.setArcContent(props => <ArcContent {...props} />)
* }
*
*/
setArcContent = ArcContent => {
this.ArcContent = ArcContent;
};
ResultCorrectCount = null;
/**
* You can use this hook to customize the ResultCorrectCount component indicating how many questions were answered correctly.
* For example, you can add a message depending on the result of the quiz taken.
* @method
* @param {React.ComponentType<ResultCorrectCountProps>} ResultCorrectCount
* @example <caption> Add conditional message based on total score </caption>
*
* //In custom_code/components/ResultCorrectCount.js...
*
* import React from "react";
* import { Text } from "react-native"
*
* const ResultCorrectCount = ({ quizVM, global, labels, correctAnswers, result, t }) => {
*
* const total = Object.keys(result.answers).length
*
* return !quizVM.hideResultCorrectQuestion && (
* <>
* <Text
* style={{
* ...global.regularText,
* marginTop: 26,
* marginBottom: 30,
* width: 209,
* textAlign: "center"
* }}
* >
* {t("quiz:correctCount", {
* questions: labels.questions.toLowerCase(),
* correct: correctAnswers,
* total
* })}
* </Text>
*
* {total == correctAnswers && <Text style={{ fontSize: 25 }}> Perfect Score!!!</Text>}
* </>
* )
* }
*
* export default ResultCorrectCount;
*
* //In custom_code/index.js...
*
* ...
*
* import ResultCorrectCount from "./components/ResultCorrectCount";
* export const applyCustomCode = (externalCodeSetup) => {
* externalCodeSetup.quizResultApi.setResultCorrectCount(props => <ResultCorrectCount {...props} />)
* }
*
*/
setResultCorrectCount = ResultCorrectCount => {
this.ResultCorrectCount = ResultCorrectCount;
};
AverageResult = null;
/**
* You can use this hook to customize the component that displays "Your Score" and "Average Score" details.
* @method
* @param {React.ComponentType<AverageResultProps>} AverageResult
* @example
*
* //In custom_code/components/AverageResult.js...
*
* import React from "react";
* import {View, Text} from "react-native";
* import {FontWeights} from "@src/styles/global";
*
* const AverageResult = ({
* quizVM,
* global,
* styles,
* progressColor,
* t,
* result
* }) => quizVM.showAverageResult && (
* <View
* style={[
* {
* justifyContent: "center",
* marginTop: 20,
* marginBottom: 20,
* width: 168
* }
* ]}
* >
* <View style={[global.row, styles.stats]}>
* <View
* style={{
* width: 8,
* height: 8,
* borderRadius: 4,
* marginRight: 6,
* backgroundColor: progressColor
* }}
* />
* <Text
* style={[global.widgetItemDesc, {marginTop: 0, flex: 1}]}
* >
* {t("quiz:yourScore")}
* </Text>
* <Text
* style={[
* global.regularText,
* {fontWeight: FontWeights.bold}
* ]}
* >
* {Math.round(result.result * 10) / 10}%
* </Text>
* </View>
*
* <View style={[global.row, styles.stats]}>
* <View
* style={{
* opacity: 0.19,
* width: 8,
* height: 8,
* borderRadius: 4,
* marginRight: 6,
* backgroundColor: rgb(26, 193, 60)
* }}
* />
* <Text
* style={[global.widgetItemDesc, {marginTop: 0, flex: 1}]}
* >
* {t("quiz:averageScore")}
* </Text>
* <Text
* style={[
* global.regularText,
* {fontWeight: FontWeights.bold}
* ]}
* >
* {Math.round(result.average_result * 10) / 10}%
* </Text>
* </View>
* </View>
* )
* export default AverageResult;
*
* //In custom_code/index.js...
*
* ...
*
* import AverageResult from "./components/AverageResult"
* export const applyCustomCode = (externalCodeSetup) => {
* externalCodeSetup.quizResultApi.setAverageResult(props => <AverageResult {...props} />)
* }
*/
setAverageResult = AverageResult => {
this.AverageResult = AverageResult;
};
ResultQuizTime = null;
/**
* You can use this hook to customize the displayed time indicating how long the user completed the quiz.
* For example, you can modify the time format.
* @method
* @param {React.ComponentType<ResultQuizTimeProps>} ResultQuizTime
* @example <caption> Change time format </caption>
*
* //In custom_code/components/ResultQuizTime.js...
*
* import React from "react";
* import {View,Text} from "react-native";
* import moment from "moment";
*
* import {FontWeights} from "@src/styles/global";
*
* const formatDateFunction = seconds => {
* return moment.duration(seconds, "seconds").format("hh.mm.ss", {trim: false});
* };
*
* const ResultQuizTime = ({
* quizVM,
* global,
* colors,
* t,
* result
* }) => !quizVM.hideResultQuizTime && (
* <View
* style={{
* width: "100%",
* borderTopWidth: 1,
* borderTopColor: "rgb(231, 233, 236)",
* paddingTop: 40,
* paddingBottom: 7,
* alignItems: "center"
* }}
* >
* <Text
* style={[
* global.quizCheckTitle,
* {
* fontWeight: FontWeights.regular,
* color: colors.descTextColor,
* marginBottom: 8
* }
* ]}
* >
* {t("quiz:yourTime")}
* </Text>
* <Text
* style={[
* global.resultsSubTitle,
* {
* color: colors.textColor,
* fontWeight: FontWeights.semiBold,
* marginBottom: 10
* }
* ]}
* >
* {formatDateFunction(result.time)}
* </Text>
* </View>
* )
*
* export default ResultQuizTime;
*
* //In custom_code/index.js...
*
* ...
*
* import ResultQuizTime from "./components/ResultQuizTime";
* export const applyCustomCode = (externalCodeSetup) => {
* externalCodeSetup.quizResultApi.setResultQuizTime(props => <ResultQuizTime {...props} />)
* }
*/
setResultQuizTime = ResultQuizTime => {
this.ResultQuizTime = ResultQuizTime;
};
RestartQuizButton = null;
/**
* You can use this hook to customize the RestartQuizButton component which allows the users to take the quiz again.
* @method
* @param {React.ComponentType<RestartQuizButtonProps>} RestartQuizButton
* @example <caption> Add a confirmation if user would like to take the test again </caption>
*
* //In custom_code/components/RestartQuizButton.js...
*
* import React from "react";
* import { Alert } from "react-native";
* import AppButton from "@src/components/AppButton";
*
* const RestartQuizButton = ({
* quizVM,
* styles,
* global,
* colors,
* onAgainClick,
* t
* }) => {
*
* const onTakeAgain = () => {
* Alert.alert(
* "Please confirm",
* "Would you like to take the quiz again?",
* [
* {
* text: "Cancel",
* style: "cancel",
* },
* {
* text: "Ok",
* onPress: onAgainClick,
* },
* ],
* );
* }
*
* return !quizVM.btnRestartQuizHidden && (
* <AppButton
* key={"button"}
* style={[
* styles.button,
* {
* backgroundColor: colors.primaryButtonBg,
* width: "100%"
* }
* ]}
* onPress={() => {
* onTakeAgain();
* }}
* labelStyle={{
* ...global.quizTakeAgainButtonLabel,
* color: colors.primaryButtonColor
* }}
* label={t("quiz:takeAgain")}
* global={global}
* loading={false}
* />)
* }
*
* export default RestartQuizButton;
*
* //In custom_code/index.js...
*
* ...
*
* import RestartQuizButton from "./components/RestartQuizButton";
*
* export const applyCustomCode = (externalCodeSetup) => {
* externalCodeSetup.quizResultApi.setRestartQuizButton(props => <RestartQuizButton {...props} />)
* }
*/
setRestartQuizButton = RestartQuizButton => {
this.RestartQuizButton = RestartQuizButton;
};
ViewDetailsQuizButton = null;
/**
* You can use this hook to customize the ViewDetailsQuizButton component which allows the users to view the Quiz Details.
* @method
* @param {React.ComponentType<ViewDetailsQuizButtonProps>} ViewDetailsQuizButton
* @example
*
* ...
*
* import AppButton from "@src/components/AppButton";
*
* export const applyCustomCode = (externalCodeSetup) => {
* externalCodeSetup.quizResultApi.setViewDetailsQuizButton(({
* global,
* colors,
* styles,
* t,
* onDetailsClick
* }) => (
* <AppButton
* key={"button"}
* style={[
* styles.button,
* {
* backgroundColor: colors.secondaryButtonBg,
* width: "100%"
* }
* ]}
* onPress={onDetailsClick}
* labelStyle={{
* ...global.quizTakeAgainButtonLabel,
* color: colors.secondaryButtonColor
* }}
* label={t("quiz:viewDetails")}
* global={global}
* loading={false}
* />
* ))
* }
*
*/
setViewDetailsQuizButton = ViewDetailsQuizButton => {
this.ViewDetailsQuizButton = ViewDetailsQuizButton;
};
ViewCertificateButton = null;
/**
* You can use this hook to customize the ViewCertificateButton component that allows the users to view their certificate for the quiz.
* @method
* @param {React.ComponentType<ViewCertificateButtonProps>} ViewCertificateButton
* @example
*
* ...
*
* import CourseActionButton from "@src/components/Course/CourseActionButton";
* import {previewDocument} from "@src/utils/previewFiles";
* export const applyCustomCode = (externalCodeSetup) => {
*
* const ViewCertificateButton = ({
* result,
* styles,
* t,
* setIsDownloadingState,
* setIsNotDownloadingState,
* downloading
* }) => result.certificate &&
* result.certificate.link && (
* <CourseActionButton
* title={t("quiz:viewCertificate")}
* style={styles.viewButton}
* labelStyle={styles.labelStyle}
* onPress={() => {
* previewDocument({
* url: result.certificate.link,
* localName: result.certificate.filename,
* token,
* t,
* beginCallback: () => {
* setIsDownloadingState();
* },
* progressCallback: progress => {},
* doneCallback: () => {
* setIsNotDownloadingState();
* },
* failCallback: () => {
* setIsNotDownloadingState();
* }
* });
* }}
* loading={downloading}
* />
* )
*
* externalCodeSetup.quizResultApi.setViewCertificateButton(props => <ViewCertificateButton {...props} />)
*
*/
setViewCertificateButton = ViewCertificateButton => {
this.ViewCertificateButton = ViewCertificateButton;
};
QuizCompleteButton = null;
/**
* You can use this hook to customize the QuizCompleteButton component or the Continue button that sends the users to the next lesson or topic.
* @method
* @param {React.ComponentType<QuizCompleteButtonProps>} QuizCompleteButton
* @example
*
* //In custom_code/components/QuizCompleteButton.js...
*
* import React from "react";
* import {View, Text} from "react-native";
* import AppTouchableOpacity from "@src/components/AppTouchableOpacity";
* import AuthWrapper from "@src/components/AuthWrapper";
* import {isColorDark} from "@src/utils/index";
*
* const QuizCompleteButton = ({
* showContinue,
* global,
* colors,
* onCompleteButtonClick,
* t
* }) => (
* <AuthWrapper actionOnGuestLogin={"hide"}>
* {showContinue && (
* <View
* style={[
* global.row,
* {
* backgroundColor: colors.bodyFrontBg,
* borderTopColor: colors.borderColor
* },
* global.quizResultButtonContainer
* ]}
* >
* <AppTouchableOpacity
* style={[
* {flex: 1},
* {
* opacity: 1,
* backgroundColor: colors.primaryButtonBg
* },
* global.quizResultButton
* ]}
* onPress={onCompleteButtonClick}
* >
* <View style={global.row}>
* <View style={global.linkWithArrow}>
* <Text
* style={[
* {
* marginLeft: 10,
* color: !isColorDark(colors.bodyFrontBg) ? "white" : "black"
* },
* global.quizResultButtonLabel
* ]}
* >
* {t("lesson:continueLessonOnQuizComplete")}
* </Text>
* </View>
* </View>
* </AppTouchableOpacity>
* </View>
* )}
* </AuthWrapper>
* );
*
* export default QuizCompleteButton;
*
* //In custom_code/index.js...
*
* ...
*
* import QuizCompleteButton from "./components/QuizCompleteButton";
*
* export const applyCustomCode = (externalCodeSetup) => {
* externalCodeSetup.quizResultApi.setQuizCompleteButton(props => <QuizCompleteButton {...props} />)
* }
*
*/
setQuizCompleteButton = QuizCompleteButton => {
this.QuizCompleteButton = QuizCompleteButton;
};
}
Source