lms/resources/js/pages/dashboard/courses/partials/live-class-status.tsx
2025-12-15 12:26:23 +01:00

156 lines
5.5 KiB
TypeScript

import { Button } from '@/components/ui/button';
import { SharedData } from '@/types/global';
import { Link, usePage } from '@inertiajs/react';
import { ExternalLink, Pencil } from 'lucide-react';
import { useEffect, useState } from 'react';
import LiveClassForm from './forms/live-class-form';
interface Props {
courseId: string | number;
liveClass: CourseLiveClass;
zoomConfig: ZoomConfigFields;
}
const LiveClassStatus = ({ courseId, liveClass, zoomConfig }: Props) => {
const [currentTime, setCurrentTime] = useState(new Date());
const { props } = usePage<SharedData>();
const { translate } = props;
const { button, dashboard } = translate;
// Get status of a live class
const getClassStatus = (liveClass: CourseLiveClass): string => {
const now = currentTime;
const classStart = new Date(liveClass.class_date_and_time);
const classEnd = liveClass.additional_info?.end_time
? new Date(liveClass.additional_info.end_time)
: new Date(classStart.getTime() + 60 * 60 * 1000); // Default 1 hour
if (now > classEnd) {
return 'ended';
} else if (now >= classStart && now <= classEnd) {
return 'live';
} else if (classStart > now) {
return 'upcoming';
}
return 'scheduled';
};
const status = getClassStatus(liveClass);
// Auto-rerender every minute, but stop when class has ended
useEffect(() => {
// Function to update time and check if class has ended
const updateTimeAndCheckStatus = () => {
const newTime = new Date();
setCurrentTime(newTime);
// Check if class has ended with new time
const classEnd = liveClass.additional_info?.end_time
? new Date(liveClass.additional_info.end_time)
: new Date(new Date(liveClass.class_date_and_time).getTime() + 60 * 60 * 1000);
// Return true if class has ended
return newTime > classEnd;
};
// Immediately check and update status on mount
const hasEnded = updateTimeAndCheckStatus();
// Don't set up interval if class has already ended
if (hasEnded) {
return;
}
// Set up interval to update current time every minute (60000ms)
const interval = setInterval(() => {
const classEnded = updateTimeAndCheckStatus();
// Clear interval if class has ended
if (classEnded) {
clearInterval(interval);
}
}, 60000); // 60 seconds = 1 minute
// Cleanup function - runs when component unmounts or dependencies change
return () => {
clearInterval(interval);
};
}, [liveClass.class_date_and_time, liveClass.additional_info?.end_time]);
const isSdkConfig = zoomConfig.zoom_web_sdk && zoomConfig.zoom_sdk_client_id && zoomConfig.zoom_sdk_client_secret ? true : false;
// Get status color
const getStatusColor = (status: string) => {
switch (status) {
case 'live':
return 'text-green-600 bg-green-100';
case 'upcoming':
return 'text-blue-600 bg-blue-100';
case 'ended':
return 'text-muted-foreground bg-gray-100';
default:
return 'text-orange-600 bg-orange-100';
}
};
return (
<>
<span className={`rounded-full px-2 py-1 text-center text-xs font-medium capitalize ${getStatusColor(status)}`}>{status}</span>
{/* Join button - show for live classes or when about to start */}
{status === 'live' ? (
isSdkConfig ? (
<Link href={route('live-class.start', liveClass.id)}>
<Button size="sm" variant={status === 'live' ? 'default' : 'outline'} className="flex w-full items-center gap-2">
<ExternalLink className="h-4 w-4" />
{button.join_class}
</Button>
</Link>
) : (
<a href={liveClass.additional_info.join_url} target="_blank">
<Button size="sm" variant={status === 'live' ? 'default' : 'outline'} className="flex w-full items-center gap-2">
<ExternalLink className="h-4 w-4" />
{button.join_class}
</Button>
</a>
)
) : (
<Button disabled variant="outline" size="sm" className="flex w-full items-center gap-2">
<ExternalLink className="h-4 w-4" />
{button.join_class}
</Button>
)}
{/* Edit and Delete buttons for admins/instructors */}
{status === 'upcoming' ? (
<LiveClassForm
courseId={courseId}
liveClass={liveClass}
title={button.edit_live_class}
handler={
<Button
size="sm"
variant="secondary"
className="bg-background border-secondary-foreground/20 flex w-full items-center gap-2 border"
>
<Pencil className="h-4 w-4" />
{button.edit_live_class}
</Button>
}
/>
) : (
<Button
size="sm"
disabled
variant="secondary"
className="bg-background border-secondary-foreground/20 flex w-full items-center gap-2 border"
>
<Pencil className="h-4 w-4" />
{button.edit_live_class}
</Button>
)}
</>
);
};
export default LiveClassStatus;