React LogoOnline Exam System

An Online Exam System is a web-based application designed to conduct examinations remotely, eliminating the need for physical presence. It provides a platform for educational institutions, corporate training centers, and other organizations to administer tests, quizzes, and assessments efficiently and securely over the internet. These systems typically encompass various functionalities for both administrators (e.g., educators, trainers) and test-takers (e.g., students, employees).

Core Features:
* User Authentication and Authorization: Secure login for students, teachers, and administrators with role-based access control.
* Question Bank Management: A repository to store, categorize, and manage a large number of questions (multiple-choice, true/false, short answer, essay, etc.).
* Exam Creation: Tools for administrators to create new exams, select questions from the bank, set time limits, assign marks, and define exam rules (e.g., random question order, shuffling options).
* Exam Delivery: A user-friendly interface for students to take exams, often including a timer, navigation between questions, and an option to review answers before submission.
* Automated Grading: For objective questions (e.g., multiple-choice), the system automatically grades answers and provides instant results. Manual grading options are available for subjective questions.
* Result Management and Reporting: Dashboards and reports for administrators to view student performance, analyze exam statistics, and generate detailed result reports.
* Security and Proctoring: Features to minimize cheating, such as question randomization, time limits, browser lockdown, webcam proctoring (monitoring via camera), and screen sharing detection.
* Accessibility: Designed to be accessible from various devices (desktops, laptops, tablets, smartphones) with an internet connection.

Benefits:
* Efficiency and Cost Savings: Reduces administrative overhead, printing costs, and venue expenses.
* Flexibility and Accessibility: Students can take exams from anywhere at any time within the defined window.
* Objectivity and Consistency: Ensures fair and consistent evaluation through standardized testing and automated grading.
* Instant Feedback: For objective tests, students often receive immediate scores and feedback.
* Data Analysis: Provides valuable data for educators to analyze student performance and identify learning gaps.

Typical Workflow (Student Perspective):
1. Login: Student logs into the system using their credentials.
2. View Available Exams: Student sees a list of exams assigned to them.
3. Start Exam: Upon starting an exam, a timer begins, and questions are displayed.
4. Answer Questions: Student navigates through questions, selects answers, or types responses.
5. Submit Exam: Student submits the exam before the time limit expires.
6. View Results: Depending on settings, student may view their score and feedback immediately or later.

Example Code

