From d0b4a53f8099f840006e5b522c32bc7d2a5db94c Mon Sep 17 00:00:00 2001 From: Leo dev Date: Mon, 2 Feb 2026 23:10:13 +0100 Subject: [PATCH] Shadcnified problems --- src/app/leaderboards/page.tsx | 6 +- src/app/problems/page.tsx | 257 ++++++++++++++--------------- src/components/ui/input.tsx | 21 +++ src/components/ui/toggle-group.tsx | 83 ++++++++++ src/components/ui/toggle.tsx | 47 ++++++ 5 files changed, 275 insertions(+), 139 deletions(-) create mode 100644 src/components/ui/input.tsx create mode 100644 src/components/ui/toggle-group.tsx create mode 100644 src/components/ui/toggle.tsx diff --git a/src/app/leaderboards/page.tsx b/src/app/leaderboards/page.tsx index 6101ae8..1d9f1ad 100644 --- a/src/app/leaderboards/page.tsx +++ b/src/app/leaderboards/page.tsx @@ -170,7 +170,7 @@ const weeklyLeaderboard = [ }, ]; -const Leaderboards = () => { +export default function Leaderboards() { const [activeTab, setActiveTab] = useState<"global" | "weekly">("global"); const categories = ["Any%", "100%", "Easy Only", "No DP", "Blind"]; @@ -268,9 +268,7 @@ const Leaderboards = () => { ); -}; - -export default Leaderboards; +} /* ---------- helpers ---------- */ diff --git a/src/app/problems/page.tsx b/src/app/problems/page.tsx index b0112c6..7af1c4f 100644 --- a/src/app/problems/page.tsx +++ b/src/app/problems/page.tsx @@ -1,180 +1,78 @@ "use client"; import { Search, Grid, List } from "lucide-react"; -import ProblemCard from "@/components/app/ProblemCard"; import { useState } from "react"; +import ProblemCard from "@/components/app/ProblemCard"; +import { Input } from "@/components/ui/input"; +import { Button } from "@/components/ui/button"; +import { Badge } from "@/components/ui/badge"; +import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group"; + const Problems = () => { const [viewMode, setViewMode] = useState<"grid" | "list">("grid"); - const problems = [ - { - name: "Two Sum Dash", - difficulty: "easy" as const, - tags: ["arrays", "hash-map"], - bestTime: "0:42", - attempts: 12453, - }, - { - name: "Binary Sprint", - difficulty: "easy" as const, - tags: ["binary-search"], - bestTime: "0:38", - attempts: 8921, - }, - { - name: "Linked List Rush", - difficulty: "medium" as const, - tags: ["linked-list", "pointers"], - bestTime: "1:24", - attempts: 6234, - }, - { - name: "Tree Traverse Blitz", - difficulty: "medium" as const, - tags: ["trees", "recursion"], - bestTime: "2:01", - attempts: 5102, - }, - { - name: "DP Gauntlet", - difficulty: "hard" as const, - tags: ["dynamic-programming"], - bestTime: "4:32", - attempts: 2341, - }, - { - name: "Graph Navigator", - difficulty: "hard" as const, - tags: ["graphs", "bfs", "dfs"], - bestTime: "3:45", - attempts: 3456, - }, - { - name: "String Scramble", - difficulty: "easy" as const, - tags: ["strings", "manipulation"], - bestTime: "0:55", - attempts: 9876, - }, - { - name: "Stack Overflow", - difficulty: "medium" as const, - tags: ["stacks", "queues"], - bestTime: "1:42", - attempts: 4567, - }, - { - name: "Heap Hero", - difficulty: "hard" as const, - tags: ["heaps", "priority-queue"], - bestTime: "3:21", - attempts: 1890, - }, - { - name: "Sliding Window Slam", - difficulty: "medium" as const, - tags: ["sliding-window", "arrays"], - bestTime: "1:56", - attempts: 5678, - }, - { - name: "Trie Triumph", - difficulty: "hard" as const, - tags: ["trie", "strings"], - bestTime: "4:12", - attempts: 1234, - }, - { - name: "Backtrack Blaster", - difficulty: "hard" as const, - tags: ["backtracking", "recursion"], - bestTime: "5:01", - attempts: 987, - }, - ]; - const categories = ["All", "Arrays", "Trees", "Graphs", "DP", "Strings"]; const difficulties = ["All", "Easy", "Medium", "Hard"]; return (
-
+
{/* Header */} -
-

Problems

+
+

Problems

Choose your battleground. Each run brings you closer to your PB.

