# Lomda Hub (Mini-LMS) Mini לומדות platform with locked progression, groups, Google OAuth login, achievements system, file uploads, and admin analytics. ## Features - **Locked Progression**: Learners must complete module N before unlocking N+1 - **Google OAuth**: Sign in with Google account - **JWT Authentication**: Access and refresh tokens for secure API access - **Achievements System**: Earn achievements for completing courses, perfect scores, and consistent learning - **File Uploads**: Admin can attach PDF/PPTX presentations to content modules - **Admin Analytics**: View statistics on users, courses, enrollments, completions, and quiz attempts - **Groups**: Restrict course access to specific user groups - **Dark/Light Theme**: Toggle between dark and light modes ## Stack - Frontend: React + Vite + TypeScript + React Router + MUI - Backend: FastAPI + SQLAlchemy 2.0 + Alembic - Database: Postgres - Auth: JWT (access + refresh) + Google OAuth - Dev: Docker Compose ## Quick start (Docker) 1. Create a `.env` file (see `.env.example` for reference) or set environment variables 2. `docker compose build` 3. `docker compose up -d` Services: - Frontend: http://localhost:5173 - Backend API: http://localhost:8000 - Backend API Docs: http://localhost:8000/docs - Postgres: localhost:5433 Default admin credentials (seeded): - Email: `admin@example.com` - Password: `admin123` ## Google OAuth setup (dev) 1. Create OAuth credentials in [Google Cloud Console](https://console.cloud.google.com/). 2. Set Authorized redirect URI to `http://localhost:8000/auth/google/callback`. 3. Set the following in `.env`: - `GOOGLE_CLIENT_ID=your_client_id` - `GOOGLE_CLIENT_SECRET=your_client_secret` - `GOOGLE_REDIRECT_URI=http://localhost:8000/auth/google/callback` - `FRONTEND_URL=http://localhost:5173` ## Environment Variables Create a `.env` file in the project root with the following variables (see `.env.example`): ```bash # Database DATABASE_URL=postgresql+psycopg2://postgres:postgres@db:5432/lomda # JWT Secrets (change in production!) JWT_SECRET_KEY=change_me_access JWT_REFRESH_SECRET_KEY=change_me_refresh # Frontend URL FRONTEND_URL=http://localhost:5173 # CORS Origins (comma-separated) CORS_ORIGINS=http://localhost:5173 # Admin Seed Credentials ADMIN_SEED_EMAIL=admin@example.com ADMIN_SEED_PASSWORD=admin123 # Google OAuth (optional) GOOGLE_CLIENT_ID= GOOGLE_CLIENT_SECRET= GOOGLE_REDIRECT_URI=http://localhost:8000/auth/google/callback # Upload Directory UPLOAD_DIR=/data/uploads # SMTP (optional, for future email features) SMTP_HOST= SMTP_PORT=587 SMTP_USER= SMTP_PASSWORD= SMTP_FROM= ``` ## Local development (no Docker) ### Backend: 1. `cd backend` 2. `python -m venv .venv && .venv\Scripts\activate` (Windows) or `source .venv/bin/activate` (Linux/Mac) 3. `pip install -r requirements.txt` 4. `alembic upgrade head` 5. `python -m app.scripts.seed` 6. `uvicorn app.main:app --reload` ### Frontend: 1. `cd frontend` 2. `npm install` 3. Create `frontend/.env` with: `VITE_API_URL=http://localhost:8000` 4. `npm run dev` ## Testing Features ### Google OAuth Login 1. Ensure `GOOGLE_CLIENT_ID` and `GOOGLE_CLIENT_SECRET` are set in `.env` 2. Visit http://localhost:5173/login 3. Click "Continue with Google" 4. Complete Google sign-in flow 5. You should be redirected back to the app authenticated ### File Uploads 1. Login as admin (`admin@example.com` / `admin123`) 2. Navigate to Admin → Courses → Select a course → Modules 3. Edit a content module 4. Upload a PDF or PPTX presentation 5. Save the module 6. As a learner, enroll in the course and open that module 7. Click "View Presentation" to open the uploaded file ### Achievements 1. Login as a learner 2. Navigate to "Achievements" in the header 3. Complete courses and quizzes to earn achievements: - **First Course Complete**: Complete your first course - **Perfect Final**: Score 100% on any final exam - **Triple Perfect**: Score 100% on three quiz attempts in a row - **Fast Finisher**: Complete a course within 24 hours of enrollment - **Consistent Learner**: Log in on 5 different days ### Admin Analytics 1. Login as admin 2. Navigate to Admin → Analytics 3. View user and course statistics 4. Click "View Details" to see detailed information on specific users or courses ### Theme Toggle - Click the sun/moon icon in the header to switch between light and dark themes - Theme preference is saved in localStorage ## Database Migrations After model changes: 1. `cd backend` 2. `alembic revision --autogenerate -m "description"` 3. `alembic upgrade head` In Docker, migrations run automatically on container startup. ## Architecture Notes - **Locked Progression**: On enrollment, first module is `unlocked`, rest are `locked`. Content modules mark completed when viewed. Quiz modules mark completed only if score >= pass_score. - **Admin vs Learner**: Admins can preview courses without enrolling. Learners must enroll and follow progression rules. - **Groups**: Courses can be restricted to specific groups. If a course has no groups, it's public (all learners can see). - **Uploads**: Stored on disk in `UPLOAD_DIR` (/data/uploads by default). Metadata tracked in database. Only authenticated users can download. - **Achievements**: Evaluated after module completion and quiz submission. Uses login_events table to track consistent learner achievement. ## Troubleshooting ### Google OAuth 307 Redirects - Ensure `GOOGLE_REDIRECT_URI` matches exactly what's configured in Google Cloud Console - Backend uses `redirect_slashes=False` to prevent automatic trailing slash redirects ### Uploads Not Working - Ensure `UPLOAD_DIR` exists and backend has write permissions - In Docker, uploads are stored in the `upload_data` volume ### Dark Mode Not Persisting - Check browser localStorage for `lomda_theme` key - Clear localStorage and try toggling theme again ## Environment - Do not commit real secrets. Use `.env` locally and keep it in `.gitignore`. - See `.env.example` for required values. ## License MIT