Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions backend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

23 changes: 14 additions & 9 deletions backend/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,18 @@ app.use(express.json({ limit: '50mb' }));
app.use(express.urlencoded({ limit: '50mb', extended: true }));
app.use(express.text({ limit: '50mb' }));

// Routes
// API routes
app.use('/api/quiz', quizRoutes);

// Serve frontend static files in production
const distPath = path.resolve(__dirname, '../dist');
app.use(express.static(distPath));
// Only serve frontend build in production
if (process.env.NODE_ENV === 'production') {
const distPath = path.resolve(__dirname, '../dist');
app.use(express.static(distPath));

// SPA fallback — serve index.html for any non-API route
app.get('*', (req, res) => {
res.sendFile(path.join(distPath, 'index.html'));
});
app.get('*', (req, res) => {
res.sendFile(path.join(distPath, 'index.html'));
});
}

// Error handler
app.use((err, req, res, next) => {
Expand All @@ -39,7 +40,11 @@ app.use((err, req, res, next) => {
details: 'File size exceeds the 50MB limit. Please upload a smaller document.',
});
}
res.status(500).json({ error: 'Internal Server Error', details: err.message });

res.status(500).json({
error: 'Internal Server Error',
details: err.message,
});
});

app.listen(PORT, () => {
Expand Down
36 changes: 10 additions & 26 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions src/App.css
Original file line number Diff line number Diff line change
Expand Up @@ -1307,4 +1307,12 @@ a {
.progress-side-panel {
order: 2;
}

.field-error {
color: #e04561;
font-size: 13px;
margin-top: 4px;
margin-bottom: 4px;
font-weight: 600;
}
}
61 changes: 40 additions & 21 deletions src/pages/FeedbackPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ function FeedbackPage() {
const selectedAnswers = location.state?.selectedAnswers || {};
const currentIndex = location.state?.currentIndex ?? 0;

// NEW: backend result support
const score = location.state?.score ?? 0;
const total = location.state?.total ?? questions.length;
const correctAnswers = location.state?.correctAnswers ?? score;
const wrongAnswers = location.state?.wrongAnswers ?? total - score;

if (!questions.length) {
return (
<div className="empty-state-page">
Expand Down Expand Up @@ -43,28 +49,34 @@ function FeedbackPage() {
<div className="feedback-layout">
<aside className="progress-side-panel themed-card">
<div className="side-title">QUIZ PROGRESS</div>

<div className="step-label">
STEP {currentIndex + 1} OF {questions.length}
Score: {score} / {total}
</div>

<div className="progress-track">
<div
className="progress-fill"
style={{ width: `${((currentIndex + 1) / questions.length) * 100}%` }}
style={{ width: `${(score / total) * 100}%` }}
></div>
</div>

<ul className="progress-list">
<li className="done-item">Basics of Arrays</li>
<li className="done-item">Linear Search</li>
<li className="active-item-text">Binary Search Logic</li>
<li>Complexity Analysis</li>
</ul>
<div className="result-breakdown">
<p>✅ Correct: {correctAnswers}</p>
<p>❌ Wrong: {wrongAnswers}</p>
</div>
</aside>

<main className="feedback-main">
<section className="feedback-header">
<h1>Keep going, Alex!</h1>
<p>Mistakes are the best way to master complex logic.</p>
<h1>
{isCorrect ? "Great job!" : "Keep going!"}
</h1>
<p>
{isCorrect
? "You're on the right track."
: "Mistakes are the best way to master complex logic."}
</p>
</section>

<section className="themed-card question-feedback-card">
Expand All @@ -76,7 +88,8 @@ function FeedbackPage() {
let boxClass = "feedback-option-box";

if (option === correctAnswer) boxClass += " correct-box";
if (userAnswer === option && option !== correctAnswer) boxClass += " wrong-box";
if (userAnswer === option && option !== correctAnswer)
boxClass += " wrong-box";

return (
<div key={index} className={boxClass}>
Expand All @@ -94,37 +107,43 @@ function FeedbackPage() {
<section className="themed-card explanation-card">
<div className="explanation-top">
<h3>AI Explanation</h3>
<div className="tag-pill small-pill">LUCID MENTOR ANALYSIS</div>
<div className="tag-pill small-pill">
LUCID MENTOR ANALYSIS
</div>
</div>

<p>
{isCorrect
? "Great job. Your answer matches the expected reasoning. This concept works because the underlying condition is already organized in a way that supports efficient searching."
: "Think of this like finding a name in a sorted phone book. Because the data is ordered, you can repeatedly eliminate half of the remaining items. That is why the more efficient approach depends on sorted input."}
? "Great job. Your answer matches the expected reasoning."
: "Think of this like searching in a sorted structure. Efficient algorithms eliminate large portions quickly, which is why ordering matters."}
</p>

<div className="explanation-actions">
<button className="primary-btn" onClick={() => navigate("/dashboard")}>
Continue to Next Question →
<button
className="primary-btn"
onClick={() => navigate("/dashboard")}
>
Go to Dashboard →
</button>
<button className="secondary-btn">
Ask AI More
</button>
<button className="secondary-btn">Ask AI More</button>
</div>
</section>

<div className="tip-grid">
<div className="tip-card themed-card">
<strong>Pro Tip</strong>
<p>
Efficient searching often depends on structure. Ordered data creates
stronger algorithmic shortcuts.
Efficient searching depends on structure. Ordered data allows
faster algorithms.
</p>
</div>

<div className="tip-card themed-card">
<strong>Confused?</strong>
<p>
Our interactive visualizer can show how the algorithm narrows the
search space.
Use visual explanations to better understand how the algorithm works.
</p>
</div>
</div>
Expand Down
Loading
Loading