import React, { useEffect, useState } from 'react'; import { StorageService } from '../services/storageService'; import { Task, TaskStatus, Priority, Subtask, UserProfile, StudyNote } from '../types'; import { Button } from '../components/ui/Button'; import { Plus, Trash2, Calendar, Tag, CheckCircle, Circle, CheckSquare, Loader2, ChevronDown, ChevronRight, X, Clock, StickyNote, PenTool, Layout as LayoutIcon, GraduationCap, Users } from 'lucide-react'; import confetti from 'canvas-confetti'; import { useLanguage } from '../contexts/LanguageContext'; const CLASSES = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', 'General']; const Planner: React.FC = () => { const { t } = useLanguage(); const [activeTab, setActiveTab] = useState<'assignments' | 'vault'>('assignments'); const [tasks, setTasks] = useState([]); const [notes, setNotes] = useState([]); const [profile, setProfile] = useState(null); const [loading, setLoading] = useState(true); const [isTaskModalOpen, setIsTaskModalOpen] = useState(false); const [isNoteModalOpen, setIsNoteModalOpen] = useState(false); const [expandedTaskId, setExpandedTaskId] = useState(null); const [newSubtaskInput, setNewSubtaskInput] = useState(''); // Assignment State const [newTask, setNewTask] = useState>({ title: '', subject: 'General', priority: Priority.MEDIUM, dueDate: new Date().toISOString().split('T')[0], description: '', subtasks: [], estimatedMinutes: 45, targetClass: '10' }); const [newNote, setNewNote] = useState>({ title: '', content: '', color: 'bg-yellow-100', textColor: 'text-gray-900', fontFamily: 'sans' }); const loadData = async () => { setLoading(true); const [t_list, p, n] = await Promise.all([ StorageService.getTasks(), StorageService.getProfile(), StorageService.getNotes() ]); setTasks(t_list); setProfile(p); setNotes(n); setLoading(false); }; useEffect(() => { loadData(); }, []); const handleSaveTask = async (e: React.FormEvent) => { e.preventDefault(); if (!newTask.title) return; const isTeacher = profile?.role === 'teacher'; const taskToSave: Task = { id: Date.now().toString(), userId: profile?.id || 'anon', title: newTask.title, subject: newTask.subject || 'General', priority: newTask.priority || Priority.MEDIUM, status: TaskStatus.TODO, dueDate: newTask.dueDate || new Date().toISOString(), description: newTask.description, subtasks: newTask.subtasks || [], estimatedMinutes: newTask.estimatedMinutes || 45, isAssignment: isTeacher, targetClass: isTeacher ? newTask.targetClass : profile?.grade }; await StorageService.saveTask(taskToSave); await loadData(); setIsTaskModalOpen(false); setNewTask({ title: '', subject: 'General', priority: Priority.MEDIUM, dueDate: new Date().toISOString().split('T')[0], description: '', subtasks: [], estimatedMinutes: 45, targetClass: '10' }); if (isTeacher) confetti({ particleCount: 40, spread: 60 }); }; const handleSaveNote = async (e: React.FormEvent) => { e.preventDefault(); if (!newNote.title || !newNote.content) return; await StorageService.saveNote(newNote); await loadData(); setIsNoteModalOpen(false); setNewNote({ title: '', content: '', color: 'bg-yellow-100', textColor: 'text-gray-900', fontFamily: 'sans' }); }; const deleteNote = async (id: string) => { if (confirm('Delete this note?')) { await StorageService.deleteNote(id); await loadData(); } }; const toggleStatus = async (task: Task) => { let updatedStatus: TaskStatus; if (task.status === TaskStatus.COMPLETED) { updatedStatus = TaskStatus.TODO; } else if (task.status === TaskStatus.SUBMITTED) { updatedStatus = TaskStatus.TODO; } else { if (profile?.role === 'teacher') { updatedStatus = TaskStatus.COMPLETED; confetti({ particleCount: 100, spread: 70, origin: { y: 0.6 } }); StorageService.addPoints(10, 50); } else { updatedStatus = TaskStatus.SUBMITTED; } } const updatedTasks = tasks.map(t => t.id === task.id ? { ...t, status: updatedStatus } : t); setTasks(updatedTasks); await StorageService.saveTask({ ...task, status: updatedStatus }); }; const deleteTask = async (id: string) => { if (confirm('Permanently remove this task?')) { setTasks(prev => prev.filter(t => t.id !== id)); await StorageService.deleteTask(id); } }; const handleToggleExpand = (taskId: string) => { setExpandedTaskId(expandedTaskId === taskId ? null : taskId); setNewSubtaskInput(''); }; const addSubtask = async (taskId: string) => { if (!newSubtaskInput.trim()) return; const task = tasks.find(t => t.id === taskId); if (!task) return; const newS: Subtask = { id: Date.now().toString(), title: newSubtaskInput, completed: false }; const updatedTask = { ...task, subtasks: [...(task.subtasks || []), newS] }; setTasks(prev => prev.map(t => t.id === taskId ? updatedTask : t)); setNewSubtaskInput(''); await StorageService.saveTask(updatedTask); }; const toggleSubtask = async (taskId: string, subtaskId: string) => { const task = tasks.find(t => t.id === taskId); if (!task) return; const updatedS = (task.subtasks || []).map(s => s.id === subtaskId ? { ...s, completed: !s.completed } : s); const updatedTask = { ...task, subtasks: updatedS }; setTasks(prev => prev.map(t => t.id === taskId ? updatedTask : t)); await StorageService.saveTask(updatedTask); }; const getGroupedTasks = () => { const today = new Date().toISOString().split('T')[0]; const overdue: Task[] = []; const dueToday: Task[] = []; const upcoming: Task[] = []; const completed: Task[] = []; const submitted: Task[] = []; tasks.forEach(t => { if (t.status === TaskStatus.COMPLETED) completed.push(t); else if (t.status === TaskStatus.SUBMITTED) submitted.push(t); else { const tDate = t.dueDate.split('T')[0]; if (tDate < today) overdue.push(t); else if (tDate === today) dueToday.push(t); else upcoming.push(t); } }); return { overdue, dueToday, upcoming, completed, submitted }; }; const { overdue, dueToday, upcoming, completed, submitted } = getGroupedTasks(); const isTeacher = profile?.role === 'teacher'; return (

