feat(patterns): tutorial system
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
import Link from "next/link";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card";
|
||||
import { getDifficultyVariant, capitalize } from "@/lib/utils";
|
||||
import type { LearningProgression as LearningProgressionType } from "@/types";
|
||||
|
||||
interface LearningProgressionProps {
|
||||
progression: LearningProgressionType;
|
||||
}
|
||||
|
||||
export function LearningProgression({ progression }: LearningProgressionProps) {
|
||||
const hasQuestions =
|
||||
progression.warmup.length > 0 ||
|
||||
progression.core.length > 0 ||
|
||||
progression.challenge.length > 0;
|
||||
|
||||
if (!hasQuestions) return null;
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Learning Path</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="space-y-6">
|
||||
{progression.warmup.length > 0 && (
|
||||
<div>
|
||||
<h4 className="font-semibold text-[var(--difficulty-easy)] mb-3 flex items-center gap-2">
|
||||
<span className="w-6 h-6 rounded-full bg-[var(--difficulty-easy-bg)] flex items-center justify-center text-sm">
|
||||
1
|
||||
</span>
|
||||
Warmup
|
||||
</h4>
|
||||
<p className="text-sm text-[var(--muted-foreground)] mb-3">
|
||||
Start here to build foundational understanding.
|
||||
</p>
|
||||
<div className="space-y-2">
|
||||
{progression.warmup.map((q) => (
|
||||
<QuestionLink key={q.id} question={q} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{progression.core.length > 0 && (
|
||||
<div>
|
||||
<h4 className="font-semibold text-[var(--difficulty-medium)] mb-3 flex items-center gap-2">
|
||||
<span className="w-6 h-6 rounded-full bg-[var(--difficulty-medium-bg)] flex items-center justify-center text-sm">
|
||||
2
|
||||
</span>
|
||||
Core Practice
|
||||
</h4>
|
||||
<p className="text-sm text-[var(--muted-foreground)] mb-3">
|
||||
Master the pattern with these representative problems.
|
||||
</p>
|
||||
<div className="space-y-2">
|
||||
{progression.core.map((q) => (
|
||||
<QuestionLink key={q.id} question={q} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{progression.challenge.length > 0 && (
|
||||
<div>
|
||||
<h4 className="font-semibold text-[var(--difficulty-hard)] mb-3 flex items-center gap-2">
|
||||
<span className="w-6 h-6 rounded-full bg-[var(--difficulty-hard-bg)] flex items-center justify-center text-sm">
|
||||
3
|
||||
</span>
|
||||
Challenge
|
||||
</h4>
|
||||
<p className="text-sm text-[var(--muted-foreground)] mb-3">
|
||||
Test your mastery with complex variations.
|
||||
</p>
|
||||
<div className="space-y-2">
|
||||
{progression.challenge.map((q) => (
|
||||
<QuestionLink key={q.id} question={q} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
interface QuestionLinkProps {
|
||||
question: LearningProgressionType["warmup"][number];
|
||||
}
|
||||
|
||||
function QuestionLink({ question }: QuestionLinkProps) {
|
||||
return (
|
||||
<Link
|
||||
href={`/questions/${question.slug}`}
|
||||
className="flex items-center justify-between p-3 rounded-lg border border-[var(--border)] bg-[var(--card)] hover:border-[var(--primary)] transition-colors"
|
||||
>
|
||||
<span className="font-medium">{question.title}</span>
|
||||
<div className="flex items-center gap-2">
|
||||
{question.leetcode_id && (
|
||||
<span className="text-xs text-[var(--muted-foreground)]">
|
||||
#{question.leetcode_id}
|
||||
</span>
|
||||
)}
|
||||
<Badge variant={getDifficultyVariant(question.difficulty)}>
|
||||
{capitalize(question.difficulty)}
|
||||
</Badge>
|
||||
</div>
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user