Files
Event-Management-System/RIT-EVENT-MANAGEMENT--main/components/StatusTrackerView.tsx

591 lines
32 KiB
TypeScript

import React, { useState, useMemo, useEffect } from 'react';
import { createPortal } from 'react-dom';
import { Event } from '../types';
import { uploadToSupabase, supabase } from '../supabase';
interface StatusTrackerViewProps {
event: Event;
registration?: any;
onBack: () => void;
onUploadCertificate: (data: string) => Promise<string>;
onShowCreateTeam?: () => void;
onShowJoinTeam?: () => void;
}
const SuccessPopup: React.FC<{ onClose: () => void }> = ({ onClose }) => (
<div className="fixed inset-0 z-[10005] flex items-center justify-center p-6 bg-black/80 backdrop-blur-xl animate-in fade-in duration-300">
<div className="bg-white rounded-[3rem] w-full max-w-sm p-12 shadow-2xl flex flex-col items-center text-center animate-in zoom-in-95 duration-500">
<div className="w-24 h-24 bg-emerald-100 text-emerald-500 rounded-full flex items-center justify-center text-4xl mb-8 shadow-inner">
<i className="fas fa-cloud-check"></i>
</div>
<h3 className="text-2xl font-black text-slate-900 mb-2 uppercase tracking-tight">File Captured</h3>
<p className="text-gray-500 font-bold text-[10px] uppercase tracking-[0.3em] mb-10">Proof uploaded successfully</p>
<button
onClick={onClose}
className="w-full py-5 bg-emerald-600 text-white rounded-2xl font-black uppercase tracking-widest text-[11px] hover:bg-emerald-700 transition-all shadow-xl shadow-emerald-200 active:scale-95"
>
Track Verification
</button>
</div>
</div>
);
const StatusTrackerView: React.FC<StatusTrackerViewProps> = ({ event, registration, onBack, onUploadCertificate, onShowCreateTeam, onShowJoinTeam }) => {
const fileInputRef = React.useRef<HTMLInputElement>(null);
const [isUploading, setIsUploading] = useState(false);
const [showSuccess, setShowSuccess] = useState(false);
const [now, setNow] = useState(new Date());
const [attendanceRecords, setAttendanceRecords] = useState<any[]>([]);
const fetchAttendance = async () => {
if (!registration?.id) return;
const { data, error } = await supabase
.from('attendance_records')
.select('*')
.eq('registration_id', registration.id);
if (!error && data) {
setAttendanceRecords(data);
}
};
const odUrl = registration?.od_url || registration?.od;
const certUrl = registration?.certification_url || registration?.certifications;
const certStatus = registration?.certification_status || registration?.certification_approval;
const [liveOdUrl, setLiveOdUrl] = useState(odUrl);
const [liveCertUrl, setLiveCertUrl] = useState(certUrl);
const [liveCertStatus, setLiveCertStatus] = useState(certStatus);
useEffect(() => {
// Dynamic refetch to catch real-time faculty OD uploads without full page reload
if (registration?.id) {
supabase.from('registrations').select('*').eq('id', registration.id).single().then(({ data }) => {
if (data) {
setLiveOdUrl(data.od_url || data.od);
setLiveCertUrl(data.certification_url || data.certifications);
setLiveCertStatus(data.certification_status || data.certification_approval);
}
});
}
if (registration?.id) {
fetchAttendance();
// Real-time subscription for attendance
const channel = supabase
.channel(`attendance-${registration.id}`)
.on(
'postgres_changes',
{
event: '*',
schema: 'public',
table: 'attendance_records',
filter: `registration_id=eq.${registration.id}`
},
() => {
fetchAttendance();
}
)
.subscribe();
return () => {
supabase.removeChannel(channel);
};
}
const timer = setInterval(() => setNow(new Date()), 30000);
return () => clearInterval(timer);
}, [registration?.id, event.id]);
const isEventEnded = event.status === 'Completed';
const progressSteps = useMemo(() => {
const isFree = event.pricingType === 'FREE';
const isPaidVerified = registration?.payment_status === 'COMPLETED';
const isManuallyEnded = event.status === 'Completed';
const isManuallyOngoing = event.status === 'Event Ongoing';
const isEnded = isManuallyEnded;
const isOngoing = isManuallyOngoing;
const hasUploaded = !!liveCertUrl;
const isApproved = liveCertStatus === 'APPROVED';
const hasUploadedOd = !!liveOdUrl;
return [
{
label: 'Registered',
status: 'completed',
icon: 'fa-user-check',
color: 'bg-emerald-500',
detail: 'Identity Secured'
},
{
label: 'TEAM',
status: !event.isTeamEvent || registration?.team_code ? 'completed' : 'active',
icon: 'fa-users',
color: 'bg-orange-500',
detail: !event.isTeamEvent ? 'Solo Mode' : (registration?.team_code ? `Team: ${registration.team_name || 'Joined'}` : 'Wait for Team')
},
{
label: 'Payment',
status: isFree || isPaidVerified ? 'completed' : 'active',
icon: 'fa-credit-card',
color: 'bg-blue-400',
detail: isFree ? 'Waiver Applied' : (isPaidVerified ? 'Funds Verified' : 'Awaiting Payment')
},
{
label: 'Ticket',
status: isFree || isPaidVerified ? 'completed' : 'pending',
icon: 'fa-ticket-alt',
color: 'bg-amber-500',
detail: isFree || isPaidVerified ? 'Access Granted' : 'Locked'
},
{
label: 'Ongoing',
status: isEnded ? 'completed' : (isOngoing ? 'active' : 'pending'),
icon: 'fa-play-circle',
color: 'bg-purple-500',
detail: isOngoing ? 'Live Session' : (isEnded ? 'Session Ended' : 'Scheduled')
},
{
label: 'Ended',
status: isEnded ? 'completed' : 'pending',
icon: 'fa-calendar-check',
color: 'bg-rose-500',
detail: isEnded ? 'Archived' : 'Wait for Admin'
},
{
label: 'Certification',
status: isApproved ? 'completed' : (isEnded ? 'active' : 'pending'),
icon: isApproved ? 'fa-check-double' : (hasUploaded ? 'fa-spinner fa-spin' : 'fa-award'),
color: isApproved ? 'bg-emerald-600' : (isEnded ? 'bg-amber-500' : 'bg-indigo-600'),
detail: isApproved ? 'Verified by Faculty' : (hasUploaded ? 'In Review' : (isEnded ? 'Upload Proof' : 'Wait for End'))
},
{
label: 'OD',
status: hasUploadedOd ? 'completed' : (isApproved ? 'active' : 'pending'),
icon: 'fa-file-signature',
color: 'bg-teal-500',
detail: hasUploadedOd ? 'OD Provided' : (isApproved ? 'Ready for Download' : 'Wait for Approval')
},
];
}, [event, registration, now, liveOdUrl, liveCertUrl, liveCertStatus]);
const handleOdDownload = async () => {
if (!liveOdUrl) return;
try {
const response = await fetch(liveOdUrl);
const blob = await response.blob();
const isPdf = liveOdUrl.toLowerCase().endsWith('.pdf') || blob.type === 'application/pdf';
const extension = isPdf ? 'pdf' : 'jpg';
const blobUrl = window.URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = blobUrl;
link.download = `OD_${event.title.replace(/\s+/g, '_')}.${extension}`;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
window.URL.revokeObjectURL(blobUrl);
} catch (err) {
console.error("OD Download failed:", err);
// Fallback: just open the URL directly if local fetch somehow fails
window.open(liveOdUrl, '_blank');
}
};
const handleFileChange = async (e: React.ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0];
const { data: { user } } = await supabase.auth.getUser();
if (file && user && registration) {
setIsUploading(true);
const reader = new FileReader();
reader.onloadend = async () => {
try {
const base64 = reader.result as string;
const fileName = `Cert_${user.id}_${event.id}_${Date.now()}.jpg`;
// STORE IN 'Certifications' BUCKET AS REQUESTED
const publicUrl = await uploadToSupabase(base64, fileName, 'Certifications');
await supabase.from('registrations').update({
certification_url: publicUrl,
certification_status: 'PENDING_APPROVAL'
}).eq('id', registration.id);
setShowSuccess(true);
} catch (err) {
console.error("Upload failed:", err);
alert("Upload failed. Please check your connection or bucket permissions.");
} finally {
setIsUploading(false);
}
};
reader.readAsDataURL(file);
}
};
return (
<div className="pt-40 pb-16 px-6 md:px-12 lg:px-24 bg-[#F3F4F6] min-h-screen animate-in fade-in duration-500 font-inter">
{showSuccess && <SuccessPopup onClose={() => { setShowSuccess(false); window.location.reload(); }} />}
<div className="max-w-7xl mx-auto">
<div className="flex flex-col md:flex-row md:items-center justify-between gap-6 mb-16">
<div className="flex flex-col items-start">
<button onClick={onBack} className="flex items-center gap-2 text-[#f97316] font-black uppercase tracking-[0.2em] mb-6 text-[10px] group">
<i className="fas fa-arrow-left transition-transform group-hover:-translate-x-1"></i> Return to Hub
</button>
<h1 className="text-6xl font-black text-[#1A202C] tracking-tighter mb-2 leading-none uppercase">REAL-TIME <span className="text-[#f97316]">PROGRESS</span></h1>
<p className="text-gray-400 font-bold uppercase tracking-[0.3em] text-xs">Tracking Node: {event.title}</p>
</div>
</div>
<div className="bg-white rounded-[3.5rem] p-8 md:p-16 shadow-xl shadow-gray-900/5 border border-gray-100 mb-12 relative overflow-hidden">
<div className="relative z-10 w-full overflow-x-auto no-scrollbar pb-6">
<div className="min-w-[800px] relative">
{/* Continuous Line Background */}
<div
className="absolute top-2.5 h-1.5 bg-gray-100 rounded-full z-0"
style={{ left: `${100 / (progressSteps.length * 2)}%`, right: `${100 / (progressSteps.length * 2)}%` }}
></div>
{/* Active Line Foreground */}
<div
className="absolute top-2.5 h-1.5 bg-gradient-to-r from-emerald-400 to-orange-400 rounded-full z-0 transition-all duration-1000"
style={{
left: `${100 / (progressSteps.length * 2)}%`,
width: `calc(${
(progressSteps.findIndex(s => s.status === 'active') !== -1
? progressSteps.findIndex(s => s.status === 'active')
: Math.max(0, progressSteps.filter(s => s.status === 'completed').length - 1))
/ (progressSteps.length - 1)
} * (100% - ${100 / progressSteps.length}%))`
}}
></div>
{/* Steps Container */}
<div className="flex w-full justify-between items-start relative z-10">
{progressSteps.map((step, idx) => (
<div key={idx} className="flex flex-col items-center flex-1 relative group cursor-pointer">
{/* Dot */}
<div className={`w-6 h-6 rounded-full border-4 border-white shadow-sm mb-10 transition-all duration-500 group-hover:scale-125 ${
step.status === 'completed' ? 'bg-emerald-500' :
step.status === 'active' ? 'bg-orange-500 ring-4 ring-orange-100' :
'bg-gray-200'
}`}></div>
{/* Icon */}
<div className={`w-16 h-16 md:w-20 md:h-20 rounded-full flex items-center justify-center transition-all duration-500 mb-6 group-hover:-translate-y-2 group-hover:shadow-lg ${
step.status === 'completed' ? 'bg-emerald-50 text-emerald-500 group-hover:bg-emerald-100' :
step.status === 'active' ? 'bg-white border-2 border-orange-500 text-orange-500 shadow-[0_0_20px_rgba(249,115,22,0.2)] scale-110 group-hover:scale-125' :
'bg-gray-50 text-gray-300 group-hover:bg-gray-100 group-hover:text-gray-500'
}`}>
<i className={`fas ${step.icon} text-xl md:text-2xl transition-transform duration-300 group-hover:scale-110`}></i>
</div>
{/* Text */}
<div className="text-center transition-transform duration-300 group-hover:translate-y-1">
<span className={`block text-[10px] md:text-xs font-black uppercase tracking-[0.15em] mb-1.5 transition-colors duration-300 ${
step.status === 'active' ? 'text-orange-500' :
step.status === 'completed' ? 'text-gray-700 group-hover:text-emerald-600' :
'text-gray-400 group-hover:text-gray-600'
}`}>{step.label}</span>
<p className="text-[9px] font-bold text-gray-400 uppercase tracking-widest whitespace-nowrap">{step.detail}</p>
</div>
</div>
))}
</div>
{/* Attendance Tracker Redesign (Node-based) */}
<div className="mt-20 pt-12 border-t border-gray-100 flex flex-col items-center">
<div className="flex items-center gap-3 mb-10">
<div className="w-1.5 h-4 bg-[#f97316] rounded-full"></div>
<span className="text-[11px] font-black text-slate-800 uppercase tracking-[0.2em]">Attendance Milestones</span>
</div>
<div className="w-full max-w-4xl relative">
{(() => {
const allSessions: { label: string, status: string, day: string, batch: string }[] = [];
if (event.schedule && event.schedule.length > 0) {
// Group by day_idx
const dayMap = new Map<number, typeof event.schedule>();
event.schedule.forEach(s => {
if (!dayMap.has(s.day_idx)) dayMap.set(s.day_idx, []);
dayMap.get(s.day_idx)!.push(s);
});
const sortedDays = Array.from(dayMap.entries()).sort((a, b) => a[0] - b[0]);
sortedDays.forEach(([dayIdx, slots]) => {
slots!.forEach((slot) => {
const dLabel = `Day ${dayIdx}`;
const bLabel = `Batch ${slot.batch_idx}`;
const record = attendanceRecords.find(r => r.day_label === dLabel && r.batch_label === bLabel);
allSessions.push({
label: `D${dayIdx} B${slot.batch_idx}`,
day: dLabel,
batch: bLabel,
status: record?.is_present ? 'completed' : (record?.is_present === false ? 'absent' : 'pending')
});
});
});
} else {
const record = attendanceRecords.find(r => r.day_label === 'Day 1');
allSessions.push({
label: 'Day 1',
day: 'Day 1',
batch: '',
status: record?.is_present ? 'completed' : (record?.is_present === false ? 'absent' : 'pending')
});
}
return (
<div className="relative">
{/* Connecting Line Background */}
<div
className="absolute top-2.5 h-1.5 bg-gray-100 rounded-full z-0"
style={{ left: `${100 / (allSessions.length * 2)}%`, right: `${100 / (allSessions.length * 2)}%` }}
></div>
{/* Connecting Line Foreground */}
<div
className="absolute top-2.5 h-1.5 bg-emerald-500 rounded-full z-0 transition-all duration-1000"
style={{
left: `${100 / (allSessions.length * 2)}%`,
width: `calc(${
(allSessions.findIndex(s => s.status === 'pending') !== -1
? Math.max(0, allSessions.findIndex(s => s.status === 'pending') - 1)
: Math.max(0, allSessions.filter(s => s.status === 'completed').length - 1))
/ Math.max(1, allSessions.length - 1)
} * (100% - ${100 / allSessions.length}%))`
}}
></div>
{/* Nodes */}
<div className="flex w-full justify-between items-start relative z-10">
{allSessions.map((session, sIdx) => (
<div key={sIdx} className="flex flex-col items-center flex-1 relative group cursor-pointer">
{/* Dot on line */}
<div className={`w-6 h-6 rounded-full border-4 border-white shadow-sm mb-10 transition-all duration-500 group-hover:scale-125 ${
session.status === 'completed' ? 'bg-emerald-500' :
session.status === 'absent' ? 'bg-rose-500 animate-pulse' :
'bg-gray-200'
}`}></div>
{/* Large Circle Shaped Indicator */}
<div className={`w-16 h-16 md:w-20 md:h-20 rounded-full flex items-center justify-center transition-all duration-500 mb-6 group-hover:-translate-y-2 group-hover:shadow-lg ${
session.status === 'completed' ? 'bg-emerald-50 text-emerald-500 group-hover:bg-emerald-100 border-2 border-emerald-500/20' :
session.status === 'absent' ? 'bg-rose-50 text-rose-500 group-hover:bg-rose-100 border-2 border-rose-500/20' :
'bg-gray-50 text-gray-300 group-hover:bg-gray-100 group-hover:text-gray-500 border-2 border-slate-100'
}`}>
<i className={`fas ${
session.status === 'completed' ? 'fa-calendar-check' :
session.status === 'absent' ? 'fa-calendar-times' :
'fa-calendar'
} text-xl md:text-2xl transition-transform duration-300 group-hover:scale-110`}></i>
</div>
{/* Text */}
<div className="text-center transition-transform duration-300 group-hover:translate-y-1">
<span className={`block text-[10px] md:text-xs font-black uppercase tracking-[0.15em] mb-1.5 transition-colors duration-300 ${
session.status === 'completed' ? 'text-[#1A202C]' :
session.status === 'absent' ? 'text-rose-500' :
'text-gray-400 group-hover:text-gray-600'
}`}>{session.label}</span>
<p className="text-[9px] font-bold text-gray-400 uppercase tracking-widest whitespace-nowrap">
{session.status === 'completed' ? 'Attended' :
session.status === 'absent' ? 'Absent' : 'Upcoming'}
</p>
</div>
</div>
))}
</div>
</div>
);
})()}
</div>
<div className="mt-12 bg-gray-50/50 px-8 py-3 rounded-2xl border border-gray-100">
<p className="text-[10px] font-black text-gray-500 uppercase tracking-[0.2em] flex items-center gap-3">
<i className="fas fa-chart-line text-[#f97316]"></i>
{attendanceRecords.filter(r => r.is_present).length} / {Math.max(1, event.schedule?.length || 1)} Sessions Attended
</p>
</div>
</div>
</div>
{/* Team Management Buttons - Relocated from RegistrationsView */}
{event.isTeamEvent && !registration?.team_code && (
<div className="mt-12 p-10 bg-white rounded-[3.5rem] shadow-xl shadow-gray-900/5 border border-gray-100 relative overflow-hidden group animate-in slide-in-from-bottom-5">
<div className="absolute top-0 right-0 w-32 h-32 bg-orange-50 rounded-full -translate-y-1/2 translate-x-1/2 blur-2xl group-hover:bg-orange-100 transition-colors"></div>
<div className="flex flex-col md:flex-row items-center justify-between gap-8 relative z-10">
<div className="text-center md:text-left">
<div className="flex justify-center md:justify-start items-center gap-3 mb-3">
<div className="w-2 h-5 bg-[#f97316] rounded-full"></div>
<span className="text-xs font-black text-slate-900 uppercase tracking-widest">Team Management</span>
</div>
<p className="text-xs text-slate-400 font-bold uppercase tracking-widest max-w-md">This is a team event. Form your own team or join an existing alliance to participate in this competition.</p>
</div>
<div className="flex items-center gap-4 w-full md:w-auto">
<button
onClick={onShowCreateTeam}
className="flex-1 md:flex-none py-5 px-10 bg-white border-2 border-slate-100 text-slate-900 rounded-2xl font-black uppercase text-[10px] tracking-[0.2em] shadow-sm hover:border-[#f97316] hover:text-[#f97316] transition-all active:scale-95 flex items-center justify-center gap-2"
>
<i className="fas fa-plus-circle"></i> Create Team
</button>
<button
onClick={onShowJoinTeam}
className="flex-1 md:flex-none py-5 px-10 bg-slate-900 text-white rounded-2xl font-black uppercase text-[10px] tracking-[0.2em] shadow-xl shadow-gray-200 hover:bg-black transition-all active:scale-95 flex items-center justify-center gap-2"
>
<i className="fas fa-right-to-bracket"></i> Join Alliance
</button>
</div>
</div>
</div>
)}
</div>
</div>
{/* OD Document Download Section */}
{liveOdUrl && (
<div className="bg-white rounded-[3.5rem] p-8 md:p-12 shadow-xl shadow-gray-900/5 border border-gray-100 mb-12 flex flex-col md:flex-row items-center justify-between gap-8 animate-in slide-in-from-bottom-5">
<div className="flex items-center gap-6">
<div className="w-16 h-16 bg-teal-50 text-teal-500 rounded-3xl flex items-center justify-center text-2xl shadow-inner">
<i className="fas fa-file-signature"></i>
</div>
<div>
<h3 className="text-2xl font-black text-[#1A202C] tracking-tight uppercase">Official On-Duty Document</h3>
<p className="text-[10px] font-black text-gray-400 uppercase tracking-widest mt-1">Authorized by Faculty Coordinator</p>
</div>
</div>
<div className="flex gap-4 w-full md:w-auto">
<a href={liveOdUrl} target="_blank" rel="noreferrer" className="flex-1 md:w-auto px-8 py-4 bg-gray-50 text-gray-600 rounded-2xl font-black text-[10px] uppercase tracking-widest hover:bg-gray-100 transition-all border border-gray-200 text-center">
<i className="fas fa-eye mr-2"></i> Inspect
</a>
<button onClick={handleOdDownload} className="flex-1 md:w-auto px-8 py-4 bg-teal-600 text-white rounded-2xl font-black text-[10px] uppercase tracking-widest hover:bg-teal-700 transition-all shadow-xl shadow-teal-600/20 text-center">
<i className="fas fa-download mr-2"></i> Download OD
</button>
</div>
</div>
)}
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
<div className="lg:col-span-2 bg-white p-12 rounded-[3.5rem] shadow-xl shadow-gray-900/10 border border-gray-200 flex flex-col md:flex-row items-center gap-12">
<div className="flex-1 text-center md:text-left">
<h3 className="text-3xl font-black text-[#1A202C] mb-4 uppercase tracking-tight">Certification Portal</h3>
<p className="text-gray-500 font-medium mb-8 leading-relaxed max-w-sm">Provide valid proof of attendance or task completion to finalize your official event participation.</p>
<input type="file" ref={fileInputRef} className="hidden" onChange={handleFileChange} accept="image/*" />
{!isEventEnded ? (
<div className="flex flex-col items-start gap-3">
<button
disabled
className="px-12 py-5 rounded-2xl font-black text-xs uppercase tracking-[0.3em] bg-gray-100 text-gray-400 cursor-not-allowed border border-gray-200 flex items-center gap-4"
>
<i className="fas fa-lock"></i> UPLOAD LOCKED
</button>
<p className="text-[10px] font-black text-gray-400 uppercase tracking-widest flex items-center gap-2">
<i className="fas fa-hourglass-half text-[#f97316]"></i>
Upload unlocks once admin marks event as Ended
</p>
</div>
) : (
<>
<button
onClick={() => fileInputRef.current?.click()}
disabled={isUploading || liveCertStatus === 'APPROVED'}
className={`px-12 py-5 rounded-2xl font-black text-xs uppercase tracking-[0.3em] shadow-2xl transition-all active:scale-95 flex items-center gap-4 ${liveCertStatus === 'APPROVED' ? 'bg-emerald-50 text-emerald-500 cursor-not-allowed border border-emerald-100' :
isUploading ? 'bg-gray-200 text-gray-400 cursor-wait' : 'bg-[#1A202C] text-white hover:bg-black'
}`}
>
{isUploading ? <><i className="fas fa-spinner fa-spin"></i> SYNCING...</> :
liveCertStatus === 'APPROVED' ? <><i className="fas fa-check-double"></i> VERIFIED</> :
liveCertUrl ? <><i className="fas fa-clock"></i> RE-UPLOAD PROOF</> :
<><i className="fas fa-cloud-arrow-up"></i> UPLOAD PROOF</>}
</button>
{liveCertStatus === 'PENDING_APPROVAL' && (
<p className="mt-4 text-[10px] font-black text-[#f97316] uppercase tracking-widest flex items-center gap-2">
<i className="fas fa-info-circle"></i> Awaiting Faculty Review
</p>
)}
</>
)}
</div>
<div className="w-full md:w-64 aspect-square bg-gray-50 rounded-[2.5rem] border-2 border-dashed border-gray-200 flex items-center justify-center overflow-hidden group">
{liveCertUrl ? (
<img src={liveCertUrl} className="w-full h-full object-cover group-hover:scale-110 transition-transform duration-500" alt="Proof" />
) : (
<div className="text-center p-6">
<i className="fas fa-image text-gray-200 text-4xl mb-4"></i>
<p className="text-[10px] font-black text-gray-300 uppercase tracking-widest">Preview Area</p>
</div>
)}
</div>
</div>
<div className="bg-[#1A202C] p-12 rounded-[3.5rem] text-white shadow-2xl shadow-gray-900/20 relative overflow-hidden">
<div className="absolute top-0 right-0 w-32 h-32 bg-white/5 rounded-full -translate-y-1/2 translate-x-1/2 blur-2xl"></div>
<h3 className="text-2xl font-black mb-10 tracking-tight uppercase flex items-center gap-4">
Event Info
<span className="w-2 h-2 rounded-full bg-emerald-500 animate-pulse"></span>
</h3>
<div className="space-y-8">
<div className="flex justify-between items-center border-b border-white/5 pb-4">
<span className="text-white/40 text-[10px] font-black uppercase tracking-widest">Conducting Club</span>
<span className="text-white font-black text-[11px] uppercase">{event.club || 'N/A'}</span>
</div>
<div className="flex justify-between items-center border-b border-white/5 pb-4">
<span className="text-white/40 text-[10px] font-black uppercase tracking-widest">Enrollment Status</span>
<span className="text-white font-black text-[11px] uppercase">{registration?.payment_status || 'PENDING'}</span>
</div>
{event.durationDays && (
<div className="flex justify-between items-center border-b border-white/5 pb-4">
<span className="text-white/40 text-[10px] font-black uppercase tracking-widest">Duration</span>
<span className="text-white font-black text-[11px] uppercase">{event.durationDays} Days</span>
</div>
)}
{event.schedule && event.schedule.length > 0 && (
<div className="flex justify-between items-center border-b border-white/5 pb-4">
<span className="text-white/40 text-[10px] font-black uppercase tracking-widest">Sessions</span>
<span className="text-white font-black text-[11px] uppercase">
{event.schedule.length} Total
</span>
</div>
)}
<div className="flex justify-between items-center border-b border-white/5 pb-4">
<span className="text-white/40 text-[10px] font-black uppercase tracking-widest">Attendance Progress</span>
<span className="text-emerald-400 font-black text-[11px] uppercase">
{attendanceRecords.filter(r => r.is_present).length} Marked
</span>
</div>
<div className="flex justify-between items-center border-b border-white/5 pb-4">
<span className="text-white/40 text-[10px] font-black uppercase tracking-widest">Certification</span>
<span className={`font-black text-[11px] uppercase ${liveCertStatus === 'APPROVED' ? 'text-emerald-400' : 'text-[#f97316]'}`}>
{liveCertStatus?.replace('_', ' ') || 'NOT SUBMITTED'}
</span>
</div>
<div className="flex justify-between items-center">
<span className="text-white/40 text-[10px] font-black uppercase tracking-widest">Verification Status</span>
<span className={`font-black text-[11px] uppercase ${liveCertStatus === 'APPROVED' ? 'text-emerald-400' : 'text-white/60'}`}>
{liveCertStatus === 'APPROVED' ? 'Finalized' : 'Pending'}
</span>
</div>
</div>
</div>
</div>
</div>
</div>
);
};
export default StatusTrackerView;