{activeTab === 'assignments' ? t("Assignments", "Assignments") : t("Personal Notes", "Personal Notes")}

{activeTab === 'assignments' ? t("Distribute academic tasks and track progress.", "Distribute academic tasks and track progress.") : t("Archive intellectual sparks with custom aesthetics.", "Archive intellectual sparks with custom aesthetics.")}

{activeTab === 'assignments' && isTeacher && ( )} {activeTab === 'vault' && ( )}
{loading ? (
) : activeTab === 'assignments' ? ( tasks.length === 0 ? (

{t("Zero Pending", "Zero Pending")}

{t("No homework assigned or goals set. Enjoy your leisure or set a new milestone.", "No homework assigned or goals set. Enjoy your leisure or set a new milestone.")}

) : (
{overdue.length > 0 && Math.round(((p.subtasks?.filter(s => s.completed).length || 0) / (p.subtasks?.length || 1)) * 100)} expandedTaskId={expandedTaskId} onToggleExpand={handleToggleExpand} addSubtask={addSubtask} toggleSubtask={toggleSubtask} newSubtaskInput={newSubtaskInput} setNewSubtaskInput={setNewSubtaskInput} isTeacher={isTeacher}/>} {dueToday.length > 0 && Math.round(((p.subtasks?.filter(s => s.completed).length || 0) / (p.subtasks?.length || 1)) * 100)} expandedTaskId={expandedTaskId} onToggleExpand={handleToggleExpand} addSubtask={addSubtask} toggleSubtask={toggleSubtask} newSubtaskInput={newSubtaskInput} setNewSubtaskInput={setNewSubtaskInput} isTeacher={isTeacher}/>} {upcoming.length > 0 && Math.round(((p.subtasks?.filter(s => s.completed).length || 0) / (p.subtasks?.length || 1)) * 100)} expandedTaskId={expandedTaskId} onToggleExpand={handleToggleExpand} addSubtask={addSubtask} toggleSubtask={toggleSubtask} newSubtaskInput={newSubtaskInput} setNewSubtaskInput={setNewSubtaskInput} isTeacher={isTeacher}/>} {submitted.length > 0 && 100} expandedTaskId={expandedTaskId} onToggleExpand={handleToggleExpand} addSubtask={addSubtask} toggleSubtask={toggleSubtask} newSubtaskInput={newSubtaskInput} setNewSubtaskInput={setNewSubtaskInput} isTeacher={isTeacher}/>} {completed.length > 0 && 100} expandedTaskId={expandedTaskId} onToggleExpand={handleToggleExpand} addSubtask={addSubtask} toggleSubtask={toggleSubtask} newSubtaskInput={newSubtaskInput} setNewSubtaskInput={setNewSubtaskInput} isTeacher={isTeacher}/>}
) ) : (
{notes.length === 0 ? (

No notes in the vault

) : ( notes.map((note) => (

{note.title}

"{note.content}"

{new Date(note.timestamp).toLocaleDateString()}
)) )}
)} {/* Task Modal */} {isTaskModalOpen && (
setIsTaskModalOpen(false)}>

{t("Assign Homework", "Assign Homework")}

Class distribution Portal

setNewTask({...newTask, title: e.target.value})} />
setNewTask({...newTask, dueDate: e.target.value})} />
setNewTask({...newTask, estimatedMinutes: parseInt(e.target.value)})} />
)} {isNoteModalOpen && (
setIsNoteModalOpen(false)}>

Vault Entry

{['bg-yellow-100', 'bg-blue-100', 'bg-green-100', 'bg-purple-100', 'bg-red-100'].map(c => ( ))}
{(['sans', 'serif', 'mono'] as const).map(f => ( ))}
setNewNote({...newNote, title: e.target.value})} placeholder="Title" />
)}
); }; const TaskGroup = ({ title, tasks, color, toggleStatus, deleteTask, calculateProgress, expandedTaskId, onToggleExpand, addSubtask, toggleSubtask, newSubtaskInput, setNewSubtaskInput, isTeacher }: any) => { const colorClasses: Record = { red: "bg-red-50 dark:bg-red-900/20 text-red-700 dark:text-red-400 border-red-200 dark:border-red-800", blue: "bg-blue-50 dark:bg-blue-900/20 text-blue-700 dark:text-blue-400 border-blue-200 dark:border-blue-800", green: "bg-green-50 dark:bg-green-900/20 text-green-700 dark:text-green-400 border-green-200 dark:border-green-800", gray: "bg-gray-50 dark:bg-gray-800 text-gray-700 dark:text-gray-400 border-gray-200 dark:border-gray-700", yellow: "bg-yellow-50 dark:bg-yellow-900/20 text-yellow-700 dark:text-yellow-400 border-yellow-200 dark:border-yellow-800" }; return (
{title} {tasks.length}
{tasks.map((task: Task, idx: number) => { const prog = calculateProgress(task); return (
{task.targetClass && Class: {task.targetClass}} {task.subject}

{task.title}

{prog}% COMPLETE
Due: {new Date(task.dueDate).toLocaleDateString()}
{task.estimatedMinutes} MIN
{expandedTaskId === task.id && (
{task.subtasks?.length === 0 &&

No subtasks defined yet.

} {task.subtasks?.map((sub: Subtask) => (
{sub.title}
))}
{!isTeacher && (
setNewSubtaskInput(e.target.value)} onKeyDown={(e: any) => e.key === 'Enter' && addSubtask(task.id)} />
)}
)}
); })}
); }; export default Planner;