From a5f5554ce6c84474ce4f3a232f225bb3ba470040 Mon Sep 17 00:00:00 2001 From: colton456p Date: Thu, 24 Oct 2024 16:41:37 -0700 Subject: [PATCH 01/24] Made frontend for courses page --- src/app/courses/(hooks)/getCourses.tsx | 13 ++++ src/app/courses/page.tsx | 104 +++++++++++++++++++++++++ src/app/page.tsx | 6 +- src/hooks/use-auth-user-query.ts | 4 +- 4 files changed, 123 insertions(+), 4 deletions(-) create mode 100644 src/app/courses/(hooks)/getCourses.tsx create mode 100644 src/app/courses/page.tsx diff --git a/src/app/courses/(hooks)/getCourses.tsx b/src/app/courses/(hooks)/getCourses.tsx new file mode 100644 index 0000000..de42266 --- /dev/null +++ b/src/app/courses/(hooks)/getCourses.tsx @@ -0,0 +1,13 @@ +"use client" + + +export const getCourses = () => { + const res = await fetch( + `${process.env.BACKEND_BASE_URI}/courses`, + { + headers: { + "Content-Type": "application/json", + }, + } + ) +} diff --git a/src/app/courses/page.tsx b/src/app/courses/page.tsx new file mode 100644 index 0000000..3bcea7a --- /dev/null +++ b/src/app/courses/page.tsx @@ -0,0 +1,104 @@ +"use client" + +import { useCourse } from "@/app/(app)/course/[courseId]/(hooks)/useCourse" +import { useAuthUser } from "@/app/(providers)/auth-user-provider" +import Logo from "@/components/Logo" +import { Avatar, AvatarFallback } from "@/components/ui/avatar" +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu" +import { + NavigationMenu, +} from "@/components/ui/navigation-menu" +import { Text } from "@/components/ui/text" +import { useLogout } from "@/hooks/use-logout" +import Link from "next/link" + + +import { + Card, + CardHeader, + CardTitle, +} from "@/components/ui/card" + + +export default function CoursesPage() { + const { authUser } = useAuthUser() + const { logoutSync } = useLogout() + const { courseId, courseName } = useCourse() + + return ( + <> + +
+ + + + | +

Teamable

+ {/* Teamable */} +
+
+ + + {authUser ? ( + + + {authUser.username[0].toUpperCase()} + + + ) : ( + + + + )} + + + Logout + + +
+
+
+ +
+
+

Your Courses

+
+ {[...Array(6)].map((_, index) => ( + + + Course Number + + + ))} +
+
+
+ +
+

Your Courses

