import React, { useState } from 'react'; import { FileText, Edit2, X, ChevronLeft, ChevronRight, Calendar, Clock } from 'lucide-react'; function StudyPlanner() { const defaultClasses = [ { id: 1, name: "Digital Forensics in Cybersecurity – D431", credits: 3, priority: true, estimatedWeeks: 2, estimatedDays: 3, completed: false, startDate: "2024-01-15", notes: "", studyNotes: "", completionNotes: "" }, { id: 2, name: "Data Management - Foundations – D426", credits: 3, priority: false, estimatedWeeks: 3, estimatedDays: 0, completed: false, startDate: "2024-02-01", notes: "", studyNotes: "", completionNotes: "" }, { id: 3, name: "Data Management - Applications – D427", credits: 3, priority: false, estimatedWeeks: 0, estimatedDays: 0, completed: false, startDate: "", notes: "", studyNotes: "", completionNotes: "" }, { id: 4, name: "Information Systems Security – C845", credits: 4, priority: false, estimatedWeeks: 0, estimatedDays: 0, completed: false, startDate: "", notes: "", studyNotes: "", completionNotes: "" }, { id: 5, name: "Introduction to Cryptography – D334", credits: 3, priority: true, estimatedWeeks: 0, estimatedDays: 0, completed: false, startDate: "", notes: "", studyNotes: "", completionNotes: "" } ]; const [darkMode, setDarkMode] = useState(false); const [classes, setClasses] = useState(defaultClasses); const [editingClass, setEditingClass] = useState(null); const [editForm, setEditForm] = useState({ name: '', credits: 3, priority: false, startDate: '' }); const [showNotesModal, setShowNotesModal] = useState(false); const [notesModalClass, setNotesModalClass] = useState(null); const [showCompletionModal, setShowCompletionModal] = useState(false); const [completionModalClass, setCompletionModalClass] = useState(null); const [tempNotes, setTempNotes] = useState(""); const [currentCalendarDate, setCurrentCalendarDate] = useState(new Date()); const [globalStartDate, setGlobalStartDate] = useState(new Date().toISOString().split('T')[0]); const [autoSchedule, setAutoSchedule] = useState(true); const [showReflections, setShowReflections] = useState(false); const monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]; const getClassColor = (classId) => { const colors = ['bg-blue-500', 'bg-emerald-500', 'bg-purple-500', 'bg-rose-500', 'bg-amber-500']; return colors[classId % colors.length]; }; const calculateTimeline = () => { // If auto-schedule is enabled, calculate dates sequentially if (autoSchedule && globalStartDate) { // Parse date properly to avoid timezone issues let currentDate = new Date(globalStartDate + 'T00:00:00'); const scheduledClasses = []; // First, schedule priority classes const priorityClasses = classes.filter(cls => !cls.completed && cls.priority && (cls.estimatedWeeks > 0 || cls.estimatedDays > 0)); const regularClasses = classes.filter(cls => !cls.completed && !cls.priority && (cls.estimatedWeeks > 0 || cls.estimatedDays > 0)); const allToSchedule = [...priorityClasses, ...regularClasses]; allToSchedule.forEach(cls => { const startDate = new Date(currentDate); const totalDays = (cls.estimatedWeeks * 7) + cls.estimatedDays; const endDate = new Date(startDate); endDate.setDate(endDate.getDate() + totalDays - 1); // End date is inclusive scheduledClasses.push({ ...cls, startDate: startDate, endDate: endDate, totalDays, autoScheduled: true }); // Move to next start date (day after this course ends) currentDate = new Date(endDate); currentDate.setDate(currentDate.getDate() + 1); }); return scheduledClasses; } // Original timeline calculation for manual dates return classes .filter(cls => !cls.completed && cls.startDate && (cls.estimatedWeeks > 0 || cls.estimatedDays > 0)) .map(cls => { const start = new Date(cls.startDate + 'T00:00:00'); const totalDays = (cls.estimatedWeeks * 7) + cls.estimatedDays; const end = new Date(start); end.setDate(end.getDate() + totalDays - 1); // End date is inclusive return { ...cls, startDate: start, endDate: end, totalDays }; }) .sort((a, b) => a.startDate - b.startDate); }; const generateCalendar = () => { const timeline = calculateTimeline(); const year = currentCalendarDate.getFullYear(); const month = currentCalendarDate.getMonth(); const firstDay = new Date(year, month, 1); const lastDay = new Date(year, month + 1, 0); const daysInMonth = lastDay.getDate(); const startingDayOfWeek = firstDay.getDay(); const calendar = []; const today = new Date(); today.setHours(0, 0, 0, 0); for (let i = 0; i < startingDayOfWeek; i++) { calendar.push(null); } for (let day = 1; day <= daysInMonth; day++) { const currentDate = new Date(year, month, day); currentDate.setHours(0, 0, 0, 0); const isToday = currentDate.toDateString() === today.toDateString(); const activeClasses = timeline.filter(cls => { const start = new Date(cls.startDate); const end = new Date(cls.endDate); start.setHours(0, 0, 0, 0); end.setHours(0, 0, 0, 0); return currentDate >= start && currentDate <= end; }); calendar.push({ day, isToday, activeClasses }); } return calendar; }; const toggleCompleted = (id) => { const cls = classes.find(c => c.id === id); if (cls && !cls.completed) { setCompletionModalClass(cls); setTempNotes(""); setShowCompletionModal(true); } else { setClasses(prev => prev.map(c => c.id === id ? { ...c, completed: false } : c)); } }; const completeClass = () => { setClasses(prev => prev.map(c => c.id === completionModalClass.id ? { ...c, completed: true, completionNotes: tempNotes, completedDate: new Date().toISOString() } : c )); setShowCompletionModal(false); setTempNotes(""); }; const formatText = (tag) => { const textarea = document.getElementById('reflectionTextarea'); const start = textarea.selectionStart; const end = textarea.selectionEnd; const text = textarea.value; const selectedText = text.substring(start, end); let formattedText = ''; switch(tag) { case 'bold': formattedText = `**${selectedText}**`; break; case 'italic': formattedText = `*${selectedText}*`; break; case 'highlight': formattedText = `==${selectedText}==`; break; case 'underline': formattedText = `__${selectedText}__`; break; } const newText = text.substring(0, start) + formattedText + text.substring(end); setTempNotes(newText); }; const renderFormattedText = (text) => { if (!text) return null; // Simple markdown-like formatting let formatted = text .replace(/\*\*(.*?)\*\*/g, '$1') .replace(/\*(.*?)\*/g, '$1') .replace(/__(.*?)__/g, '$1') .replace(/==(.*?)==/g, '$1'); return
; }; const openNotes = (cls) => { setNotesModalClass(cls); setTempNotes(cls.studyNotes || ""); setShowNotesModal(true); }; const saveNotes = () => { setClasses(prev => prev.map(c => c.id === notesModalClass.id ? { ...c, studyNotes: tempNotes } : c )); setShowNotesModal(false); }; const startEdit = (cls) => { setEditingClass(cls.id); setEditForm({ name: cls.name, credits: cls.credits, priority: cls.priority, startDate: cls.startDate }); }; const saveEdit = () => { setClasses(prev => prev.map(c => c.id === editingClass ? { ...c, ...editForm, credits: parseInt(editForm.credits) } : c )); setEditingClass(null); }; const deleteClass = (id) => { setClasses(prev => prev.filter(c => c.id !== id)); }; const updateTime = (id, field, value) => { setClasses(prev => prev.map(c => c.id === id ? { ...c, [field]: parseInt(value) || 0 } : c )); }; const timeline = calculateTimeline(); const completedCount = classes.filter(c => c.completed).length; const totalCredits = classes.reduce((sum, c) => sum + c.credits, 0); const completedCredits = classes.filter(c => c.completed).reduce((sum, c) => sum + c.credits, 0); const calendarDays = generateCalendar(); return (Track courses and plan your schedule
No reflections yet. Complete a course to add your first reflection!
) : ( classes.filter(c => c.completed && c.completionNotes).map(cls => (Add dates and time estimates to see timeline
) : ({item.startDate.toLocaleDateString()} → {item.endDate.toLocaleDateString()}
Duration: {item.estimatedWeeks}w {item.estimatedDays}d
You've completed {completionModalClass?.name}