Skip to content

Commit

Permalink
Minor fixes.
Browse files Browse the repository at this point in the history
Signed-off-by: Aliwoto <aminnimaj@gmail.com>
  • Loading branch information
ALiwoto committed Aug 25, 2024
1 parent 79fb111 commit 1e596aa
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 29 deletions.
5 changes: 5 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import ExamInfoPage from './pages/examInfoPage';
import SearchExamPage from './pages/searchExamPage';
import ChangePasswordPage from './pages/changePasswordPage';
import PassChangeRedirectPage from './pages/passChangeRedirectPage';
import ExamHallPage from './pages/examHallPage';

const App: React.FC = () => {
const [isLoggedIn, setIsLoggedIn] = useState<boolean>(apiClient.isLoggedIn());
Expand Down Expand Up @@ -137,6 +138,10 @@ const App: React.FC = () => {
path="/searchExam"
element={apiClient.canSearchTopics() ? <SearchExamPage /> : <Navigate to="/dashboard" />}
/>
<Route
path="/examHall"
element={isLoggedIn ? <ExamHallPage /> : <Navigate to="/login" />}
/>
<Route path="*" element={<Navigate to={isLoggedIn ? "/dashboard" : "/login"} />} />
</Routes>
</Router>
Expand Down
11 changes: 6 additions & 5 deletions src/components/rendering/RenderAllQuestions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,13 @@ interface RenderQuestionsListProps {
}

const RenderAllQuestions: React.FC<RenderQuestionsListProps> = ({ ...props }) => {
console.log(props.questions);
return (
<Container maxWidth="md">
{props.questions.map((question) => (
<Paper key={question.question_id} elevation={3} sx={{ p: 3, mb: 3 }}>
<Box display="flex" justifyContent="space-between" alignItems="center" mb={2}>
{props.editingId === question.question_id && props.canEditQuestions ? (
{props.editingId !== question.question_id || !props.canEditQuestions ? (
<Typography variant="h6">
{question.question_title}
</Typography>
Expand All @@ -58,10 +59,10 @@ const RenderAllQuestions: React.FC<RenderQuestionsListProps> = ({ ...props }) =>
CurrentAppTranslation.EditText}
</Button>
</Box>
{props.editingId === question.question_id && props.canEditQuestions ? (
{props.editingId !== question.question_id || !props.canEditQuestions ? (
<Typography variant="body1" gutterBottom>
{question.description}
</Typography>) : (
{question.description}
</Typography>) : (
<TextField
fullWidth
multiline
Expand All @@ -74,7 +75,7 @@ const RenderAllQuestions: React.FC<RenderQuestionsListProps> = ({ ...props }) =>
/>
)}
{apiClient.getQuestionOptions(question).map((option, index) => (
props.editingId === question.question_id ?
props.editingId !== question.question_id ?
(<Typography key={index} variant="body2">{`${index + 1}. ${option}`}</Typography>) :
(<TextField
key={index}
Expand Down
30 changes: 20 additions & 10 deletions src/pages/examHallPage.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import React, { useEffect, useReducer, useState } from 'react';
import { Typography, Button, TextField, Paper, Box, Container, Pagination, CircularProgress } from '@mui/material';
import { Button, Box, Pagination, CircularProgress } from '@mui/material';
import { AnswerQuestionData, CreateExamQuestionData, ExamQuestionInfo, GetExamInfoResult } from '../api';
import { extractErrorDetails } from '../utils/errorUtils';
import useAppSnackbar from '../components/snackbars/useAppSnackbars';
import apiClient from '../apiClient';
import { DashboardContainer } from '../components/containers/dashboardContainer';
import RenderAllQuestions from '../components/rendering/RenderAllQuestions';
import { autoSetWindowTitle } from '../utils/commonUtils';
import { CurrentAppTranslation } from '../translations/appTranslation';

const PageLimit = 10;

export var forceUpdateExamHallPage = () => { };

export default function Component() {
const ExamHallPage: React.FC = () => {
const urlSearch = new URLSearchParams(window.location.search);
const examId = parseInt(urlSearch.get('examId')!);
const providedPage = urlSearch.get('page');
Expand Down Expand Up @@ -109,6 +110,8 @@ export default function Component() {
// for a question. if the question is already being edited, we will cancel
// the edit mode. otherwise, we will set the editingId to the question_id.
if (id == editingId) {
// remove all questions that have id of -1
setQuestions(questions.filter(q => q.question_id !== -1));
setEditingId(null);
} else {
setEditingId(id);
Expand Down Expand Up @@ -250,7 +253,7 @@ export default function Component() {
}}>
<CircularProgress size={60} />
</Box>
) : <RenderAllQuestions editingId={editingId}
) : <RenderAllQuestions key={`q-renderer-id-${editingId}`} editingId={editingId}
questions={questions}
handleEdit={handleEdit}
handleSubmit={handleSubmit}
Expand All @@ -260,7 +263,18 @@ export default function Component() {
isParticipating={examInfo?.has_participated ?? false}
canEditQuestions={examInfo?.can_edit_question ?? false}
/>}
<Button variant="contained" color="primary" onClick={handleAddNewQuestion}>Add New Question</Button>
{editingId !== -1 && examInfo?.can_edit_question && (
<Box sx={{
display: 'flex',
justifyContent: 'center',
margin: '0 auto',
mt: 4,
}}>
<Button variant="contained" color="primary" onClick={handleAddNewQuestion}>
{CurrentAppTranslation.AddNewQuestionText}
</Button>
</Box>
)}
</Box>
<Box sx={{ display: 'flex', justifyContent: 'center', margin: '0 auto', }}>
<Pagination
Expand All @@ -269,10 +283,6 @@ export default function Component() {
</Box>
</DashboardContainer>
);
// return (
// <Container maxWidth="md">
// <Typography variant="h4" gutterBottom>Online Exam</Typography>
}

// </Container>
// );
}
export default ExamHallPage;
56 changes: 42 additions & 14 deletions src/pages/examInfoPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import RenderAllFields from '../components/rendering/RenderAllFields';

export var forceUpdateExamInfoPage = () => { };

var ExamCountdownId = 0;

const ExamInfoPage = () => {
const [examData, setExamData] = useState<EditExamData>({
exam_id: 0,
Expand All @@ -26,7 +28,7 @@ const ExamInfoPage = () => {
const [examInfo, setExamInfo] = useState<GetExamInfoResult | null>(null);
const [, forceUpdate] = useReducer(x => x + 1, 0);
const [isEditing, setIsEditing] = useState(false);
const [isUserNotFound, setIsUserNotFound] = useState(false);
const [isExamNotFound, setIsUserNotFound] = useState(false);
const snackbar = useAppSnackbar();

forceUpdateExamInfoPage = () => {
Expand Down Expand Up @@ -58,6 +60,24 @@ const ExamInfoPage = () => {
is_public: result.is_public,
});
setExamInfo(result);

if (examInfo?.can_participate && !examInfo.has_started && !examInfo.has_finished) {
ExamCountdownId = window.setInterval(() => {
if (!examInfo.starts_in || examInfo.starts_in < 0) {
clearInterval(ExamCountdownId);

// automatically redirect the user to the exam hall
setTimeout(() => {
window.location.href = `/examHall?examId=${targetExamId}`;
}, 5000);
}

setExamInfo({
...examInfo,
starts_in: examInfo.starts_in! - 1,
});
}, 60000);
}
} catch (error: any) {
const [errCode, errMessage] = extractErrorDetails(error);
snackbar.error(`Failed to get exam info (${errCode}): ${errMessage}`);
Expand Down Expand Up @@ -116,15 +136,13 @@ const ExamInfoPage = () => {
`examInfo_examId_${examData.exam_id}`,
"Exam Info",
`${window.location.pathname}?examId=${encodeURIComponent(examData.exam_id!)
}&edit=${isEditing ? '0' : '1'
}`,
}&edit=${isEditing ? '0' : '1'}`,
);
} catch (error: any) {
const [errCode, errMessage] = extractErrorDetails(error);
snackbar.error(`Failed (${errCode}) - ${errMessage}`);
return;
}

};

const handleParticipate = async () => {
Expand All @@ -147,6 +165,10 @@ const ExamInfoPage = () => {
}
};

const handleExamHall = () => {
window.location.href = `/examHall?examId=${examData.exam_id}`;
}

if (!examData) {
// maybe return better stuff here in future?
return (
Expand All @@ -156,7 +178,7 @@ const ExamInfoPage = () => {
);
}

if (isUserNotFound) {
if (isExamNotFound) {
return (
<DashboardContainer>
<Typography>{CurrentAppTranslation.ExamNotFoundText}</Typography>
Expand All @@ -173,15 +195,21 @@ const ExamInfoPage = () => {
<Button variant="contained" onClick={isEditing ? handleSave : handleEdit}>
{isEditing ? CurrentAppTranslation.SaveText : CurrentAppTranslation.EditText}
</Button>
{examInfo?.can_participate && <Button variant="contained" onClick={handleParticipate}>
{CurrentAppTranslation.ParticipateText}
</Button>}
<Button variant="contained" onClick={isEditing ? handleSave : handleEdit}>
{isEditing ? CurrentAppTranslation.SaveText : CurrentAppTranslation.EditText}
</Button>
<Button variant="contained" onClick={isEditing ? handleSave : handleEdit}>
{isEditing ? CurrentAppTranslation.SaveText : CurrentAppTranslation.EditText}
</Button>
{(!isEditing && examInfo?.can_participate && !examInfo.has_participated) && (
<Button variant="contained" onClick={handleParticipate}>
{CurrentAppTranslation.ParticipateText}
</Button>
)}
{(!isEditing && examInfo?.can_edit_question) && (
<Button variant="contained" onClick={handleExamHall}>
{CurrentAppTranslation.QuestionsText}
</Button>
)}
{(!isEditing && examInfo?.has_participated && examInfo.has_started) && (
<Button variant="contained" onClick={handleExamHall}>
{CurrentAppTranslation.ExamHallText}
</Button>
)}
</Box>
<Grid container spacing={2}>
{RenderAllFields({
Expand Down
3 changes: 3 additions & 0 deletions src/translations/appTranslation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ export class AppTranslationBase {
CreateCourseButtonText: string = "Create Course";
SaveText: string = "Save";
ParticipateText: string = "Participate";
QuestionsText: string = "Questions";
ExamHallText : string = "Exam Hall";
ConfirmText: string = "Confirm";
SubmitText: string = "Submit";
ChosenOptionText: string = "Chosen Option";
Expand All @@ -79,6 +81,7 @@ export class AppTranslationBase {
CreateNewCourseText: string = "Create New Course";
CreateCourseText: string = "Create Course";
CreateExamText: string = "Create Exam";
AddNewQuestionText: string = "Add New Question";
DeleteTopicButtonText: string = "Delete Topic";
CancelButtonText: string = "Cancel";
SendEmailToUseText: string = "Send email confirmation to user";
Expand Down
3 changes: 3 additions & 0 deletions src/translations/faTranslation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ class FaTranslation extends AppTranslationBase {
CreateTopicButtonText: string = "ایجاد موضوع";
SaveText: string = "ذخیره";
ParticipateText: string = "شرکت در آزمون";
QuestionsText: string = "سوالات";
ExamHallText: string = "سالن امتحان";
ConfirmText: string = "تایید";
SubmitText: string = "ثبت";
ChosenOptionText: string = "گزینه انتخابی";
Expand All @@ -76,6 +78,7 @@ class FaTranslation extends AppTranslationBase {
CreateNewCourseText: string = "ایجاد دوره جدید";
CreateCourseText: string = "ایجاد دوره";
CreateExamText: string = "ایجاد آزمون";
AddNewQuestionText: string = "افزودن سوال جدید";
DeleteTopicButtonText: string = "حذف موضوع";
CreateCourseButtonText: string = "ایجاد دوره";
CancelButtonText: string = "لغو";
Expand Down

0 comments on commit 1e596aa

Please sign in to comment.