fix: smart CBT result/back routing for DPPs and add Test Type selector in Admin panel
This commit is contained in:
@@ -646,6 +646,7 @@ class ManualQuestionInput(BaseModel):
|
||||
|
||||
class ManualTestCreate(BaseModel):
|
||||
title: str
|
||||
type: str = "CBT"
|
||||
exam_pattern: str
|
||||
time_limit: int
|
||||
scheduled_date: Optional[datetime] = None
|
||||
@@ -707,7 +708,7 @@ def create_manual_test(
|
||||
# 1. Create the test object
|
||||
test_obj = models.Test(
|
||||
title=data.title,
|
||||
type="Mock",
|
||||
type=data.type,
|
||||
exam_pattern=models.ExamEnum(data.exam_pattern),
|
||||
sections={},
|
||||
total_time=data.time_limit,
|
||||
|
||||
@@ -41,6 +41,7 @@ export default function AdminTestsPage() {
|
||||
|
||||
// Upload Form State
|
||||
const [title, setTitle] = useState("")
|
||||
const [testType, setTestType] = useState("CBT")
|
||||
const [examPattern, setExamPattern] = useState("JEE_Main")
|
||||
const [timeLimit, setTimeLimit] = useState("180")
|
||||
const [scheduledDate, setScheduledDate] = useState<Date | null>(null)
|
||||
@@ -180,6 +181,7 @@ export default function AdminTestsPage() {
|
||||
|
||||
const payload = {
|
||||
title,
|
||||
type: testType,
|
||||
exam_pattern: examPattern,
|
||||
time_limit: parseInt(timeLimit),
|
||||
admin_id: userId,
|
||||
@@ -237,6 +239,27 @@ export default function AdminTestsPage() {
|
||||
<Input required value={title} onChange={e => setTitle(e.target.value)} placeholder="e.g. JEE Main Mock Test 1" />
|
||||
</div>
|
||||
|
||||
{/* TEST TYPE — KEY DIFFERENTIATOR */}
|
||||
<div className="space-y-2">
|
||||
<label className="text-sm font-medium flex items-center gap-2">
|
||||
Test Type
|
||||
<span className="text-[10px] text-muted-foreground font-normal">(determines which section it appears in)</span>
|
||||
</label>
|
||||
<select
|
||||
className="flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2"
|
||||
value={testType}
|
||||
onChange={(e) => setTestType(e.target.value)}
|
||||
>
|
||||
<option value="CBT">🎯 CBT Mock Test — appears in Mock Tests section</option>
|
||||
<option value="DPS">📋 DPP (Daily Practice) — appears in PrepPilot AI section</option>
|
||||
</select>
|
||||
<p className="text-[11px] text-muted-foreground">
|
||||
{testType === 'CBT'
|
||||
? '✅ This will appear under Dashboard → Mock Tests (CBT) for students to attempt.'
|
||||
: '✅ This will appear under AI Coach → PrepPilot AI as a DPP with full CBT interface.'}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<label className="text-sm font-medium">Exam Pattern</label>
|
||||
<select
|
||||
|
||||
@@ -316,6 +316,7 @@ export default function CBTExamPage({ params }: { params: Promise<{ examId: stri
|
||||
<ExamResult
|
||||
payload={payload}
|
||||
attemptId={attemptId}
|
||||
examType={examType}
|
||||
onRetake={examType === 'DPS' ? () => {
|
||||
resetExamState();
|
||||
window.location.reload();
|
||||
|
||||
@@ -62,6 +62,10 @@ export default function AttemptHistoryPage({ params }: { params: Promise<{ attem
|
||||
fetchHistoryData();
|
||||
}, [attemptId, userId]);
|
||||
|
||||
// Smart back route based on test type
|
||||
const backRoute = test?.type === 'DPS' ? '/dashboard/ai-coach/cbt-dpp' : '/dashboard/cbt';
|
||||
const backLabel = test?.type === 'DPS' ? '← Back to PrepPilot AI' : '← Back to Tests';
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="flex h-screen items-center justify-center">
|
||||
@@ -83,8 +87,8 @@ export default function AttemptHistoryPage({ params }: { params: Promise<{ attem
|
||||
|
||||
return (
|
||||
<div className="max-w-6xl mx-auto p-8 animate-in fade-in slide-in-from-bottom-4 duration-500">
|
||||
<Link href="/dashboard/cbt" className="inline-flex items-center text-sm text-muted-foreground hover:text-foreground mb-6 transition-colors">
|
||||
<ArrowLeft size={16} className="mr-2" /> Back to Tests
|
||||
<Link href={backRoute} className="inline-flex items-center text-sm text-muted-foreground hover:text-foreground mb-6 transition-colors">
|
||||
<ArrowLeft size={16} className="mr-2" /> {test?.type === 'DPS' ? 'Back to PrepPilot AI' : 'Back to Tests'}
|
||||
</Link>
|
||||
|
||||
<div className="flex flex-col md:flex-row gap-8 mb-10">
|
||||
|
||||
@@ -19,11 +19,15 @@ interface ExamAttemptPayload {
|
||||
interface ExamResultProps {
|
||||
payload: ExamAttemptPayload;
|
||||
attemptId: string | null;
|
||||
examType?: string; // 'CBT' or 'DPS'
|
||||
onRetake: () => void;
|
||||
}
|
||||
|
||||
export function ExamResult({ payload, attemptId, onRetake }: ExamResultProps) {
|
||||
export function ExamResult({ payload, attemptId, examType, onRetake }: ExamResultProps) {
|
||||
const router = useRouter();
|
||||
const isDPP = examType === 'DPS';
|
||||
const backRoute = isDPP ? '/dashboard/ai-coach/cbt-dpp' : '/dashboard/cbt';
|
||||
const backLabel = isDPP ? 'Back to PrepPilot AI' : 'Back to Mock Tests';
|
||||
const answered = payload.answers.filter(a => a.selected_answer !== null).length;
|
||||
const unanswered = payload.total_questions - answered;
|
||||
|
||||
@@ -114,7 +118,7 @@ export function ExamResult({ payload, attemptId, onRetake }: ExamResultProps) {
|
||||
|
||||
<div className="flex flex-col sm:flex-row gap-4 justify-center pt-8">
|
||||
<Button variant="outline" size="lg" className="rounded-xl h-14 px-8 font-bold text-lg gap-2" onClick={onRetake}>
|
||||
<RotateCcw className="size-5" /> Retake Mock Test
|
||||
<RotateCcw className="size-5" /> {isDPP ? 'Retake DPP' : 'Retake Mock Test'}
|
||||
</Button>
|
||||
{attemptId && (
|
||||
<Button
|
||||
@@ -146,10 +150,10 @@ export function ExamResult({ payload, attemptId, onRetake }: ExamResultProps) {
|
||||
} catch (err) {
|
||||
console.error("Error exiting fullscreen", err);
|
||||
}
|
||||
router.push("/dashboard/cbt");
|
||||
router.push(backRoute);
|
||||
}}
|
||||
>
|
||||
Dashboard <ArrowRight className="size-5" />
|
||||
{backLabel} <ArrowRight className="size-5" />
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user