feat: Add authentic JEE/NEET mock tests and fix CBT frontend filtering

This commit is contained in:
2026-09-24 19:55:12 +05:30
parent 48350bc996
commit a294ee8b9e
9 changed files with 10079 additions and 266 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -175,268 +175,60 @@ def seed_local_database():
jee_test_id = UUID("b6faa295-3bf5-4de2-a587-d72b889629c4") jee_test_id = UUID("b6faa295-3bf5-4de2-a587-d72b889629c4")
neet_test_id = UUID("e7c80521-825b-4c07-889a-ee646c05d762") neet_test_id = UUID("e7c80521-825b-4c07-889a-ee646c05d762")
def generate_dummy_questions(subject: str, count: int, exam: models.ExamEnum, admin_id: UUID, start_idx: int = 1): # --- MOCK TESTS from admin_uploads JSON files ---
qs = [] print("Seeding Mock tests from admin_uploads...")
for i in range(start_idx, count + start_idx): _script_dir = os.path.dirname(os.path.abspath(__file__))
_docker_path = os.path.join(_script_dir, "admin_uploads")
_local_path = os.path.join(_script_dir, "..", "admin_uploads")
mock_json_dir = _docker_path if os.path.isdir(_docker_path) else _local_path
mock_json_files = sorted(glob.glob(os.path.join(mock_json_dir, "mock_*.json")))
for json_path in mock_json_files:
with open(json_path, "r", encoding="utf-8") as f:
raw_questions = json.load(f)
is_neet = "neet" in json_path.lower()
pattern = models.ExamEnum.NEET if is_neet else models.ExamEnum.JEE_MAIN
title = "NEET UG Full Mock Test (2025)" if is_neet else "JEE Advanced Paper 1 (2025)"
sections = {}
for raw_q in raw_questions:
subject = raw_q.get("subject", "General")
if subject not in sections:
sections[subject] = {"name": subject, "questions": [], "time_limit": 45 if is_neet else 60}
q = models.Question( q = models.Question(
id=uuid4(), id=uuid4(),
subject=subject, subject=subject,
topic=f"Generic Topic {i}", topic=raw_q.get("topic", "Mixed"),
subtopic=f"Subtopic {i}", subtopic=raw_q.get("subtopic", "Mixed"),
difficulty="Medium", difficulty=raw_q.get("difficulty", "Medium"),
type=models.QuestionTypeEnum.MCQ_SINGLE, type=models.QuestionTypeEnum(raw_q.get("type", "MCQ_Single")),
question_text=f"This is a simulated {exam.value} {subject} question #{i} for mock exam scaling.", question_text=raw_q.get("question_text", ""),
question_text_hi=f"यह एक अनुरूपित {exam.value} {subject} प्रश्न #{i} है।", options=raw_q.get("options"),
options={"A": "Option A", "B": "Option B", "C": "Option C", "D": "Option D"}, correct_answer=raw_q.get("correct_answer"),
options_hi={"A": "विकल्प A", "B": "विकल्प B", "C": "विकल्प C", "D": "विकल्प D"}, solution_text=raw_q.get("solution_text", ""),
correct_answer={"correct": "A"}, language=models.MediumEnum.ENGLISH,
solution_text="Simulated solution for the mock test.", exam=pattern,
solution_text_hi="मॉक टेस्ट के लिए अनुरूपित समाधान।",
language=models.MediumEnum.BILINGUAL,
year=2024,
exam=exam,
created_by=admin_id created_by=admin_id
) )
qs.append(q) session.add(q)
return qs sections[subject]["questions"].append(str(q.id))
# --- JEE QUESTIONS --- mock_test = models.Test(
id=neet_test_id if is_neet else jee_test_id,
# Physics 1 title=title,
jq1 = models.Question( type="Mock",
id=uuid4(), exam_pattern=pattern,
subject="Physics", sections=sections,
topic="Electrostatics", total_time=180,
subtopic="Coulomb's Law", difficulty="Mixed",
difficulty="Medium", scheduled_date=datetime.utcnow(),
type=models.QuestionTypeEnum.MCQ_SINGLE, is_active=True,
question_text="Two point charges placed at a distance $r$ in air exert a force $F$ on each other. At what distance will they exert the same force if placed in a medium of dielectric constant $K=4$?", created_by=admin_id
question_text_hi="वायु में $r$ दूरी पर स्थित दो बिंदु आवेश एक दूसरे पर $F$ बल लगाते हैं। यदि उन्हें $K=4$ परावैद्युतांक वाले माध्यम में रखा जाए, तो वे किस दूरी पर समान बल लगाएंगे?", )
options={"A": "$r$", "B": "$r/2$", "C": "$2r$", "D": "$r/4$"}, session.add(mock_test)
options_hi={"A": "$r$", "B": "$r/2$", "C": "$2r$", "D": "$r/4$"},
correct_answer={"correct": "B"},
solution_text="Force in medium $F' = \\frac{F}{K}$. To maintain same force, $r' = \\frac{r}{\\sqrt{K}} = \\frac{r}{\\sqrt{4}} = \\frac{r}{2}$.",
solution_text_hi="माध्यम में बल $F' = \\frac{F}{K}$। समान बल बनाए रखने के लिए, $r' = \\frac{r}{\\sqrt{K}} = \\frac{r}{\\sqrt{4}} = \\frac{r}{2}$।",
language=models.MediumEnum.BILINGUAL,
year=2024,
exam=models.ExamEnum.JEE_MAIN,
created_by=admin_id
)
# Physics 2
jq2 = models.Question(
id=uuid4(),
subject="Physics",
topic="Mechanics",
subtopic="Rotational Motion",
difficulty="Hard",
type=models.QuestionTypeEnum.MCQ_SINGLE,
question_text="A solid cylinder of mass $M$ and radius $R$ is rolling without slipping down an inclined plane of angle $\\theta$. What is the minimum coefficient of static friction $\\mu_s$ required to prevent slipping?",
question_text_hi="द्रव्यमान $M$ और त्रिज्या $R$ का एक ठोस बेलन कोण $\\theta$ के एक झुके हुए तल पर बिना फिसले लुढ़क रहा है। फिसलने से रोकने के लिए आवश्यक न्यूनतम स्थैतिक घर्षण गुणांक $\\mu_s$ क्या है?",
options={"A": "$\\frac{1}{3} \\tan \\theta$", "B": "$\\frac{2}{3} \\tan \\theta$", "C": "$\\frac{1}{2} \\tan \\theta$", "D": "$\\tan \\theta$"},
options_hi={"A": "$\\frac{1}{3} \\tan \\theta$", "B": "$\\frac{2}{3} \\tan \\theta$", "C": "$\\frac{1}{2} \\tan \\theta$", "D": "$\\tan \\theta$"},
correct_answer={"correct": "A"},
solution_text="$a = \\frac{g \\sin \\theta}{1 + \\frac{k^2}{R^2}}$. For solid cylinder $k^2 = \\frac{R^2}{2}$. So $a = \\frac{2}{3} g \\sin \\theta$. Friction $f = Mg \\sin \\theta - Ma = \\frac{1}{3} Mg \\sin \\theta$. Since $f \\le \\mu_s Mg \\cos \\theta$, $\\mu_s \\ge \\frac{1}{3} \\tan \\theta$.",
solution_text_hi="$a = \\frac{g \\sin \\theta}{1 + \\frac{k^2}{R^2}}$। ठोस बेलन के लिए $k^2 = \\frac{R^2}{2}$। इसलिए $a = \\frac{2}{3} g \\sin \\theta$। घर्षण $f = Mg \\sin \\theta - Ma = \\frac{1}{3} Mg \\sin \\theta$। चूंकि $f \\le \\mu_s Mg \\cos \\theta$, $\\mu_s \\ge \\frac{1}{3} \\tan \\theta$ है।",
language=models.MediumEnum.BILINGUAL,
year=2023,
exam=models.ExamEnum.JEE_MAIN,
created_by=admin_id
)
# Chemistry 1
jq3 = models.Question(
id=uuid4(),
subject="Chemistry",
topic="Physical Chemistry",
subtopic="Chemical Kinetics",
difficulty="Medium",
type=models.QuestionTypeEnum.MCQ_SINGLE,
question_text="For a first-order reaction, the time required for $99\\%$ completion is $x$ times the time required for $90\\%$ completion. The value of $x$ is:",
question_text_hi="एक प्रथम-कोटि की अभिक्रिया के लिए, $99\\%$ पूर्ण होने में लगा समय $90\\%$ पूर्ण होने में लगे समय का $x$ गुना है। $x$ का मान है:",
options={"A": "$2$", "B": "$10$", "C": "$3$", "D": "$4$"},
options_hi={"A": "$2$", "B": "$10$", "C": "$3$", "D": "$4$"},
correct_answer={"correct": "A"},
solution_text="$t = \\frac{2.303}{k} \\log \\frac{100}{100-x}$. $t_{99} = \\frac{2.303}{k} \\log 100 = 2 \\times \\frac{2.303}{k}$. $t_{90} = \\frac{2.303}{k} \\log 10 = 1 \\times \\frac{2.303}{k}$. Therefore $x = 2$.",
solution_text_hi="$t = \\frac{2.303}{k} \\log \\frac{100}{100-x}$। $t_{99} = \\frac{2.303}{k} \\log 100 = 2 \\times \\frac{2.303}{k}$। $t_{90} = \\frac{2.303}{k} \\log 10 = 1 \\times \\frac{2.303}{k}$। इसलिए $x = 2$ है।",
language=models.MediumEnum.BILINGUAL,
year=2024,
exam=models.ExamEnum.JEE_MAIN,
created_by=admin_id
)
# Maths 1
jq4 = models.Question(
id=uuid4(),
subject="Mathematics",
topic="Calculus",
subtopic="Definite Integration",
difficulty="Hard",
type=models.QuestionTypeEnum.MCQ_SINGLE,
question_text="The value of the integral $\\int_{0}^{\\pi/2} \\frac{\\sin^3 x}{\\sin^3 x + \\cos^3 x} dx$ is:",
question_text_hi="समाकल $\\int_{0}^{\\pi/2} \\frac{\\sin^3 x}{\\sin^3 x + \\cos^3 x} dx$ का मान है:",
options={"A": "$\\pi/2$", "B": "$\\pi/4$", "C": "$0$", "D": "$\\pi/8$"},
options_hi={"A": "$\\pi/2$", "B": "$\\pi/4$", "C": "$0$", "D": "$\\pi/8$"},
correct_answer={"correct": "B"},
solution_text="Let $I = \\int_{0}^{\\pi/2} \\frac{\\sin^3 x}{\\sin^3 x + \\cos^3 x} dx$. Using $\\int_0^a f(x)dx = \\int_0^a f(a-x)dx$, we get $I = \\int_{0}^{\\pi/2} \\frac{\\cos^3 x}{\\cos^3 x + \\sin^3 x} dx$. Adding both, $2I = \\int_{0}^{\\pi/2} 1 dx = \\pi/2$. Thus $I = \\pi/4$.",
solution_text_hi="माना $I = \\int_{0}^{\\pi/2} \\frac{\\sin^3 x}{\\sin^3 x + \\cos^3 x} dx$। गुणधर्म $\\int_0^a f(x)dx = \\int_0^a f(a-x)dx$ का उपयोग करने पर, $I = \\int_{0}^{\\pi/2} \\frac{\\cos^3 x}{\\cos^3 x + \\sin^3 x} dx$। दोनों को जोड़ने पर, $2I = \\int_{0}^{\\pi/2} 1 dx = \\pi/2$। इसलिए $I = \\pi/4$ है।",
language=models.MediumEnum.BILINGUAL,
year=2023,
exam=models.ExamEnum.JEE_MAIN,
created_by=admin_id
)
jee_physics_dummies = generate_dummy_questions("Physics", 28, models.ExamEnum.JEE_MAIN, admin_id, start_idx=3)
jee_chem_dummies = generate_dummy_questions("Chemistry", 29, models.ExamEnum.JEE_MAIN, admin_id, start_idx=2)
jee_math_dummies = generate_dummy_questions("Mathematics", 29, models.ExamEnum.JEE_MAIN, admin_id, start_idx=2)
session.add_all([jq1, jq2, jq3, jq4])
session.add_all(jee_physics_dummies)
session.add_all(jee_chem_dummies)
session.add_all(jee_math_dummies)
# --- NEET QUESTIONS ---
# Biology 1
nq1 = models.Question(
id=uuid4(),
subject="Botany",
topic="Genetics",
subtopic="Translation",
difficulty="Easy",
type=models.QuestionTypeEnum.MCQ_SINGLE,
question_text="Which of the following codons codes for Methionine and also acts as an initiator codon?",
question_text_hi="निम्नलिखित में से कौन सा कोडॉन मेथियोनिन के लिए कोड करता है और एक प्रारंभक कोडॉन के रूप में भी कार्य करता है?",
options={"A": "AUG", "B": "GUG", "C": "UAA", "D": "UAG"},
options_hi={"A": "AUG", "B": "GUG", "C": "UAA", "D": "UAG"},
correct_answer={"correct": "A"},
solution_text="AUG is the starting codon (initiator codon) in eukaryotes and prokaryotes and also codes for the amino acid methionine.",
solution_text_hi="AUG यूकेरियोट्स और प्रोकैरियोट्स में प्रारंभिक कोडॉन (प्रारंभक कोडॉन) है और अमीनो एसिड मेथियोनिन के लिए भी कोड करता है।",
language=models.MediumEnum.BILINGUAL,
year=2024,
exam=models.ExamEnum.NEET,
created_by=admin_id
)
# Physics 1 (NEET)
nq2 = models.Question(
id=uuid4(),
subject="Physics",
topic="Kinematics",
subtopic="Motion under Gravity",
difficulty="Medium",
type=models.QuestionTypeEnum.MCQ_SINGLE,
question_text="A ball is thrown vertically upward with a velocity of $20\\text{ m/s}$ from the top of a tower. If the height of the tower is $25\\text{ m}$, the time taken by the ball to reach the ground is (take $g = 10\\text{ m/s}^2$):",
question_text_hi="एक मीनार के शीर्ष से एक गेंद को $20\\text{ मी/से}$ के वेग से लंबवत ऊपर की ओर फेंका जाता है। यदि मीनार की ऊंचाई $25\\text{ मीटर}$ है, तो गेंद को जमीन पर पहुंचने में लगा समय है ($g = 10\\text{ मी/से}^2$ लें):",
options={"A": "$5\\text{ s}$", "B": "$3\\text{ s}$", "C": "$4\\text{ s}$", "D": "$2\\text{ s}$"},
options_hi={"A": "$5\\text{ सेकंड}$", "B": "$3\\text{ सेकंड}$", "C": "$4\\text{ सेकंड}$", "D": "$2\\text{ सेकंड}$"},
correct_answer={"correct": "A"},
solution_text="Using $s = ut + \\frac{1}{2}at^2$. Taking upward direction positive: $-25 = 20t - \\frac{1}{2}(10)t^2 \\implies 5t^2 - 20t - 25 = 0 \\implies t^2 - 4t - 5 = 0 \\implies (t-5)(t+1) = 0$. Since time cannot be negative, $t = 5\\text{ s}$.",
solution_text_hi="$s = ut + \\frac{1}{2}at^2$ का उपयोग करने पर। ऊपर की दिशा को धनात्मक मानने पर: $-25 = 20t - \\frac{1}{2}(10)t^2 \\implies 5t^2 - 20t - 25 = 0 \\implies t^2 - 4t - 5 = 0 \\implies (t-5)(t+1) = 0$। चूंकि समय ऋणात्मक नहीं हो सकता, $t = 5$ सेकंड है।",
language=models.MediumEnum.BILINGUAL,
year=2023,
exam=models.ExamEnum.NEET,
created_by=admin_id
)
# Chemistry 1 (NEET)
nq3 = models.Question(
id=uuid4(),
subject="Chemistry",
topic="Periodic Table",
subtopic="Ionic Radii",
difficulty="Medium",
type=models.QuestionTypeEnum.MCQ_SINGLE,
question_text="Which of the following represents the correct order of increasing ionic radii for isoelectronic species?",
question_text_hi="समइलेक्ट्रॉनिक प्रजातियों के लिए बढ़ती हुई आयनिक त्रिज्या का सही क्रम निम्नलिखित में से कौन सा दर्शाता है?",
options={"A": "$\\text{O}^{2-} < \\text{F}^- < \\text{Na}^+$", "B": "$\\text{Na}^+ < \\text{F}^- < \\text{O}^{2-}$", "C": "$\\text{F}^- < \\text{Na}^+ < \\text{O}^{2-}$", "D": "$\\text{O}^{2-} < \\text{Na}^+ < \\text{F}^-$"},
options_hi={"A": "$\\text{O}^{2-} < \\text{F}^- < \\text{Na}^+$", "B": "$\\text{Na}^+ < \\text{F}^- < \\text{O}^{2-}$", "C": "$\\text{F}^- < \\text{Na}^+ < \\text{O}^{2-}$", "D": "$\\text{O}^{2-} < \\text{Na}^+ < \\text{F}^-$"},
correct_answer={"correct": "B"},
solution_text="For isoelectronic species, ionic radii decrease with increase in atomic number (or nuclear charge). Nuclear charge: $\\text{Na}^+ (11) > \\text{F}^- (9) > \\text{O}^{2-} (8)$. Therefore, the correct order is $\\text{Na}^+ < \\text{F}^- < \\text{O}^{2-}$.",
solution_text_hi="समइलेक्ट्रॉनिक प्रजातियों के लिए, परमाणु संख्या (या नाभिकीय आवेश) में वृद्धि के साथ आयनिक त्रिज्या कम होती जाती है। नाभिकीय आवेश: $\\text{Na}^+ (11) > \\text{F}^- (9) > \\text{O}^{2-} (8)$। इसलिए, सही क्रम $\\text{Na}^+ < \\text{F}^- < \\text{O}^{2-}$ है।",
language=models.MediumEnum.BILINGUAL,
year=2024,
exam=models.ExamEnum.NEET,
created_by=admin_id
)
neet_physics_dummies = generate_dummy_questions("Physics", 49, models.ExamEnum.NEET, admin_id, start_idx=2)
neet_chem_dummies = generate_dummy_questions("Chemistry", 49, models.ExamEnum.NEET, admin_id, start_idx=2)
neet_botany_dummies = generate_dummy_questions("Botany", 49, models.ExamEnum.NEET, admin_id, start_idx=2)
neet_zoology_dummies = generate_dummy_questions("Zoology", 50, models.ExamEnum.NEET, admin_id, start_idx=1)
session.add_all([nq1, nq2, nq3])
session.add_all(neet_physics_dummies)
session.add_all(neet_chem_dummies)
session.add_all(neet_botany_dummies)
session.add_all(neet_zoology_dummies)
# --- TESTS CREATION ---
# 1. JEE Mock Test
jee_test = models.Test(
id=jee_test_id,
title="JEE Main Full Mock Test #1 (2025)",
type="Mock",
exam_pattern=models.ExamEnum.JEE_MAIN,
sections={
"Physics": {
"name": "Physics",
"questions": [str(jq1.id), str(jq2.id)] + [str(q.id) for q in jee_physics_dummies],
"time_limit": 60
},
"Chemistry": {
"name": "Chemistry",
"questions": [str(jq3.id)] + [str(q.id) for q in jee_chem_dummies],
"time_limit": 60
},
"Mathematics": {
"name": "Mathematics",
"questions": [str(jq4.id)] + [str(q.id) for q in jee_math_dummies],
"time_limit": 60
}
},
total_time=180,
difficulty="Mixed",
scheduled_date=datetime.utcnow(),
created_by=admin_id
)
session.add(jee_test)
# 2. NEET Mock Test
neet_test = models.Test(
id=neet_test_id,
title="NEET UG Full Mock Test #1 (2025)",
type="Mock",
exam_pattern=models.ExamEnum.NEET,
sections={
"Physics": {
"name": "Physics",
"questions": [str(nq2.id)] + [str(q.id) for q in neet_physics_dummies],
"time_limit": 45
},
"Chemistry": {
"name": "Chemistry",
"questions": [str(nq3.id)] + [str(q.id) for q in neet_chem_dummies],
"time_limit": 45
},
"Botany": {
"name": "Botany",
"questions": [str(nq1.id)] + [str(q.id) for q in neet_botany_dummies],
"time_limit": 45
},
"Zoology": {
"name": "Zoology",
"questions": [str(q.id) for q in neet_zoology_dummies],
"time_limit": 45
}
},
total_time=180,
difficulty="Mixed",
scheduled_date=datetime.utcnow(),
created_by=admin_id
)
session.add(neet_test)
session.commit() session.commit()
@@ -516,9 +308,9 @@ def seed_local_database():
dps_session.commit() dps_session.commit()
print("\n=== LOCAL SEED COMPLETED SUCCESSFULLY ===") print("\n=== LOCAL SEED COMPLETED SUCCESSFULLY ===")
print(f"JEE Test ID: {jee_test.id}") print(f"JEE Test ID: {jee_test_id}")
print(f"NEET Test ID: {neet_test.id}") print(f"NEET Test ID: {neet_test_id}")
print(f"DPS Sheets: {len(dps_json_files)} seeded from admin_uploads/\n") print("DPS Sheets: seeded from admin_uploads/\n")
if __name__ == "__main__": if __name__ == "__main__":
seed_local_database() seed_local_database()