{/* Filters */} -
+
{/* Search */}
- - + +
{/* Category Filter */} -
- {categories.map((cat) => ( - + ))}
{/* Difficulty Filter */}
- {difficulties.map((diff) => ( - + ))}
{/* View Toggle */} -
- - -
+ +
{/* Problem Grid */} @@ -195,3 +93,92 @@ const Problems = () => { }; export default Problems; + +/* ---------------- data ---------------- */ + +const problems = [ + { + name: "Two Sum Dash", + difficulty: "easy" as const, + tags: ["arrays", "hash-map"], + bestTime: "0:42", + attempts: 12453, + }, + { + name: "Binary Sprint", + difficulty: "easy" as const, + tags: ["binary-search"], + bestTime: "0:38", + attempts: 8921, + }, + { + name: "Linked List Rush", + difficulty: "medium" as const, + tags: ["linked-list", "pointers"], + bestTime: "1:24", + attempts: 6234, + }, + { + name: "Tree Traverse Blitz", + difficulty: "medium" as const, + tags: ["trees", "recursion"], + bestTime: "2:01", + attempts: 5102, + }, + { + name: "DP Gauntlet", + difficulty: "hard" as const, + tags: ["dynamic-programming"], + bestTime: "4:32", + attempts: 2341, + }, + { + name: "Graph Navigator", + difficulty: "hard" as const, + tags: ["graphs", "bfs", "dfs"], + bestTime: "3:45", + attempts: 3456, + }, + { + name: "String Scramble", + difficulty: "easy" as const, + tags: ["strings", "manipulation"], + bestTime: "0:55", + attempts: 9876, + }, + { + name: "Stack Overflow", + difficulty: "medium" as const, + tags: ["stacks", "queues"], + bestTime: "1:42", + attempts: 4567, + }, + { + name: "Heap Hero", + difficulty: "hard" as const, + tags: ["heaps", "priority-queue"], + bestTime: "3:21", + attempts: 1890, + }, + { + name: "Sliding Window Slam", + difficulty: "medium" as const, + tags: ["sliding-window", "arrays"], + bestTime: "1:56", + attempts: 5678, + }, + { + name: "Trie Triumph", + difficulty: "hard" as const, + tags: ["trie", "strings"], + bestTime: "4:12", + attempts: 1234, + }, + { + name: "Backtrack Blaster", + difficulty: "hard" as const, + tags: ["backtracking", "recursion"], + bestTime: "5:01", + attempts: 987, + }, +]; diff --git a/src/components/ui/input.tsx b/src/components/ui/input.tsx new file mode 100644 index 0000000..8916905 --- /dev/null +++ b/src/components/ui/input.tsx @@ -0,0 +1,21 @@ +import * as React from "react" + +import { cn } from "@/lib/utils" + +function Input({ className, type, ...props }: React.ComponentProps<"input">) { + return ( + + ) +} + +export { Input } diff --git a/src/components/ui/toggle-group.tsx b/src/components/ui/toggle-group.tsx new file mode 100644 index 0000000..9894607 --- /dev/null +++ b/src/components/ui/toggle-group.tsx @@ -0,0 +1,83 @@ +"use client" + +import * as React from "react" +import { type VariantProps } from "class-variance-authority" +import { ToggleGroup as ToggleGroupPrimitive } from "radix-ui" + +import { cn } from "@/lib/utils" +import { toggleVariants } from "@/components/ui/toggle" + +const ToggleGroupContext = React.createContext< + VariantProps & { + spacing?: number + } +>({ + size: "default", + variant: "default", + spacing: 0, +}) + +function ToggleGroup({ + className, + variant, + size, + spacing = 0, + children, + ...props +}: React.ComponentProps & + VariantProps & { + spacing?: number + }) { + return ( + + + {children} + + + ) +} + +function ToggleGroupItem({ + className, + children, + variant, + size, + ...props +}: React.ComponentProps & + VariantProps) { + const context = React.useContext(ToggleGroupContext) + + return ( + + {children} + + ) +} + +export { ToggleGroup, ToggleGroupItem } diff --git a/src/components/ui/toggle.tsx b/src/components/ui/toggle.tsx new file mode 100644 index 0000000..901c7f4 --- /dev/null +++ b/src/components/ui/toggle.tsx @@ -0,0 +1,47 @@ +"use client" + +import * as React from "react" +import { cva, type VariantProps } from "class-variance-authority" +import { Toggle as TogglePrimitive } from "radix-ui" + +import { cn } from "@/lib/utils" + +const toggleVariants = cva( + "inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium hover:bg-muted hover:text-muted-foreground disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0 focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] outline-none transition-[color,box-shadow] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive whitespace-nowrap", + { + variants: { + variant: { + default: "bg-transparent", + outline: + "border border-input bg-transparent shadow-xs hover:bg-accent hover:text-accent-foreground", + }, + size: { + default: "h-9 px-2 min-w-9", + sm: "h-8 px-1.5 min-w-8", + lg: "h-10 px-2.5 min-w-10", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, + } +) + +function Toggle({ + className, + variant, + size, + ...props +}: React.ComponentProps & + VariantProps) { + return ( + + ) +} + +export { Toggle, toggleVariants }