import React, { useState, useEffect } from 'react'; import { User, Shield, Activity, BookOpen, Pill, Stethoscope, Brain, Baby, Users, Briefcase, ChevronRight, ArrowLeft, CheckCircle, XCircle, Database, Upload, RefreshCw, LogOut, Clock, Award, AlertTriangle, Check, Trash2, X } from 'lucide-react'; // --- Initial Mock Data --- const INITIAL_DATA = { nclex: [], // Will hold mixed/uploaded questions pharm: [ { id: 1, question: "A client is prescribed lisinopril. Which finding requires immediate nursing action?", options: [ "Dry cough", "Dizziness upon standing", "Swelling of the lips and tongue", "Serum potassium 4.2 mEq/L" ], correct: 2, explanation: "Swelling of the lips and tongue indicates angioedema, a potentially life-threatening adverse reaction to ACE inhibitors like lisinopril that can compromise the airway. Dry cough and orthostatic hypotension are common side effects but not emergencies." } ], medsurg: [ { id: 201, question: "A client with COPD is admitted with an exacerbation. The pulse oximeter reads 86% on room air. Which action should the nurse take first?", options: [ "Administer oxygen at 4 L/min via nasal cannula", "Place the client in a high-Fowler's position", "Prepare for endotracheal intubation", "Assess the client's arterial blood gases (ABGs)" ], correct: 1, explanation: "Placing the client in a high-Fowler's position promotes chest expansion and improves oxygenation immediately with the least invasiveness. Oxygen should be administered cautiously in COPD (usually starting at 1-2 L/min) to avoid suppressing the hypoxic drive, making 4 L/min too high as a starting action." }, { id: 202, question: "A nurse is caring for a client 4 hours post-thyroidectomy. Which finding requires immediate intervention?", options: [ "Sore throat and hoarseness", "Calcium level of 9.0 mg/dL", "Noisy breathing (stridor)", "Pain at the incision site rating 4/10" ], correct: 2, explanation: "Stridor indicates airway obstruction due to edema or laryngeal nerve damage and is a medical emergency requiring immediate action (often intubation or tracheostomy). Sore throat, mild hypocalcemia (normal is ~8.5-10.5), and pain are expected or less urgent findings." }, { id: 203, question: "The nurse is caring for a client with a chest tube. The nurse notes continuous bubbling in the water seal chamber. What is the priority action?", options: [ "Clamp the chest tube immediately", "Increase the suction pressure", "Check the drainage system for leaks", "Document the finding as normal" ], correct: 2, explanation: "Continuous bubbling in the water seal chamber indicates an air leak in the system. The priority is to locate the leak (checking connections from the patient to the unit). Clamping is only done for specific checks and can cause tension pneumothorax if done inappropriately." }, { id: 204, question: "A client with diabetes mellitus type 1 is found unresponsive. The blood glucose is 42 mg/dL. Which medication should the nurse anticipate administering?", options: [ "Regular insulin SQ", "Glucagon IM", "Metformin PO", "Dextrose 5% in Water IV" ], correct: 1, explanation: "For an unresponsive client with severe hypoglycemia who cannot swallow, Glucagon IM or Dextrose 50% IV (not D5W, which is too dilute) is the standard treatment. Insulin would worsen the condition." } ], default: [ { id: 99, question: "Which action is the priority when caring for a client with a potential cervical spine injury?", options: [ "Assess pupil reaction", "Immobilize the head and neck", "Check for sensation in extremities", "Administer pain medication" ], correct: 1, explanation: "The priority is to prevent further injury. Immobilizing the head and neck stabilizes the cervical spine. Assessment comes after ensuring safety/stabilization in this specific trauma context." } ] }; const CATEGORIES = [ { id: 'nclex', title: 'NCLEX RN Mixed', sub: 'All Topics', icon: Activity, color: 'bg-blue-100 text-blue-600' }, { id: 'pharm', title: 'Pharmacology', sub: 'Meds & Doses', icon: Pill, color: 'bg-purple-100 text-purple-600' }, { id: 'medsurg', title: 'Med-Surg', sub: 'Clinical Care', icon: Stethoscope, color: 'bg-emerald-100 text-emerald-600' }, { id: 'fund', title: 'Fundamentals', sub: 'Basics', icon: BookOpen, color: 'bg-amber-100 text-amber-600' }, { id: 'psych', title: 'Psychiatry', sub: 'Mental Health', icon: Brain, color: 'bg-pink-100 text-pink-600' }, { id: 'mat', title: 'Maternity', sub: 'OB & Newborn', icon: Baby, color: 'bg-rose-100 text-rose-600' }, { id: 'peds', title: 'Pediatrics', sub: 'Child Health', icon: Users, color: 'bg-orange-100 text-orange-600' }, { id: 'lead', title: 'Leadership', sub: 'Ethics & Mgmt', icon: Briefcase, color: 'bg-slate-100 text-slate-600' }, ]; // --- Components --- const Logo = () => (
GoodLife Nursing Logo { e.target.onerror = null; e.target.style.display = 'none'; e.target.parentNode.innerHTML = ''; }} />

