From 4d08bdbda97381e49038a935556edd625b9e9b07 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 14 Nov 2025 12:45:55 +0700 Subject: [PATCH] docs: add brownfield documentation (architecture, endpoints, admin UI, runbook) --- docs/technical/brownfield-documentation.md | 106 +++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 docs/technical/brownfield-documentation.md diff --git a/docs/technical/brownfield-documentation.md b/docs/technical/brownfield-documentation.md new file mode 100644 index 0000000..b7387ab --- /dev/null +++ b/docs/technical/brownfield-documentation.md @@ -0,0 +1,106 @@ +# Brownfield Documentation — LMS-BGN + +Ringkasan teknis kondisi kode saat ini (brownfield) untuk LMS-BGN, mencakup arsitektur, endpoint backend aktif, proxy API frontend, perubahan UI Admin, data model yang dipakai, serta runbook pengembangan lokal. Dokumen ini fokus pada konteks yang telah berjalan setelah integrasi CRUD Course, daftar Instructors, dan CourseForm di Admin. + +## Snapshot Arsitektur +- Frontend: Next.js (App Router) dengan TypeScript; API proxy di `src/app/api/*`. +- Backend: Express server di `backend/src/server.js` dengan penyimpanan in-memory. +- Komunikasi: Frontend memanggil proxy Next → meneruskan ke Backend (`BASE` fallback `http://localhost:8001`). +- Media: Upload gambar disimpan ke `public/uploads` (lokal) via route Next `/api/uploads`. + +## Data Model Utama (In-Memory) +- `Course`: `{ id, title, instructor, progress, status, color, thumbnail, duration, modules, enrolled }` + - `status`: `"draft" | "published" | "archived"` + - `color`: hex `#RRGGBB` + - `thumbnail`: path publik (mis. `/uploads/.png`) + - `duration`: menit (integer > 0) +- `Instructor`: `{ id, name, email }` +- `ExamSession`: `{ id, examId, userId, answers, score?, startedAt? }` (outline) +- `Certificate`: data minimal untuk resend (outline) + +## Backend Endpoints (aktif) +Base dev: `http://localhost:8001` + +- Courses + - `GET /api/courses` — list + pagination + search (`q`), respon `{ data, total, page, pageSize }` + - `GET /api/courses/:courseId` — detail course + - `POST /api/courses` — create (validasi: `title`, `instructor`, `duration`, `thumbnail`, `color`, `status`) + - `PUT /api/courses/:courseId` — update (validasi serupa) + - `DELETE /api/courses/:courseId` — delete (204 jika sukses) +- Instructors + - `GET /api/instructors` — list + optional search `q`; respon `{ data, total }` +- Modules & Assignments + - `POST /api/modules/:moduleId/progress` — update progres modul, body `{ progressPercent }` + - `POST /api/assignments/:assignmentId/submission` — requires `idempotencyKey`; 201 jika baru, 409 duplikat +- Exams & Certificates + - `GET /api/exams` — list ujian (pagination + search) + - `POST /api/exam-session` — create session (`examId`, `userId`) + - `POST /api/exam-session/:sessionId/score` — skor jawaban (mode batch), Bearer optional; mendukung MCQ, scenario/video, puzzle, dsb. + - `GET /api/exam-session/:sessionId/summary` — ringkasan hasil + - `POST /api/certificates/:certificateId/resend` — resend email (idempotency + rate limit sederhana) + +Catatan: Beberapa endpoint berasal dari implementasi awal dan sebagian telah diperluas. Penyimpanan masih in-memory; restart server akan menghapus data. + +## Frontend API Proxy (Next.js) +`BASE` fallback: `http://localhost:8001` + +- `src/app/api/courses/route.ts` + - `GET` → `/api/courses` (backend) + - `POST` → `/api/courses` (backend) +- `src/app/api/courses/[courseId]/route.ts` + - `GET` → `/api/courses/:courseId` + - `PUT` → `/api/courses/:courseId` + - `DELETE` → `/api/courses/:courseId` +- `src/app/api/instructors/route.ts` + - `GET` → `/api/instructors?q=` +- `src/app/api/uploads/route.ts` + - `POST` — validasi mime image & ukuran (≤ 5MB); simpan ke `public/uploads`; balikan path publik untuk preview + +## Perubahan UI Admin (yang berjalan) +- `src/components/admin/CourseForm.tsx` (client component) + - Upload gambar dengan preview (via `/api/uploads`) + - Input durasi (spinner number) + - Color picker (hex) + - Dropdown Instructor (fetch dari `/api/instructors`, dengan search) + - Submit create/update ke proxy `/api/courses` atau `/api/courses/[courseId]` +- `src/app/admin/courses/create/page.tsx` + - Menggunakan `CourseForm` untuk pembuatan course; redirect setelah sukses +- `src/app/admin/courses/[id]/edit/page.tsx` + - Menggunakan `CourseForm` untuk edit; prefill dari API; redirect setelah sukses + +## Runbook Dev Lokal +- Backend + - Jalankan di `backend/`: PowerShell → `$env:PORT=8001; npm run dev` + - Health/Smoke: akses `GET http://localhost:8001/api/instructors` atau `GET /api/courses` +- Frontend + - Jalankan di root: `npm run dev` (otomatis pindah ke port `3001` jika `3000` terpakai) + - Preview Admin Create: `http://localhost:3001/admin/courses/create` + - Preview Admin Edit: `http://localhost:3001/admin/courses//edit` +- Contoh smoke (PowerShell) + - Create course: `Invoke-RestMethod -Method Post -Uri http://localhost:8001/api/courses -ContentType application/json -Body '{"title":"Knife Basics","instructor":"i1","duration":60,"thumbnail":"/uploads/x.png","color":"#3366FF","status":"draft"}'` + - Update course: `Invoke-RestMethod -Method Put -Uri http://localhost:8001/api/courses/ -ContentType application/json -Body '{"title":"Knife Basics Updated"}'` + - Delete course: `Invoke-WebRequest -Method Delete -Uri http://localhost:8001/api/courses/` (cek status 204) + +## Batasan Saat Ini +- Penyimpanan in-memory (data hilang saat restart; bukan produksi) +- Validasi sederhana (color hex, status enum, durasi > 0) — belum ada skema terpadu +- Upload lokal ke `public/uploads` (tanpa CDN, tanpa antivirus) +- Tidak ada autentikasi/otorisasi untuk Admin; proxy terbuka di dev +- Idempotency untuk assignments & rate limit untuk resend sederhana (in-memory) +- Ketergantungan pada BASE `http://localhost:8001` untuk dev; environment management minimal + +## Rekomendasi Next Steps +- Persistensi: migrasi ke DB (PostgreSQL/SQLite dev) + ORM (Prisma) +- Skema & tipe: definisikan tipe terpadu (Zod/TypeScript) untuk API + frontend +- Upload: integrasi storage (S3/MinIO) + validasi server-side kuat +- AuthZ: tambahkan auth (JWT/NextAuth) & guard route Admin +- Observabilitas: logging terstruktur + request tracing sederhana +- Testing: tambah unit/integrasi untuk backend (Jest/Supertest) dan e2e smoke +- Analytics Admin: tambahkan agregasi & export CSV/XLSX, konsisten dengan PRD + +## Referensi & Jejak +- PRD: `docs/mbg-lms-prd.md` +- Epic 2: `docs/Epic 2 — Course & Learning Management.md` +- Tech Spec: `docs/technical/tech-spec-lms-bgn.md` +- QA Smoke: `docs/qa/assessments/backend-endpoints.http`, `docs/qa/assessments/curl-examples.md` +- Proxy & Admin UI: `src/app/api/*`, `src/components/admin/CourseForm.tsx`, `src/app/admin/courses/*` \ No newline at end of file