11
fix_print.py Normal file
View File

@@ -0,0 +1,11 @@
import os
with open('backend/seed.py', 'r', encoding='utf-8') as f:
content = f.read()
content = content.replace('print(f"JEE Test ID: {jee_test.id}")', 'print(f"JEE Test ID: {jee_test_id}")')
content = content.replace('print(f"NEET Test ID: {neet_test.id}")', 'print(f"NEET Test ID: {neet_test_id}")')
content = content.replace('print(f"DPS Sheets: {len(dps_json_files)} seeded from admin_uploads/\\n")', 'print("DPS Sheets: seeded from admin_uploads/\\n")')
with open('backend/seed.py', 'w', encoding='utf-8') as f:
f.write(content)

File diff suppressed because it is too large Load Diff

82
modify.py Normal file
View File

@@ -0,0 +1,82 @@
import os
with open('backend/seed.py', 'r', encoding='utf-8') as f:
lines = f.readlines()
new_lines = []
skip = False
for i, line in enumerate(lines):
if 'jee_test_id = UUID' in line:
skip = True
new_lines.append(line)
new_lines.append(lines[i+1]) # neet_test_id
replacement = """
# --- MOCK TESTS from admin_uploads JSON files ---
print("Seeding Mock tests from admin_uploads...")
_script_dir = os.path.dirname(os.path.abspath(__file__))
_docker_path = os.path.join(_script_dir, "admin_uploads")
_local_path = os.path.join(_script_dir, "..", "admin_uploads")
mock_json_dir = _docker_path if os.path.isdir(_docker_path) else _local_path
mock_json_files = sorted(glob.glob(os.path.join(mock_json_dir, "mock_*.json")))
for json_path in mock_json_files:
with open(json_path, "r", encoding="utf-8") as f:
raw_questions = json.load(f)
is_neet = "neet" in json_path.lower()
pattern = models.ExamEnum.NEET if is_neet else models.ExamEnum.JEE_MAIN
title = "NEET UG Full Mock Test (2025)" if is_neet else "JEE Advanced Paper 1 (2025)"
sections = {}
for raw_q in raw_questions:
subject = raw_q.get("subject", "General")
if subject not in sections:
sections[subject] = {"name": subject, "questions": [], "time_limit": 45 if is_neet else 60}
q = models.Question(
id=uuid4(),
subject=subject,
topic=raw_q.get("topic", "Mixed"),
subtopic=raw_q.get("subtopic", "Mixed"),
difficulty=raw_q.get("difficulty", "Medium"),
type=models.QuestionTypeEnum(raw_q.get("type", "MCQ_Single")),
question_text=raw_q.get("question_text", ""),
options=raw_q.get("options"),
correct_answer=raw_q.get("correct_answer"),
solution_text=raw_q.get("solution_text", ""),
language=models.MediumEnum.ENGLISH,
exam=pattern,
created_by=admin_id
)
session.add(q)
sections[subject]["questions"].append(str(q.id))
mock_test = models.Test(
id=neet_test_id if is_neet else jee_test_id,
title=title,
type="Mock",
exam_pattern=pattern,
sections=sections,
total_time=180,
difficulty="Mixed",
scheduled_date=datetime.utcnow(),
is_active=True,
created_by=admin_id
)
session.add(mock_test)
session.commit()
"""
new_lines.append(replacement)
elif '--- DPS (Daily Practice Sheets)' in line:
skip = False
if not skip:
new_lines.append(line)
with open('backend/seed.py', 'w', encoding='utf-8') as f:
f.writelines(new_lines)

