feat(patterns): tutorial system
This commit is contained in:
@@ -1,8 +1,18 @@
|
||||
import type { Metadata } from "next";
|
||||
import { getPattern, getQuestions } from "@/lib/api";
|
||||
import { QuestionCard } from "@/components/questions/question-card";
|
||||
import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card";
|
||||
import { notFound } from "next/navigation";
|
||||
import { getPatternTutorial } from "@/lib/api";
|
||||
import { Card, CardHeader, CardTitle, CardContent } from "@/components/ui/card";
|
||||
import { CodeBlock } from "@/components/ui/code-block";
|
||||
import { Markdown } from "@/components/ui/markdown";
|
||||
import { Callout } from "@/components/ui/callout";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import {
|
||||
CommonMistakesList,
|
||||
LearningProgression,
|
||||
PatternVariations,
|
||||
RecognitionSignals,
|
||||
RelatedPatterns,
|
||||
} from "@/components/patterns";
|
||||
|
||||
interface PageProps {
|
||||
params: Promise<{ slug: string }>;
|
||||
@@ -12,7 +22,7 @@ export async function generateMetadata({ params }: PageProps): Promise<Metadata>
|
||||
const { slug } = await params;
|
||||
|
||||
try {
|
||||
const pattern = await getPattern(slug);
|
||||
const pattern = await getPatternTutorial(slug);
|
||||
const description =
|
||||
pattern.description ||
|
||||
`Learn the ${pattern.name} pattern with ${pattern.question_count} practice problems.`;
|
||||
@@ -37,52 +47,142 @@ export default async function PatternDetailPage({ params }: PageProps) {
|
||||
const { slug } = await params;
|
||||
|
||||
let pattern;
|
||||
let questions;
|
||||
try {
|
||||
[pattern, questions] = await Promise.all([
|
||||
getPattern(slug),
|
||||
getQuestions({ pattern: slug, limit: 50 }),
|
||||
]);
|
||||
pattern = await getPatternTutorial(slug);
|
||||
} catch {
|
||||
notFound();
|
||||
}
|
||||
|
||||
const difficultyLabels = ["Beginner", "Easy", "Intermediate", "Advanced", "Expert"];
|
||||
const difficultyLabel = pattern.difficulty_level
|
||||
? difficultyLabels[pattern.difficulty_level - 1] || "Intermediate"
|
||||
: null;
|
||||
|
||||
return (
|
||||
<div className="max-w-4xl mx-auto space-y-8">
|
||||
{/* Header */}
|
||||
<div>
|
||||
<h1 className="text-3xl font-bold mb-2">{pattern.name}</h1>
|
||||
<div className="flex items-center gap-3 mb-2">
|
||||
<h1 className="text-3xl font-bold">{pattern.name}</h1>
|
||||
{difficultyLabel && (
|
||||
<Badge variant="outline">{difficultyLabel}</Badge>
|
||||
)}
|
||||
</div>
|
||||
<p className="text-[var(--muted-foreground)]">
|
||||
{pattern.question_count} questions using this pattern
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Description */}
|
||||
{pattern.description && (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Description</CardTitle>
|
||||
<CardTitle>What is {pattern.name}?</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>{pattern.description}</CardContent>
|
||||
<CardContent>
|
||||
<Markdown>{pattern.description}</Markdown>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
{/* Metaphor - The relatable analogy */}
|
||||
{pattern.metaphor && (
|
||||
<Callout variant="insight" title="Think of it like this...">
|
||||
<Markdown>{pattern.metaphor}</Markdown>
|
||||
</Callout>
|
||||
)}
|
||||
|
||||
{/* Core Concept - The "aha!" insight */}
|
||||
{pattern.core_concept && (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Core Concept</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<Markdown>{pattern.core_concept}</Markdown>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
{/* Visualization - ASCII diagram walkthrough */}
|
||||
{pattern.visualization && (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Visual Walkthrough</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<Markdown>{pattern.visualization}</Markdown>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
{/* Code Template */}
|
||||
{pattern.code_template && (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Code Template</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<p className="text-sm text-[var(--muted-foreground)] mb-4">
|
||||
Use this skeleton as a starting point for problems using this pattern:
|
||||
</p>
|
||||
<CodeBlock
|
||||
code={pattern.code_template}
|
||||
language="python"
|
||||
label="Pattern code template"
|
||||
/>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
{/* Recognition Signals */}
|
||||
{pattern.recognition_signals && pattern.recognition_signals.length > 0 && (
|
||||
<RecognitionSignals signals={pattern.recognition_signals} />
|
||||
)}
|
||||
|
||||
{/* When to Use */}
|
||||
{pattern.when_to_use && (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>When to Use</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="whitespace-pre-wrap">
|
||||
{pattern.when_to_use}
|
||||
<CardContent>
|
||||
<Markdown>{pattern.when_to_use}</Markdown>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
<div className="space-y-4">
|
||||
<h2 className="text-xl font-semibold">Questions</h2>
|
||||
<div className="grid gap-4">
|
||||
{questions.items.map((question) => (
|
||||
<QuestionCard key={question.id} question={question} />
|
||||
))}
|
||||
</div>
|
||||
{/* Common Mistakes */}
|
||||
{pattern.common_mistakes && pattern.common_mistakes.length > 0 && (
|
||||
<CommonMistakesList mistakes={pattern.common_mistakes} />
|
||||
)}
|
||||
|
||||
{/* Pattern Variations */}
|
||||
{pattern.variations && pattern.variations.length > 0 && (
|
||||
<PatternVariations variations={pattern.variations} />
|
||||
)}
|
||||
|
||||
{/* Learning Progression */}
|
||||
{pattern.learning_progression && (
|
||||
<LearningProgression progression={pattern.learning_progression} />
|
||||
)}
|
||||
|
||||
{/* Related Patterns */}
|
||||
<div className="grid md:grid-cols-2 gap-6">
|
||||
{pattern.prerequisite_patterns && pattern.prerequisite_patterns.length > 0 && (
|
||||
<RelatedPatterns
|
||||
title="Prerequisites"
|
||||
description="Learn these patterns first:"
|
||||
patterns={pattern.prerequisite_patterns}
|
||||
/>
|
||||
)}
|
||||
{pattern.related_patterns && pattern.related_patterns.length > 0 && (
|
||||
<RelatedPatterns
|
||||
title="Related Patterns"
|
||||
description="Explore similar techniques:"
|
||||
patterns={pattern.related_patterns}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user