mirror of
https://github.com/rzmk/learnhouse.git
synced 2025-12-19 04:19:25 +00:00
122 lines
No EOL
4.4 KiB
TypeScript
122 lines
No EOL
4.4 KiB
TypeScript
import React, { useState, useEffect } from 'react'
|
|
import { Check, Square, ArrowRight, Folder, FileText, Video, Layers, BookOpenCheck } from 'lucide-react'
|
|
import { getUriWithOrg } from '@services/config/config'
|
|
import Link from 'next/link'
|
|
import Modal from '@components/Objects/StyledElements/Modal/Modal'
|
|
|
|
interface CourseProgressProps {
|
|
course: any
|
|
orgslug: string
|
|
isOpen: boolean
|
|
onClose: () => void
|
|
}
|
|
|
|
const CourseProgress: React.FC<CourseProgressProps> = ({ course, orgslug, isOpen, onClose }) => {
|
|
const [completedActivities, setCompletedActivities] = useState(0)
|
|
const [totalActivities, setTotalActivities] = useState(0)
|
|
|
|
useEffect(() => {
|
|
let total = 0
|
|
let completed = 0
|
|
|
|
course.chapters.forEach((chapter: any) => {
|
|
chapter.activities.forEach((activity: any) => {
|
|
total++
|
|
if (isActivityDone(activity)) {
|
|
completed++
|
|
}
|
|
})
|
|
})
|
|
|
|
setTotalActivities(total)
|
|
setCompletedActivities(completed)
|
|
}, [course])
|
|
|
|
const isActivityDone = (activity: any) => {
|
|
const run = course?.trail?.runs?.find(
|
|
(run: any) => run.course_id === course.id
|
|
)
|
|
if (run) {
|
|
return run.steps.find((step: any) => step.activity_id === activity.id)
|
|
}
|
|
return false
|
|
}
|
|
|
|
const getActivityTypeIcon = (activityType: string) => {
|
|
switch (activityType) {
|
|
case 'TYPE_VIDEO':
|
|
return <Video size={16} className="text-gray-400" />
|
|
case 'TYPE_DOCUMENT':
|
|
return <FileText size={16} className="text-gray-400" />
|
|
case 'TYPE_DYNAMIC':
|
|
return <Layers size={16} className="text-gray-400" />
|
|
case 'TYPE_ASSIGNMENT':
|
|
return <BookOpenCheck size={16} className="text-gray-400" />
|
|
default:
|
|
return <FileText size={16} className="text-gray-400" />
|
|
}
|
|
}
|
|
|
|
const progressPercentage = totalActivities > 0 ? (completedActivities / totalActivities) * 100 : 0
|
|
const radius = 40
|
|
const circumference = 2 * Math.PI * radius
|
|
const strokeDashoffset = circumference - (progressPercentage / 100) * circumference
|
|
|
|
const dialogContent = (
|
|
<div className="space-y-4">
|
|
{course.chapters.map((chapter: any) => (
|
|
<div key={chapter.chapter_uuid} className="bg-gray-50 rounded-lg overflow-hidden">
|
|
<div className="px-4 py-3 bg-gray-100 font-semibold text-gray-700 flex items-center space-x-2">
|
|
<Folder size={16} className="text-gray-400" />
|
|
<span>{chapter.name}</span>
|
|
</div>
|
|
<div className="divide-y divide-gray-100">
|
|
{chapter.activities.map((activity: any) => {
|
|
const activityId = activity.activity_uuid.replace('activity_', '')
|
|
const courseId = course.course_uuid.replace('course_', '')
|
|
return (
|
|
<Link
|
|
key={activity.activity_uuid}
|
|
href={getUriWithOrg(orgslug, '') + `/course/${courseId}/activity/${activityId}`}
|
|
>
|
|
<div className="px-4 py-3 hover:bg-gray-100 transition-colors flex items-center group">
|
|
<div className="flex items-center space-x-3 flex-1">
|
|
{isActivityDone(activity) ? (
|
|
<div className="relative">
|
|
<Square size={18} className="stroke-[2] text-teal-600" />
|
|
<Check size={18} className="stroke-[2.5] text-teal-600 absolute top-0 left-0" />
|
|
</div>
|
|
) : (
|
|
<Square size={18} className="stroke-[2] text-gray-300" />
|
|
)}
|
|
<div className="flex items-center space-x-2">
|
|
{getActivityTypeIcon(activity.activity_type)}
|
|
<span className="text-gray-700 group-hover:text-gray-900">
|
|
{activity.name}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<ArrowRight size={16} className="text-gray-400 group-hover:text-gray-600" />
|
|
</div>
|
|
</Link>
|
|
)
|
|
})}
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
)
|
|
|
|
return (
|
|
<Modal
|
|
isDialogOpen={isOpen}
|
|
onOpenChange={onClose}
|
|
dialogContent={dialogContent}
|
|
dialogTitle="Course Progress"
|
|
dialogDescription={`${completedActivities} of ${totalActivities} activities completed`}
|
|
minWidth="md"
|
|
/>
|
|
)
|
|
}
|
|
|
|
export default CourseProgress
|