chore: setup project meta and ignore docs
This commit is contained in:
4
.gemini/settings.json
Normal file
4
.gemini/settings.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"mcpServers": {}
|
||||
}
|
||||
|
||||
0
.geminiignore
Normal file
0
.geminiignore
Normal file
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1 +1,2 @@
|
||||
.worktrees/
|
||||
docs/
|
||||
|
||||
64
GEMINI.md
Normal file
64
GEMINI.md
Normal file
@@ -0,0 +1,64 @@
|
||||
# TutorTool: Attendance Tracking System
|
||||
|
||||
TutorTool is a full-stack web application for tracking student attendance in tutoring sessions. It features a Rust backend and a SvelteKit frontend.
|
||||
|
||||
## Project Overview
|
||||
|
||||
- **Architecture**: Monorepo with a Rust backend (Axum) and a SvelteKit 5 frontend.
|
||||
- **Backend**:
|
||||
- **Framework**: Axum (async) on Tokio.
|
||||
- **Database**: SQLite via SQLx. Migrations are automatically run at startup.
|
||||
- **Auth**: JWT-based authentication (`jsonwebtoken` crate) with bcrypt for passwords.
|
||||
- **Static Serving**: Serves the compiled SvelteKit frontend as a Single-Page App (SPA).
|
||||
- **Frontend**:
|
||||
- **Framework**: SvelteKit 5 using Svelte Runes (`$state`, `$derived`, etc.).
|
||||
- **Build Tool**: Vite.
|
||||
- **Styling**: Vanilla CSS (based on design handoff).
|
||||
- **API**: Centralized fetch wrapper in `src/lib/api.ts`.
|
||||
|
||||
## Build and Run
|
||||
|
||||
### Prerequisites
|
||||
- Rust 1.95.0 (pinned via `rust-toolchain.toml`)
|
||||
- Node.js & npm
|
||||
- SQLite
|
||||
|
||||
### Key Commands
|
||||
- `make dev`: Starts both backend and frontend in parallel (requires `JWT_SECRET` and `DATABASE_URL` in environment).
|
||||
- `make build`: Performs a full production build (frontend first, then backend).
|
||||
- `cargo test`: Runs all backend unit and integration tests (uses `sqlx::test`).
|
||||
- `npm run check`: Performs TypeScript and Svelte type checking for the frontend.
|
||||
|
||||
### Environment Variables
|
||||
- `DATABASE_URL`: Path to the SQLite database (e.g., `sqlite:./dev.db`).
|
||||
- `JWT_SECRET`: Secret key for signing and verifying JWT tokens.
|
||||
- `STATIC_DIR`: Path to the compiled frontend (defaults to `../frontend/build`).
|
||||
|
||||
## Development Conventions
|
||||
|
||||
### Backend (Rust)
|
||||
- **Error Handling**: Uses a custom `AppError` enum (see `error.rs`) that implements `IntoResponse`.
|
||||
- **Database**: Queries use runtime `sqlx::query()` / `sqlx::query_as()`. **Note**: While CLAUDE.md mentions compile-time queries might need `DATABASE_URL`, the current implementation primarily uses runtime queries to simplify CI/CD.
|
||||
- **Routing**: Routes are modularized in `backend/src/routes/` and merged in `routes/mod.rs`.
|
||||
- **Auth**: Use the `TutorClaims` extractor in route handlers to enforce authentication and access the current user's ID and email.
|
||||
|
||||
### Frontend (SvelteKit)
|
||||
- **Runes**: Use Svelte 5 Runes for state management.
|
||||
- **Type Safety**: Ensure `frontend/src/lib/types.ts` is kept in sync with `backend/src/models.rs`.
|
||||
- **Layouts**:
|
||||
- `src/routes/login/`: Public login page.
|
||||
- `src/routes/admin/`: Protected admin routes (tutor dashboard).
|
||||
- `src/routes/s/[code]/`: Public student check-in page.
|
||||
|
||||
## Key Files
|
||||
- `backend/src/main.rs`: Entry point and server configuration.
|
||||
- `backend/src/db.rs`: Database initialization and migration logic.
|
||||
- `backend/src/auth.rs`: JWT encoding/decoding and Axum extractor.
|
||||
- `backend/src/models.rs`: Shared data models (DB rows and Request/Response DTOs).
|
||||
- `frontend/src/lib/api.ts`: API client for frontend-backend communication.
|
||||
- `frontend/src/lib/RoomCanvas.svelte`: Interactive SVG-based room layout component.
|
||||
- `conductor/attendance-tool.md`: Detailed implementation plan and project scope.
|
||||
|
||||
## Project History & Context
|
||||
- The project was migrated/continued from a feature branch as documented in `conductor/attendance-tool.md`.
|
||||
- Deployment is targeted at Kubernetes with a 3-stage Docker build.
|
||||
161
conductor/attendance-tool.md
Normal file
161
conductor/attendance-tool.md
Normal file
@@ -0,0 +1,161 @@
|
||||
# Implementation Plan: Attendance Tracking Tool (Continuation)
|
||||
|
||||
**Objective:** Complete the backend API, scaffold the SvelteKit frontend, implement all frontend views based on the provided design handoff, and set up deployment manifests. This plan picks up from where the `.worktrees/feature-tutortool` workspace left off (Tasks 1-8 completed).
|
||||
|
||||
**Scope:**
|
||||
- Complete backend APIs for attendance, notes, and exports.
|
||||
- Serve SvelteKit SPA fallback via Axum.
|
||||
- Scaffold SvelteKit frontend.
|
||||
- Implement UI pages for Admin tools (Dashboard, Courses, Rooms, Sessions, Attendance, Notes, Export) and Student Check-in.
|
||||
- Configure local development (Makefile, Docker Compose) and K8s manifests.
|
||||
|
||||
---
|
||||
|
||||
## 1. Backend Completion
|
||||
|
||||
### Task 9: Admin Attendance & Notes APIs
|
||||
**Files to Create/Modify:**
|
||||
- `backend/src/routes/attendance.rs`
|
||||
- `backend/src/routes/notes.rs`
|
||||
|
||||
**Implementation Steps:**
|
||||
- Add `POST /api/admin/slots/:id/attendance` (manual entry) and `DELETE /api/admin/slots/:slot_id/attendance/:student_id`.
|
||||
- Add `GET /api/admin/sessions/:id/attendance` (per-week matrix) and `GET /api/admin/students/:id/attendance`.
|
||||
- Add `PUT /api/admin/slots/:slot_id/notes/:student_id` (upsert note).
|
||||
- Add `GET /api/admin/slots/:slot_id/notes` and `GET /api/admin/students/:id/notes`.
|
||||
- Write corresponding unit tests.
|
||||
|
||||
### Task 10: Export API
|
||||
**Files to Create/Modify:**
|
||||
- `backend/src/routes/export.rs`
|
||||
|
||||
**Implementation Steps:**
|
||||
- Add `GET /api/admin/export/session/:id/csv` and `/md` (merged per-session weekly attendance).
|
||||
- Add `GET /api/admin/export/course/:id/csv` and `/md` (full course matrix with Bonus points calculation: +3 if unexcused absences <= 1).
|
||||
- Add `GET /api/admin/backup` (using `VACUUM INTO '/tmp/backup-<timestamp>.sqlite'` then streaming as `application/octet-stream`).
|
||||
- Ensure all endpoints verify `TutorClaims` and course access.
|
||||
|
||||
### Task 11: Static File Serving & Route Assembly
|
||||
**Files to Modify:**
|
||||
- `backend/src/main.rs`
|
||||
- `backend/src/routes/mod.rs`
|
||||
|
||||
**Implementation Steps:**
|
||||
- Merge `attendance`, `notes`, and `export` routers in `routes/mod.rs`.
|
||||
- Configure `tower_http::services::ServeDir` in `main.rs` to serve the SvelteKit static build.
|
||||
- Set up `ServeFile::new(format!("{static_dir}/index.html"))` as the SPA fallback service.
|
||||
|
||||
---
|
||||
|
||||
## 2. Frontend Development
|
||||
|
||||
### Task 12: Scaffold SvelteKit Frontend
|
||||
**Files to Create/Modify:**
|
||||
- `frontend/package.json`, `svelte.config.js`, `vite.config.ts`, `src/app.html`, `src/lib/types.ts`, `src/lib/api.ts`, `src/lib/auth.ts`
|
||||
|
||||
**Implementation Steps:**
|
||||
- Initialize SvelteKit with `@sveltejs/adapter-static` configured for SPA fallback.
|
||||
- Setup Vite proxy `/api` -> `http://localhost:3000`.
|
||||
- Create TypeScript types mirroring the backend database models.
|
||||
- Implement API client fetch wrapper (`api.ts`).
|
||||
- Set up Svelte store for JWT auth (`auth.ts`).
|
||||
|
||||
### Task 13: Login Page & Admin Auth Guard
|
||||
**Files to Create/Modify:**
|
||||
- `frontend/src/routes/login/+page.svelte`
|
||||
- `frontend/src/routes/admin/+layout.svelte`
|
||||
|
||||
**Implementation Steps:**
|
||||
- Implement the tutor login form and API integration.
|
||||
- Protect `/admin` routes using an `onMount` check redirecting unauthenticated users to `/login`.
|
||||
|
||||
### Task 14: Dashboard & Slot Management
|
||||
**Files to Create/Modify:**
|
||||
- `frontend/src/routes/admin/+page.svelte`
|
||||
|
||||
**Implementation Steps:**
|
||||
- Display all sessions/slots.
|
||||
- Implement toggles for slot status (`closed`, `open`, `locked`).
|
||||
- Display check-in link and copy button when a slot is `open`.
|
||||
|
||||
### Task 15: Courses & Students UI
|
||||
**Files to Create/Modify:**
|
||||
- `frontend/src/routes/admin/courses/+page.svelte`
|
||||
|
||||
**Implementation Steps:**
|
||||
- List courses and forms to create new courses.
|
||||
- Per-course student management: list students, add individual student, import from CSV, and delete students.
|
||||
|
||||
### Task 16: Room Layout Editor
|
||||
**Files to Create/Modify:**
|
||||
- `frontend/src/lib/RoomCanvas.svelte`
|
||||
- `frontend/src/routes/admin/rooms/+page.svelte`
|
||||
|
||||
**Implementation Steps:**
|
||||
- Implement SVG-based `RoomCanvas.svelte` supporting interactive (draggable/editable) mode, student check-in mode, and tutor notes mode.
|
||||
- Build room management UI: list rooms, create rooms, and edit JSON room layouts visually.
|
||||
|
||||
### Task 17: Sessions & Slots UI
|
||||
**Files to Create/Modify:**
|
||||
- `frontend/src/routes/admin/sessions/+page.svelte`
|
||||
|
||||
**Implementation Steps:**
|
||||
- Form to create sessions (course, week_nr, date).
|
||||
- Form to add slots within a session (room, tutor, start_time, end_time).
|
||||
|
||||
### Task 18: Student Check-in Page
|
||||
**Files to Create/Modify:**
|
||||
- `frontend/src/routes/s/[code]/+page.svelte`
|
||||
|
||||
**Implementation Steps:**
|
||||
- Fetch slot info. If no identity cookie exists, show name dropdown filtered to the course.
|
||||
- Display `RoomCanvas` indicating free/occupied seats.
|
||||
- Handle FCFS seat locking API calls (`POST /api/checkin`) and update UI.
|
||||
- Support read-only mode for locked/closed slots.
|
||||
|
||||
### Task 19: Attendance & Notes UI
|
||||
**Files to Create/Modify:**
|
||||
- `frontend/src/routes/admin/attendance/+page.svelte`
|
||||
- `frontend/src/routes/admin/notes/+page.svelte`
|
||||
|
||||
**Implementation Steps:**
|
||||
- Build matrix tables (per-week and per-student) for manual attendance marking/removal.
|
||||
- Build notes UI utilizing `RoomCanvas` for clicking on seats to leave inline text notes.
|
||||
|
||||
### Task 20: Export UI
|
||||
**Files to Create/Modify:**
|
||||
- `frontend/src/routes/admin/export/+page.svelte`
|
||||
|
||||
**Implementation Steps:**
|
||||
- Provide buttons to download weekly CSV/Markdown, full course matrix, and SQLite backup directly from the admin interface.
|
||||
|
||||
---
|
||||
|
||||
## 3. DevOps & Deployment
|
||||
|
||||
### Task 21: Local Dev Environment
|
||||
**Files to Create/Modify:**
|
||||
- `Makefile`
|
||||
- `docker-compose.yml`
|
||||
|
||||
**Implementation Steps:**
|
||||
- Write `Makefile` with commands: `dev`, `dev-backend`, `dev-frontend`, `test`, `build`, `compose-up`.
|
||||
- Create `docker-compose.yml` for testing the production image locally using SQLite mounted via volume.
|
||||
|
||||
### Task 22: Dockerfile & K8s Manifests
|
||||
**Files to Create/Modify:**
|
||||
- `Dockerfile`
|
||||
- `k8s/deployment.yaml`, `k8s/service.yaml`, `k8s/ingress.yaml`, `k8s/pvc.yaml`, `k8s/cronjob.yaml`
|
||||
|
||||
**Implementation Steps:**
|
||||
- Write a 3-stage `Dockerfile` (frontend build, backend build, alpine + sqlite runtime).
|
||||
- Write `pvc.yaml` for SQLite persistent storage.
|
||||
- Write `deployment.yaml`, `service.yaml`, and `ingress.yaml` (`tutor.puchstein.dev`).
|
||||
- Write `cronjob.yaml` running at 3 AM daily, executing `sqlite3 /data/attendance.db "VACUUM INTO '/data/backup-$(date +%F).sqlite'"` and pruning files older than 7 days.
|
||||
|
||||
---
|
||||
|
||||
## Verification Strategy
|
||||
1. **Unit Tests:** Execute `cargo test` in `backend/` to verify all new endpoints (Tasks 9-11).
|
||||
2. **End-to-End Test:** Start `make dev` and manually verify all critical paths: tutor login, session/slot creation, student check-in with cookie persistence, FCFS seat collision handling, manual attendance, and exporting.
|
||||
3. **Deployment Test:** Run `make compose-up` to ensure the built Docker container operates as expected, serving Svelte SPA fallback via Axum properly.
|
||||
Reference in New Issue
Block a user