diff --git a/app/(app)/feature-flag-example/_client.tsx b/app/(app)/feature-flag-example/_client.tsx deleted file mode 100644 index 2645a8e0..00000000 --- a/app/(app)/feature-flag-example/_client.tsx +++ /dev/null @@ -1,26 +0,0 @@ -"use client"; -import { type Session } from "next-auth"; -import { notFound } from "next/navigation"; -import { isFlagEnabled, FEATURE_FLAGS } from "@/utils/flags"; - -const Content = ({ session }: { session: Session | null }) => { - const flagEnabled = isFlagEnabled(FEATURE_FLAGS.FEATURE_FLAG_TEST); - - if (!flagEnabled) { - notFound(); - } - - return ( -
-

- This page is behind a feature flag. It will work in development or when - the flag is turned on. -

-

- {session ? "User is logged in" : "User is not logged in"} -

-
- ); -}; - -export default Content; diff --git a/components/Course/CourseCard.tsx b/components/Course/CourseCard.tsx new file mode 100644 index 00000000..2269aa8b --- /dev/null +++ b/components/Course/CourseCard.tsx @@ -0,0 +1,42 @@ + +import React from "react"; +import { Course } from "./type"; + +interface CourseCardProps { + course: Course; + onStartCourse: (courseId: number) => void; // Change to number to match your mock data +} + +const CourseCard: React.FC = ({ course, onStartCourse }) => { + return ( +
+ {/* Course Title */} +

{course.title}

+ + {/* Course Description */} +

+ {course.description} +

+ + {/* Course Progress */} +
+

Progress:

+
+ {course.progress}% +
+
+ + {/* Start Course Button */} + +
+ ); +}; + +export default CourseCard; diff --git a/components/Course/feature-flag-example/_client.tsx b/components/Course/feature-flag-example/_client.tsx new file mode 100644 index 00000000..56912627 --- /dev/null +++ b/components/Course/feature-flag-example/_client.tsx @@ -0,0 +1,22 @@ +"use client"; + +import { type Session } from "next-auth"; +import { notFound } from "next/navigation"; +import { isFlagEnabled, FEATURE_FLAGS } from "@/utils/flags"; +import CoursesLanding from "@/components/Course"; + +const Content = ({ session }: { session: Session | null }) => { + const flagEnabled = isFlagEnabled(FEATURE_FLAGS.COURSES_LANDING); // Adjust to the correct flag + + if (!flagEnabled) { + notFound(); // Show 404 page if the feature flag is not enabled + } + + return ( +
+ +
+ ); +}; + +export default Content; diff --git a/app/(app)/feature-flag-example/page.tsx b/components/Course/feature-flag-example/page.tsx similarity index 60% rename from app/(app)/feature-flag-example/page.tsx rename to components/Course/feature-flag-example/page.tsx index 1e691253..a3588aaf 100644 --- a/app/(app)/feature-flag-example/page.tsx +++ b/components/Course/feature-flag-example/page.tsx @@ -2,11 +2,11 @@ import Content from "./_client"; import { getServerAuthSession } from "@/server/auth"; export const metadata = { - title: "This is a feature flag example", + title: "Courses Landing Page", }; -export default async function Page() { - // Example of grabbing session in case it is needed +export default async function CoursesPage() { + // Get session if needed for authentication purposes const session = await getServerAuthSession(); return ; diff --git a/components/Course/index.tsx b/components/Course/index.tsx new file mode 100644 index 00000000..b6fd4809 --- /dev/null +++ b/components/Course/index.tsx @@ -0,0 +1,39 @@ + +import React from "react"; +import { useRouter } from "next/router"; +import { mockCourses } from "./mock"; +import CourseCard from "./CourseCard"; +import { type Session } from "next-auth"; + +const CoursesLanding = ({ session }: { session: Session | null }) => { + const router = useRouter(); // Initialize the useRouter hook + + const handleStartCourse = (courseId: number) => { + // Navigate to the course content page + router.push(`/courses/${courseId}`); + + }; + + return ( +
+ {/* Page Title */} +

Courses

+ + {/* Courses List with aria-label for accessibility */} +
+ {mockCourses.map((course) => ( + + ))} +
+
+ ); +}; + +export default CoursesLanding; diff --git a/components/Course/mock.ts b/components/Course/mock.ts new file mode 100644 index 00000000..7cec145b --- /dev/null +++ b/components/Course/mock.ts @@ -0,0 +1,66 @@ +import { Course } from "./type"; + +// Define the UserProgress type +type UserProgress = { + coursesProgress: Array<{ + courseId: number; // Use string for the ID + progress: number; // Progress percentage + featured: boolean; // Include the featured status if needed + }>; +}; + +// Mock courses data +export const mockCourses: Course[] = [ + { + id: 1, // Changed to string + title: "Introduction to Web Development", + description: + "Learn the basics of HTML, CSS, and JavaScript to build responsive websites.", + progress: 90, + featured: true, + }, + { + id: 2, + title: "Advanced JavaScript Concepts", + description: + "Deep dive into JavaScript with a focus on ES6+ features and asynchronous programming.", + progress: 65, + featured: false, + }, + { + id: 3, + title: "React for Beginners", + description: + "Understand the fundamentals of React and how to build interactive UIs.", + progress: 30, + featured: true, + }, + { + id: 4, + title: "Full-Stack Web Development", + description: + "Learn to build full-stack applications using modern technologies like Node.js and Express.", + progress: 45, + featured: false, + }, + { + id: 5, + title: "Version Control with Git and GitHub", + description: + "Master version control using Git and learn how to collaborate on GitHub.", + progress: 80, + featured: true, + }, +]; + +// Function to generate user progress +export const generateUserProgress = (courses: Course[]): UserProgress => ({ + coursesProgress: courses.map((course) => ({ + courseId: course.id, // Use the course ID + progress: course.progress, // Use the course progress + featured: course.featured, // Include featured status if needed + })), +}); + +// Generate the user progress based on mockCourses +export const userProgress: UserProgress = generateUserProgress(mockCourses); diff --git a/components/Course/type.ts b/components/Course/type.ts new file mode 100644 index 00000000..d8452325 --- /dev/null +++ b/components/Course/type.ts @@ -0,0 +1,11 @@ + + + + +export interface Course { + id: number; + title: string; + description?: string; + progress: number; + featured: boolean; +} diff --git a/utils/flags.ts b/utils/flags.ts index af14b6ed..20b73e4f 100644 --- a/utils/flags.ts +++ b/utils/flags.ts @@ -2,7 +2,7 @@ import { posthog } from "posthog-js"; export const FEATURE_FLAGS = { FEATURE_FLAG_TEST: "feature-flag-test", - // Add more feature flags as needed + COURSES_LANDING: "courses-landing", } as const; export type FeatureFlagName = @@ -17,11 +17,11 @@ export function isDevEnvironment() { export const isFlagEnabled = ( featureFlag: FeatureFlagName, - disableDevCheck = false, // Disable dev check to force feature flag to be checked always + disableDevCheck = false, ) => { if (!disableDevCheck && isDevEnvironment()) { console.log("Feature flag check skipped in development environment"); - return true; + return true; // Always true in dev environments unless you want to test differently } return posthog.isFeatureEnabled(featureFlag); };