```javascript
import React, { useState } from 'react';
import './OnlineExam.css'; // Assume you have some basic CSS for styling

const questionsData = [
  {
    id: 1,
    text: "What is the capital of France?",
    options: [
      { id: 'a', text: "Berlin" },
      { id: 'b', text: "Madrid" },
      { id: 'c', text: "Paris" },
      { id: 'd', text: "Rome" },
    ],
    correctOptionId: 'c',
  },
  {
    id: 2,
    text: "Which programming language is React built upon?",
    options: [
      { id: 'a', text: "Python" },
      { id: 'b', text: "Java" },
      { id: 'c', text: "JavaScript" },
      { id: 'd', text: "C#" },
    ],
    correctOptionId: 'c',
  },
  {
    id: 3,
    text: "What does HTML stand for?",
    options: [
      { id: 'a', text: "HyperText Markup Language" },
      { id: 'b', text: "High-Level Text Machine Language" },
      { id: 'c', text: "Hyperlink and Text Markup Language" },
      { id: 'd', text: "Home Tool Management Language" },
    ],
    correctOptionId: 'a',
  },
];

function OnlineExam() {
  const [currentQuestionIndex, setCurrentQuestionIndex] = useState(0);
  const [selectedAnswers, setSelectedAnswers] = useState({}); // Stores {questionId: selectedOptionId}
  const [showResults, setShowResults] = useState(false);
  const [score, setScore] = useState(0);

  const handleOptionChange = (questionId, optionId) => {
    setSelectedAnswers({
      ...selectedAnswers,
      [questionId]: optionId,
    });
  };

  const handleSubmitExam = () => {
    let calculatedScore = 0;
    questionsData.forEach(question => {
      if (selectedAnswers[question.id] === question.correctOptionId) {
        calculatedScore += 1;
      }
    });
    setScore(calculatedScore);
    setShowResults(true);
  };

  const currentQuestion = questionsData[currentQuestionIndex];

  if (showResults) {
    return (
      <div className="exam-container results-container">
        <h2>Exam Results</h2>
        <p>You scored {score} out of {questionsData.length} questions correctly.</p>
        <h3>Review Answers:</h3>
        {questionsData.map(question => (
          <div key={question.id} className="question-review">
            <p><strong>Q: {question.text}</strong></p>
            <p>
              Your Answer: {
                question.options.find(opt => opt.id === selectedAnswers[question.id])?.text || 'Not answered'
              }
            </p>
            <p>
              Correct Answer: {
                question.options.find(opt => opt.id === question.correctOptionId)?.text
              }
            </p>
            {selectedAnswers[question.id] === question.correctOptionId ? (
              <span className="correct-answer">✓ Correct</span>
            ) : (
              <span className="incorrect-answer">✗ Incorrect</span>
            )}
            <hr />
          </div>
        ))}
      </div>
    );
  }

  return (
    <div className="exam-container">
      <h1>Online Exam System</h1>
      <div className="question-card">
        <p className="question-number">
          Question {currentQuestionIndex + 1} of {questionsData.length}
        </p>
        <p className="question-text">{currentQuestion.text}</p>
        <div className="options-list">
          {currentQuestion.options.map(option => (
            <label key={option.id} className="option-label">
              <input
                type="radio"
                name={`question-${currentQuestion.id}`}
                value={option.id}
                checked={selectedAnswers[currentQuestion.id] === option.id}
                onChange={() => handleOptionChange(currentQuestion.id, option.id)}
              />
              {option.text}
            </label>
          ))}
        </div>
      </div>
      <div className="navigation-buttons">
        <button
          onClick={() => setCurrentQuestionIndex(prev => Math.max(0, prev - 1))}
          disabled={currentQuestionIndex === 0}
        >
          Previous
        </button>
        {currentQuestionIndex < questionsData.length - 1 ? (
          <button
            onClick={() => setCurrentQuestionIndex(prev => prev + 1)}
          >
            Next
          </button>
        ) : (
          <button onClick={handleSubmitExam} className="submit-button">
            Submit Exam
          </button>
        )}
      </div>
    </div>
  );
}

export default OnlineExam;

/* Basic CSS (OnlineExam.css) for demonstration */
/*
.exam-container {
  max-width: 700px;
  margin: 40px auto;
  padding: 30px;
  border: 1px solid #ddd;
  border-radius: 8px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
  background-color: #fff;
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}

h1 {
  text-align: center;
  color: #333;
  margin-bottom: 30px;
}

.question-card {
  background-color: #f9f9f9;
  border: 1px solid #eee;
  border-radius: 6px;
  padding: 20px;
  margin-bottom: 25px;
}

.question-number {
  font-size: 0.9em;
  color: #777;
  margin-bottom: 10px;
}

.question-text {
  font-size: 1.2em;
  font-weight: 600;
  color: #333;
  margin-bottom: 20px;
}

.options-list label {
  display: block;
  padding: 12px 15px;
  margin-bottom: 10px;
  border: 1px solid #e0e0e0;
  border-radius: 5px;
  cursor: pointer;
  transition: background-color 0.2s ease;
}

.options-list label:hover {
  background-color: #f0f0f0;
}

.options-list input[type="radio"] {
  margin-right: 10px;
  transform: scale(1.1);
}

.navigation-buttons {
  display: flex;
  justify-content: space-between;
  margin-top: 30px;
}

.navigation-buttons button {
  padding: 12px 25px;
  border: none;
  border-radius: 5px;
  cursor: pointer;
  font-size: 1em;
  font-weight: 500;
  transition: background-color 0.2s ease, transform 0.1s ease;
}

.navigation-buttons button:hover {
  transform: translateY(-1px);
}

.navigation-buttons button:disabled {
  background-color: #cccccc;
  cursor: not-allowed;
  transform: none;
}

.navigation-buttons button:not([disabled]) {
  background-color: #007bff;
  color: white;
}

.submit-button {
  background-color: #28a745 !important;
}

.submit-button:hover {
  background-color: #218838 !important;
}

.results-container h2 {
  text-align: center;
  color: #007bff;
  margin-bottom: 25px;
}

.results-container p {
  font-size: 1.1em;
  text-align: center;
  margin-bottom: 15px;
}

.question-review {
    margin-bottom: 20px;
    padding: 15px;
    border: 1px solid #e9ecef;
    border-radius: 5px;
    background-color: #f8f9fa;
}

.question-review p {
    text-align: left;
    margin-bottom: 5px;
    font-size: 1em;
}

.question-review strong {
    color: #495057;
}

.correct-answer {
    color: #28a745;
    font-weight: bold;
}

.incorrect-answer {
    color: #dc3545;
    font-weight: bold;
}
*/
```