Skip to content

Commit

Permalink
Merge branch 'HansGabriel:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
3LL4N authored Dec 6, 2023
2 parents bd6c591 + a34004c commit ecfecc0
Show file tree
Hide file tree
Showing 11 changed files with 69 additions and 68 deletions.
3 changes: 3 additions & 0 deletions apps/expo/src/components/bottom-sheet/ChoiceBottomSheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { Foundation } from "@expo/vector-icons";

import type { FC } from "react";
import type { QuestionType } from "../../stores/useQuestionStore";
import useError from "../../screens/create-question/hooks";

interface Props {
goToCreateQuestion: (questionType: QuestionType) => void;
Expand All @@ -19,7 +20,9 @@ const ChoiceBottomSheet: FC<Props> = ({
goToCreateQuestion,
closeBottomSheet,
}) => {
const { resetErrors } = useError();
const handleChoicePress = (questionType: QuestionType) => () => {
resetErrors();
goToCreateQuestion(questionType);
closeBottomSheet?.();
};
Expand Down
5 changes: 4 additions & 1 deletion apps/expo/src/components/dropdowns/DeleteDropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,10 @@ const DeleteDropdown: FC<Props> = ({
onCancel={() => {
setOpenAlert(false);
}}
onConfirm={onDelete}
onConfirm={() => {
onDelete();
setOpenAlert(false);
}}
/>
</>
);
Expand Down
2 changes: 1 addition & 1 deletion apps/expo/src/components/headers/ReusableHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ interface HeaderProps extends ViewProps {
}

export const ReusableHeader: FC<HeaderProps> = ({
screenName,
screenName = "",
optionIcon,
onIconPress,
backIcon = <LeftArrowIcon />,
Expand Down
2 changes: 1 addition & 1 deletion apps/expo/src/forms/CreateTestForm/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ const CreateTestForm: FC<Props> = ({

const createMultipleQuestions = (inputMessage: string) => {
const numOfQuestions =
numberOfQuestionOptions.find((option) => option.isSelected)?.value ?? 1;
numberOfQuestionOptions.find((option) => option.isSelected)?.value ?? 5;

if (inputMessage.length <= 0) {
setErrorInAIQuestion(true);
Expand Down
2 changes: 1 addition & 1 deletion apps/expo/src/screens/create-question/ChoiceCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -669,7 +669,7 @@ export const IdentificationCards = ({
borderRadius="full"
fontStyle="bold"
textColor="white"
TOwidth="[50%]"
TOwidth="[45%]"
Vwidth="full"
Vheight="12"
onPress={addChoice}
Expand Down
36 changes: 15 additions & 21 deletions apps/expo/src/screens/create-question/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ export const CreateQuestionScreen: FC = () => {
const [selectedQuestionId, setSelectedQuestionId] = useState<number>(0);
const [choices, setChoices] = useState<Choice[]>([]);
const [isDeleting, setIsDeleting] = useState(false);
const [openDeleteAlert, setOpenDeleteAlert] = useState(false);
const [isChoiceModalTouched, setIsChoiceModalTouched] = useState(false);

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

Expand Down Expand Up @@ -194,6 +194,8 @@ export const CreateQuestionScreen: FC = () => {
};

const goToCreateQuestion = (selectedQuestionType: QuestionType) => {
resetErrors();
setIsChoiceModalTouched(false);
if (isLastQuestionInEdit()) {
deleteLastQuestion();
addEmptyQuestion(selectedQuestionType);
Expand Down Expand Up @@ -258,13 +260,13 @@ export const CreateQuestionScreen: FC = () => {
{
id: 0,
text: "True",
isCorrect: data.answer,
isCorrect: data.choices[0]!.isCorrect,
styles: choiceStyles[0]!.styles,
},
{
id: 1,
text: "False",
isCorrect: !data.answer,
isCorrect: data.choices[1]!.isCorrect,
styles: choiceStyles[1]!.styles,
},
]);
Expand Down Expand Up @@ -357,6 +359,7 @@ export const CreateQuestionScreen: FC = () => {

const handleOpenModal = (index: number) => () => {
setSelectedQuestionId(index);
setIsChoiceModalTouched(true);
setShowModal(true);
};

Expand Down Expand Up @@ -452,12 +455,11 @@ export const CreateQuestionScreen: FC = () => {
time: timeLimitOptions.find((option) => option.isSelected)?.value ?? 0,
};
}

if (!question) return false;

resetErrors();
editQuestion(selectedIndex!, question);
resetQuestionImage();
resetErrors();
successToast({
title: "Success",
message: "Question saved successfully",
Expand All @@ -472,7 +474,10 @@ export const CreateQuestionScreen: FC = () => {
title: "Missing field",
message: "Title cannot be empty",
});
} else if (!errorState.choicesError.every((item) => item === undefined)) {
} else if (
isChoiceModalTouched &&
!errorState.choicesError.every((item) => item === undefined)
) {
errorToast({
title: "Missing field",
message: "Choices cannot be empty",
Expand All @@ -493,7 +498,7 @@ export const CreateQuestionScreen: FC = () => {
) {
errorToast({
title: "Missing field",
message: "Please select a correct answer",
message: "Please assign a correct answer",
});
}
}
Expand Down Expand Up @@ -619,7 +624,6 @@ export const CreateQuestionScreen: FC = () => {
}

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

const handleGenerateQuestion = () => {
Expand Down Expand Up @@ -667,14 +671,15 @@ export const CreateQuestionScreen: FC = () => {
screenName={"Create Question"}
optionIcon={
<QuestionOptionsDropdown
isDeleting={isDeleting}
setOpenDeleteAlert={() => setOpenDeleteAlert(true)}
isSaved={!isSaved}
handleSaveAnswer={handleSaveAnswer(() => {
setIsSaved(false);
})}
/>
}
showDeleteIcon={true}
onDeletePress={handleDelete}
isDeleting={isDeleting}
backIcon={<Feather name="x" size={24} color="black" />}
handleExit={handleExitScreen}
/>
Expand Down Expand Up @@ -1001,17 +1006,6 @@ 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
Original file line number Diff line number Diff line change
@@ -1,31 +1,16 @@
import React from "react";
import { TouchableOpacity, View, ActivityIndicator } from "react-native";
import { AntDesign } from "@expo/vector-icons";
import { TouchableOpacity, View } from "react-native";
import { Entypo } from "@expo/vector-icons";
import type { FC } from "react";

interface Props {
isDeleting: boolean;
setOpenDeleteAlert: () => void;
isSaved: boolean;
handleSaveAnswer: () => void;
}

const QuestionOptionsDropdown: FC<Props> = ({
isDeleting,
setOpenDeleteAlert,
isSaved,
handleSaveAnswer,
}) => {
const QuestionOptionsDropdown: FC<Props> = ({ isSaved, handleSaveAnswer }) => {
return (
<View className="relative flex-row space-x-4">
<TouchableOpacity onPress={setOpenDeleteAlert} disabled={isDeleting}>
{isDeleting ? (
<ActivityIndicator size="small" color="red" />
) : (
<AntDesign name="delete" size={24} color="red" />
)}
</TouchableOpacity>
<View className="relative flex-row space-x-5 self-center">
<TouchableOpacity disabled={isSaved} onPress={handleSaveAnswer}>
<Entypo name="save" size={25} color="rgb(79 70 229)" />
</TouchableOpacity>
Expand Down
37 changes: 15 additions & 22 deletions apps/expo/src/screens/create-reviewer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,12 @@ import { AlertModal } from "../../components/modals/AlertModal";
import ChoiceModal from "../../components/modals/ChoiceModal";
import type { Option } from "./types";
import { NUMBER_OF_QUESTIONS_OPTIONS } from "./constants";
import useQuestionStore, { QuestionType } from "../../stores/useQuestionStore";
import useQuestionStore from "../../stores/useQuestionStore";
import { AppButton } from "../../components/buttons/AppButton";
import * as DocumentPicker from "expo-document-picker";
import * as FileSystem from "expo-file-system";
import {
extractHighlightedText,
mapQuestionType,
} from "../../utils/helpers/strings";

interface CacheOptions {
Expand All @@ -70,17 +69,6 @@ export const CreateReviewerScreen = ({
type: "create",
};
const richText = useRef<RichEditor | null>(null);
const types: QuestionType[] = [
"multiple_choice",
"true_or_false",
"multi_select",
"identification",
];
const randomizeQuestionType = Math.floor(Math.random() * types.length);
const questionType = types[randomizeQuestionType];
const mappedQuestionType = mapQuestionType(
questionType !== undefined ? questionType : "multiple_choice",
);
const [isHighlighterToggled, setIsHighlighterToggled] = useState(false);
const [isChoiceModalToggled, setIsChoiceModalToggled] = useState(false);
const [isPDFUploading, setIsPDFUploading] = useState(false);
Expand All @@ -95,8 +83,6 @@ export const CreateReviewerScreen = ({
);
const [showNumberofQuestionsModal, setShowNumberOfQuestionsModal] =
useState(false);

const addEmptyQuestion = useQuestionStore((state) => state.addEmptyQuestion);
const setLastIndex = useQuestionStore((state) => state.setLastIndex);
const { addQuestions, removeBlankQuestions } = useQuestionStore();

Expand All @@ -116,7 +102,7 @@ export const CreateReviewerScreen = ({
const { mutate: readFile } = trpc.pdfTextExtraction.extractText.useMutation();

const { mutate: generateMultipleQuestions, isLoading: isGenerating } =
trpc.gptApi.generateMultipleQuestions.useMutation();
trpc.gptApi.generateMultipleRandomQuestions.useMutation();

const {
mutate: createReviewer,
Expand Down Expand Up @@ -367,7 +353,7 @@ export const CreateReviewerScreen = ({

const createMultipleQuestions = (inputMessage: string) => {
const numOfQuestions =
numberOfQuestionOptions.find((option) => option.isSelected)?.value ?? 1;
numberOfQuestionOptions.find((option) => option.isSelected)?.value ?? 5;

if (inputMessage === " ") {
setShowNumberOfQuestionsModal(false);
Expand All @@ -379,9 +365,7 @@ export const CreateReviewerScreen = ({
generateMultipleQuestions(
{
message: inputMessage,
questionType: mappedQuestionType,
numOfQuestions: numOfQuestions,
numOfChoicesPerQuestion: 4,
},
{
onSuccess: (data) => {
Expand Down Expand Up @@ -413,11 +397,11 @@ export const CreateReviewerScreen = ({
choices: [
{
text: "True",
isCorrect: question.answer,
isCorrect: question.choices[0]?.isCorrect ?? false,
},
{
text: "False",
isCorrect: !question.answer,
isCorrect: question.choices[1]?.isCorrect ?? false,
},
],
inEdit: false,
Expand All @@ -426,6 +410,16 @@ export const CreateReviewerScreen = ({
points: question.points,
};
}
if (question.type === "identification") {
return {
type: "identification",
choices: question.choices,
inEdit: false,
title: question.question,
time: question.timeLimit,
points: question.points,
};
}
return {
type: "multiple_choice",
choices: [],
Expand All @@ -435,7 +429,6 @@ export const CreateReviewerScreen = ({
}),
);
removeBlankQuestions();
addEmptyQuestion("multiple_choice");
setLastIndex();
setShowNumberOfQuestionsModal(false);
successToast({
Expand Down
7 changes: 6 additions & 1 deletion packages/api/src/functions/randomQuestionsHandlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,13 +85,16 @@ export const generateCombinedQuestionPrompts = (
type
]()}\n`;
}

typeCounts[type] = 0;
});

return combinedPrompts.trim();
};

export const processGeneratedQuestions = (
generatedMessage: string,
numOfQuestions: number,
): ParsedQuestion[] => {
const questionBlocks = generatedMessage
.split("separator")
Expand All @@ -116,5 +119,7 @@ export const processGeneratedQuestions = (
}
});

return parsedQuestions;
const sliceParsedQuestions = parsedQuestions.slice(0, numOfQuestions);

return sliceParsedQuestions;
};
15 changes: 14 additions & 1 deletion packages/api/src/router/gptApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,20 @@ export const gptApiRouter = router({

const generatedMessage = await fetchGPT(promptText);

const processedQuestions = processGeneratedQuestions(generatedMessage);
const processedQuestions = processGeneratedQuestions(
generatedMessage,
numOfQuestions,
);

if (processedQuestions.length < numOfQuestions) {
const regenerateMessage = await fetchGPT(promptText);
const reprocessedQuestions = processGeneratedQuestions(
regenerateMessage,
numOfQuestions,
);

return reprocessedQuestions;
}

return processedQuestions;
}),
Expand Down
7 changes: 6 additions & 1 deletion packages/schema/src/question.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,12 @@ export const questionSchema = z.discriminatedUnion("type", [
}),
z.object({
question: z.string(),
answer: z.boolean(),
choices: z.array(
z.object({
isCorrect: z.boolean(),
text: z.string(),
}),
),
type: z.literal("trueOrFalse"),
timeLimit: timeLimitSchema,
points: pointsSchema,
Expand Down

0 comments on commit ecfecc0

Please sign in to comment.