HelloWorld97/layeredlearner-assignment-mastermind
0
1// Main application script for LayeredLearner2 3// Storage key4const STORAGE_KEY = 'LayeredAssignmentTracker_v1';5 6// Initial sample data7const sampleData = {8 courses: [9 {10 id: 'course_1',11 name: 'Biology 11',12 units: ['unit_1', 'unit_2'],13 createdAt: Date.now() - 30 * 24 * 60 * 60 * 100014 },15 {16 id: 'course_2',17 name: 'Calculus 12',18 units: ['unit_3'],19 createdAt: Date.now() - 15 * 24 * 60 * 60 * 100020 }21 ],22 units: [23 {24 id: 'unit_1',25 courseId: 'course_1',26 name: 'Cell Biology',27 material: 'Cells are the basic unit of life. Topics include cell structure, organelles, membrane transport, and cellular processes like photosynthesis and respiration.',28 createdAt: Date.now() - 28 * 24 * 60 * 60 * 100029 },30 {31 id: 'unit_2',32 courseId: 'course_1',33 name: 'Genetics',34 material: 'Study of genes, heredity, and variation in living organisms. Covers DNA structure, replication, transcription, translation, and genetic disorders.',35 createdAt: Date.now() - 14 * 24 * 60 * 60 * 100036 },37 {38 id: 'unit_3',39 courseId: 'course_2',40 name: 'Differential Calculus',41 material: 'Introduction to derivatives, limits, and their applications. Topics include power rule, chain rule, product rule, and optimization problems.',42 createdAt: Date.now() - 10 * 24 * 60 * 60 * 100043 }44 ],45 assignments: [46 {47 id: 'assign_1',48 courseId: 'course_1',49 unitId: 'unit_1',50 name: 'Mitochondria Essay',51 type: 'written',52 status: 'in progress',53 link: '',54 ai: {55 assignmentStructure: null,56 draftRank: null,57 draftFeedback: null,58 practiceTest: null,59 summary: null,60 answerKey: null61 },62 draft: 'Mitochondria are often called the powerhouses of the cell...',63 final: '',64 grade: null,65 gradeFeedback: [],66 createdAt: Date.now() - 7 * 24 * 60 * 60 * 1000,67 updatedAt: Date.now() - 2 * 24 * 60 * 60 * 100068 },69 {70 id: 'assign_2',71 courseId: 'course_2',72 unitId: 'unit_3',73 name: 'Derivatives Quiz',74 type: 'quiz',75 status: 'not started',76 link: '',77 ai: {78 assignmentStructure: null,79 draftRank: null,80 draftFeedback: null,81 practiceTest: null,82 summary: null,83 answerKey: null84 },85 draft: '',86 final: '',87 grade: null,88 gradeFeedback: [],89 createdAt: Date.now() - 3 * 24 * 60 * 60 * 1000,90 updatedAt: Date.now() - 3 * 24 * 60 * 60 * 100091 }92 ],93 lastSavedAt: Date.now()94};95 96// Application state97let appState = {98 courses: [],99 units: [],100 assignments: [],101 filters: {102 course: null,103 unit: null,104 type: [],105 status: [],106 search: ''107 },108 sort: {109 field: 'updatedAt',110 direction: 'desc'111 }112};113 114// Initialize application115function initApp() {116 loadState();117 renderCourses();118 renderAssignments();119 updateStats();120 setupEventListeners();121 feather.replace();122}123 124// Storage functions125function loadState() {126 try {127 const saved = localStorage.getItem(STORAGE_KEY);128 if (saved) {129 const parsed = JSON.parse(saved);130 appState.courses = parsed.courses || [];131 appState.units = parsed.units || [];132 appState.assignments = parsed.assignments || [];133 } else {134 // Load sample data135 appState = { ...sampleData, filters: appState.filters, sort: appState.sort };136 saveState();137 }138 } catch (error) {139 console.error('Failed to load state:', error);140 showToast('Error loading data. Loading sample data.', 'error');141 appState = { ...sampleData, filters: appState.filters, sort: appState.sort };142 }143}144 145function saveState() {146 try {147 const stateToSave = {148 courses: appState.courses,149 units: appState.units,150 assignments: appState.assignments,151 lastSavedAt: Date.now()152 };153 localStorage.setItem(STORAGE_KEY, JSON.stringify(stateToSave));154 } catch (error) {155 console.error('Failed to save state:', error);156 showToast('Error saving data.', 'error');157 }158}159 160// Render functions161function renderCourses() {162 const container = document.getElementById('courses-list');163 if (!container) return;164 165 if (appState.courses.length === 0) {166 container.innerHTML = `167 <div class="text-center py-8 text-gray-500">168 <i data-feather="book" class="w-12 h-12 mx-auto mb-3 text-gray-300"></i>169 <p>No courses yet. Add your first course!</p>170 </div>171 `;172 return;173 }174 175 container.innerHTML = appState.courses.map(course => {176 const courseUnits = appState.units.filter(u => u.courseId === course.id);177 const courseAssignments = appState.assignments.filter(a => a.courseId === course.id);178 179 return `180 <div class="course-card p-4 rounded-lg border border-gray-200 hover:border-primary/50 transition-all-200 hover-card">181 <div class="flex justify-between items-start mb-2">182 <h3 class="font-bold text-gray-800">${course.name}</h3>183 <div class="flex gap-1">184 <button class="edit-course-btn p-1 text-gray-400 hover:text-primary" data-id="${course.id}">185 <i data-feather="edit-2" class="w-4 h-4"></i>186 </button>187 <button class="delete-course-btn p-1 text-gray-400 hover:text-red-500" data-id="${course.id}">188 <i data-feather="trash-2" class="w-4 h-4"></i>189 </button>190 </div>191 </div>192 <div class="flex items-center gap-4 text-sm text-gray-600 mb-3">193 <span class="flex items-center gap-1">194 <i data-feather="layers" class="w-3 h-3"></i>195 ${courseUnits.length} units196 </span>197 <span class="flex items-center gap-1">198 <i data-feather="file-text" class="w-3 h-3"></i>199 ${courseAssignments.length} assignments200 </span>201 </div>202 <div class="space-y-1">203 ${courseUnits.slice(0, 3).map(unit => `204 <div class="text-sm text-gray-600 flex items-center gap-2">205 <i data-feather="folder" class="w-3 h-3 text-gray-400"></i>206 ${unit.name}207 </div>208 `).join('')}209 ${courseUnits.length > 3 ? `210 <div class="text-sm text-gray-500">211 +${courseUnits.length - 3} more units212 </div>213 ` : ''}214 </div>215 </div>216 `;217 }).join('');218 219 feather.replace();220}221 222function renderAssignments() {223 const container = document.getElementById('assignments-table-body');224 const emptyState = document.getElementById('empty-state');225 226 if (!container) return;227 228 // Apply filters and sorting229 let filteredAssignments = [...appState.assignments];230 231 // Apply course filter232 if (appState.filters.course) {233 filteredAssignments = filteredAssignments.filter(a => a.courseId === appState.filters.course);234 }235 236 // Apply unit filter237 if (appState.filters.unit) {238 filteredAssignments = filteredAssignments.filter(a => a.unitId === appState.filters.unit);239 }240 241 // Apply type filter242 if (appState.filters.type.length > 0) {243 filteredAssignments = filteredAssignments.filter(a => appState.filters.type.includes(a.type));244 }245 246 // Apply status filter247 if (appState.filters.status.length > 0) {248 filteredAssignments = filteredAssignments.filter(a => appState.filters.status.includes(a.status));249 }250 251 // Apply search252 if (appState.filters.search) {253 const searchLower = appState.filters.search.toLowerCase();254 filteredAssignments = filteredAssignments.filter(a => {255 const course = appState.courses.find(c => c.id === a.courseId);256 const unit = appState.units.find(u => u.id === a.unitId);257 return (258 a.name.toLowerCase().includes(searchLower) ||259 (course && course.name.toLowerCase().includes(searchLower)) ||260 (unit && unit.name.toLowerCase().includes(searchLower))261 );262 });263 }264 265 // Apply sorting266 filteredAssignments.sort((a, b) => {267 let aVal, bVal;268 269 switch (appState.sort.field) {270 case 'course':271 aVal = appState.courses.find(c => c.id === a.courseId)?.name || '';272 bVal = appState.courses.find(c => c.id === b.courseId)?.name || '';273 break;274 case 'unit':275 aVal = appState.units.find(u => u.id === a.unitId)?.name || '';276 bVal = appState.units.find(u => u.id === b.unitId)?.name || '';277 break;278 default:279 aVal = a[appState.sort.field];280 bVal = b[appState.sort.field];281 }282 283 if (appState.sort.direction === 'asc') {284 return aVal > bVal ? 1 : -1;285 } else {286 return aVal < bVal ? 1 : -1;287 }288 });289 290 // Show/hide empty state291 if (filteredAssignments.length === 0) {292 container.innerHTML = '';293 if (emptyState) emptyState.classList.remove('hidden');294 return;295 }296 297 if (emptyState) emptyState.classList.add('hidden');298 299 // Render assignments300 container.innerHTML = filteredAssignments.map(assignment => {301 const course = appState.courses.find(c => c.id === assignment.courseId);302 const unit = appState.units.find(u => u.id === assignment.unitId);303 304 const statusClass = `status-${assignment.status.replace(/\s+/g, '-')}`;305 const typeClass = `type-${assignment.type}`;306 307 const statusText = assignment.status.split('_').map(word => 308 word.charAt(0).toUpperCase() + word.slice(1)309 ).join(' ');310 311 const typeText = assignment.type.split('_').map(word => 312 word.charAt(0).toUpperCase() + word.slice(1)313 ).join(' ');314 315 return `316 <tr class="border-b border-gray-100 table-row-hover" data-id="${assignment.id}">317 <td class="py-4 px-4">318 <div class="font-medium text-gray-800">${course?.name || 'Unknown'}</div>319 </td>320 <td class="py-4 px-4">321 <div class="text-gray-600">${unit?.name || 'No Unit'}</div>322 </td>323 <td class="py-4 px-4">324 <div class="font-medium text-gray-800">${assignment.name}</div>325 ${assignment.link ? `326 <a href="${assignment.link}" target="_blank" class="text-xs text-primary hover:underline flex items-center gap-1">327 <i data-feather="external-link" class="w-3 h-3"></i>328 Open link329 </a>330 ` : ''}331 </td>332 <td class="py-4 px-4">333 <span class="${typeClass} type-indicator">${typeText}</span>334 </td>335 <td class="py-4 px-4">336 <span class="${statusClass} status-badge">${statusText}</span>337 </td>338 <td class="py-4 px-4">339 <div class="flex gap-2">340 <a href="assignment.html?id=${assignment.id}" class="p-2 text-gray-400 hover:text-primary rounded hover:bg-gray-100">341 <i data-feather="eye" class="w-4 h-4"></i>342 </a>343 <button class="edit-assignment-btn p-2 text-gray-400 hover:text-secondary rounded hover:bg-gray-100" data-id="${assignment.id}">344 <i data-feather="edit-2" class="w-4 h-4"></i>345 </button>346 <button class="delete-assignment-btn p-2 text-gray-400 hover:text-red-500 rounded hover:bg-gray-100" data-id="${assignment.id}">347 <i data-feather="trash-2" class="w-4 h-4"></i>348 </button>349 </div>350 </td>351 </tr>352 `;353 }).join('');354 355 feather.replace();356}357 358function updateStats() {359 document.getElementById('total-courses').textContent = appState.courses.length;360 document.getElementById('total-assignments').textContent = appState.assignments.length;361 document.getElementById('in-progress').textContent = appState.assignments.filter(a => 362 a.status === 'in progress' || a.status === 'draft done'363 ).length;364 document.getElementById('completed').textContent = appState.assignments.filter(a => 365 a.status === 'submitted' || a.status === 'graded'366 ).length;367}368 369// Event listeners370function setupEventListeners() {371 // Add course button372 document.getElementById('add-course-btn')?.addEventListener('click', () => {373 showCourseModal();374 });375 376 // Add assignment button377 document.getElementById('add-assignment-btn')?.addEventListener('click', () => {378 showAssignmentModal();379 });380 381 // Empty state add button382 document.getElementById('empty-add-btn')?.addEventListener('click', () => {383 showAssignmentModal();384 });385 386 // Export data387 document.getElementById('export-data')?.addEventListener('click', exportData);388 389 // Import data390 document.getElementById('import-data')?.addEventListener('click', () => {391 document.getElementById('import-file')?.click();392 });393 394 // Reset sample data395 document.getElementById('reset-sample')?.addEventListener('click', resetSampleData);396 397 // File input for import398 const fileInput = document.createElement('input');399 fileInput.type = 'file';400 fileInput.accept = '.json';401 fileInput.id = 'import-file';402 fileInput.style.display = 'none';403 fileInput.addEventListener('change', importData);404 document.body.appendChild(fileInput);405 406 // Table sorting407 document.querySelectorAll('.sortable').forEach(th => {408 th.addEventListener('click', () => {409 const field = th.dataset.sort;410 if (appState.sort.field === field) {411 appState.sort.direction = appState.sort.direction === 'asc' ? 'desc' : 'asc';412 } else {413 appState.sort.field = field;414 appState.sort.direction = 'asc';415 }416 renderAssignments();417 });418 });419 420 // Delegated event listeners for dynamic content421 document.addEventListener('click', (e) => {422 // Edit course423 if (e.target.closest('.edit-course-btn')) {424 const btn = e.target.closest('.edit-course-btn');425 const courseId = btn.dataset.id;426 showCourseModal(courseId);427 }428 429 // Delete course430 if (e.target.closest('.delete-course-btn')) {431 const btn = e.target.closest('.delete-course-btn');432 const courseId = btn.dataset.id;433 deleteCourse(courseId);434 }435 436 // Edit assignment437 if (e.target.closest('.edit-assignment-btn')) {438 const btn = e.target.closest('.edit-assignment-btn');439 const assignmentId = btn.dataset.id;440 showAssignmentModal(assignmentId);441 }442 443 // Delete assignment444 if (e.target.closest('.delete-assignment-btn')) {445 const btn = e.target.closest('.delete-assignment-btn');446 const assignmentId = btn.dataset.id;447 deleteAssignment(assignmentId);448 }449 450 // Assignment row click (navigate to assignment page)451 if (e.target.closest('tr[data-id]') && !e.target.closest('button')) {452 const row = e.target.closest('tr[data-id]');453 const assignmentId = row.dataset.id;454 window.location.href = `assignment.html?id=${assignmentId}`;455 }456 });457}458 459// Modal functions460function showCourseModal(courseId = null) {461 const modal = document.createElement('custom-course-modal');462 modal.setAttribute('course-id', courseId || '');463 document.getElementById('modal-container').appendChild(modal);464}465 466function showAssignmentModal(assignmentId = null) {467 const modal = document.createElement('custom-assignment-modal');468 modal.setAttribute('assignment-id', assignmentId || '');469 document.getElementById('modal-container').appendChild(modal);470}471 472function showConfirmDialog(options) {473 const dialog = document.createElement('custom-confirm-dialog');474 dialog.setAttribute('title', options.title || 'Confirm Action');475 dialog.setAttribute('message', options.message || 'Are you sure?');476 dialog.setAttribute('confirm-text', options.confirmText || 'Confirm');477 dialog.setAttribute('cancel-text', options.cancelText || 'Cancel');478 479 dialog.addEventListener('confirm', () => {480 if (options.onConfirm) options.onConfirm();481 dialog.remove();482 });483 484 dialog.addEventListener('cancel', () => {485 if (options.onCancel) options.onCancel();486 dialog.remove();487 });488 489 document.getElementById('modal-container').appendChild(dialog);490}491 492// Data operations493function deleteCourse(courseId) {494 const course = appState.courses.find(c => c.id === courseId);495 if (!course) return;496 497 const courseAssignments = appState.assignments.filter(a => a.courseId === courseId);498 const courseUnits = appState.units.filter(u => u.courseId === courseId);499 500 showConfirmDialog({501 title: 'Delete Course',502 message: `This will delete "${course.name}" and all ${courseUnits.length} units and ${courseAssignments.length} assignments. Type DELETE to confirm.`,503 confirmText: 'Delete',504 cancelText: 'Cancel',505 onConfirm: () => {506 // Remove course507 appState.courses = appState.courses.filter(c => c.id !== courseId);508 509 // Remove associated units510 appState.units = appState.units.filter(u => u.courseId !== courseId);511 512 // Remove associated assignments513 appState.assignments = appState.assignments.filter(a => a.courseId !== courseId);514 515 saveState();516 renderCourses();517 renderAssignments();518 updateStats();519 showToast('Course deleted successfully', 'success');520 }521 });522}523 524function deleteAssignment(assignmentId) {525 const assignment = appState.assignments.find(a => a.id === assignmentId);526 if (!assignment) return;527 528 showConfirmDialog({529 title: 'Delete Assignment',530 message: `Delete "${assignment.name}"? This action cannot be undone.`,531 confirmText: 'Delete',532 cancelText: 'Cancel',533 onConfirm: () => {534 appState.assignments = appState.assignments.filter(a => a.id !== assignmentId);535 saveState();536 renderAssignments();537 updateStats();538 showToast('Assignment deleted', 'success');539 }540 });541}542 543// Import/Export functions544function exportData() {545 const data = {546 courses: appState.courses,547 units: appState.units,548 assignments: appState.assignments,549 exportedAt: Date.now()550 };551 552 const blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' });553 const url = URL.createObjectURL(blob);554 const a = document.createElement('a');555 a.href = url;556 a.download = `layeredlearner-export-${new Date().toISOString().split('T')[0]}.json`;557 document.body.appendChild(a);558 a.click();559 document.body.removeChild(a);560 URL.revokeObjectURL(url);561 562 showToast('Data exported successfully', 'success');563}564 565function importData(event) {566 const file = event.target.files[0];567 if (!file) return;568 569 const reader = new FileReader();570 reader.onload = function(e) {571 try {572 const importedData = JSON.parse(e.target.result);573 574 showConfirmDialog({575 title: 'Import Data',576 message: 'This will replace all current data. Are you sure?',577 confirmText: 'Import',578 cancelText: 'Cancel',579 onConfirm: () => {580 appState.courses = importedData.courses || [];581 appState.units = importedData.units || [];582 appState.assignments = importedData.assignments || [];583 saveState();584 renderCourses();585 renderAssignments();586 updateStats();587 showToast('Data imported successfully', 'success');588 }589 });590 } catch (error) {591 showToast('Invalid data file', 'error');592 }593 };594 reader.readAsText(file);595 event.target.value = '';596}597 598function resetSampleData() {599 showConfirmDialog({600 title: 'Load Sample Data',601 message: 'This will replace all current data with sample data. Are you sure?',602 confirmText: 'Load Sample',603 cancelText: 'Cancel',604 onConfirm: () => {605 appState = { ...sampleData, filters: appState.filters, sort: appState.sort };606 saveState();607 renderCourses();608 renderAssignments();609 updateStats();610 showToast('Sample data loaded', 'success');611 }612 });613}614 615// Utility functions616function showToast(message, type = 'info') {617 // Remove existing toast618 const existingToast = document.querySelector('.toast');619 if (existingToast) existingToast.remove();620 621 // Create toast622 const toast = document.createElement('div');623 toast.className = `toast fixed bottom-4 right-4 px-4 py-3 rounded-lg shadow-hard z-50 animate-fade-in ${624 type === 'success' ? 'bg-green-500 text-white' :625 type === 'error' ? 'bg-red-500 text-white' :626 'bg-gray-800 text-white'627 }`;628 toast.textContent = message;629 630 // Add icon631 const icon = document.createElement('i');632 icon.setAttribute('data-feather', 633 type === 'success' ? 'check-circle' :634 type === 'error' ? 'alert-circle' :635 'info'636 );637 icon.className = 'inline w-4 h-4 mr-2';638 toast.prepend(icon);639 640 document.body.appendChild(toast);641 feather.replace();642 643 // Auto remove644 setTimeout(() => {645 toast.remove();646 }, 3000);647}648 649// Generate unique ID650function generateId(prefix) {651 return `${prefix}_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;652}653 654// Filter functions (called from filter-bar component)655function updateFilters(newFilters) {656 appState.filters = { ...appState.filters, ...newFilters };657 renderAssignments();658}659 660function clearFilters() {661 appState.filters = {662 course: null,663 unit: null,664 type: [],665 status: [],666 search: ''667 };668 renderAssignments();669}670 671// Public API for components672window.appState = appState;673window.initApp = initApp;674window.saveState = saveState;675window.generateId = generateId;676window.showToast = showToast;677window.updateFilters = updateFilters;678window.clearFilters = clearFilters;679 680// Course and unit getters for components681window.getCourses = () => appState.courses;682window.getUnits = (courseId) => appState.units.filter(u => u.courseId === courseId);683window.getCourseById = (id) => appState.courses.find(c => c.id === id);684window.getUnitById = (id) => appState.units.find(u => u.id === id);685window.getAssignmentById = (id) => appState.assignments.find(a => a.id === id);686 687// Course operations for components688window.saveCourse = (courseData) => {689 if (courseData.id) {690 // Update existing course691 const index = appState.courses.findIndex(c => c.id === courseData.id);692 if (index !== -1) {693 appState.courses[index] = { ...appState.courses[index], ...courseData };694 }695 } else {696 // Create new course697 const newCourse = {698 id: generateId('course'),699 name: courseData.name,700 units: [],701 createdAt: Date.now()702 };703 appState.courses.push(newCourse);704 }705 saveState();706 renderCourses();707 renderAssignments();708 updateStats();709 showToast('Course saved successfully', 'success');710};711 712// Assignment operations for components713window.saveAssignment = (assignmentData) => {714 if (assignmentData.id) {715 // Update existing assignment716 const index = appState.assignments.findIndex(a => a.id === assignmentData.id);717 if (index !== -1) {718 appState.assignments[index] = { 719 ...appState.assignments[index], 720 ...assignmentData,721 updatedAt: Date.now()722 };723 }724 } else {725 // Create new assignment726 const newAssignment = {727 id: generateId('assign'),728 ...assignmentData,729 ai: {730 assignmentStructure: null,731 draftRank: null,732 draftFeedback: null,733 practiceTest: null,734 summary: null,735 answerKey: null736 },737 draft: '',738 final: '',739 grade: null,740 gradeFeedback: [],741 createdAt: Date.now(),742 updatedAt: Date.now()743 };744 appState.assignments.push(newAssignment);745 }746 saveState();747 renderAssignments();748 updateStats();749 showToast('Assignment saved successfully', 'success');750};751 752// Unit operations for components753window.saveUnit = (unitData) => {754 if (unitData.id) {755 // Update existing unit756 const index = appState.units.findIndex(u => u.id === unitData.id);757 if (index !== -1) {758 appState.units[index] = { ...appState.units[index], ...unitData };759 }760 } else {761 // Create new unit762 const newUnit = {763 id: generateId('unit'),764 ...unitData,765 createdAt: Date.now()766 };767 appState.units.push(newUnit);768 769 // Add unit to course's units array770 const courseIndex = appState.courses.findIndex(c => c.id === unitData.courseId);771 if (courseIndex !== -1) {772 if (!appState.courses[courseIndex].units.includes(newUnit.id)) {773 appState.courses[courseIndex].units.push(newUnit.id);774 }775 }776 }777 saveState();778 showToast('Unit saved successfully', 'success');779};780 781// AI simulation function (for demo purposes)782window.simulateAIResponse = (task, context) => {783 // Simulate API call delay784 return new Promise((resolve) => {785 setTimeout(() => {786 let response;787 788 switch (task) {789 case 'generate_structure':790 response = {791 outline: [792 {793 heading: "Introduction",794 purpose: "Establish context and thesis",795 bullet_points: [796 "Hook: Start with an engaging statement about mitochondria",797 "Background: Briefly explain mitochondrial function",798 "Thesis: State the main argument about mitochondrial importance"799 ],800 estimated_word_count: 150801 },802 {803 heading: "Structure and Function",804 purpose: "Describe mitochondrial anatomy and processes",805 bullet_points: [806 "Describe double membrane structure",807 "Explain ATP production process",808 "Discuss role in cellular respiration"809 ],810 estimated_word_count: 250811 },812 {813 heading: "Conclusion",814 purpose: "Summarize key points and implications",815 bullet_points: [816 "Restate thesis in new words",817 "Summarize main findings",818 "Discuss broader implications"819 ],820 estimated_word_count: 150821 }822 ],823 notes: "Focus on clarity and scientific accuracy. Include at least 3 reputable sources."824 };825 break;826 827 case 'rank_draft':828 response = {829 score: 78,830 strengths: [831 "Clear explanation of ATP production",832 "Good use of scientific terminology",833 "Logical structure and flow"834 ],835 improvements: [836 "Add more specific examples of mitochondrial diseases",837 "Expand on the evolutionary significance",838 "Include recent research citations"839 ],840 suggestedSnippet: "Recent studies in mitochondrial biology have revealed fascinating insights into cellular aging processes, suggesting that mitochondrial efficiency directly correlates with overall cellular health and longevity."841 };842 break;843 844 case 'generate_practice_test':845 response = {846 questions: [847 {848 q: "What is the primary function of mitochondria?",849 type: "mcq",850 choices: ["Protein synthesis", "ATP production", "DNA replication", "Waste removal"],851 answer: "B",852 explanation: "Mitochondria are often called the 'powerhouses of the cell' because they produce ATP through cellular respiration."853 },854 {855 q: "Describe the structure of a mitochondrion.",856 type: "short",857 answer: "Double membrane organelle with inner membrane folds called cristae.",858 explanation: "The double membrane creates compartments for different stages of cellular respiration."859 }860 ]861 };862 break;863 864 default:865 response = { message: "AI analysis complete" };866 }867 868 resolve(response);869 }, 1500); // Simulate 1.5 second delay870 });871};