siddharth-sahu-21 commited on
Commit
611ea55
·
1 Parent(s): 03d5320

resume and notes upload button

Browse files
Files changed (1) hide show
  1. Frontend/src/pages/quize.tsx +136 -25
Frontend/src/pages/quize.tsx CHANGED
@@ -1,5 +1,5 @@
1
- import React, { useState } from "react";
2
- import { FileSpreadsheet, Code2, ListChecks } from "lucide-react";
3
  import MCQQuizPage from "../components/quize/mcq";
4
 
5
  const CodingQuizPage = ({ onBack }: any) => (
@@ -17,19 +17,82 @@ const CodingQuizPage = ({ onBack }: any) => (
17
  const ResumeGeneratedQuize: React.FC = () => {
18
  const [showQuiz, setShowQuiz] = useState(false);
19
  const [quizType, setQuizType] = useState<"mcq" | "coding" | null>(null);
 
 
 
 
20
 
21
- const buttonClass =
22
- "w-full py-3 rounded-lg bg-gradient-to-r from-blue-500 to-blue-700 hover:from-blue-400 hover:to-blue-600 font-medium transition shadow-lg shadow-blue-500/30 text-white mt-4";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
 
24
- // Load Quiz Page
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
  if (showQuiz) {
26
  if (quizType === "mcq")
27
- return <MCQQuizPage onBack={() => setShowQuiz(false)} />;
28
 
29
  if (quizType === "coding")
30
- return <CodingQuizPage onBack={() => setShowQuiz(false)} />;
31
  }
32
 
 
 
 
 
33
  const OutputTypeOption = ({ icon, title, desc, value }: any) => (
34
  <div
35
  onClick={() => setQuizType(value)}
@@ -49,18 +112,69 @@ const ResumeGeneratedQuize: React.FC = () => {
49
  </div>
50
  );
51
 
52
- const SourceCard = ({ icon, title, desc, actionText }: any) => (
53
  <div className="p-6 bg-slate-900/60 rounded-2xl shadow-xl border border-slate-700 hover:bg-slate-800/70 transition flex flex-col h-full">
54
  <div className="flex items-start gap-4 mb-4">
55
- {icon}
56
  <div>
57
- <h2 className="text-2xl font-bold">{title}</h2>
58
- <p className="text-gray-400 mt-1 text-sm">{desc}</p>
59
  </div>
60
  </div>
61
- <button className={buttonClass.replace("w-full", "w-fit px-6")}>
62
- {actionText}
63
- </button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
  </div>
65
  );
66
 
@@ -75,13 +189,8 @@ const ResumeGeneratedQuize: React.FC = () => {
75
  <h3 className="text-3xl font-bold mb-6 text-gray-100 border-b border-blue-700 pb-2">
76
  1. Select Quiz Source
77
  </h3>
78
- <div className="space-y-8">
79
- <SourceCard
80
- icon={<FileSpreadsheet className="w-8 h-8 text-cyan-400" />}
81
- title="Resume/Note PDF Upload"
82
- desc="Generate quizzes based on your uploaded resume or notes."
83
- actionText="Upload"
84
- />
85
  </div>
86
  </div>
87
 
@@ -96,6 +205,8 @@ const ResumeGeneratedQuize: React.FC = () => {
96
  </label>
97
  <textarea
98
  rows={4}
 
 
99
  placeholder="e.g., 'Focus on Python only'"
100
  className="w-full p-3 rounded-lg bg-black/40 border border-slate-700 text-gray-100 placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-purple-600 transition"
101
  ></textarea>
@@ -130,12 +241,12 @@ const ResumeGeneratedQuize: React.FC = () => {
130
  className={
131
  buttonClass +
132
  " text-xl mt-8 " +
133
- (!quizType
134
  ? "opacity-50 cursor-not-allowed"
135
  : "opacity-100 cursor-pointer")
136
  }
137
- disabled={!quizType}
138
- onClick={() => setShowQuiz(true)}
139
  >
140
  Generate Quiz Now
141
  </button>
@@ -144,4 +255,4 @@ const ResumeGeneratedQuize: React.FC = () => {
144
  );
145
  };
146
 
147
- export default ResumeGeneratedQuize;
 
1
+ import React, { useState, useRef } from "react";
2
+ import { FileSpreadsheet, Code2, ListChecks, FileText, Upload, X } from "lucide-react";
3
  import MCQQuizPage from "../components/quize/mcq";
4
 
5
  const CodingQuizPage = ({ onBack }: any) => (
 
17
  const ResumeGeneratedQuize: React.FC = () => {
18
  const [showQuiz, setShowQuiz] = useState(false);
19
  const [quizType, setQuizType] = useState<"mcq" | "coding" | null>(null);
20
+ const [uploadType, setUploadType] = useState<"resume" | "notes" | null>(null);
21
+ const [uploadedFile, setUploadedFile] = useState<string | null>(null);
22
+ const [fileError, setFileError] = useState<string | null>(null);
23
+ const [fileObject, setFileObject] = useState<File | null>(null);
24
 
25
+ const [customPrompt, setCustomPrompt] = useState("");
26
+ const [quizData, setQuizData] = useState(null);
27
+
28
+ const resumeInputRef = useRef<HTMLInputElement>(null);
29
+ const notesInputRef = useRef<HTMLInputElement>(null);
30
+
31
+ const MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB
32
+
33
+ const handleFileUpload = (event: React.ChangeEvent<HTMLInputElement>, type: "resume" | "notes") => {
34
+ const file = event.target.files?.[0];
35
+ if (!file) return;
36
+
37
+ if (file.type !== "application/pdf") {
38
+ setFileError("Please upload a PDF file");
39
+ return;
40
+ }
41
+
42
+ if (file.size > MAX_FILE_SIZE) {
43
+ setFileError(`File size exceeds 10MB. Your file is ${(file.size / (1024 * 1024)).toFixed(2)}MB`);
44
+ return;
45
+ }
46
+
47
+ setFileError(null);
48
+ setUploadType(type);
49
+ setUploadedFile(file.name);
50
+ setFileObject(file); // <-- Store actual file object
51
+ };
52
 
53
+ const handleResumeClick = () => resumeInputRef.current?.click();
54
+ const handleNotesClick = () => notesInputRef.current?.click();
55
+
56
+ const clearUpload = () => {
57
+ setUploadedFile(null);
58
+ setUploadType(null);
59
+ setFileError(null);
60
+ setFileObject(null);
61
+ };
62
+
63
+ // ---------- SEND PDF TO BACKEND ----------
64
+ const generateQuiz = async () => {
65
+ if (!fileObject || !quizType) return;
66
+
67
+ const formData = new FormData();
68
+ formData.append("file", fileObject);
69
+ formData.append("quiz_type", quizType);
70
+ formData.append("instructions", customPrompt);
71
+
72
+ const response = await fetch("http://localhost:8000/generate-quiz", {
73
+ method: "POST",
74
+ body: formData,
75
+ });
76
+
77
+ const data = await response.json();
78
+
79
+ setQuizData(data); // store quiz data
80
+ setShowQuiz(true); // navigate to quiz page
81
+ };
82
+
83
+ // Load quiz UI
84
  if (showQuiz) {
85
  if (quizType === "mcq")
86
+ return <MCQQuizPage data={quizData} onBack={() => setShowQuiz(false)} />;
87
 
88
  if (quizType === "coding")
89
+ return <CodingQuizPage data={quizData} onBack={() => setShowQuiz(false)} />;
90
  }
91
 
92
+ // ---- UI COMPONENTS (same as your original) ----
93
+ const buttonClass =
94
+ "w-full py-3 rounded-lg bg-gradient-to-r from-blue-500 to-blue-700 hover:from-blue-400 hover:to-blue-600 font-medium transition shadow-lg shadow-blue-500/30 text-white mt-4";
95
+
96
  const OutputTypeOption = ({ icon, title, desc, value }: any) => (
97
  <div
98
  onClick={() => setQuizType(value)}
 
112
  </div>
113
  );
114
 
115
+ const SourceCard = () => (
116
  <div className="p-6 bg-slate-900/60 rounded-2xl shadow-xl border border-slate-700 hover:bg-slate-800/70 transition flex flex-col h-full">
117
  <div className="flex items-start gap-4 mb-4">
118
+ <FileSpreadsheet className="w-8 h-8 text-cyan-400" />
119
  <div>
120
+ <h2 className="text-2xl font-bold">Upload Materials</h2>
121
+ <p className="text-gray-400 mt-1 text-sm">Upload your resume or notes (Max 10MB)</p>
122
  </div>
123
  </div>
124
+
125
+ <input
126
+ ref={resumeInputRef}
127
+ type="file"
128
+ accept=".pdf"
129
+ onChange={(e) => handleFileUpload(e, "resume")}
130
+ className="hidden"
131
+ />
132
+ <input
133
+ ref={notesInputRef}
134
+ type="file"
135
+ accept=".pdf"
136
+ onChange={(e) => handleFileUpload(e, "notes")}
137
+ className="hidden"
138
+ />
139
+
140
+ <div className="flex gap-3 mt-4">
141
+ <button
142
+ onClick={handleResumeClick}
143
+ className="flex-1 py-2 px-4 bg-cyan-600 hover:bg-cyan-700 rounded-lg text-white font-medium transition flex items-center justify-center gap-2"
144
+ >
145
+ <Upload className="w-4 h-4" />
146
+ Resume
147
+ </button>
148
+ <button
149
+ onClick={handleNotesClick}
150
+ className="flex-1 py-2 px-4 bg-purple-600 hover:bg-purple-700 rounded-lg text-white font-medium transition flex items-center justify-center gap-2"
151
+ >
152
+ <Upload className="w-4 h-4" />
153
+ Notes
154
+ </button>
155
+ </div>
156
+
157
+ {fileError && (
158
+ <div className="mt-4 p-3 bg-red-500/20 border border-red-500/50 rounded-lg">
159
+ <p className="text-sm text-red-300">{fileError}</p>
160
+ </div>
161
+ )}
162
+
163
+ {uploadedFile && (
164
+ <div className="mt-4 p-3 bg-green-500/20 border border-green-500/50 rounded-lg flex items-center justify-between">
165
+ <div>
166
+ <p className="text-sm text-green-300 font-medium">File uploaded successfully</p>
167
+ <p className="text-xs text-green-200 mt-1">{uploadedFile}</p>
168
+ <p className="text-xs text-green-200">{uploadType === "resume" ? "Resume" : "Notes"}</p>
169
+ </div>
170
+ <button
171
+ onClick={clearUpload}
172
+ className="text-green-300 hover:text-green-200"
173
+ >
174
+ <X className="w-4 h-4" />
175
+ </button>
176
+ </div>
177
+ )}
178
  </div>
179
  );
180
 
 
189
  <h3 className="text-3xl font-bold mb-6 text-gray-100 border-b border-blue-700 pb-2">
190
  1. Select Quiz Source
191
  </h3>
192
+ <div className="space-y-4">
193
+ <SourceCard />
 
 
 
 
 
194
  </div>
195
  </div>
196
 
 
205
  </label>
206
  <textarea
207
  rows={4}
208
+ value={customPrompt}
209
+ onChange={(e) => setCustomPrompt(e.target.value)}
210
  placeholder="e.g., 'Focus on Python only'"
211
  className="w-full p-3 rounded-lg bg-black/40 border border-slate-700 text-gray-100 placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-purple-600 transition"
212
  ></textarea>
 
241
  className={
242
  buttonClass +
243
  " text-xl mt-8 " +
244
+ (!quizType || !fileObject
245
  ? "opacity-50 cursor-not-allowed"
246
  : "opacity-100 cursor-pointer")
247
  }
248
+ disabled={!quizType || !fileObject}
249
+ onClick={generateQuiz} // <--- SEND PDF TO BACKEND
250
  >
251
  Generate Quiz Now
252
  </button>
 
255
  );
256
  };
257
 
258
+ export default ResumeGeneratedQuize;