From caae3a0fef28249d5a79126b278e914a171567f0 Mon Sep 17 00:00:00 2001 From: D240021 Date: Sun, 29 Mar 2026 10:22:27 -0600 Subject: [PATCH] feat: create Learning Track Card Component --- components/LearningTrackCard.tsx | 102 +++++++++++++++++++++++++++++++ package-lock.json | 13 ++++ 2 files changed, 115 insertions(+) create mode 100644 components/LearningTrackCard.tsx diff --git a/components/LearningTrackCard.tsx b/components/LearningTrackCard.tsx new file mode 100644 index 0000000..4f1e943 --- /dev/null +++ b/components/LearningTrackCard.tsx @@ -0,0 +1,102 @@ +'use client'; + +import Image from 'next/image'; +import Link from 'next/link'; + +import { cn } from '@/lib/utils'; + +const categoryStyles = { + beginner: 'bg-green-100 text-green-800', + intermediate: 'bg-blue-100 text-blue-800', + advanced: 'bg-purple-100 text-purple-800', +} as const; + +export type LearningTrackCategory = keyof typeof categoryStyles; + +const categoryLabels: Record = { + beginner: 'Beginner', + intermediate: 'Intermediate', + advanced: 'Advanced', +}; + +export interface LearningTrackCardProps { + imageSrc: string; + imageAlt: string; + category: LearningTrackCategory; + title: string; + description: string; + lessonCount: number; + durationLabel: string; + href?: string; + onStartLearning?: () => void; + className?: string; +} + +const buttonClassName = + 'flex w-full items-center justify-center rounded-lg bg-[#9d17ff] px-4 py-3 text-sm font-semibold text-white transition hover:bg-[#8a0ee6] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[#9d17ff] focus-visible:ring-offset-2'; + +export default function LearningTrackCard({ + imageSrc, + imageAlt, + category, + title, + description, + lessonCount, + durationLabel, + href, + onStartLearning, + className, +}: LearningTrackCardProps) { + return ( +
+
+ {imageAlt} +
+ +
+ + {categoryLabels[category]} + + +

{title}

+ +

{description}

+ +
+ + {lessonCount} {lessonCount === 1 ? 'lesson' : 'lessons'} + + {durationLabel} +
+ +
+ {href ? ( + + Start Learning + + ) : ( + + )} +
+
+
+ ); +} diff --git a/package-lock.json b/package-lock.json index 2426466..bac1a0c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -80,6 +80,7 @@ "integrity": "sha512-H3mcG6ZDLTlYfaSNi0iOKkigqMFvkTKlGUYlD8GW7nNOYRrevuA46iTypPyv+06V3fEmvvazfntkBU34L0azAw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@babel/code-frame": "^7.28.6", "@babel/generator": "^7.28.6", @@ -1725,6 +1726,7 @@ "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", "devOptional": true, "license": "MIT", + "peer": true, "dependencies": { "csstype": "^3.2.2" } @@ -1784,6 +1786,7 @@ "integrity": "sha512-npiaib8XzbjtzS2N4HlqPvlpxpmZ14FjSJrteZpPxGUaYPlvhzlzUZ4mZyABo0EFrOWnvyd0Xxroq//hKhtAWg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.53.0", "@typescript-eslint/types": "8.53.0", @@ -2283,6 +2286,7 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -2666,6 +2670,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -3349,6 +3354,7 @@ "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -3534,6 +3540,7 @@ "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@rtsao/scc": "^1.1.0", "array-includes": "^3.1.9", @@ -6110,6 +6117,7 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.2.3.tgz", "integrity": "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==", "license": "MIT", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -6119,6 +6127,7 @@ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.3.tgz", "integrity": "sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==", "license": "MIT", + "peer": true, "dependencies": { "scheduler": "^0.27.0" }, @@ -6131,6 +6140,7 @@ "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.71.2.tgz", "integrity": "sha512-1CHvcDYzuRUNOflt4MOq3ZM46AronNJtQ1S7tnX6YN4y72qhgiUItpacZUAQ0TyWYci3yz1X+rXaSxiuEm86PA==", "license": "MIT", + "peer": true, "engines": { "node": ">=18.0.0" }, @@ -6968,6 +6978,7 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -7140,6 +7151,7 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -7446,6 +7458,7 @@ "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz", "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==", "license": "MIT", + "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" }