Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import React, { useState, useEffect } from 'react';
- import { useParams } from 'react-router-dom';
- import axios from 'axios';
- import { Header } from './Header';
- import { Footer } from './Footer';
- import { Button } from "@/components/ui/button";
- import { Loader2, TestTube, BadgeCheck, BookOpen, Download } from "lucide-react";
- import { cn } from "@/lib/utils";
- import { useTheme } from "@/hooks/useTheme";
- import { useScrollAnimation } from "@/hooks/useScrollAnimation";
- import '../styles/GenerateTest.css';
- import '../styles/MockTest.css';
- import { BlockMath, InlineMath } from "react-katex";
- import "katex/dist/katex.min.css";
- // Subject background images and colors
- const subjectThemes: Record<string, { bgImage: string, primaryColor: string, icon: React.ElementType }> = {
- biology: {
- bgImage: "https://images.unsplash.com/photo-1530026405186-ed1f139313f8",
- primaryColor: "rgba(16, 185, 129, 0.8)", // green
- icon: TestTube
- },
- chemistry: {
- bgImage: "https://images.unsplash.com/photo-1603126857599-f6e157fa2fe6",
- primaryColor: "rgba(124, 58, 237, 0.8)", // purple
- icon: TestTube
- },
- physics: {
- bgImage: "https://images.unsplash.com/photo-1636466497217-26a8cbeaf0aa",
- primaryColor: "rgba(59, 130, 246, 0.8)", // blue
- icon: TestTube
- },
- mathematics: {
- bgImage: "https://images.unsplash.com/photo-1635372722656-389f87a941db",
- primaryColor: "rgba(239, 68, 68, 0.8)", // red
- icon: TestTube
- },
- default: {
- bgImage: "https://images.unsplash.com/photo-1488190211105-8b0e65b80b4e",
- primaryColor: "rgba(79, 70, 229, 0.8)", // indigo
- icon: TestTube
- }
- };
- const GenerateTest = () => {
- const { subject = "" } = useParams();
- const [loading, setLoading] = useState(false);
- const [testResult, setTestResult] = useState('');
- const { isDarkMode } = useTheme();
- // Animation refs
- const fadeInRef = useScrollAnimation({ animation: 'fade' });
- const slideUpRef = useScrollAnimation({ animation: 'slide', direction: 'up', delay: 3 });
- // Format subject for display (capitalize first letter)
- const formattedSubject = subject
- .replace(/_/g, " ")
- .split(" ")
- .map(word => word.charAt(0).toUpperCase() + word.slice(1))
- .join(" ");
- const subjectKey = subject.toLowerCase().replace(/_/g, "");
- const { bgImage, primaryColor, icon: SubjectIcon } = subjectThemes[subjectKey] || subjectThemes.default;
- const generateTest = async () => {
- setLoading(true);
- setTestResult('');
- try {
- const res = await axios.post("http://127.0.0.1:8001/api/generate", {
- subject: subject.toLowerCase(),
- });
- setTestResult(res.data.mock_test);
- } catch (error: any) {
- console.error("Error generating test:", error.response?.data || error);
- alert("An error occurred while generating the test.");
- } finally {
- setLoading(false);
- }
- };
- const handlePrint = () => {
- window.print();
- };
- const formatResponse = (text: string): JSX.Element[] | null => {
- if (!text) return null;
- const formattedElements: JSX.Element[] = [];
- let currentOptions: JSX.Element[] = [];
- let questionCount = 0;
- let insideSection = false;
- text.split("\n").forEach((line, index) => {
- if (line.startsWith("###")) {
- questionCount = 0;
- insideSection = true;
- formattedElements.push(
- <h3 key={index} className="formatted-subheading">
- {line.replace("###", "").trim()}
- </h3>
- );
- } else if (line.match(/^\d+\./)) {
- if (insideSection) {
- questionCount++;
- const questionText = line.replace(/^\d+\.\s*/, "").trim();
- const containsMath = questionText.includes("$") || questionText.includes("\\(");
- formattedElements.push(
- <div key={index} className="mcq-container">
- <p className="mcq-question">
- {`${questionCount}. `}
- {containsMath ? <BlockMath>{questionText}</BlockMath> : questionText}
- </p>
- </div>
- );
- } else {
- formattedElements.push(
- <p key={index} className="formatted-text">
- {line}
- </p>
- );
- }
- } else if (line.match(/^[a-d]\)/i)) {
- const optionText = line.replace(/^[a-d]\)\s*/, "").trim();
- const containsMath = optionText.includes("$") || optionText.includes("\\(");
- currentOptions.push(
- <span key={index} className="mcq-option">
- {containsMath ? <InlineMath>{optionText}</InlineMath> : optionText}
- </span>
- );
- } else {
- const containsMath = line.includes("$") || line.includes("\\(");
- formattedElements.push(
- <p key={index} className="formatted-text">
- {containsMath ? <InlineMath>{line}</InlineMath> : line}
- </p>
- );
- }
- });
- if (currentOptions.length > 0) {
- formattedElements.push(
- <div key="final-options" className="mcq-options">{currentOptions}</div>
- );
- }
- return formattedElements;
- };
- return (
- <div className={cn(
- "min-h-screen",
- isDarkMode
- ? "bg-gradient-to-b from-gray-900 via-gray-800 to-gray-900"
- : "bg-gradient-to-b from-blue-50 via-indigo-50/30 to-white"
- )}>
- <Header />
- {/* Particles background */}
- <div id="particles-js" className="fixed inset-0 pointer-events-none"></div>
- <div className="pt-28 pb-20 px-4 container max-w-4xl mx-auto relative">
- {/* Hero section with background image */}
- <div className="text-center mb-10" ref={fadeInRef}>
- <div className="inline-block p-2 rounded-full bg-primary/10 mb-4 animate-bounce">
- <SubjectIcon className="h-6 w-6 text-primary" />
- </div>
- <h1 className={cn(
- "text-3xl md:text-5xl font-bold mb-4",
- "animate-fade-in"
- )}>
- Generate {formattedSubject} Mock Test
- </h1>
- <p className="text-muted-foreground text-lg max-w-2xl mx-auto mb-8 animate-fade-in stagger-1">
- Create customized mock tests with detailed solutions to test your knowledge and prepare for exams.
- </p>
- <div className="flex items-center justify-center gap-4 mb-12 animate-fade-in stagger-2">
- <Button
- size="lg"
- onClick={generateTest}
- className="gap-2 px-8 py-6 h-auto rounded-full font-semibold text-lg shadow-lg hover:shadow-xl hover:scale-105 transition-all"
- style={{
- background: primaryColor,
- borderColor: 'transparent'
- }}
- disabled={loading}
- >
- {loading ? (
- <>
- <Loader2 className="h-5 w-5 animate-spin" />
- Generating Test...
- </>
- ) : (
- <>
- <TestTube className="h-5 w-5" />
- Create {formattedSubject} Test
- </>
- )}
- </Button>
- </div>
- <div className="grid grid-cols-1 md:grid-cols-3 gap-6 max-w-3xl mx-auto animate-fade-in stagger-3">
- <div className={cn(
- "rounded-xl p-5 flex flex-col items-center text-center hover:scale-105 transition-all",
- isDarkMode ? "bg-gray-800/50" : "bg-white/80 shadow-sm",
- "border border-primary/10"
- )}>
- <BookOpen className="h-10 w-10 text-primary mb-3" />
- <h3 className="font-semibold text-lg mb-1">Curriculum-Aligned</h3>
- <p className="text-muted-foreground text-sm">Tests based on the official syllabus and exam patterns</p>
- </div>
- <div className={cn(
- "rounded-xl p-5 flex flex-col items-center text-center hover:scale-105 transition-all",
- isDarkMode ? "bg-gray-800/50" : "bg-white/80 shadow-sm",
- "border border-primary/10"
- )}>
- <BadgeCheck className="h-10 w-10 text-primary mb-3" />
- <h3 className="font-semibold text-lg mb-1">Detailed Solutions</h3>
- <p className="text-muted-foreground text-sm">Step-by-step explanations for every question</p>
- </div>
- <div className={cn(
- "rounded-xl p-5 flex flex-col items-center text-center hover:scale-105 transition-all",
- isDarkMode ? "bg-gray-800/50" : "bg-white/80 shadow-sm",
- "border border-primary/10"
- )}>
- <Download className="h-10 w-10 text-primary mb-3" />
- <h3 className="font-semibold text-lg mb-1">Downloadable PDF</h3>
- <p className="text-muted-foreground text-sm">Save tests for offline practice and reference</p>
- </div>
- </div>
- </div>
- {/* Test Result */}
- {loading && (
- <div className="flex flex-col items-center justify-center p-10 text-center">
- <div className="w-16 h-16 border-4 border-primary/30 border-t-primary rounded-full animate-spin mb-4"></div>
- <p className="text-lg font-medium">Generating your test...</p>
- <p className="text-muted-foreground">This may take a few moments</p>
- </div>
- )}
- {testResult && (
- <div
- className={cn(
- "rounded-2xl p-6 md:p-8 animate-fade-in",
- isDarkMode ? "bg-gray-800/70" : "bg-white/90 shadow-lg",
- "border border-primary/10"
- )}
- ref={slideUpRef}
- >
- <div className="mb-6 flex justify-between items-center">
- <h2 className="text-2xl font-bold">{formattedSubject} Mock Test</h2>
- <Button variant="outline" className="rounded-full gap-2" onClick={handlePrint}>
- <Download className="h-4 w-4" />
- Download PDF
- </Button>
- </div>
- <div className="test-result">
- <div className="formatted-output">{formatResponse(testResult)}</div>
- </div>
- <div className="mt-8 flex flex-col sm:flex-row gap-4 justify-center">
- <Button
- onClick={generateTest}
- className="gap-2"
- variant="outline"
- >
- <TestTube className="h-4 w-4" />
- Generate Another Test
- </Button>
- <Button className="gap-2">
- View Solutions
- </Button>
- </div>
- </div>
- )}
- </div>
- <Footer />
- </div>
- );
- };
- export default GenerateTest;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement