wire up pages
This commit is contained in:
@@ -0,0 +1,159 @@
|
||||
import { getQuestions, getCategories, getPatterns } from "@/lib/api";
|
||||
import { QuestionCard } from "@/components/questions/question-card";
|
||||
import Link from "next/link";
|
||||
|
||||
interface SearchParams {
|
||||
difficulty?: string;
|
||||
category?: string;
|
||||
pattern?: string;
|
||||
search?: string;
|
||||
page?: string;
|
||||
}
|
||||
|
||||
export default async function QuestionsPage({
|
||||
searchParams,
|
||||
}: {
|
||||
searchParams: Promise<SearchParams>;
|
||||
}) {
|
||||
const params = await searchParams;
|
||||
const [questionsResponse, categoriesResponse, patternsResponse] =
|
||||
await Promise.all([
|
||||
getQuestions({
|
||||
difficulty: params.difficulty,
|
||||
category: params.category,
|
||||
pattern: params.pattern,
|
||||
search: params.search,
|
||||
page: params.page ? parseInt(params.page) : 1,
|
||||
}),
|
||||
getCategories(),
|
||||
getPatterns(),
|
||||
]);
|
||||
|
||||
const difficulties = ["easy", "medium", "hard"];
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<h1 className="text-3xl font-bold">Questions</h1>
|
||||
|
||||
<div className="flex flex-wrap gap-4 p-4 rounded-lg bg-[var(--secondary)]">
|
||||
<div className="space-y-1">
|
||||
<label className="text-sm text-[var(--muted-foreground)]">
|
||||
Difficulty
|
||||
</label>
|
||||
<div className="flex gap-2">
|
||||
<Link
|
||||
href="/questions"
|
||||
className={`px-3 py-1 rounded text-sm ${
|
||||
!params.difficulty
|
||||
? "bg-[var(--primary)] text-[var(--primary-foreground)]"
|
||||
: "bg-[var(--card)] hover:bg-[var(--muted)]"
|
||||
}`}
|
||||
>
|
||||
All
|
||||
</Link>
|
||||
{difficulties.map((d) => (
|
||||
<Link
|
||||
key={d}
|
||||
href={`/questions?difficulty=${d}`}
|
||||
className={`px-3 py-1 rounded text-sm capitalize ${
|
||||
params.difficulty === d
|
||||
? "bg-[var(--primary)] text-[var(--primary-foreground)]"
|
||||
: "bg-[var(--card)] hover:bg-[var(--muted)]"
|
||||
}`}
|
||||
>
|
||||
{d}
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-1">
|
||||
<label className="text-sm text-[var(--muted-foreground)]">
|
||||
Category
|
||||
</label>
|
||||
<select
|
||||
defaultValue={params.category || ""}
|
||||
className="px-3 py-1 rounded text-sm bg-[var(--card)] border border-[var(--border)]"
|
||||
onChange={(e) => {
|
||||
const url = new URL(window.location.href);
|
||||
if (e.target.value) {
|
||||
url.searchParams.set("category", e.target.value);
|
||||
} else {
|
||||
url.searchParams.delete("category");
|
||||
}
|
||||
window.location.href = url.toString();
|
||||
}}
|
||||
>
|
||||
<option value="">All Categories</option>
|
||||
{categoriesResponse.items.map((cat) => (
|
||||
<option key={cat.id} value={cat.slug}>
|
||||
{cat.name} ({cat.question_count})
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div className="space-y-1">
|
||||
<label className="text-sm text-[var(--muted-foreground)]">
|
||||
Pattern
|
||||
</label>
|
||||
<select
|
||||
defaultValue={params.pattern || ""}
|
||||
className="px-3 py-1 rounded text-sm bg-[var(--card)] border border-[var(--border)]"
|
||||
onChange={(e) => {
|
||||
const url = new URL(window.location.href);
|
||||
if (e.target.value) {
|
||||
url.searchParams.set("pattern", e.target.value);
|
||||
} else {
|
||||
url.searchParams.delete("pattern");
|
||||
}
|
||||
window.location.href = url.toString();
|
||||
}}
|
||||
>
|
||||
<option value="">All Patterns</option>
|
||||
{patternsResponse.items.map((pat) => (
|
||||
<option key={pat.id} value={pat.slug}>
|
||||
{pat.name} ({pat.question_count})
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="text-sm text-[var(--muted-foreground)]">
|
||||
Showing {questionsResponse.items.length} of {questionsResponse.total}{" "}
|
||||
questions
|
||||
</div>
|
||||
|
||||
<div className="grid gap-4">
|
||||
{questionsResponse.items.map((question) => (
|
||||
<QuestionCard key={question.id} question={question} />
|
||||
))}
|
||||
</div>
|
||||
|
||||
{questionsResponse.pages > 1 && (
|
||||
<div className="flex justify-center gap-2">
|
||||
{Array.from({ length: questionsResponse.pages }, (_, i) => i + 1).map(
|
||||
(page) => (
|
||||
<Link
|
||||
key={page}
|
||||
href={`/questions?page=${page}${
|
||||
params.difficulty ? `&difficulty=${params.difficulty}` : ""
|
||||
}${params.category ? `&category=${params.category}` : ""}${
|
||||
params.pattern ? `&pattern=${params.pattern}` : ""
|
||||
}`}
|
||||
className={`px-3 py-1 rounded ${
|
||||
page === questionsResponse.page
|
||||
? "bg-[var(--primary)] text-[var(--primary-foreground)]"
|
||||
: "bg-[var(--secondary)] hover:bg-[var(--muted)]"
|
||||
}`}
|
||||
>
|
||||
{page}
|
||||
</Link>
|
||||
)
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user