GoodLife Nursing

AI-Powered Exam Prep
); // --- Helpers --- const formatTime = (seconds) => { const mins = Math.floor(seconds / 60); const secs = seconds % 60; return `${mins}:${secs.toString().padStart(2, '0')}`; }; export default function App() { const [view, setView] = useState('login'); // login, dashboard, quiz, results, admin const [userRole, setUserRole] = useState(null); const [userName, setUserName] = useState(''); const [activeTab, setActiveTab] = useState('student'); const [loginError, setLoginError] = useState(''); // Quiz State const [selectedCategory, setSelectedCategory] = useState(null); const [currentQuestionIndex, setCurrentQuestionIndex] = useState(0); const [showExplanation, setShowExplanation] = useState(false); const [selectedAnswer, setSelectedAnswer] = useState(null); const [score, setScore] = useState(0); const [quizHistory, setQuizHistory] = useState([]); // Array of { questionId, correct } const [timeLeft, setTimeLeft] = useState(0); // Database State - NOW WITH LOCAL STORAGE SUPPORT const [questionBank, setQuestionBank] = useState(() => { try { const savedData = localStorage.getItem('goodlife_db'); return savedData ? JSON.parse(savedData) : INITIAL_DATA; } catch (e) { console.error("Failed to load save", e); return INITIAL_DATA; } }); const [totalCount, setTotalCount] = useState(2042); const [uploadStatus, setUploadStatus] = useState(null); const [isSyncing, setIsSyncing] = useState(false); // UI States for Admin const [resetConfirm, setResetConfirm] = useState(false); const [showUploadInput, setShowUploadInput] = useState(false); const [jsonInput, setJsonInput] = useState(''); // --- Effects --- // Auto-save Effect useEffect(() => { try { localStorage.setItem('goodlife_db', JSON.stringify(questionBank)); } catch (e) { console.error("Failed to save data (likely quota exceeded)", e); } }, [questionBank]); // Timer Effect useEffect(() => { let timer; if (view === 'quiz' && timeLeft > 0) { timer = setInterval(() => { setTimeLeft((prev) => { if (prev <= 1) { clearInterval(timer); setView('results'); return 0; } return prev - 1; }); }, 1000); } return () => clearInterval(timer); }, [view, timeLeft]); // Update total count simulation useEffect(() => { let count = 0; Object.values(questionBank).forEach(arr => count += arr.length); setTotalCount(2042 + count); }, [questionBank]); // --- Handlers --- const handleLogin = (e) => { e.preventDefault(); setLoginError(''); if (activeTab === 'student') { if (!userName.trim()) return; setUserRole('student'); setView('dashboard'); } else { const pw = e.target.password.value; if (pw === 'admin123') { setUserRole('admin'); setView('admin'); } else { setLoginError('Incorrect password. Try "admin123"'); } } }; const startQuiz = (category) => { let quizQuestions = []; if (category.id === 'nclex') { Object.values(questionBank).forEach(arr => { quizQuestions = [...quizQuestions, ...arr]; }); if (quizQuestions.length === 0) quizQuestions = questionBank.default; } else { quizQuestions = questionBank[category.id] || questionBank.default; } setSelectedCategory({ ...category, questions: quizQuestions }); setCurrentQuestionIndex(0); setScore(0); setQuizHistory([]); setShowExplanation(false); setSelectedAnswer(null); setTimeLeft(quizQuestions.length * 60); setView('quiz'); }; const handleAnswer = (index) => { if (selectedAnswer !== null) return; setSelectedAnswer(index); setShowExplanation(true); const questions = selectedCategory.questions; const currentQ = questions[currentQuestionIndex]; const isCorrect = index === currentQ.correct; if (isCorrect) { setScore(s => s + 1); } setQuizHistory(prev => [...prev, { question: currentQ, userAnswer: index, isCorrect: isCorrect }]); }; const nextQuestion = () => { const questions = selectedCategory.questions; if (currentQuestionIndex + 1 < questions.length) { setCurrentQuestionIndex(p => p + 1); setSelectedAnswer(null); setShowExplanation(false); } else { setView('results'); } }; const processJsonUpload = () => { if (!jsonInput.trim()) return; try { const parsed = JSON.parse(jsonInput); if (!Array.isArray(parsed)) throw new Error("Input is not an array. Must start with '['"); const valid = parsed.every(q => q.question && Array.isArray(q.options) && typeof q.correct === 'number'); if (!valid) throw new Error("Invalid format. Questions need 'question', 'options', 'correct' (number), 'explanation'."); setQuestionBank(prev => ({ ...prev, nclex: [...prev.nclex, ...parsed], medsurg: [...prev.medsurg, ...parsed] })); setUploadStatus(`Success! Saved ${parsed.length} questions.`); setJsonInput(''); setShowUploadInput(false); setTimeout(() => setUploadStatus(null), 3000); } catch (e) { alert("Error parsing JSON: " + e.message); } }; const handleResetDatabase = () => { if (!resetConfirm) { setResetConfirm(true); setTimeout(() => setResetConfirm(false), 3000); // Reset confirm state after 3s return; } // Actual Reset localStorage.removeItem('goodlife_db'); setQuestionBank(INITIAL_DATA); setUploadStatus("Database reset to defaults."); setResetConfirm(false); setTimeout(() => setUploadStatus(null), 3000); } const handleSync = () => { if (isSyncing) return; setIsSyncing(true); setTimeout(() => { setIsSyncing(false); }, 2000); }; // --- Views --- if (view === 'login') { return (
{activeTab === 'student' ? ( <>
setUserName(e.target.value)} />
) : ( <>
{loginError &&

{loginError}

}

Hint: use "admin123"

)}
© 2024 GoodLife Nursing AI • Secure Access
); } if (view === 'dashboard') { return (
{userName.charAt(0).toUpperCase()}

Hello, {userName}

Ready to learn

Readiness Score

0%

Based on recent performance

Study Categories

{CATEGORIES.map((cat) => ( ))}
); } if (view === 'quiz') { const questions = selectedCategory?.questions || []; const currentQ = questions[currentQuestionIndex]; const isLast = currentQuestionIndex + 1 >= questions.length; if (!currentQ) return
Error loading question
; return (
{/* Quiz Header with Timer */}
{selectedCategory?.title} Q {currentQuestionIndex + 1} of {questions.length}
{formatTime(timeLeft)}
{/* Progress Bar */}

{currentQ.question}

{currentQ.options.map((option, idx) => { let btnClass = "w-full text-left p-4 rounded-xl border-2 transition-all font-medium text-sm relative "; if (selectedAnswer === null) { btnClass += "border-gray-100 hover:border-pink-200 hover:bg-pink-50 text-gray-700"; } else { if (idx === currentQ.correct) { btnClass += "border-green-500 bg-green-50 text-green-800"; } else if (idx === selectedAnswer) { btnClass += "border-red-500 bg-red-50 text-red-800"; } else { btnClass += "border-gray-100 text-gray-400 opacity-60"; } } return ( ); })}
{showExplanation && (

AI Tutor Explanation

{currentQ.explanation}

)}
); } if (view === 'results') { const totalQ = selectedCategory?.questions.length || 0; const percent = Math.round((score / totalQ) * 100); const passed = percent >= 75; return (
{passed ? : }

{percent}%

{passed ? 'Great Job! You Passed.' : 'Keep Practicing. You can do it.'}

{score}
Correct
{totalQ - score}
Incorrect

Review Incorrect Answers

{quizHistory.filter(h => !h.isCorrect).length === 0 ? (

No incorrect answers to review!

) : ( quizHistory.filter(h => !h.isCorrect).map((item, i) => (

{item.question.question}

You Answered{item.question.options[item.userAnswer]}
Correct Answer{item.question.options[item.question.correct]}
Rationale {item.question.explanation}
)) )}
); } if (view === 'admin') { return (

Boss Menu

Content Management System

Database Status

{totalCount.toLocaleString()} questions

Simulate database population

Manual JSON Upload

{showUploadInput && ( )}
{uploadStatus && (
{uploadStatus}
)} {!showUploadInput ? (
setShowUploadInput(true)} className="border-2 border-dashed border-gray-600 rounded-xl p-8 text-center hover:border-gray-500 transition-colors cursor-pointer bg-gray-800/50" >

Click to paste JSON batch

Supports full NCLEX arrays

) : (