File diff suppressed because it is too large Load Diff

View File

@@ -43,11 +43,11 @@ export default function CBTPage() {
if (!userRes.ok) throw new Error("Failed to load user target exam"); if (!userRes.ok) throw new Error("Failed to load user target exam");
const userData = await userRes.json(); const userData = await userRes.json();
const pattern = userData.target_exam; const pattern = userData.target_exam;
setTargetExam(pattern === "NEET" ? "NEET" : pattern === "JEE_Advanced" ? "JEE Advanced" : "JEE"); setTargetExam(pattern === "JEE_NEET" ? "JEE & NEET" : pattern === "NEET" ? "NEET" : pattern === "JEE_Advanced" ? "JEE Advanced" : "JEE");
// Only set the initial pattern if it hasn't been changed by the user // Only set the initial pattern if it hasn't been changed by the user
if (!selectedPattern) { if (!selectedPattern) {
setSelectedPattern(pattern.startsWith("JEE") ? "JEE" : "NEET"); setSelectedPattern(pattern === "JEE_NEET" ? "JEE_NEET" : pattern.startsWith("JEE") ? "JEE" : "NEET");
} }
} catch (err) { } catch (err) {
console.error("Error loading user:", err); console.error("Error loading user:", err);
@@ -62,11 +62,11 @@ export default function CBTPage() {
async function loadTests() { async function loadTests() {
setLoading(true); setLoading(true);
try { try {
let url = `/api/tests?user_id=${userId}`; let url = `/api/tests?user_id=${userId}&type=Mock`;
if (selectedPattern !== "JEE") { if (selectedPattern !== "JEE" && selectedPattern !== "JEE_NEET") {
url += `&exam_pattern=${selectedPattern}`; url += `&exam_pattern=${selectedPattern}`;
} }
const testRes = await fetch(url); const testRes = await fetchWithAuth(url);
if (testRes.ok) { if (testRes.ok) {
let testsData = await testRes.json(); let testsData = await testRes.json();
if (selectedPattern === "JEE") { if (selectedPattern === "JEE") {

View File

@@ -160,6 +160,14 @@ export default function DashboardLayout({ children }: { children: ReactNode }) {
active={pathname.startsWith("/dashboard/cbt")} active={pathname.startsWith("/dashboard/cbt")}
isLocked={!hasAccessTo("weekly-test-series")} isLocked={!hasAccessTo("weekly-test-series")}
/> />
<NavItem
section="pro"
href="/dashboard/dpp"
icon={<FileText size={17} />}
label="Daily Practice (DPP)"
active={pathname.startsWith("/dashboard/dpp")}
isLocked={!hasAccessTo("chapter-wise-progress-tracking")}
/>
<NavItem <NavItem
section="pro" section="pro"