Skip to content

Commit

Permalink
fix: made test history screen more intuitive
Browse files Browse the repository at this point in the history
  • Loading branch information
EdmelKun committed Dec 4, 2023
1 parent ebd0a2c commit 68be60f
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 66 deletions.
9 changes: 7 additions & 2 deletions apps/expo/src/components/cards/QuestionCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ interface QuestionCardProps {
index: number;
type?: "history" | "create";
goToEditQuestion?: (index: number) => () => void;
goToQuestionHistory?: (questionId: string) => () => void;
goToQuestionHistory?: (
questionId: string,
questionIndex: number,
) => () => void;
}

const QuestionCard: FC<QuestionCardProps> = ({
Expand All @@ -42,7 +45,9 @@ const QuestionCard: FC<QuestionCardProps> = ({
key={index}
onPress={match(type)
.with("create", () => goToEditQuestion?.(index))
.with("history", () => goToQuestionHistory?.((question as Question).id))
.with("history", () =>
goToQuestionHistory?.((question as Question).id, index),
)
.exhaustive()}
>
<View className="flex shrink grow basis-0 items-center justify-start self-stretch rounded-xl border border-zinc-200 bg-white">
Expand Down
133 changes: 81 additions & 52 deletions apps/expo/src/screens/create-question/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,26 @@ export const CreateQuestionScreen: FC = () => {

const question = getSelectedQuestion();
const questionType = question?.type;
const [openAlert, setOpenAlert] = useState(false);
const [isSaved, setIsSaved] = useState<boolean>(false);
const [isTextInputFocused, setIsTextInputFocused] = useState<boolean>(false);
const [errorInAIQuestion, setErrorInAIQuestion] = useState(false);
const [showModal, setShowModal] = useState<boolean>(false);
const [showQuestionModal, setShowQuestionModal] = useState<boolean>(false);
const [showTimeLimitModal, setShowTimeLimitModal] = useState<boolean>(false);
const [showPointModal, setShowPointModal] = useState<boolean>(false);
const [questionTitle, setQuestionTitle] = useState<string>(
question?.title ?? "",
);
const [aiQuestion, setAiQuestion] = useState<string>("");
const [selectedQuestionId, setSelectedQuestionId] = useState<number>(0);
const [choices, setChoices] = useState<Choice[]>([]);
const [isDeleting, setIsDeleting] = useState(false);
const [openDeleteAlert, setOpenDeleteAlert] = useState(false);

const { height, width } = Dimensions.get("window");

const bottomSheetRef = useRef<BottomSheet>(null);

const getSelectedChoices = () => {
if (!question) {
Expand Down Expand Up @@ -166,24 +186,6 @@ export const CreateQuestionScreen: FC = () => {
isSelected: option.value === question?.points,
})),
);
const [openAlert, setOpenAlert] = useState(false);
const [isSaved, setIsSaved] = useState<boolean>(false);
const [isTextInputFocused, setIsTextInputFocused] = useState<boolean>(false);
const [errorInAIQuestion, setErrorInAIQuestion] = useState(false);
const [showModal, setShowModal] = useState<boolean>(false);
const [showQuestionModal, setShowQuestionModal] = useState<boolean>(false);
const [showTimeLimitModal, setShowTimeLimitModal] = useState<boolean>(false);
const [showPointModal, setShowPointModal] = useState<boolean>(false);
const [questionTitle, setQuestionTitle] = useState<string>(
question?.title ?? "",
);
const [aiQuestion, setAiQuestion] = useState<string>("");
const [selectedQuestionId, setSelectedQuestionId] = useState<number>(0);
const [choices, setChoices] = useState<Choice[]>([]);

const { height, width } = Dimensions.get("window");

const bottomSheetRef = useRef<BottomSheet>(null);

const snapPoints = useMemo(() => ["5%", "25%", "70%"], []);

Expand Down Expand Up @@ -571,42 +573,53 @@ export const CreateQuestionScreen: FC = () => {
};

const handleDelete = () => {
deleteQuestion(selectedIndex!);
const index = selectedIndex ? selectedIndex - 1 : 0;
setSelectedIndex(index);
setSelectedQuestionId(index);
setQuestionImage(questions[index]?.image ?? undefined);
const selectedQuestion = questions[index];
setIsDeleting(true);
if (questions.length <= 1) {
errorToast({
title: "Error",
message: "Cannot delete first question item",
});
} else {
deleteQuestion(selectedIndex!);
const index = selectedIndex ? selectedIndex - 1 : 0;
setSelectedIndex(index);
setSelectedQuestionId(index);
setQuestionImage(questions[index]?.image ?? undefined);
const selectedQuestion = questions[index];

if (
selectedQuestion?.type === "multiple_choice" ||
selectedQuestion?.type === "true_or_false" ||
selectedQuestion?.type === "multi_select" ||
selectedQuestion?.type === "identification"
) {
setQuestionTitle(selectedQuestion.title);
setChoices(
selectedQuestion.choices.map((choice, idx) => ({
id: idx,
text: choice.text ?? "",
isCorrect: choice.isCorrect,
styles: choiceStyles[idx]!.styles,
})),
);
if (
selectedQuestion?.type === "multiple_choice" ||
selectedQuestion?.type === "true_or_false" ||
selectedQuestion?.type === "multi_select" ||
selectedQuestion?.type === "identification"
) {
setQuestionTitle(selectedQuestion.title);
setChoices(
selectedQuestion.choices.map((choice, idx) => ({
id: idx,
text: choice.text ?? "",
isCorrect: choice.isCorrect,
styles: choiceStyles[idx]!.styles,
})),
);

setTimeLimitOptions((prev) =>
prev.map((option) => ({
...option,
isSelected: option.value === selectedQuestion.time,
})),
);
setPointOptions((prev) =>
prev.map((option) => ({
...option,
isSelected: option.value === selectedQuestion.points,
})),
);
setTimeLimitOptions((prev) =>
prev.map((option) => ({
...option,
isSelected: option.value === selectedQuestion.time,
})),
);
setPointOptions((prev) =>
prev.map((option) => ({
...option,
isSelected: option.value === selectedQuestion.points,
})),
);
}
}

setIsDeleting(false);
setOpenDeleteAlert(false);
};

const handleGenerateQuestion = () => {
Expand Down Expand Up @@ -652,7 +665,12 @@ export const CreateQuestionScreen: FC = () => {
>
<ReusableHeader
screenName={"Create Question"}
optionIcon={<QuestionOptionsDropdown onDelete={handleDelete} />}
optionIcon={
<QuestionOptionsDropdown
isDeleting={isDeleting}
setOpenDeleteAlert={() => setOpenDeleteAlert(true)}
/>
}
backIcon={<Feather name="x" size={24} color="black" />}
handleExit={handleExitScreen}
/>
Expand Down Expand Up @@ -994,6 +1012,17 @@ export const CreateQuestionScreen: FC = () => {
}}
onConfirm={goBack}
/>

<AlertModal
isVisible={openDeleteAlert}
alertTitle={"Are you sure?"}
alertDescription={"Do you want to delete this question?"}
confirmButtonText={"Yes"}
isCancelButtonVisible={true}
cancelButtonText={"Cancel"}
onCancel={() => setOpenDeleteAlert(false)}
onConfirm={handleDelete}
/>
</View>
</SafeAreaView>
);
Expand Down
3 changes: 2 additions & 1 deletion apps/expo/src/screens/settings/HistoryTest.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import React from "react";
import { useNavigation } from "@react-navigation/native";
import { Dimensions, View, TouchableOpacity, SafeAreaView } from "react-native";
import { Dimensions, View, TouchableOpacity } from "react-native";
import { FlashList } from "@shopify/flash-list";
import SettingsHeader from "../../components/headers/SettingsHeader";
import { SkeletonLoader } from "../../components/loaders/SkeletonLoader";
import { trpc } from "../../utils/trpc";
import ViewAllScreenTestCard from "../../components/view-all-display/tests/ViewAllScreenTestCard";
import { IMAGE_PLACEHOLDER } from "../../constants";
import { SafeAreaView } from "react-native-safe-area-context";

export const HistoryTestScreen = () => {
const { height, width } = Dimensions.get("window");
Expand Down
42 changes: 35 additions & 7 deletions apps/expo/src/screens/test-history/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { View, SafeAreaView, Dimensions, Alert } from "react-native";
import { View, Dimensions, Alert } from "react-native";
import { RootStackScreenProps } from "../../types";
import { FlashList } from "@shopify/flash-list";
import QuestionCard from "../../components/cards/QuestionCard";
Expand All @@ -9,6 +9,9 @@ import { AppButton } from "../../components/buttons/AppButton";
import useGoBack from "../../hooks/useGoBack";

import type { FC } from "react";
import { SafeAreaView } from "react-native-safe-area-context";
import SettingsHeader from "../../components/headers/SettingsHeader";
import { SkeletonLoader } from "../../components/loaders/SkeletonLoader";

type TestHistoryProps = RootStackScreenProps<"TestHistory">;

Expand All @@ -25,6 +28,29 @@ export const TestHistoryScreen: FC<TestHistoryProps> = ({
historyId,
});

if (!testHistory || isFetchingUser) {
return (
<SafeAreaView className="flex-1" style={{ height: height, width: width }}>
<SettingsHeader screenName={"Test History"} />

<View className="my-5 h-[50%] w-[90%] flex-col justify-between self-center">
<View className="mt-7">
<SkeletonLoader isCircular={true} width={"100%"} height={100} />
</View>
<View className="mt-7">
<SkeletonLoader isCircular={true} width={"100%"} height={100} />
</View>
<View className="mt-7">
<SkeletonLoader isCircular={true} width={"100%"} height={100} />
</View>
<View className="mt-7">
<SkeletonLoader isCircular={true} width={"100%"} height={100} />
</View>
</View>
</SafeAreaView>
);
}

const goToScoreBoard = () => {
if (!testId) return;
navigation.navigate("Scoreboard", {
Expand Down Expand Up @@ -52,11 +78,13 @@ export const TestHistoryScreen: FC<TestHistoryProps> = ({
);
};

const goToQuestionHistory = (questionId: string) => () => {
navigation.navigate("QuestionHistory", {
questionId: questionId,
});
};
const goToQuestionHistory =
(questionId: string, questionIndex: number) => () => {
navigation.navigate("QuestionHistory", {
questionId: questionId,
questionIndex: questionIndex,
});
};

return (
<SafeAreaView
Expand All @@ -66,7 +94,7 @@ export const TestHistoryScreen: FC<TestHistoryProps> = ({
}}
>
<ReusableHeader
screenName="Test History"
screenName={testHistory?.title}
backIcon={<Feather name="x" size={24} color="black" />}
handleExit={testId ? goToHome : goBack}
/>
Expand Down
23 changes: 19 additions & 4 deletions apps/expo/src/screens/test-history/question.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
/* eslint-disable @typescript-eslint/no-empty-function */
import {
View,
SafeAreaView,
Dimensions,
ScrollView,
Text,
Expand All @@ -26,6 +25,9 @@ import {
import type { FC } from "react";
import type { ModifiedChoice } from "../play-test/TestCard";
import { ChoiceStatus } from "../play-test";
import { SafeAreaView } from "react-native-safe-area-context";
import SettingsHeader from "../../components/headers/SettingsHeader";
import { SkeletonLoader } from "../../components/loaders/SkeletonLoader";

type QuestionHistoryProps = RootStackScreenProps<"QuestionHistory">;

Expand All @@ -34,15 +36,28 @@ export const QuestionHistoryScreen: FC<QuestionHistoryProps> = ({
route,
}) => {
const { height, width } = Dimensions.get("window");
const { questionId } = route.params;
const { questionId, questionIndex } = route.params;

const { data: question, isLoading: isFetchingQuestion } =
trpc.testHistory.getUserQuestionHistoryById.useQuery({
questionId: questionId,
});

if (!question || isFetchingQuestion) {
return <></>;
return (
<SafeAreaView className="flex-1" style={{ height: height, width: width }}>
<SettingsHeader screenName={"Question #"} />

<View className="my-5 h-[50%] w-[90%] flex-col justify-evenly self-center">
<View className="mt-7">
<SkeletonLoader isCircular={true} width={"100%"} height={100} />
</View>
<View className="mt-7">
<SkeletonLoader isCircular={true} width={"100%"} height={250} />
</View>
</View>
</SafeAreaView>
);
}

const renderChoice = (choice: ModifiedChoice) => {
Expand Down Expand Up @@ -91,7 +106,7 @@ export const QuestionHistoryScreen: FC<QuestionHistoryProps> = ({
<>
<SafeAreaView className="flex-1" style={{ height: height, width: width }}>
<ReusableHeader
screenName="Test History"
screenName={"Question " + (questionIndex + 1).toString()}
backIcon={<Feather name="x" size={24} color="black" />}
handleExit={() => navigation.goBack()}
/>
Expand Down
1 change: 1 addition & 0 deletions apps/expo/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ export type RootStackParamList = {
};
QuestionHistory: {
questionId: string;
questionIndex: number;
};
HistoryTest: undefined;
};
Expand Down

0 comments on commit 68be60f

Please sign in to comment.