![]() Server : Apache/2 System : Linux server-15-235-50-60 5.15.0-164-generic #174-Ubuntu SMP Fri Nov 14 20:25:16 UTC 2025 x86_64 User : gositeme ( 1004) PHP Version : 8.2.29 Disable Function : exec,system,passthru,shell_exec,proc_close,proc_open,dl,popen,show_source,posix_kill,posix_mkfifo,posix_getpwuid,posix_setpgid,posix_setsid,posix_setuid,posix_setgid,posix_seteuid,posix_setegid,posix_uname Directory : /home/gositeme/backups/lavocat.quebec/backup-20250730-021618/src/pages/jurist/ |
import React, { useState, useEffect } from 'react';
import { useRouter } from 'next/router';
import { useSession } from 'next-auth/react';
import LayoutWithSidebar from '@/components/LayoutWithSidebar';
import {
BookOpen,
Plus,
Edit,
Trash2,
Eye,
Download,
Share2,
Bookmark,
Star,
Calendar,
Users,
TrendingUp,
CheckCircle,
Clock,
AlertCircle,
Filter,
Search,
ChevronDown,
ChevronUp,
ExternalLink,
Save,
Upload,
BarChart3,
Award,
Globe,
GraduationCap,
FileText,
Video,
Image,
Link,
MessageSquare,
ThumbsUp,
ThumbsDown
} from 'lucide-react';
interface Course {
id: string;
title: string;
code: string;
description: string;
semester: string;
year: string;
credits: number;
enrollment: number;
maxEnrollment: number;
status: 'active' | 'archived' | 'draft' | 'planned';
instructor: string;
teachingAssistants: string[];
syllabus: string;
materials: CourseMaterial[];
assignments: Assignment[];
schedule: ScheduleItem[];
evaluations: Evaluation[];
notes: string;
tags: string[];
}
interface CourseMaterial {
id: string;
title: string;
type: 'document' | 'video' | 'presentation' | 'link' | 'image' | 'audio';
url: string;
description: string;
uploadDate: string;
size?: string;
downloads: number;
isPublic: boolean;
tags: string[];
}
interface Assignment {
id: string;
title: string;
description: string;
dueDate: string;
weight: number;
type: 'essay' | 'exam' | 'presentation' | 'project' | 'participation';
submissions: number;
averageGrade?: number;
status: 'draft' | 'published' | 'grading' | 'completed';
}
interface ScheduleItem {
id: string;
title: string;
date: string;
time: string;
duration: number;
type: 'lecture' | 'discussion' | 'workshop' | 'exam' | 'office_hours';
location: string;
materials: string[];
notes: string;
}
interface Evaluation {
id: string;
studentName: string;
rating: number;
comment: string;
date: string;
helpful: boolean;
}
interface TeachingStats {
totalCourses: number;
activeCourses: number;
totalStudents: number;
totalMaterials: number;
averageRating: number;
totalDownloads: number;
thisSemesterCourses: number;
}
const JuristTeaching: React.FC = () => {
const { data: session, status } = useSession();
const router = useRouter();
const [isLoading, setIsLoading] = useState(true);
const [searchQuery, setSearchQuery] = useState('');
const [selectedStatus, setSelectedStatus] = useState<string>('all');
const [selectedSemester, setSelectedSemester] = useState<string>('all');
const [sortBy, setSortBy] = useState<string>('date');
const [showFilters, setShowFilters] = useState(false);
const [showNewCourseModal, setShowNewCourseModal] = useState(false);
const [selectedCourse, setSelectedCourse] = useState<Course | null>(null);
// Mock data - replace with actual API calls
const [courses] = useState<Course[]>([
{
id: '1',
title: 'Constitutional Law and Theory',
code: 'LAW-401',
description: 'Advanced study of constitutional law principles, interpretation methods, and theoretical frameworks.',
semester: 'Fall',
year: '2024',
credits: 3,
enrollment: 45,
maxEnrollment: 50,
status: 'active',
instructor: 'Dr. Marie Dubois',
teachingAssistants: ['Sarah Johnson', 'Michael Chen'],
syllabus: '/uploads/syllabi/constitutional-law-2024.pdf',
materials: [
{
id: '1',
title: 'Constitutional Interpretation Methods',
type: 'document',
url: '/uploads/materials/constitutional-interpretation.pdf',
description: 'Comprehensive guide to various methods of constitutional interpretation',
uploadDate: '2024-08-15',
size: '2.3 MB',
downloads: 156,
isPublic: true,
tags: ['Constitutional Law', 'Interpretation', 'Theory']
},
{
id: '2',
title: 'Supreme Court Cases Analysis',
type: 'video',
url: '/uploads/materials/supreme-court-analysis.mp4',
description: 'Video analysis of landmark Supreme Court decisions',
uploadDate: '2024-08-20',
size: '45.2 MB',
downloads: 89,
isPublic: false,
tags: ['Case Law', 'Supreme Court', 'Analysis']
}
],
assignments: [
{
id: '1',
title: 'Constitutional Analysis Essay',
description: 'Analyze a recent constitutional case using multiple interpretation methods',
dueDate: '2024-10-15',
weight: 30,
type: 'essay',
submissions: 42,
averageGrade: 85,
status: 'grading'
},
{
id: '2',
title: 'Midterm Examination',
description: 'Comprehensive examination covering constitutional theory and case law',
dueDate: '2024-11-01',
weight: 25,
type: 'exam',
submissions: 0,
status: 'published'
}
],
schedule: [
{
id: '1',
title: 'Introduction to Constitutional Theory',
date: '2024-09-03',
time: '14:00',
duration: 90,
type: 'lecture',
location: 'Room 301, Law Building',
materials: ['constitutional-interpretation.pdf'],
notes: 'First class - course overview and expectations'
},
{
id: '2',
title: 'Office Hours',
date: '2024-09-05',
time: '16:00',
duration: 60,
type: 'office_hours',
location: 'Office 205, Law Building',
materials: [],
notes: 'Drop-in office hours for questions and discussion'
}
],
evaluations: [
{
id: '1',
studentName: 'Anonymous',
rating: 5,
comment: 'Excellent course with engaging discussions and clear explanations.',
date: '2024-08-30',
helpful: true
}
],
notes: 'Strong student engagement. Consider adding more contemporary case studies.',
tags: ['Constitutional Law', 'Theory', 'Advanced', 'Graduate']
},
{
id: '2',
title: 'Legal Research and Writing',
code: 'LAW-201',
description: 'Fundamental skills in legal research, analysis, and academic writing.',
semester: 'Fall',
year: '2024',
credits: 2,
enrollment: 35,
maxEnrollment: 40,
status: 'active',
instructor: 'Dr. Marie Dubois',
teachingAssistants: ['Emily Rodriguez'],
syllabus: '/uploads/syllabi/legal-research-2024.pdf',
materials: [
{
id: '3',
title: 'Legal Research Guide',
type: 'document',
url: '/uploads/materials/legal-research-guide.pdf',
description: 'Step-by-step guide to legal research methods',
uploadDate: '2024-08-10',
size: '1.8 MB',
downloads: 234,
isPublic: true,
tags: ['Research', 'Writing', 'Methods']
}
],
assignments: [
{
id: '3',
title: 'Research Memorandum',
description: 'Write a legal memorandum on a given topic using proper research methods',
dueDate: '2024-09-30',
weight: 40,
type: 'essay',
submissions: 0,
status: 'published'
}
],
schedule: [],
evaluations: [],
notes: 'Focus on practical research skills and writing clarity.',
tags: ['Research', 'Writing', 'Fundamental', 'Undergraduate']
},
{
id: '3',
title: 'Comparative Legal Systems',
code: 'LAW-501',
description: 'Comparative analysis of legal systems across different jurisdictions and cultures.',
semester: 'Spring',
year: '2025',
credits: 3,
enrollment: 0,
maxEnrollment: 30,
status: 'planned',
instructor: 'Dr. Marie Dubois',
teachingAssistants: [],
syllabus: '',
materials: [],
assignments: [],
schedule: [],
evaluations: [],
notes: 'Course in planning phase. Need to develop comparative case studies.',
tags: ['Comparative Law', 'International', 'Advanced', 'Graduate']
}
]);
const [stats] = useState<TeachingStats>({
totalCourses: 6,
activeCourses: 2,
totalStudents: 80,
totalMaterials: 15,
averageRating: 4.3,
totalDownloads: 1247,
thisSemesterCourses: 2
});
useEffect(() => {
if (status === 'loading') return;
if (!session) {
router.push('/auth/login');
return;
}
if (session.user?.role !== 'JURIST') {
router.push('/unauthorized');
return;
}
setIsLoading(false);
}, [session, status, router]);
const getStatusColor = (status: string) => {
switch (status) {
case 'active': return 'bg-green-100 text-green-800';
case 'archived': return 'bg-gray-100 text-gray-800';
case 'draft': return 'bg-yellow-100 text-yellow-800';
case 'planned': return 'bg-blue-100 text-blue-800';
default: return 'bg-gray-100 text-gray-800';
}
};
const getMaterialTypeIcon = (type: string) => {
switch (type) {
case 'document': return <FileText className="w-4 h-4" />;
case 'video': return <Video className="w-4 h-4" />;
case 'presentation': return <BarChart3 className="w-4 h-4" />;
case 'link': return <Link className="w-4 h-4" />;
case 'image': return <Image className="w-4 h-4" />;
case 'audio': return <Globe className="w-4 h-4" />;
default: return <FileText className="w-4 h-4" />;
}
};
if (isLoading) {
return (
<LayoutWithSidebar>
<div className="min-h-screen bg-gray-50 flex items-center justify-center">
<div className="text-center">
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-600 mx-auto"></div>
<p className="mt-4 text-gray-600">Loading teaching resources...</p>
</div>
</div>
</LayoutWithSidebar>
);
}
return (
<LayoutWithSidebar>
<div className="min-h-screen bg-gray-50">
{/* Header */}
<div className="bg-white shadow-sm border-b">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex justify-between items-center py-6">
<div>
<h1 className="text-3xl font-bold text-gray-900">Teaching Resources</h1>
<p className="mt-1 text-sm text-gray-500">
Manage course materials, syllabi, and educational content
</p>
</div>
<div className="flex items-center space-x-4">
<button
onClick={() => setShowNewCourseModal(true)}
className="bg-blue-600 text-white px-4 py-2 rounded-lg hover:bg-blue-700 transition-colors flex items-center"
>
<Plus className="w-4 h-4 mr-2" />
New Course
</button>
</div>
</div>
</div>
</div>
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
{/* Stats Grid */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
<div className="bg-white rounded-lg shadow p-6">
<div className="flex items-center">
<div className="p-2 bg-blue-100 rounded-lg">
<BookOpen className="w-6 h-6 text-blue-600" />
</div>
<div className="ml-4">
<p className="text-sm font-medium text-gray-600">Total Courses</p>
<p className="text-2xl font-bold text-gray-900">{stats.totalCourses}</p>
</div>
</div>
</div>
<div className="bg-white rounded-lg shadow p-6">
<div className="flex items-center">
<div className="p-2 bg-green-100 rounded-lg">
<CheckCircle className="w-6 h-6 text-green-600" />
</div>
<div className="ml-4">
<p className="text-sm font-medium text-gray-600">Active Courses</p>
<p className="text-2xl font-bold text-gray-900">{stats.activeCourses}</p>
</div>
</div>
</div>
<div className="bg-white rounded-lg shadow p-6">
<div className="flex items-center">
<div className="p-2 bg-purple-100 rounded-lg">
<Users className="w-6 h-6 text-purple-600" />
</div>
<div className="ml-4">
<p className="text-sm font-medium text-gray-600">Total Students</p>
<p className="text-2xl font-bold text-gray-900">{stats.totalStudents}</p>
</div>
</div>
</div>
<div className="bg-white rounded-lg shadow p-6">
<div className="flex items-center">
<div className="p-2 bg-orange-100 rounded-lg">
<Download className="w-6 h-6 text-orange-600" />
</div>
<div className="ml-4">
<p className="text-sm font-medium text-gray-600">Total Downloads</p>
<p className="text-2xl font-bold text-gray-900">{stats.totalDownloads}</p>
</div>
</div>
</div>
</div>
{/* Quick Actions */}
<div className="bg-white rounded-lg shadow p-6 mb-8">
<h2 className="text-lg font-semibold text-gray-900 mb-4">Quick Actions</h2>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
<button className="flex items-center p-4 border border-gray-200 rounded-lg hover:bg-gray-50 transition-colors">
<GraduationCap className="w-5 h-5 text-blue-600 mr-3" />
<span className="text-sm font-medium">Create Course</span>
</button>
<button className="flex items-center p-4 border border-gray-200 rounded-lg hover:bg-gray-50 transition-colors">
<Upload className="w-5 h-5 text-green-600 mr-3" />
<span className="text-sm font-medium">Upload Materials</span>
</button>
<button className="flex items-center p-4 border border-gray-200 rounded-lg hover:bg-gray-50 transition-colors">
<Calendar className="w-5 h-5 text-yellow-600 mr-3" />
<span className="text-sm font-medium">Schedule Class</span>
</button>
<button className="flex items-center p-4 border border-gray-200 rounded-lg hover:bg-gray-50 transition-colors">
<Star className="w-5 h-5 text-purple-600 mr-3" />
<span className="text-sm font-medium">Student Feedback</span>
</button>
</div>
</div>
{/* Search and Filters */}
<div className="bg-white rounded-lg shadow p-6 mb-8">
<div className="flex items-center space-x-4">
<div className="flex-1">
<div className="relative">
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 text-gray-400 w-5 h-5" />
<input
type="text"
placeholder="Search courses..."
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
className="w-full pl-10 pr-4 py-3 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent"
/>
</div>
</div>
<button
onClick={() => setShowFilters(!showFilters)}
className="flex items-center space-x-2 px-4 py-3 border border-gray-300 rounded-lg hover:bg-gray-50 transition-colors"
>
<Filter className="w-4 h-4" />
<span>Filters</span>
{showFilters ? <ChevronUp className="w-4 h-4" /> : <ChevronDown className="w-4 h-4" />}
</button>
</div>
{/* Filters */}
{showFilters && (
<div className="mt-6 grid grid-cols-1 md:grid-cols-3 gap-4">
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">Status</label>
<select
value={selectedStatus}
onChange={(e) => setSelectedStatus(e.target.value)}
className="w-full border border-gray-300 rounded-lg px-3 py-2 focus:ring-2 focus:ring-blue-500 focus:border-transparent"
>
<option value="all">All Status</option>
<option value="active">Active</option>
<option value="archived">Archived</option>
<option value="draft">Draft</option>
<option value="planned">Planned</option>
</select>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">Semester</label>
<select
value={selectedSemester}
onChange={(e) => setSelectedSemester(e.target.value)}
className="w-full border border-gray-300 rounded-lg px-3 py-2 focus:ring-2 focus:ring-blue-500 focus:border-transparent"
>
<option value="all">All Semesters</option>
<option value="Fall">Fall</option>
<option value="Spring">Spring</option>
<option value="Summer">Summer</option>
<option value="Winter">Winter</option>
</select>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-2">Sort By</label>
<select
value={sortBy}
onChange={(e) => setSortBy(e.target.value)}
className="w-full border border-gray-300 rounded-lg px-3 py-2 focus:ring-2 focus:ring-blue-500 focus:border-transparent"
>
<option value="date">Date</option>
<option value="title">Title</option>
<option value="enrollment">Enrollment</option>
<option value="status">Status</option>
</select>
</div>
</div>
)}
</div>
{/* Courses List */}
<div className="bg-white rounded-lg shadow">
<div className="p-6 border-b border-gray-200">
<div className="flex items-center justify-between">
<h2 className="text-lg font-semibold text-gray-900">Your Courses</h2>
<span className="text-sm text-gray-500">{courses.length} courses</span>
</div>
</div>
<div className="p-6">
<div className="space-y-6">
{courses.map((course) => (
<div key={course.id} className="border border-gray-200 rounded-lg p-6 hover:shadow-md transition-shadow">
<div className="flex items-start justify-between">
<div className="flex-1">
<div className="flex items-center space-x-3 mb-2">
<span className={`px-2 py-1 text-xs font-medium rounded-full ${getStatusColor(course.status)}`}>
{course.status.toUpperCase()}
</span>
<span className="px-2 py-1 text-xs font-medium rounded-full bg-blue-100 text-blue-800">
{course.code}
</span>
<span className="px-2 py-1 text-xs font-medium rounded-full bg-gray-100 text-gray-800">
{course.credits} Credits
</span>
</div>
<h3 className="text-lg font-semibold text-gray-900 mb-2">{course.title}</h3>
<p className="text-gray-700 mb-3">{course.description}</p>
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4">
<div>
<p className="text-sm text-gray-600">
<strong>Instructor:</strong> {course.instructor}
</p>
<p className="text-sm text-gray-600">
<strong>Semester:</strong> {course.semester} {course.year}
</p>
<p className="text-sm text-gray-600">
<strong>Enrollment:</strong> {course.enrollment}/{course.maxEnrollment}
</p>
{course.teachingAssistants.length > 0 && (
<p className="text-sm text-gray-600">
<strong>TAs:</strong> {course.teachingAssistants.join(', ')}
</p>
)}
</div>
<div>
<p className="text-sm text-gray-600">
<strong>Materials:</strong> {course.materials.length}
</p>
<p className="text-sm text-gray-600">
<strong>Assignments:</strong> {course.assignments.length}
</p>
<p className="text-sm text-gray-600">
<strong>Schedule Items:</strong> {course.schedule.length}
</p>
<p className="text-sm text-gray-600">
<strong>Evaluations:</strong> {course.evaluations.length}
</p>
</div>
</div>
{/* Materials Preview */}
{course.materials.length > 0 && (
<div className="mb-4">
<h4 className="text-sm font-medium text-gray-900 mb-2">Recent Materials</h4>
<div className="space-y-2">
{course.materials.slice(0, 3).map((material) => (
<div key={material.id} className="flex items-center space-x-2 p-2 bg-gray-50 rounded">
{getMaterialTypeIcon(material.type)}
<span className="text-sm text-gray-700">{material.title}</span>
<span className="text-xs text-gray-500">({material.downloads} downloads)</span>
</div>
))}
</div>
</div>
)}
<div className="flex items-center space-x-2 mb-4">
{course.tags.map((tag) => (
<span key={tag} className="px-2 py-1 bg-gray-100 text-gray-700 text-xs rounded">
{tag}
</span>
))}
</div>
<div className="flex items-center justify-between">
<div className="flex items-center space-x-2">
<button className="p-2 text-gray-400 hover:text-gray-600">
<MessageSquare className="w-4 h-4" />
<span className="text-xs ml-1">{course.evaluations.length}</span>
</button>
<button className="p-2 text-gray-400 hover:text-gray-600">
<Download className="w-4 h-4" />
<span className="text-xs ml-1">{course.materials.reduce((sum, m) => sum + m.downloads, 0)}</span>
</button>
<button className="p-2 text-gray-400 hover:text-gray-600">
<Calendar className="w-4 h-4" />
<span className="text-xs ml-1">{course.schedule.length}</span>
</button>
</div>
<div className="flex items-center space-x-2">
<button className="p-2 text-gray-400 hover:text-gray-600">
<Eye className="w-4 h-4" />
</button>
<button className="p-2 text-gray-400 hover:text-gray-600">
<Edit className="w-4 h-4" />
</button>
<button className="p-2 text-gray-400 hover:text-gray-600">
<Share2 className="w-4 h-4" />
</button>
<button className="p-2 text-gray-400 hover:text-red-600">
<Trash2 className="w-4 h-4" />
</button>
</div>
</div>
</div>
</div>
</div>
))}
</div>
</div>
</div>
</div>
</div>
</LayoutWithSidebar>
);
};
export default JuristTeaching;