+
+ {[...Array(6)].map((_, index) => ( + + + Course Number + + + ))} +
+
+ + ) +} + +const CoursesPageView = () => { + // return ( + // + // ) +} diff --git a/src/app/page.tsx b/src/app/page.tsx index f463bc5..dff0144 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,6 +1,6 @@ -import { redirect } from "next/navigation" -import { ROUTES } from "@/routes" import { authUserQueryFn } from "@/hooks/use-auth-user-query" +import { ROUTES } from "@/routes" +import { redirect } from "next/navigation" import { getTokenAuthHeaderServer } from "../../utils/auth-server" export default async function Home() { @@ -10,5 +10,5 @@ export default async function Home() { if (!user) redirect(ROUTES.SIGN_UP) if (!user.course_memberships.length) redirect(ROUTES.AUTH_ERROR) - redirect(`/course/${user.course_memberships[0].course}/setup`) + redirect(`/courses`) } diff --git a/src/hooks/use-auth-user-query.ts b/src/hooks/use-auth-user-query.ts index 7eee83d..586651d 100644 --- a/src/hooks/use-auth-user-query.ts +++ b/src/hooks/use-auth-user-query.ts @@ -1,5 +1,5 @@ -import { useQuery } from "@tanstack/react-query" import { AuthUser } from "@/_temp_types/user" +import { useQuery } from "@tanstack/react-query" import { getTokenAuthHeader } from "../../utils/auth" export const useAuthUserQuery = () => { @@ -25,8 +25,10 @@ export const authUserQueryFn = async ({ }, }, ) + if (res.status === 401) return null const data = await res.json() if (!res.ok) throw data + console.log(data) return data } From debd3c52646348a6fb7b3c8c079b363c9cb5f1b8 Mon Sep 17 00:00:00 2001 From: colton456p Date: Thu, 24 Oct 2024 16:45:46 -0700 Subject: [PATCH 02/24] got rid of a print statement that was added to one of the pages for testing reasons --- src/hooks/use-auth-user-query.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/hooks/use-auth-user-query.ts b/src/hooks/use-auth-user-query.ts index 586651d..ea987a7 100644 --- a/src/hooks/use-auth-user-query.ts +++ b/src/hooks/use-auth-user-query.ts @@ -29,6 +29,5 @@ export const authUserQueryFn = async ({ if (res.status === 401) return null const data = await res.json() if (!res.ok) throw data - console.log(data) return data } From a7829fafce6d7a8d9cccdf8bef28157638e6bc8f Mon Sep 17 00:00:00 2001 From: colton456p Date: Mon, 4 Nov 2024 16:25:53 -0800 Subject: [PATCH 03/24] Fixed issue with course name not displaying in card --- src/app/courses/(hooks)/getCourses.tsx | 13 ---- src/app/courses/page.tsx | 93 +++++++++++++++----------- 2 files changed, 53 insertions(+), 53 deletions(-) delete mode 100644 src/app/courses/(hooks)/getCourses.tsx diff --git a/src/app/courses/(hooks)/getCourses.tsx b/src/app/courses/(hooks)/getCourses.tsx deleted file mode 100644 index de42266..0000000 --- a/src/app/courses/(hooks)/getCourses.tsx +++ /dev/null @@ -1,13 +0,0 @@ -"use client" - - -export const getCourses = () => { - const res = await fetch( - `${process.env.BACKEND_BASE_URI}/courses`, - { - headers: { - "Content-Type": "application/json", - }, - } - ) -} diff --git a/src/app/courses/page.tsx b/src/app/courses/page.tsx index 3bcea7a..97e7940 100644 --- a/src/app/courses/page.tsx +++ b/src/app/courses/page.tsx @@ -1,9 +1,13 @@ "use client" -import { useCourse } from "@/app/(app)/course/[courseId]/(hooks)/useCourse" import { useAuthUser } from "@/app/(providers)/auth-user-provider" import Logo from "@/components/Logo" import { Avatar, AvatarFallback } from "@/components/ui/avatar" +import { + Card, + CardHeader, + CardTitle, +} from "@/components/ui/card" import { DropdownMenu, DropdownMenuContent, @@ -14,21 +18,21 @@ import { NavigationMenu, } from "@/components/ui/navigation-menu" import { Text } from "@/components/ui/text" +import { useAuthUserQuery } from "@/hooks/use-auth-user-query" import { useLogout } from "@/hooks/use-logout" import Link from "next/link" +import { useRouter } from "next/navigation" - -import { - Card, - CardHeader, - CardTitle, -} from "@/components/ui/card" - +import { Separator } from "@/components/ui/separator" export default function CoursesPage() { const { authUser } = useAuthUser() const { logoutSync } = useLogout() - const { courseId, courseName } = useCourse() + const { data: userData, isLoading, error } = useAuthUserQuery() + const router = useRouter() + const handleCardClick = (courseId: number) => { + router.push(`/course/${courseId}/setup`) + } return ( <> @@ -39,7 +43,6 @@ export default function CoursesPage() { |

Teamable

- {/* Teamable */}
@@ -62,43 +65,53 @@ export default function CoursesPage() {
-
+ +
+
+
+
+

Your Courses

+ {isLoading &&

Loading courses...

} + {error &&

Failed to load courses

} +
+ {userData?.course_memberships && userData.course_memberships.map((membership) => ( + handleCardClick(membership.course.id)} + > + + + {membership.course.name} + + + + ))} +
+
+
-
-
-

Your Courses

-
- {[...Array(6)].map((_, index) => ( - +
+

Your Courses

+ {isLoading &&

Loading courses...

} + {error &&

Failed to load courses

} +
+ {userData?.course_memberships && userData.course_memberships.map((membership) => ( + handleCardClick(membership.course.id)} + > - Course Number + + {membership.course.name} + ))}
- -
-

Your Courses

-
- {[...Array(6)].map((_, index) => ( - - - Course Number - - - ))} -
-
) -} - -const CoursesPageView = () => { - // return ( - // - // ) -} +} \ No newline at end of file From 81dfcf93dea702359a225663a947b73066e62802 Mon Sep 17 00:00:00 2001 From: colton456p Date: Tue, 5 Nov 2024 10:13:33 -0800 Subject: [PATCH 04/24] Applied frontend design fixes --- src/app/courses/page.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/app/courses/page.tsx b/src/app/courses/page.tsx index 97e7940..dd5b720 100644 --- a/src/app/courses/page.tsx +++ b/src/app/courses/page.tsx @@ -30,7 +30,7 @@ export default function CoursesPage() { const { logoutSync } = useLogout() const { data: userData, isLoading, error } = useAuthUserQuery() const router = useRouter() - const handleCardClick = (courseId: number) => { + const openCourseHomePageRouter = (courseId: number) => { router.push(`/course/${courseId}/setup`) } @@ -78,7 +78,7 @@ export default function CoursesPage() { handleCardClick(membership.course.id)} + onClick={() => openCourseHomePageRouter(membership.course.id)} > @@ -99,8 +99,8 @@ export default function CoursesPage() { {userData?.course_memberships && userData.course_memberships.map((membership) => ( handleCardClick(membership.course.id)} + className="w-[350px] mb-4 cursor-pointer hover:bg-gray-100 transition" + onClick={() => openCourseHomePageRouter(membership.course.id)} > From 1b13d12154ae3f82e1bc362c954f7eba288eaa43 Mon Sep 17 00:00:00 2001 From: colton456p Date: Tue, 5 Nov 2024 10:15:47 -0800 Subject: [PATCH 05/24] formatting --- src/app/courses/page.tsx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/app/courses/page.tsx b/src/app/courses/page.tsx index dd5b720..e59c3b1 100644 --- a/src/app/courses/page.tsx +++ b/src/app/courses/page.tsx @@ -75,9 +75,9 @@ export default function CoursesPage() { {error &&

Failed to load courses

}
{userData?.course_memberships && userData.course_memberships.map((membership) => ( - openCourseHomePageRouter(membership.course.id)} > @@ -97,9 +97,9 @@ export default function CoursesPage() { {error &&

Failed to load courses

}
{userData?.course_memberships && userData.course_memberships.map((membership) => ( - openCourseHomePageRouter(membership.course.id)} > @@ -114,4 +114,4 @@ export default function CoursesPage() {
) -} \ No newline at end of file +} From ae4568cb66bd50b952205071dc932aa780c3e57a Mon Sep 17 00:00:00 2001 From: colton456p Date: Thu, 7 Nov 2024 14:02:35 -0800 Subject: [PATCH 06/24] Change design of courses pages --- src/_temp_types/user.ts | 3 ++- src/app/courses/page.tsx | 30 ++++++++++-------------------- 2 files changed, 12 insertions(+), 21 deletions(-) diff --git a/src/_temp_types/user.ts b/src/_temp_types/user.ts index 00da8b1..cc0741b 100644 --- a/src/_temp_types/user.ts +++ b/src/_temp_types/user.ts @@ -5,7 +5,8 @@ export interface AuthUser { last_name: string; email: string; is_staff: boolean; - course_memberships: Array<{ course: number }>; + // course_memberships: Array<{ course: number }>; + course_memberships: Array<{ course: {id: number, name: string} }>; } export interface AnonUser { diff --git a/src/app/courses/page.tsx b/src/app/courses/page.tsx index e59c3b1..628e231 100644 --- a/src/app/courses/page.tsx +++ b/src/app/courses/page.tsx @@ -18,7 +18,6 @@ import { NavigationMenu, } from "@/components/ui/navigation-menu" import { Text } from "@/components/ui/text" -import { useAuthUserQuery } from "@/hooks/use-auth-user-query" import { useLogout } from "@/hooks/use-logout" import Link from "next/link" import { useRouter } from "next/navigation" @@ -28,11 +27,7 @@ import { Separator } from "@/components/ui/separator" export default function CoursesPage() { const { authUser } = useAuthUser() const { logoutSync } = useLogout() - const { data: userData, isLoading, error } = useAuthUserQuery() const router = useRouter() - const openCourseHomePageRouter = (courseId: number) => { - router.push(`/course/${courseId}/setup`) - } return ( <> @@ -66,22 +61,19 @@ export default function CoursesPage() {
-
-
+
-
+

Your Courses

- {isLoading &&

Loading courses...

} - {error &&

Failed to load courses

} -
- {userData?.course_memberships && userData.course_memberships.map((membership) => ( +
+ {authUser?.course_memberships && authUser.course_memberships.map((membership) => ( openCourseHomePageRouter(membership.course.id)} + className="w-full h-full pb-14 cursor-pointer hover:bg-gray-100 transition" + onClick={() => router.push(`/course/${membership.course.id}/setup`)} > - + {membership.course.name} @@ -93,14 +85,12 @@ export default function CoursesPage() {

Your Courses

- {isLoading &&

Loading courses...

} - {error &&

Failed to load courses

}
- {userData?.course_memberships && userData.course_memberships.map((membership) => ( + {authUser?.course_memberships && authUser.course_memberships.map((membership) => ( openCourseHomePageRouter(membership.course.id)} + className="w-[350px] m-2 pb-14" + onClick={() => router.push(`/course/${membership.course.id}/setup`)} > From 46160c426579ef07402bf4217f3981d22dc44d26 Mon Sep 17 00:00:00 2001 From: colton456p Date: Thu, 7 Nov 2024 14:04:16 -0800 Subject: [PATCH 07/24] removed unneeded comment --- src/_temp_types/user.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/_temp_types/user.ts b/src/_temp_types/user.ts index cc0741b..5af973f 100644 --- a/src/_temp_types/user.ts +++ b/src/_temp_types/user.ts @@ -5,7 +5,6 @@ export interface AuthUser { last_name: string; email: string; is_staff: boolean; - // course_memberships: Array<{ course: number }>; course_memberships: Array<{ course: {id: number, name: string} }>; } From 834265019832f7b5497fd34474bb8745638b4c80 Mon Sep 17 00:00:00 2001 From: colton456p Date: Thu, 7 Nov 2024 14:26:17 -0800 Subject: [PATCH 08/24] fixed course_memberships datatypes --- src/_temp_types/user.ts | 2 +- src/app/courses/page.tsx | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/_temp_types/user.ts b/src/_temp_types/user.ts index 5af973f..715cc7b 100644 --- a/src/_temp_types/user.ts +++ b/src/_temp_types/user.ts @@ -5,7 +5,7 @@ export interface AuthUser { last_name: string; email: string; is_staff: boolean; - course_memberships: Array<{ course: {id: number, name: string} }>; + course_memberships: Array<{ id: number, name: string } >; } export interface AnonUser { diff --git a/src/app/courses/page.tsx b/src/app/courses/page.tsx index 628e231..fdb6046 100644 --- a/src/app/courses/page.tsx +++ b/src/app/courses/page.tsx @@ -68,13 +68,13 @@ export default function CoursesPage() {
{authUser?.course_memberships && authUser.course_memberships.map((membership) => ( router.push(`/course/${membership.course.id}/setup`)} + onClick={() => router.push(`/course/${membership.id}/setup`)} > - {membership.course.name} + {membership.name} @@ -88,13 +88,13 @@ export default function CoursesPage() {
{authUser?.course_memberships && authUser.course_memberships.map((membership) => ( router.push(`/course/${membership.course.id}/setup`)} + onClick={() => router.push(`/course/${membership.id}/setup`)} > - {membership.course.name} + {membership.name} From 4af49c2b70c250bb932469597f181f0fa53d4ee7 Mon Sep 17 00:00:00 2001 From: colton456p Date: Thu, 7 Nov 2024 14:46:21 -0800 Subject: [PATCH 09/24] added loading state --- src/app/courses/page.tsx | 71 ++++++++++++++++++++++++++-------------- 1 file changed, 46 insertions(+), 25 deletions(-) diff --git a/src/app/courses/page.tsx b/src/app/courses/page.tsx index fdb6046..9056732 100644 --- a/src/app/courses/page.tsx +++ b/src/app/courses/page.tsx @@ -17,17 +17,26 @@ import { import { NavigationMenu, } from "@/components/ui/navigation-menu" +import { Separator } from "@/components/ui/separator" import { Text } from "@/components/ui/text" import { useLogout } from "@/hooks/use-logout" import Link from "next/link" import { useRouter } from "next/navigation" +import { useEffect, useState } from "react" -import { Separator } from "@/components/ui/separator" +import { ReloadIcon } from "@radix-ui/react-icons" export default function CoursesPage() { const { authUser } = useAuthUser() const { logoutSync } = useLogout() const router = useRouter() + const [loading, setLoading] = useState(true) + + useEffect(() => { + if (authUser?.course_memberships) { + setLoading(false) + } + }, [authUser]) return ( <> @@ -65,41 +74,53 @@ export default function CoursesPage() {

Your Courses

-
- {authUser?.course_memberships && authUser.course_memberships.map((membership) => ( + {loading ? ( +
+ +
+ ) : ( +
+ {authUser?.course_memberships.map((membership) => ( + router.push(`/course/${membership.id}/setup`)} + > + + + {membership.name} + + + + ))} +
+ )} +
+
+ +
+

Your Courses

+ {loading ? ( +
+ +
+ ) : ( +
+ {authUser?.course_memberships.map((membership) => ( router.push(`/course/${membership.id}/setup`)} > - + {membership.name} ))}
-
-
- -
-

Your Courses

-
- {authUser?.course_memberships && authUser.course_memberships.map((membership) => ( - router.push(`/course/${membership.id}/setup`)} - > - - - {membership.name} - - - - ))} -
+ )}
From 303c6167d3fc8789cc83dcd51fbca1e86cd02cf6 Mon Sep 17 00:00:00 2001 From: colton456p Date: Thu, 21 Nov 2024 15:34:38 -0800 Subject: [PATCH 10/24] base frontend for desktop implemented --- package.json | 1 + src/app/(app)/course/[courseId]/home/page.tsx | 109 ++++++++++++++++++ .../(app)/course/[courseId]/setup/page.tsx | 7 +- .../(app)/course/[courseId]/students/page.tsx | 11 +- .../course/[courseId]/team-sets/page.tsx | 16 +-- yarn.lock | 5 + 6 files changed, 132 insertions(+), 17 deletions(-) create mode 100644 src/app/(app)/course/[courseId]/home/page.tsx diff --git a/package.json b/package.json index b9e13f2..14d41a8 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "lucide-react": "^0.306.0", "next": "14.0.4", "react": "^18", + "react-circular-progressbar": "^2.1.0", "react-dom": "^18", "tailwind-merge": "^2.2.0", "tailwindcss-animate": "^1.0.7", diff --git a/src/app/(app)/course/[courseId]/home/page.tsx b/src/app/(app)/course/[courseId]/home/page.tsx new file mode 100644 index 0000000..160275c --- /dev/null +++ b/src/app/(app)/course/[courseId]/home/page.tsx @@ -0,0 +1,109 @@ +"use client" +import { useCourse } from "@/app/(app)/course/[courseId]/(hooks)/useCourse" +import PageView from "@/components/views/Page" +import { CircularProgressbar, buildStyles } from 'react-circular-progressbar' +import 'react-circular-progressbar/dist/styles.css' + +const HomePage = () => { + const { courseId } = useCourse() + const onboardingPercentage = 65 + const onboardingNextStep = "Generate Teams" + + const attributes = [ + "Requirement #1", + "Requirement #2", + "Requirement #3", + "Requirement #4", + "Requirement #5", + "Requirement #6", + "Requirement #7", + "Requirement #8", + "Requirement #9", + "Requirement #10", + ] + + const chunkSize = 4 + const groupedAttributes = [] + for (let i = 0; i < attributes.length; i += chunkSize) { + groupedAttributes.push(attributes.slice(i, i + chunkSize)) + } + + return ( + +

+ Welcome back!{" "} + + Wanting to start a new team formation? + +

+ +
+
+ +
+
+

+ You are {onboardingPercentage}% done with your current onboarding process. +

+

+ Next step: + + {onboardingNextStep} + +

+
+
+ +
+

Sign up Stats

+
+
    +
  • Number of Students Enrolled on Your LMS: 50
  • +
  • Total Team Formation Acceptions: 10
  • +
+
+
+ +
+

Previous Team Formation

+
+
    +
  • Number of Adopted Attributes: 16
  • +
  • Team Formation Date: 10/09/2023
  • +
+
+
+ +
+

Attributes Used

+
+
+ {groupedAttributes.map((group, index) => ( +
    + {group.map((attribute, idx) => ( +
  • {attribute}
  • + ))} +
+ ))} +
+
+
+
+ ) +} + +export default HomePage diff --git a/src/app/(app)/course/[courseId]/setup/page.tsx b/src/app/(app)/course/[courseId]/setup/page.tsx index 30b3dd2..f843a62 100644 --- a/src/app/(app)/course/[courseId]/setup/page.tsx +++ b/src/app/(app)/course/[courseId]/setup/page.tsx @@ -1,10 +1,9 @@ "use client" -import React from "react" -import PageView from "@/components/views/Page" +import { useCourse } from "@/app/(app)/course/[courseId]/(hooks)/useCourse" import { SetupStepDetailCard } from "@/app/(app)/course/[courseId]/setup/(components)/SetupStepDetailCard" import { useSetupSteps } from "@/app/(app)/course/[courseId]/setup/(hooks)/useSetupSteps" -import { useCourse } from "@/app/(app)/course/[courseId]/(hooks)/useCourse" +import PageView from "@/components/views/Page" const SetupPage = () => { const { steps, addedComponents } = useSetupSteps() @@ -13,7 +12,7 @@ const SetupPage = () => { diff --git a/src/app/(app)/course/[courseId]/students/page.tsx b/src/app/(app)/course/[courseId]/students/page.tsx index de98eb6..024d51a 100644 --- a/src/app/(app)/course/[courseId]/students/page.tsx +++ b/src/app/(app)/course/[courseId]/students/page.tsx @@ -1,11 +1,11 @@ "use client" -import React from "react" -import { StudentsProvider, useStudents } from "./(hooks)/useStudents" +import { useCourse } from "@/app/(app)/course/[courseId]/(hooks)/useCourse" import PageView from "@/components/views/Page" -import { StudentTable } from "./(table)/student-table" -import { useImportStudentsFromLms } from "@/hooks/use-import-students-from-lms" import { useImportStudentGradebookData } from "@/hooks/use-import-student-gradebook-data" +import { useImportStudentsFromLms } from "@/hooks/use-import-students-from-lms" +import { StudentsProvider, useStudents } from "./(hooks)/useStudents" +import { StudentTable } from "./(table)/student-table" export default function StudentsPage() { return ( @@ -16,6 +16,7 @@ export default function StudentsPage() { } const StudentsPageView = () => { + const { courseId } = useCourse() const { refetch } = useStudents() const { importStudentsFromLmsAsync, @@ -31,7 +32,7 @@ const StudentsPageView = () => { Date: Thu, 21 Nov 2024 16:44:16 -0800 Subject: [PATCH 11/24] added hooks for getting onboarding progress --- .../(hooks)/calculateOnboardingCompletion.tsx | 17 +++++++++++++++++ src/app/(app)/course/[courseId]/home/page.tsx | 18 ++++++++---------- src/app/(app)/course/[courseId]/setup/page.tsx | 1 + 3 files changed, 26 insertions(+), 10 deletions(-) create mode 100644 src/app/(app)/course/[courseId]/home/(hooks)/calculateOnboardingCompletion.tsx diff --git a/src/app/(app)/course/[courseId]/home/(hooks)/calculateOnboardingCompletion.tsx b/src/app/(app)/course/[courseId]/home/(hooks)/calculateOnboardingCompletion.tsx new file mode 100644 index 0000000..ab269d1 --- /dev/null +++ b/src/app/(app)/course/[courseId]/home/(hooks)/calculateOnboardingCompletion.tsx @@ -0,0 +1,17 @@ +import { useSetupSteps } from "@/app/(app)/course/[courseId]/setup/(hooks)/useSetupSteps" + +export const CalculateOnboardingCompletion = () => { + const { steps } = useSetupSteps() + const enabledSteps = steps.filter((step) => step.enabled) + + const completedSteps = enabledSteps.filter((step) => step.completed) + + const completionPercentage = Math.round((completedSteps.length / enabledSteps.length) * 100) + + const firstIncompleteStep = enabledSteps.find((step) => !step.completed) + + return { + completionPercentage, + nextStepTitle: firstIncompleteStep ? firstIncompleteStep.title : null, + } +} diff --git a/src/app/(app)/course/[courseId]/home/page.tsx b/src/app/(app)/course/[courseId]/home/page.tsx index 160275c..3b63507 100644 --- a/src/app/(app)/course/[courseId]/home/page.tsx +++ b/src/app/(app)/course/[courseId]/home/page.tsx @@ -3,11 +3,10 @@ import { useCourse } from "@/app/(app)/course/[courseId]/(hooks)/useCourse" import PageView from "@/components/views/Page" import { CircularProgressbar, buildStyles } from 'react-circular-progressbar' import 'react-circular-progressbar/dist/styles.css' - +import { CalculateOnboardingCompletion } from "./(hooks)/calculateOnboardingCompletion" const HomePage = () => { const { courseId } = useCourse() - const onboardingPercentage = 65 - const onboardingNextStep = "Generate Teams" + const { completionPercentage, nextStepTitle } = CalculateOnboardingCompletion() const attributes = [ "Requirement #1", @@ -22,10 +21,9 @@ const HomePage = () => { "Requirement #10", ] - const chunkSize = 4 const groupedAttributes = [] - for (let i = 0; i < attributes.length; i += chunkSize) { - groupedAttributes.push(attributes.slice(i, i + chunkSize)) + for (let i = 0; i < attributes.length; i += 4) { + groupedAttributes.push(attributes.slice(i, i + 4)) } return ( @@ -40,8 +38,8 @@ const HomePage = () => {
{

- You are {onboardingPercentage}% done with your current onboarding process. + You are {completionPercentage}% done with your current onboarding process.

Next step: @@ -62,7 +60,7 @@ const HomePage = () => { href={`/course/${courseId}/setup`} className="underline hover:font-bold" > - {onboardingNextStep} + {nextStepTitle}

diff --git a/src/app/(app)/course/[courseId]/setup/page.tsx b/src/app/(app)/course/[courseId]/setup/page.tsx index f843a62..2d51fba 100644 --- a/src/app/(app)/course/[courseId]/setup/page.tsx +++ b/src/app/(app)/course/[courseId]/setup/page.tsx @@ -5,6 +5,7 @@ import { SetupStepDetailCard } from "@/app/(app)/course/[courseId]/setup/(compon import { useSetupSteps } from "@/app/(app)/course/[courseId]/setup/(hooks)/useSetupSteps" import PageView from "@/components/views/Page" + const SetupPage = () => { const { steps, addedComponents } = useSetupSteps() const { courseId } = useCourse() From e7fc8bc3059eae3f0df7f5afba8d6fba7387273b Mon Sep 17 00:00:00 2001 From: colton456p Date: Thu, 21 Nov 2024 16:44:34 -0800 Subject: [PATCH 12/24] linter --- .../[courseId]/home/(hooks)/calculateOnboardingCompletion.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/(app)/course/[courseId]/home/(hooks)/calculateOnboardingCompletion.tsx b/src/app/(app)/course/[courseId]/home/(hooks)/calculateOnboardingCompletion.tsx index ab269d1..6fd6fa6 100644 --- a/src/app/(app)/course/[courseId]/home/(hooks)/calculateOnboardingCompletion.tsx +++ b/src/app/(app)/course/[courseId]/home/(hooks)/calculateOnboardingCompletion.tsx @@ -7,7 +7,7 @@ export const CalculateOnboardingCompletion = () => { const completedSteps = enabledSteps.filter((step) => step.completed) const completionPercentage = Math.round((completedSteps.length / enabledSteps.length) * 100) - + const firstIncompleteStep = enabledSteps.find((step) => !step.completed) return { From 33d6aa3610e2989bb88e7cabc82a4bd997091dc9 Mon Sep 17 00:00:00 2001 From: colton456p Date: Thu, 21 Nov 2024 16:55:39 -0800 Subject: [PATCH 13/24] added adjustments for mobile --- src/app/(app)/course/[courseId]/home/page.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/app/(app)/course/[courseId]/home/page.tsx b/src/app/(app)/course/[courseId]/home/page.tsx index 3b63507..9b185e1 100644 --- a/src/app/(app)/course/[courseId]/home/page.tsx +++ b/src/app/(app)/course/[courseId]/home/page.tsx @@ -27,7 +27,7 @@ const HomePage = () => { } return ( - +

Welcome back!{" "} @@ -35,8 +35,8 @@ const HomePage = () => {

-
-
+
+
{ })} />
-
+

- You are {completionPercentage}% done with your current onboarding process. + You are {completionPercentage}% done with your current onboarding process.

Next step: @@ -89,7 +89,7 @@ const HomePage = () => {

Attributes Used

-
+
{groupedAttributes.map((group, index) => (
    {group.map((attribute, idx) => ( From 6cc7afc053ce49f0b6d3300a0d367e6da349f687 Mon Sep 17 00:00:00 2001 From: colton456p Date: Thu, 21 Nov 2024 17:01:21 -0800 Subject: [PATCH 14/24] changed text --- src/app/(app)/course/[courseId]/home/page.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/(app)/course/[courseId]/home/page.tsx b/src/app/(app)/course/[courseId]/home/page.tsx index 9b185e1..bdf9e6d 100644 --- a/src/app/(app)/course/[courseId]/home/page.tsx +++ b/src/app/(app)/course/[courseId]/home/page.tsx @@ -70,7 +70,7 @@ const HomePage = () => {

    Sign up Stats

      -
    • Number of Students Enrolled on Your LMS: 50
    • +
    • Students Enrolled on Your LMS: 50
    • Total Team Formation Acceptions: 10
    From eb9a50abe6db7b715fb89802e5acd52b76049ea6 Mon Sep 17 00:00:00 2001 From: colton456p Date: Thu, 21 Nov 2024 17:32:24 -0800 Subject: [PATCH 15/24] added use case for when onboarding is complete --- src/app/(app)/course/[courseId]/home/page.tsx | 71 ++++++++++--------- 1 file changed, 39 insertions(+), 32 deletions(-) diff --git a/src/app/(app)/course/[courseId]/home/page.tsx b/src/app/(app)/course/[courseId]/home/page.tsx index bdf9e6d..8eaaa4d 100644 --- a/src/app/(app)/course/[courseId]/home/page.tsx +++ b/src/app/(app)/course/[courseId]/home/page.tsx @@ -30,41 +30,48 @@ const HomePage = () => {

    Welcome back!{" "} - - Wanting to start a new team formation? - + {completionPercentage === 100 ? ( + + Wanting to start a new team formation? + + ) : ( + Your onboarding process is incomplete... + )}

    -
    -
    - -
    -
    -

    - You are {completionPercentage}% done with your current onboarding process. -

    -

    - Next step: - - {nextStepTitle} - -

    + {completionPercentage !== 100 && ( +
    +
    + +
    +
    +

    + You are {completionPercentage}% done with your current onboarding process. +

    +

    + Next step: + + {nextStepTitle} + +

    +
    -
    + )} +

    Sign up Stats

    From 4a18b9da76204af56247bd4b54ecc5556b6e65c2 Mon Sep 17 00:00:00 2001 From: colton456p Date: Fri, 22 Nov 2024 13:28:48 -0800 Subject: [PATCH 16/24] added num of students --- src/app/(app)/course/[courseId]/home/page.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/app/(app)/course/[courseId]/home/page.tsx b/src/app/(app)/course/[courseId]/home/page.tsx index 8eaaa4d..bd6666d 100644 --- a/src/app/(app)/course/[courseId]/home/page.tsx +++ b/src/app/(app)/course/[courseId]/home/page.tsx @@ -3,10 +3,14 @@ import { useCourse } from "@/app/(app)/course/[courseId]/(hooks)/useCourse" import PageView from "@/components/views/Page" import { CircularProgressbar, buildStyles } from 'react-circular-progressbar' import 'react-circular-progressbar/dist/styles.css' +import { useStudents } from "../students/(hooks)/useStudents" import { CalculateOnboardingCompletion } from "./(hooks)/calculateOnboardingCompletion" const HomePage = () => { const { courseId } = useCourse() const { completionPercentage, nextStepTitle } = CalculateOnboardingCompletion() + const {totalStudents} = useStudents() + + console.log(totalStudents) const attributes = [ "Requirement #1", From 96b11f84c0a027cd067f654b7228aad64ae68e55 Mon Sep 17 00:00:00 2001 From: colton456p Date: Tue, 26 Nov 2024 16:00:39 -0800 Subject: [PATCH 17/24] fixed the total Students hook --- .../[courseId]/home/(hooks)/useTeamSets.tsx | 0 .../home/(hooks)/useTotalStudents.tsx | 29 +++++++++++++++++++ src/app/(app)/course/[courseId]/home/page.tsx | 15 +++++++--- src/app/(app)/course/[courseId]/page.tsx | 2 +- src/app/courses/page.tsx | 4 +-- 5 files changed, 43 insertions(+), 7 deletions(-) create mode 100644 src/app/(app)/course/[courseId]/home/(hooks)/useTeamSets.tsx create mode 100644 src/app/(app)/course/[courseId]/home/(hooks)/useTotalStudents.tsx diff --git a/src/app/(app)/course/[courseId]/home/(hooks)/useTeamSets.tsx b/src/app/(app)/course/[courseId]/home/(hooks)/useTeamSets.tsx new file mode 100644 index 0000000..e69de29 diff --git a/src/app/(app)/course/[courseId]/home/(hooks)/useTotalStudents.tsx b/src/app/(app)/course/[courseId]/home/(hooks)/useTotalStudents.tsx new file mode 100644 index 0000000..5ef887c --- /dev/null +++ b/src/app/(app)/course/[courseId]/home/(hooks)/useTotalStudents.tsx @@ -0,0 +1,29 @@ +"use client"; + +import { useCourse } from "@/app/(app)/course/[courseId]/(hooks)/useCourse"; +import { useQuery } from "@tanstack/react-query"; + +const useTotalStudentsQuery = ({ courseId }: { courseId: number }) => { + const studentQuery = useQuery({ + queryKey: [`courses/${courseId}/students`], + }); + + return { + getTotalStudentsAsync: studentQuery.refetch, + ...studentQuery, + }; +}; + +export const useTotalStudents = () => { + const { courseId } = useCourse(); + const { data, isLoading, error, getTotalStudentsAsync } = useTotalStudentsQuery({ + courseId: Number(courseId), + }); + + return { + totalStudents: data?.count ?? 0, + isLoading, + error, + refetch: getTotalStudentsAsync, + }; +}; diff --git a/src/app/(app)/course/[courseId]/home/page.tsx b/src/app/(app)/course/[courseId]/home/page.tsx index bd6666d..a388557 100644 --- a/src/app/(app)/course/[courseId]/home/page.tsx +++ b/src/app/(app)/course/[courseId]/home/page.tsx @@ -1,16 +1,23 @@ "use client" import { useCourse } from "@/app/(app)/course/[courseId]/(hooks)/useCourse" import PageView from "@/components/views/Page" +import { useToast } from "@/hooks/use-toast" import { CircularProgressbar, buildStyles } from 'react-circular-progressbar' import 'react-circular-progressbar/dist/styles.css' -import { useStudents } from "../students/(hooks)/useStudents" import { CalculateOnboardingCompletion } from "./(hooks)/calculateOnboardingCompletion" +import { useTotalStudents } from "./(hooks)/useTotalStudents" const HomePage = () => { const { courseId } = useCourse() const { completionPercentage, nextStepTitle } = CalculateOnboardingCompletion() - const {totalStudents} = useStudents() + const { totalStudents, error } = useTotalStudents(); + const {toast} = useToast(); - console.log(totalStudents) + if (error) { + toast({ + title: "Error fetching students", + description: "There was an error fetching the number of student enrolled on your LMS.", + }) + } const attributes = [ "Requirement #1", @@ -81,7 +88,7 @@ const HomePage = () => {

    Sign up Stats

      -
    • Students Enrolled on Your LMS: 50
    • +
    • Students Enrolled on Your LMS: {totalStudents}
    • Total Team Formation Acceptions: 10
    diff --git a/src/app/(app)/course/[courseId]/page.tsx b/src/app/(app)/course/[courseId]/page.tsx index becb379..d3ecb63 100644 --- a/src/app/(app)/course/[courseId]/page.tsx +++ b/src/app/(app)/course/[courseId]/page.tsx @@ -1,7 +1,7 @@ import { redirect } from "next/navigation" const CourseHomepage = async ({ params }: { params: { courseId: string } }) => { - redirect(`/course/${params.courseId}/setup`) + redirect(`/course/${params.courseId}/home`) } export default CourseHomepage diff --git a/src/app/courses/page.tsx b/src/app/courses/page.tsx index 9056732..35ed77b 100644 --- a/src/app/courses/page.tsx +++ b/src/app/courses/page.tsx @@ -84,7 +84,7 @@ export default function CoursesPage() { router.push(`/course/${membership.id}/setup`)} + onClick={() => router.push(`/course/${membership.id}/home`)} > @@ -110,7 +110,7 @@ export default function CoursesPage() { router.push(`/course/${membership.id}/setup`)} + onClick={() => router.push(`/course/${membership.id}/home`)} > From edc2994fecba3c938d236b167a19f7ca3c43fa55 Mon Sep 17 00:00:00 2001 From: colton456p Date: Wed, 27 Nov 2024 17:05:53 -0800 Subject: [PATCH 18/24] added hooks for attributes and date --- .../home/(hooks)/use-attributes.tsx | 46 ++++++++++ .../[courseId]/home/(hooks)/useTeamSets.tsx | 0 .../home/(hooks)/useTotalStudents.tsx | 20 ++--- src/app/(app)/course/[courseId]/home/page.tsx | 85 ++++++++++--------- 4 files changed, 101 insertions(+), 50 deletions(-) create mode 100644 src/app/(app)/course/[courseId]/home/(hooks)/use-attributes.tsx delete mode 100644 src/app/(app)/course/[courseId]/home/(hooks)/useTeamSets.tsx diff --git a/src/app/(app)/course/[courseId]/home/(hooks)/use-attributes.tsx b/src/app/(app)/course/[courseId]/home/(hooks)/use-attributes.tsx new file mode 100644 index 0000000..afb57c4 --- /dev/null +++ b/src/app/(app)/course/[courseId]/home/(hooks)/use-attributes.tsx @@ -0,0 +1,46 @@ +"use client" + +import { useCourse } from "@/app/(app)/course/[courseId]/(hooks)/useCourse" +import { useQuery } from "@tanstack/react-query" + +interface PastAttributesResponse { + team_set_name: string; + formation_date: string; + total_attributes_used: number; + attributes: { name: string }[]; +} + +const usePastAttributesQuery = ({ courseId }: { courseId: number }) => { + const attributeQuery = useQuery({ + queryKey: [`courses/${courseId}/previous-attributes`], + }) + + return { + getPastAttributes: attributeQuery.refetch, + ...attributeQuery, + } +} + +export const usePastAttributes = () => { + const { courseId } = useCourse() + const { data, isLoading, error, getPastAttributes } = usePastAttributesQuery({ + courseId: Number(courseId), + }) + + const formattedData = data + ? { + ...data, + formation_date: new Date(data.formation_date) + .toISOString() + .split("T")[0] + .replace(/-/g, "/"), + } + : undefined + + return { + data: formattedData, + isLoading, + error, + refetch: getPastAttributes, + } +} diff --git a/src/app/(app)/course/[courseId]/home/(hooks)/useTeamSets.tsx b/src/app/(app)/course/[courseId]/home/(hooks)/useTeamSets.tsx deleted file mode 100644 index e69de29..0000000 diff --git a/src/app/(app)/course/[courseId]/home/(hooks)/useTotalStudents.tsx b/src/app/(app)/course/[courseId]/home/(hooks)/useTotalStudents.tsx index 5ef887c..1034788 100644 --- a/src/app/(app)/course/[courseId]/home/(hooks)/useTotalStudents.tsx +++ b/src/app/(app)/course/[courseId]/home/(hooks)/useTotalStudents.tsx @@ -1,29 +1,29 @@ -"use client"; +"use client" -import { useCourse } from "@/app/(app)/course/[courseId]/(hooks)/useCourse"; -import { useQuery } from "@tanstack/react-query"; +import { useCourse } from "@/app/(app)/course/[courseId]/(hooks)/useCourse" +import { useQuery } from "@tanstack/react-query" const useTotalStudentsQuery = ({ courseId }: { courseId: number }) => { const studentQuery = useQuery({ queryKey: [`courses/${courseId}/students`], - }); + }) return { getTotalStudentsAsync: studentQuery.refetch, ...studentQuery, - }; -}; + } +} export const useTotalStudents = () => { - const { courseId } = useCourse(); + const { courseId } = useCourse() const { data, isLoading, error, getTotalStudentsAsync } = useTotalStudentsQuery({ courseId: Number(courseId), - }); + }) return { totalStudents: data?.count ?? 0, isLoading, error, refetch: getTotalStudentsAsync, - }; -}; + } +} diff --git a/src/app/(app)/course/[courseId]/home/page.tsx b/src/app/(app)/course/[courseId]/home/page.tsx index a388557..1b8b8f5 100644 --- a/src/app/(app)/course/[courseId]/home/page.tsx +++ b/src/app/(app)/course/[courseId]/home/page.tsx @@ -2,40 +2,36 @@ import { useCourse } from "@/app/(app)/course/[courseId]/(hooks)/useCourse" import PageView from "@/components/views/Page" import { useToast } from "@/hooks/use-toast" +import { useEffect } from "react" import { CircularProgressbar, buildStyles } from 'react-circular-progressbar' import 'react-circular-progressbar/dist/styles.css' import { CalculateOnboardingCompletion } from "./(hooks)/calculateOnboardingCompletion" +import { usePastAttributes } from "./(hooks)/use-attributes" import { useTotalStudents } from "./(hooks)/useTotalStudents" const HomePage = () => { const { courseId } = useCourse() const { completionPercentage, nextStepTitle } = CalculateOnboardingCompletion() - const { totalStudents, error } = useTotalStudents(); - const {toast} = useToast(); + const { totalStudents, error: totalStudentsError } = useTotalStudents() + const { data: pastAttributes, error: pastAttributesError } = usePastAttributes() + const {toast} = useToast() - if (error) { - toast({ - title: "Error fetching students", - description: "There was an error fetching the number of student enrolled on your LMS.", - }) - } + useEffect(() => { + if (totalStudentsError) { + toast({ + title: "Error fetching students", + description: "There was an error fetching the number of students enrolled on your LMS.", + }) + } + if (pastAttributesError) { + toast({ + title: "Error fetching attributes", + description: "There was an error fetching the attributes used in previous team formation.", + }) + } + }, [totalStudentsError, pastAttributesError, toast]) - const attributes = [ - "Requirement #1", - "Requirement #2", - "Requirement #3", - "Requirement #4", - "Requirement #5", - "Requirement #6", - "Requirement #7", - "Requirement #8", - "Requirement #9", - "Requirement #10", - ] - const groupedAttributes = [] - for (let i = 0; i < attributes.length; i += 4) { - groupedAttributes.push(attributes.slice(i, i + 4)) - } + const noTeamSets = !pastAttributes || Object.keys(pastAttributes).length === 0 return ( @@ -88,8 +84,8 @@ const HomePage = () => {

    Sign up Stats

      -
    • Students Enrolled on Your LMS: {totalStudents}
    • -
    • Total Team Formation Acceptions: 10
    • +
    • Students Enrolled on Your LMS: 30
    • +
    • Total Team Formation Acceptions: {totalStudents}
    @@ -98,26 +94,35 @@ const HomePage = () => {

    Previous Team Formation

      -
    • Number of Adopted Attributes: 16
    • -
    • Team Formation Date: 10/09/2023
    • +
    • Number of Adopted Attributes: {pastAttributes?.total_attributes_used}
    • +
    • Team Formation Date: {pastAttributes?.formation_date}
    -
    -

    Attributes Used

    -
    -
    - {groupedAttributes.map((group, index) => ( -
      - {group.map((attribute, idx) => ( -
    • {attribute}
    • - ))} -
    - ))} + {!noTeamSets && pastAttributes && ( +
    +

    Attributes Used

    +
    +
    + {pastAttributes.attributes.length > 0 ? ( + pastAttributes.attributes.map( + (attribute: { name: string }, index: number) => ( +
      +
    • {attribute.name}
    • +
    + ) + ) + ) : ( +
      +
    • No attributes used
    • +
    + )} +
    -
    + )} + ) } From 56af785b7edf64f4c7f15a369c94751f59044322 Mon Sep 17 00:00:00 2001 From: colton456p Date: Tue, 3 Dec 2024 16:06:17 -0800 Subject: [PATCH 19/24] reformatted code to enhance its quality, readability, reusability, and scalability. --- src/_temp_types/homeAttributes.ts | 8 ++ .../home/(components)/AttributesUsed.tsx | 28 ++++ .../home/(components)/InfoSection.tsx | 32 +++++ .../home/(components)/OnboardingProgress.tsx | 60 ++++++++ .../{use-attributes.tsx => useAttributes.tsx} | 0 .../home/(hooks)/useHandleErrors.ts | 26 ++++ src/app/(app)/course/[courseId]/home/page.tsx | 135 ++++-------------- src/components/ui/circular-progress-bar.tsx | 27 ++++ utils/format-date.ts | 2 + 9 files changed, 209 insertions(+), 109 deletions(-) create mode 100644 src/_temp_types/homeAttributes.ts create mode 100644 src/app/(app)/course/[courseId]/home/(components)/AttributesUsed.tsx create mode 100644 src/app/(app)/course/[courseId]/home/(components)/InfoSection.tsx create mode 100644 src/app/(app)/course/[courseId]/home/(components)/OnboardingProgress.tsx rename src/app/(app)/course/[courseId]/home/(hooks)/{use-attributes.tsx => useAttributes.tsx} (100%) create mode 100644 src/app/(app)/course/[courseId]/home/(hooks)/useHandleErrors.ts create mode 100644 src/components/ui/circular-progress-bar.tsx create mode 100644 utils/format-date.ts diff --git a/src/_temp_types/homeAttributes.ts b/src/_temp_types/homeAttributes.ts new file mode 100644 index 0000000..94fd01d --- /dev/null +++ b/src/_temp_types/homeAttributes.ts @@ -0,0 +1,8 @@ +export interface Attribute { + name: string; +} + +export interface InfoItem { + label: string; + value: string | number; +} diff --git a/src/app/(app)/course/[courseId]/home/(components)/AttributesUsed.tsx b/src/app/(app)/course/[courseId]/home/(components)/AttributesUsed.tsx new file mode 100644 index 0000000..c53a9e5 --- /dev/null +++ b/src/app/(app)/course/[courseId]/home/(components)/AttributesUsed.tsx @@ -0,0 +1,28 @@ +import { Attribute } from "@/_temp_types/homeAttributes" + +const AttributesUsed = ({ attributes }: { attributes: Attribute[] }) => ( +
    +

    Attributes Used

    +
    +
    + {attributes.length > 0 ? ( + attributes.map((attribute, index) => ( +
      +
    • {attribute.name}
    • +
    + )) + ) : ( +
      +
    • No attributes used
    • +
    + )} +
    +
    +
    +) + +AttributesUsed.defaultProps = { + attributes: [], +} + +export default AttributesUsed diff --git a/src/app/(app)/course/[courseId]/home/(components)/InfoSection.tsx b/src/app/(app)/course/[courseId]/home/(components)/InfoSection.tsx new file mode 100644 index 0000000..28846f4 --- /dev/null +++ b/src/app/(app)/course/[courseId]/home/(components)/InfoSection.tsx @@ -0,0 +1,32 @@ +import { InfoItem } from "@/_temp_types/homeAttributes" + +const InfoSection = ({ + title, + items = [], +}: { + title: string; + items?: InfoItem[]; +}) => ( +
    +

    {title}

    +
    + {items.length > 0 ? ( +
      + {items.map((item, index) => ( +
    • + {item.label}: {item.value} +
    • + ))} +
    + ) : ( +

    No data available

    + )} +
    +
    +) + +InfoSection.defaultProps = { + items: [], +} + +export default InfoSection diff --git a/src/app/(app)/course/[courseId]/home/(components)/OnboardingProgress.tsx b/src/app/(app)/course/[courseId]/home/(components)/OnboardingProgress.tsx new file mode 100644 index 0000000..0290e70 --- /dev/null +++ b/src/app/(app)/course/[courseId]/home/(components)/OnboardingProgress.tsx @@ -0,0 +1,60 @@ +import CircularProgressBar from "@/components/ui/circular-progress-bar" + +interface OnboardingProgressProps { + completionPercentage: number; + nextStepTitle: string; + courseId: string | number; +} + +const OnboardingProgress = ({ + completionPercentage, + nextStepTitle, + courseId, +}: OnboardingProgressProps) => { + return ( + <> +

    + Welcome back!{" "} + {completionPercentage === 100 ? ( + + Wanting to start a new team formation? + + ) : ( + + Your onboarding process is incomplete... + + )} +

    + + {completionPercentage !== 100 && ( +
    +
    + +
    +
    +

    + You are {completionPercentage}% done with your current onboarding process. +

    +

    + Next step: + + {nextStepTitle} + +

    +
    +
    + )} + + ) +} + +export default OnboardingProgress diff --git a/src/app/(app)/course/[courseId]/home/(hooks)/use-attributes.tsx b/src/app/(app)/course/[courseId]/home/(hooks)/useAttributes.tsx similarity index 100% rename from src/app/(app)/course/[courseId]/home/(hooks)/use-attributes.tsx rename to src/app/(app)/course/[courseId]/home/(hooks)/useAttributes.tsx diff --git a/src/app/(app)/course/[courseId]/home/(hooks)/useHandleErrors.ts b/src/app/(app)/course/[courseId]/home/(hooks)/useHandleErrors.ts new file mode 100644 index 0000000..56fd2df --- /dev/null +++ b/src/app/(app)/course/[courseId]/home/(hooks)/useHandleErrors.ts @@ -0,0 +1,26 @@ +import { useToast } from "@/hooks/use-toast" +import { useEffect } from "react" + +interface ErrorState { + totalStudentsError?: any; + pastAttributesError?: any; +} + +export const useHandleErrors = ({ totalStudentsError, pastAttributesError }: ErrorState) => { + const { toast } = useToast() + + useEffect(() => { + if (totalStudentsError) { + toast({ + title: "Error fetching students", + description: "There was an error fetching the number of students enrolled on your LMS.", + }) + } + if (pastAttributesError) { + toast({ + title: "Error fetching attributes", + description: "There was an error fetching the attributes used in previous team formation.", + }) + } + }, [totalStudentsError, pastAttributesError, toast]) +} diff --git a/src/app/(app)/course/[courseId]/home/page.tsx b/src/app/(app)/course/[courseId]/home/page.tsx index 1b8b8f5..ac8f904 100644 --- a/src/app/(app)/course/[courseId]/home/page.tsx +++ b/src/app/(app)/course/[courseId]/home/page.tsx @@ -1,128 +1,45 @@ "use client" + +import { formatDate } from "@/../utils/format-date" import { useCourse } from "@/app/(app)/course/[courseId]/(hooks)/useCourse" import PageView from "@/components/views/Page" -import { useToast } from "@/hooks/use-toast" -import { useEffect } from "react" -import { CircularProgressbar, buildStyles } from 'react-circular-progressbar' -import 'react-circular-progressbar/dist/styles.css' +import "react-circular-progressbar/dist/styles.css" +import AttributesUsed from "./(components)/AttributesUsed" +import InfoSection from "./(components)/InfoSection" +import OnboardingProgress from "./(components)/OnboardingProgress" import { CalculateOnboardingCompletion } from "./(hooks)/calculateOnboardingCompletion" -import { usePastAttributes } from "./(hooks)/use-attributes" +import { usePastAttributes } from "./(hooks)/useAttributes" +import { useHandleErrors } from "./(hooks)/useHandleErrors" import { useTotalStudents } from "./(hooks)/useTotalStudents" + const HomePage = () => { const { courseId } = useCourse() const { completionPercentage, nextStepTitle } = CalculateOnboardingCompletion() const { totalStudents, error: totalStudentsError } = useTotalStudents() const { data: pastAttributes, error: pastAttributesError } = usePastAttributes() - const {toast} = useToast() - useEffect(() => { - if (totalStudentsError) { - toast({ - title: "Error fetching students", - description: "There was an error fetching the number of students enrolled on your LMS.", - }) - } - if (pastAttributesError) { - toast({ - title: "Error fetching attributes", - description: "There was an error fetching the attributes used in previous team formation.", - }) - } - }, [totalStudentsError, pastAttributesError, toast]) + useHandleErrors({ totalStudentsError, pastAttributesError }) + const signUpStats = [ + { label: "Students Enrolled on Your LMS", value: 30 }, + { label: "Total Team Formation Acceptions", value: totalStudents }, + ] - const noTeamSets = !pastAttributes || Object.keys(pastAttributes).length === 0 + const previousTeamFormation = [ + { label: "Number of Adopted Attributes", value: pastAttributes?.total_attributes_used || 0 }, + { label: "Team Formation Date", value: pastAttributes ? formatDate(pastAttributes.formation_date) : "N/A" }, + ] return ( -

    - Welcome back!{" "} - {completionPercentage === 100 ? ( - - Wanting to start a new team formation? - - ) : ( - Your onboarding process is incomplete... - )} -

    - - {completionPercentage !== 100 && ( -
    -
    - -
    -
    -

    - You are {completionPercentage}% done with your current onboarding process. -

    -

    - Next step: - - {nextStepTitle} - -

    -
    -
    - )} - - -
    -

    Sign up Stats

    -
    -
      -
    • Students Enrolled on Your LMS: 30
    • -
    • Total Team Formation Acceptions: {totalStudents}
    • -
    -
    -
    - -
    -

    Previous Team Formation

    -
    -
      -
    • Number of Adopted Attributes: {pastAttributes?.total_attributes_used}
    • -
    • Team Formation Date: {pastAttributes?.formation_date}
    • -
    -
    -
    - - {!noTeamSets && pastAttributes && ( -
    -

    Attributes Used

    -
    -
    - {pastAttributes.attributes.length > 0 ? ( - pastAttributes.attributes.map( - (attribute: { name: string }, index: number) => ( -
      -
    • {attribute.name}
    • -
    - ) - ) - ) : ( -
      -
    • No attributes used
    • -
    - )} -
    -
    -
    - )} - + + + +
    ) } diff --git a/src/components/ui/circular-progress-bar.tsx b/src/components/ui/circular-progress-bar.tsx new file mode 100644 index 0000000..e363047 --- /dev/null +++ b/src/components/ui/circular-progress-bar.tsx @@ -0,0 +1,27 @@ +"use client" + +import React from "react" +import { CircularProgressbar, buildStyles } from "react-circular-progressbar" +import "react-circular-progressbar/dist/styles.css" + +const progressBarStyles = buildStyles({ + rotation: -0.5, + strokeLinecap: "round", + textSize: "24px", + pathColor: "#000", + textColor: "#000", + trailColor: "#e6e6e6", +}) + +interface CircularProgressProps { + value: number; + text: string; +} + +const CircularProgressBar: React.FC = ({ value, text }) => { + return ( + + ) +} + +export default CircularProgressBar diff --git a/utils/format-date.ts b/utils/format-date.ts new file mode 100644 index 0000000..c716e74 --- /dev/null +++ b/utils/format-date.ts @@ -0,0 +1,2 @@ +export const formatDate = (dateString: string) => + dateString.split("T")[0].replace(/-/g, "/") From 528e719c4dd230996eed24efb213c6bed346754e Mon Sep 17 00:00:00 2001 From: colton456p Date: Tue, 3 Dec 2024 17:03:23 -0800 Subject: [PATCH 20/24] fixed frontend display --- .../[courseId]/home/(components)/AttributesUsed.tsx | 6 +++--- .../[courseId]/home/(components)/InfoSection.tsx | 10 +++++++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/app/(app)/course/[courseId]/home/(components)/AttributesUsed.tsx b/src/app/(app)/course/[courseId]/home/(components)/AttributesUsed.tsx index c53a9e5..fbb3ff6 100644 --- a/src/app/(app)/course/[courseId]/home/(components)/AttributesUsed.tsx +++ b/src/app/(app)/course/[courseId]/home/(components)/AttributesUsed.tsx @@ -4,15 +4,15 @@ const AttributesUsed = ({ attributes }: { attributes: Attribute[] }) => (

    Attributes Used

    -
    +
    0 ? "grid-cols-1 sm:grid-cols-4" : ""}`}> {attributes.length > 0 ? ( attributes.map((attribute, index) => ( -
      +
      • {attribute.name}
      )) ) : ( -
        +
        • No attributes used
        )} diff --git a/src/app/(app)/course/[courseId]/home/(components)/InfoSection.tsx b/src/app/(app)/course/[courseId]/home/(components)/InfoSection.tsx index 28846f4..84f3e4f 100644 --- a/src/app/(app)/course/[courseId]/home/(components)/InfoSection.tsx +++ b/src/app/(app)/course/[courseId]/home/(components)/InfoSection.tsx @@ -11,10 +11,14 @@ const InfoSection = ({

        {title}

        {items.length > 0 ? ( -
          +
            {items.map((item, index) => ( -
          • - {item.label}: {item.value} +
          • + {item.label}: + {item.value}
          • ))}
          From 9dd60ed9d7e6af031a0a1f7782d865337ee34c80 Mon Sep 17 00:00:00 2001 From: colton456p Date: Wed, 4 Dec 2024 11:34:57 -0800 Subject: [PATCH 21/24] Added backend for the total number of students on canvas --- .../[courseId]/home/(hooks)/useTotalStudents.tsx | 11 ++++++++--- src/app/(app)/course/[courseId]/home/page.tsx | 6 +++--- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/app/(app)/course/[courseId]/home/(hooks)/useTotalStudents.tsx b/src/app/(app)/course/[courseId]/home/(hooks)/useTotalStudents.tsx index 1034788..3968b75 100644 --- a/src/app/(app)/course/[courseId]/home/(hooks)/useTotalStudents.tsx +++ b/src/app/(app)/course/[courseId]/home/(hooks)/useTotalStudents.tsx @@ -4,8 +4,12 @@ import { useCourse } from "@/app/(app)/course/[courseId]/(hooks)/useCourse" import { useQuery } from "@tanstack/react-query" const useTotalStudentsQuery = ({ courseId }: { courseId: number }) => { - const studentQuery = useQuery({ - queryKey: [`courses/${courseId}/students`], + const studentQuery = useQuery< + unknown, + unknown, + { total_students: number; opted_in_students: number } + >({ + queryKey: [`courses/${courseId}/student-counts`], }) return { @@ -21,7 +25,8 @@ export const useTotalStudents = () => { }) return { - totalStudents: data?.count ?? 0, + totalStudents: data?.total_students ?? 0, + optedInStudents: data?.opted_in_students ?? 0, isLoading, error, refetch: getTotalStudentsAsync, diff --git a/src/app/(app)/course/[courseId]/home/page.tsx b/src/app/(app)/course/[courseId]/home/page.tsx index ac8f904..4299560 100644 --- a/src/app/(app)/course/[courseId]/home/page.tsx +++ b/src/app/(app)/course/[courseId]/home/page.tsx @@ -15,14 +15,14 @@ import { useTotalStudents } from "./(hooks)/useTotalStudents" const HomePage = () => { const { courseId } = useCourse() const { completionPercentage, nextStepTitle } = CalculateOnboardingCompletion() - const { totalStudents, error: totalStudentsError } = useTotalStudents() + const { totalStudents, optedInStudents, error: totalStudentsError } = useTotalStudents() const { data: pastAttributes, error: pastAttributesError } = usePastAttributes() useHandleErrors({ totalStudentsError, pastAttributesError }) const signUpStats = [ - { label: "Students Enrolled on Your LMS", value: 30 }, - { label: "Total Team Formation Acceptions", value: totalStudents }, + { label: "Students Enrolled on Your LMS", value: totalStudents }, + { label: "Total Team Formation Acceptions", value: optedInStudents }, ] const previousTeamFormation = [ From 20ef7d8606b1679a7a8939803bdb8895cdb8e8bc Mon Sep 17 00:00:00 2001 From: colton456p Date: Wed, 4 Dec 2024 12:09:08 -0800 Subject: [PATCH 22/24] added loading state --- .../(hooks)/calculateOnboardingCompletion.tsx | 3 +- src/app/(app)/course/[courseId]/home/page.tsx | 34 ++++++++++++------- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/src/app/(app)/course/[courseId]/home/(hooks)/calculateOnboardingCompletion.tsx b/src/app/(app)/course/[courseId]/home/(hooks)/calculateOnboardingCompletion.tsx index 6fd6fa6..2ea0cfb 100644 --- a/src/app/(app)/course/[courseId]/home/(hooks)/calculateOnboardingCompletion.tsx +++ b/src/app/(app)/course/[courseId]/home/(hooks)/calculateOnboardingCompletion.tsx @@ -1,7 +1,7 @@ import { useSetupSteps } from "@/app/(app)/course/[courseId]/setup/(hooks)/useSetupSteps" export const CalculateOnboardingCompletion = () => { - const { steps } = useSetupSteps() + const { steps, isLoading } = useSetupSteps() const enabledSteps = steps.filter((step) => step.enabled) const completedSteps = enabledSteps.filter((step) => step.completed) @@ -13,5 +13,6 @@ export const CalculateOnboardingCompletion = () => { return { completionPercentage, nextStepTitle: firstIncompleteStep ? firstIncompleteStep.title : null, + isLoading, } } diff --git a/src/app/(app)/course/[courseId]/home/page.tsx b/src/app/(app)/course/[courseId]/home/page.tsx index 4299560..5aff76b 100644 --- a/src/app/(app)/course/[courseId]/home/page.tsx +++ b/src/app/(app)/course/[courseId]/home/page.tsx @@ -3,6 +3,7 @@ import { formatDate } from "@/../utils/format-date" import { useCourse } from "@/app/(app)/course/[courseId]/(hooks)/useCourse" import PageView from "@/components/views/Page" +import { ReloadIcon } from "@radix-ui/react-icons" import "react-circular-progressbar/dist/styles.css" import AttributesUsed from "./(components)/AttributesUsed" import InfoSection from "./(components)/InfoSection" @@ -14,12 +15,13 @@ import { useTotalStudents } from "./(hooks)/useTotalStudents" const HomePage = () => { const { courseId } = useCourse() - const { completionPercentage, nextStepTitle } = CalculateOnboardingCompletion() - const { totalStudents, optedInStudents, error: totalStudentsError } = useTotalStudents() - const { data: pastAttributes, error: pastAttributesError } = usePastAttributes() - + const { completionPercentage, nextStepTitle, isLoading: isLoadingOnboarding } = CalculateOnboardingCompletion() + const { totalStudents, optedInStudents, isLoading: isLoadingStudents, error: totalStudentsError } = useTotalStudents() + const { data: pastAttributes, isLoading: isLoadingAttributes, error: pastAttributesError } = usePastAttributes() useHandleErrors({ totalStudentsError, pastAttributesError }) + const isLoading = isLoadingOnboarding || isLoadingStudents || isLoadingAttributes + const signUpStats = [ { label: "Students Enrolled on Your LMS", value: totalStudents }, { label: "Total Team Formation Acceptions", value: optedInStudents }, @@ -32,14 +34,22 @@ const HomePage = () => { return ( - - - - + {isLoading ? ( +
          + +
          + ) : ( + <> + + + + + + )}
          ) } From 0da73faa85b99d7c836b7fb0ecbbe96578024880 Mon Sep 17 00:00:00 2001 From: colton456p Date: Mon, 9 Dec 2024 13:53:51 -0800 Subject: [PATCH 23/24] small quality fixes --- .../[courseId]/home/(components)/OnboardingProgress.tsx | 4 ++-- src/app/(app)/course/[courseId]/home/page.tsx | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/app/(app)/course/[courseId]/home/(components)/OnboardingProgress.tsx b/src/app/(app)/course/[courseId]/home/(components)/OnboardingProgress.tsx index 0290e70..95ec8c3 100644 --- a/src/app/(app)/course/[courseId]/home/(components)/OnboardingProgress.tsx +++ b/src/app/(app)/course/[courseId]/home/(components)/OnboardingProgress.tsx @@ -23,7 +23,7 @@ const OnboardingProgress = ({ Wanting to start a new team formation? ) : ( - + Your onboarding process is incomplete... )} @@ -38,7 +38,7 @@ const OnboardingProgress = ({ />
        -

        +

        You are {completionPercentage}% done with your current onboarding process.

        diff --git a/src/app/(app)/course/[courseId]/home/page.tsx b/src/app/(app)/course/[courseId]/home/page.tsx index 5aff76b..6cc629a 100644 --- a/src/app/(app)/course/[courseId]/home/page.tsx +++ b/src/app/(app)/course/[courseId]/home/page.tsx @@ -4,7 +4,6 @@ import { formatDate } from "@/../utils/format-date" import { useCourse } from "@/app/(app)/course/[courseId]/(hooks)/useCourse" import PageView from "@/components/views/Page" import { ReloadIcon } from "@radix-ui/react-icons" -import "react-circular-progressbar/dist/styles.css" import AttributesUsed from "./(components)/AttributesUsed" import InfoSection from "./(components)/InfoSection" import OnboardingProgress from "./(components)/OnboardingProgress" From 4d3d4d8233047f13667e828c0ecca7b609575167 Mon Sep 17 00:00:00 2001 From: colton456p Date: Wed, 11 Dec 2024 12:24:45 -0800 Subject: [PATCH 24/24] Added a conditional to limit the number of attributes that will be shown on the homepage. --- .../home/(components)/AttributesUsed.tsx | 46 ++++++++++++------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/src/app/(app)/course/[courseId]/home/(components)/AttributesUsed.tsx b/src/app/(app)/course/[courseId]/home/(components)/AttributesUsed.tsx index fbb3ff6..8c7b3be 100644 --- a/src/app/(app)/course/[courseId]/home/(components)/AttributesUsed.tsx +++ b/src/app/(app)/course/[courseId]/home/(components)/AttributesUsed.tsx @@ -1,25 +1,37 @@ import { Attribute } from "@/_temp_types/homeAttributes" -const AttributesUsed = ({ attributes }: { attributes: Attribute[] }) => ( -

        -

        Attributes Used

        -
        -
        0 ? "grid-cols-1 sm:grid-cols-4" : ""}`}> - {attributes.length > 0 ? ( - attributes.map((attribute, index) => ( -
          -
        • {attribute.name}
        • +const AttributesUsed = ({ attributes }: { attributes: Attribute[] }) => { + const displayedAttributes = attributes.slice(0, 15) + const hasMoreAttributes = attributes.length > 15 + + return ( +
          +

          Attributes Used

          +
          +
          0 ? "grid-cols-1 sm:grid-cols-4" : ""}`}> + {attributes.length > 0 ? ( + <> + {displayedAttributes.map((attribute, index) => ( +
            +
          • {attribute.name}
          • +
          + ))} + {hasMoreAttributes && ( +
            +
          • ...
          • +
          + )} + + ) : ( +
            +
          • No attributes used
          - )) - ) : ( -
            -
          • No attributes used
          • -
          - )} + )} +
          -
        -) + ) +} AttributesUsed.defaultProps = { attributes: [],