diff --git a/LearningPlatform/app/(student)/(shell)/courses/[slug]/page.tsx b/LearningPlatform/app/(student)/(shell)/courses/[slug]/page.tsx index 14d3e39..2e9e46a 100644 --- a/LearningPlatform/app/(student)/(shell)/courses/[slug]/page.tsx +++ b/LearningPlatform/app/(student)/(shell)/courses/[slug]/page.tsx @@ -13,7 +13,7 @@ import { prisma } from '@/lib/prisma' import { CourseHeroTitle } from '@/components/courses/course-hero-title' import { studentGlassCard, studentGlassPill } from '@/lib/student-glass-styles' import { cn } from '@/lib/utils' -import { ArchiveCourseButton } from '@/components/profile/archive-actions' +import { ArchiveCourseButton, UnarchiveCourseButton } from '@/components/profile/archive-actions' /** Same visual as dashboard `StatPill` in `flashcard-section.tsx` (server-safe duplicate). */ function CourseFlashcardStatPill({ label, count }: { label: string; count: number }) { @@ -147,6 +147,17 @@ export default async function CoursePage({ params }: { params: Promise<{ slug: s } const courseId = String(course.id) + let courseArchived = false + if (session?.user?.id) { + const archivedCourse = await prisma.courseProgress.findFirst({ + where: { + userId: session.user.id, + courseId, + }, + select: { archivedAt: true }, + }) + courseArchived = Boolean(archivedCourse?.archivedAt) + } const moduleIds = modulesWithLessons.map((m) => String(m.id)) let mainDeck = await prisma.flashcardDeck.findFirst({ where: { courseId, parentDeckId: null }, @@ -480,7 +491,11 @@ export default async function CoursePage({ params }: { params: Promise<{ slug: s )}
- + {courseArchived ? ( + + ) : ( + + )}
) diff --git a/LearningPlatform/components/profile/archive-actions.tsx b/LearningPlatform/components/profile/archive-actions.tsx index 8e5c8cb..8af50aa 100644 --- a/LearningPlatform/components/profile/archive-actions.tsx +++ b/LearningPlatform/components/profile/archive-actions.tsx @@ -1,6 +1,6 @@ 'use client' -import { useState, useTransition } from 'react' +import { useEffect, useRef, useState, useTransition } from 'react' import { useRouter } from 'next/navigation' import { Button } from '@/components/ui/button' @@ -16,88 +16,118 @@ async function postJson(url: string, body: unknown) { } } +function ActionToast({ message }: { message: string }) { + return ( +
+ {message} +
+ ) +} + +function useActionToast() { + const [toastMessage, setToastMessage] = useState(null) + const timeoutRef = useRef(null) + + useEffect(() => { + return () => { + if (timeoutRef.current !== null) { + window.clearTimeout(timeoutRef.current) + } + } + }, []) + + const showToast = (message: string) => { + if (timeoutRef.current !== null) { + window.clearTimeout(timeoutRef.current) + } + setToastMessage(message) + timeoutRef.current = window.setTimeout(() => { + setToastMessage(null) + timeoutRef.current = null + }, 2200) + } + + return { toastMessage, showToast } +} + export function ArchiveCourseButton({ courseSlug }: { courseSlug: string }) { const router = useRouter() const [pending, startTransition] = useTransition() - const [error, setError] = useState(null) + const { toastMessage, showToast } = useActionToast() return ( -
+ <> - {error ?

{error}

: null} -
+ {toastMessage ? : null} + ) } export function ArchiveDeckButton({ deckId }: { deckId: string }) { const router = useRouter() const [pending, startTransition] = useTransition() - const [error, setError] = useState(null) + const { toastMessage, showToast } = useActionToast() return ( -
+ <> - {error ?

{error}

: null} -
+ {toastMessage ? : null} + ) } export function UnarchiveCourseButton({ courseId }: { courseId: string }) { const router = useRouter() const [pending, startTransition] = useTransition() - const [error, setError] = useState(null) + const { toastMessage, showToast } = useActionToast() return ( -
+ <> - {error ?

{error}

: null} -
+ {toastMessage ? : null} + ) } export function UnarchiveDeckButton({ deckId }: { deckId: string }) { const router = useRouter() const [pending, startTransition] = useTransition() - const [error, setError] = useState(null) + const { toastMessage, showToast } = useActionToast() return ( -
+ <> - {error ?

{error}

: null} -
+ {toastMessage ? : null} + ) }