Final commit

This commit is contained in:
2026-06-23 09:37:43 +05:30
parent 2c28c27120
commit 512c04bb6f
90 changed files with 26358 additions and 0 deletions

206
frontend/src/App.tsx Normal file
View File

@@ -0,0 +1,206 @@
import { API_BASE_URL } from './lib/config';
import React, { useState } from 'react';
import { DashboardLayout } from './components/DashboardLayout';
import { InstitutionalChecklist } from './components/dashboard/InstitutionalChecklist';
import { EventProposalForm } from './components/dashboard/EventProposalForm';
import { AllEvents } from './components/dashboard/AllEvents';
import { ApprovalsView } from './components/dashboard/ApprovalsView';
import { UserManagement } from './components/dashboard/UserManagement';
import { ClassManagement } from './components/dashboard/ClassManagement';
import { LoginPage } from './pages/LoginPage';
import { AuthProvider, useAuth } from './context/AuthContext';
import { DialogProvider } from './context/DialogContext';
import { motion, AnimatePresence } from 'framer-motion';
import { StatusTimeline, type Event } from './components/dashboard/EventStatusTimeline';
import { useEffect } from 'react';
import { InstitutionalCalendar } from './components/dashboard/InstitutionalCalendar';
import { VenueTimeline } from './components/dashboard/VenueTimeline';
import { EventHistory } from './components/dashboard/EventHistory';
import { ClubInstitutionalChecklist } from './components/dashboard/ClubInstitutionalChecklist';
import { AutomationView } from './components/dashboard/AutomationView';
import { Overview } from './components/dashboard/Overview';
import { ExcelImport } from './components/dashboard/ExcelImport';
import { StudentDashboard } from './components/dashboard/StudentDashboard';
import { StudentRegistrationsView } from './components/dashboard/StudentRegistrationsView';
import { ManageNoticesView } from './components/dashboard/ManageNoticesView';
import { ManageStudentsView } from './components/dashboard/ManageStudentsView';
const AppContent: React.FC = () => {
const { isAuthenticated, user } = useAuth();
const isClubAuthorized = user?.isClubCoordinator || user?.role === 'ADMIN';
const [activeItem, setActiveItem] = useState('dashboard');
const [userEvents, setUserEvents] = useState<Event[]>([]);
const [preFillData, setPreFillData] = useState<any>(null);
const handleIncompleteClick = (data: any) => {
setPreFillData(data);
setActiveItem('propose');
};
const handleCalendarPropose = (date: string) => {
setPreFillData({ startDate: `${date}T09:00` });
setActiveItem('propose');
};
const handleClubEventClick = (data: any) => {
setPreFillData(data);
setActiveItem('propose');
};
const handleEditEvent = (event: any) => {
setPreFillData({
...event,
eventName: event.title,
venue: event.location,
socialProfile: event.guestSocialProfile,
isEditMode: true
});
setActiveItem('propose');
};
const handleSidebarClick = (item: string) => {
if (item === 'propose') setPreFillData(null);
setActiveItem(item);
};
useEffect(() => {
const handleNav = (e: any) => setActiveItem(e.detail);
window.addEventListener('navigate', handleNav);
return () => window.removeEventListener('navigate', handleNav);
}, []);
useEffect(() => {
if (isAuthenticated && activeItem === 'dashboard') {
fetch(API_BASE_URL + '/api/events')
.then(res => {
if (!res.ok) throw new Error(`HTTP error! status: ${res.status}`);
return res.json();
})
.then(data => {
if (Array.isArray(data)) {
let filtered = data;
if (user?.role === 'HOD') {
const userDepts = user?.department ? user.department.split(',').map(d => d.trim().toLowerCase()) : [];
filtered = data.filter((e: Event) => userDepts.includes(e.department?.trim().toLowerCase()));
} else if (user?.role === 'FACULTY') {
filtered = data.filter((e: Event) => e.proposer?.email === user?.email);
}
setUserEvents(filtered);
}
})
.catch(err => console.error("Failed to fetch dashboard events:", err));
}
}, [isAuthenticated, activeItem, user?.email, user?.role, user?.department]);
if (!isAuthenticated) {
return (
<AnimatePresence mode="wait">
<motion.div
key="login"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
transition={{ duration: 0.5 }}
>
<LoginPage />
</motion.div>
</AnimatePresence>
);
}
if (user?.role === 'STUDENT') {
return (
<AnimatePresence mode="wait">
<motion.div
key="student-dashboard"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
transition={{ duration: 0.5 }}
>
<StudentDashboard />
</motion.div>
</AnimatePresence>
);
}
const renderContent = () => {
const isDashboard = (
<Overview
userEvents={userEvents}
onNavigate={handleSidebarClick}
onIncompleteClick={handleIncompleteClick}
onCalendarPropose={handleCalendarPropose}
onClubEventClick={handleClubEventClick}
onEditEvent={handleEditEvent}
/>
);
switch (activeItem) {
case 'user-management':
return user?.role === 'ADMIN' ? <UserManagement /> : isDashboard;
case 'approvals':
return (user?.role === 'HOD' || user?.role === 'PRINCIPAL') ? <ApprovalsView /> : isDashboard;
case 'clubs':
return isClubAuthorized ? <ClubInstitutionalChecklist onEventClick={handleClubEventClick} /> : isDashboard;
case 'events':
return <AllEvents onEditEvent={handleEditEvent} />;
case 'propose':
return <EventProposalForm initialData={preFillData} />;
case 'checklist':
return <InstitutionalChecklist isGlobalView={true} onIncompleteClick={handleIncompleteClick} />;
case 'history':
return <EventHistory />;
case 'classes':
return user?.role === 'ADMIN' ? <ClassManagement /> : isDashboard;
case 'automation':
return (user?.role === 'ADMIN' || user?.role === 'PRINCIPAL' || user?.role === 'HOD') ? <AutomationView /> : isDashboard;
case 'import-excel':
return <ExcelImport />;
case 'student-registrations':
return (user?.role === 'FACULTY' || user?.role === 'HOD' || user?.role === 'ADMIN') ? <StudentRegistrationsView /> : isDashboard;
case 'manage-notices':
return user?.role === 'ADMIN' ? <ManageNoticesView /> : isDashboard;
case 'manage-students':
return user?.isClassIncharge ? <ManageStudentsView /> : isDashboard;
case 'dashboard':
return isDashboard;
default:
return isDashboard;
}
};
return (
<DashboardLayout
activeItem={activeItem}
onItemClick={handleSidebarClick}
>
<AnimatePresence mode="wait">
<motion.div
key={activeItem}
initial={{ opacity: 0, x: 20 }}
animate={{ opacity: 1, x: 0 }}
exit={{ opacity: 0, x: -20 }}
transition={{ duration: 0.3 }}
>
{renderContent()}
</motion.div>
</AnimatePresence>
</DashboardLayout>
);
};
function App() {
return (
<DialogProvider>
<AuthProvider>
<AppContent />
</AuthProvider>
</DialogProvider>
);
}
export default App;