Skip to content

wenzduxx/examhub-dev

Repository files navigation

🎓 ExamHub — Portal Ujian Aman & Pintar

Platform ujian digital terintegrasi AI untuk institusi pendidikan modern.

TypeScript React Express Prisma PostgreSQL Socket.io Gemini AI License


ExamHub adalah platform manajemen ujian full-stack yang menggabungkan kecerdasan buatan Google Gemini untuk pembuatan soal otomatis, monitoring kecurangan real-time via WebSocket, dan portal multi-role (Guru, Siswa, Admin) — semuanya dalam satu aplikasi monolitik yang mudah di-deploy.


📑 Daftar Isi


✨ Fitur Utama

🎓 Portal Guru / Pendidik

Fitur Deskripsi
Dashboard Analitik Ringkasan statistik ujian, aktivitas terkini, dan overview performa kelas
Manajemen Ujian (CRUD) Buat, edit, hapus, duplikat, jadwalkan, mulai/hentikan ujian
AI ExamMaker Generate soal pilihan ganda otomatis menggunakan Google Gemini AI
AI Question Polish Sempurnakan tata bahasa dan opsi pengecoh soal via AI
Live Monitor Pantau aktivitas siswa secara real-time: progres, status, pelanggaran
Laporan & Analisis Rekap nilai per ujian, per siswa, distribusi skor, dan detail jawaban
Kontrol Kecurangan 9 parameter proteksi kecurangan yang dapat dikonfigurasi per ujian

👨‍🎓 Portal Siswa

Fitur Deskripsi
Daftar Ujian Lihat ujian yang tersedia, terjadwal, dan riwayat ujian
Verifikasi Password Akses ujian terkunci dengan sandi yang diberikan guru
Pengerjaan Ujian Interface ujian fullscreen dengan timer, navigasi soal, dan auto-save
Anti-Cheat Client Deteksi tab-switch, blokir copy-paste, keyboard shortcuts, & kamera
Submit & Skor Pengumpulan otomatis dengan kalkulasi nilai instan

🛠️ Sistem

Fitur Deskripsi
Multi-Role Auth JWT + HTTP-only cookie untuk guru, siswa, dan admin
Real-time Sync Socket.io untuk live monitoring dan notifikasi
RESTful API 10 domain endpoint terstruktur rapi
Persistent Data PostgreSQL + Prisma ORM dengan schema yang teroptimasi

🏗️ Arsitektur

┌─────────────────────────────────────────────────────────┐
│                      CLIENT (Browser)                    │
│  ┌────────────┐  ┌──────────────┐  ┌──────────────────┐ │
│  │ Landing &  │  │  Portal Guru │  │  Portal Siswa    │ │
│  │ Login Page │  │  (Dashboard, │  │  (Ujian,         │ │
│  │            │  │   Monitor,   │  │   Pengerjaan,    │ │
│  │            │  │   Reports)   │  │   Riwayat)       │ │
│  └────────────┘  └──────────────┘  └──────────────────┘ │
│        React 19 + TailwindCSS 4 + Motion + Lucide       │
└──────────────┬──────────────────────┬───────────────────┘
               │ REST API (fetch)     │ WebSocket
               ▼                      ▼
┌─────────────────────────────────────────────────────────┐
│                   SERVER (Express.ts)                     │
│  ┌──────────┐  ┌───────────┐  ┌──────────────────────┐  │
│  │ Auth     │  │ API       │  │ Socket.io            │  │
│  │ (JWT +   │  │ Routes    │  │ (Live Monitor,       │  │
│  │  Cookie) │  │ (10 mods) │  │  Anti-Cheat Events)  │  │
│  └──────────┘  └───────────┘  └──────────────────────┘  │
│  ┌──────────────────────┐  ┌──────────────────────────┐  │
│  │ Gemini AI Service    │  │ Prisma ORM              │  │
│  │ (Generate & Polish)  │  │ (Query Builder)         │  │
│  └──────────┬───────────┘  └────────────┬─────────────┘  │
└─────────────┼───────────────────────────┼────────────────┘
              ▼                           ▼
    ┌──────────────────┐      ┌──────────────────────┐
    │  Google Gemini   │      │    PostgreSQL         │
    │  3.5 Flash API   │      │    Database           │
    └──────────────────┘      └──────────────────────┘

Monolith Architecture — Frontend (Vite + React) dan Backend (Express) dijalankan dalam satu proses Node.js. Pada development, Vite berjalan sebagai middleware. Pada produksi, frontend di-build menjadi static files yang dilayani oleh Express.


🛠️ Tech Stack

Layer Teknologi
Frontend React 19, TypeScript 5.8, TailwindCSS 4, Motion (Framer Motion), Lucide Icons
Backend Express 4, TypeScript, Socket.io 4, Zod (validasi)
Database PostgreSQL + Prisma 5 ORM
AI Google Gemini 3.5 Flash (@google/genai)
Auth JWT (jsonwebtoken) + bcryptjs + HTTP-only Cookies
Build Vite 6 (frontend) + esbuild (backend)
Runtime Node.js 20+, tsx (dev)

📋 Prasyarat

Pastikan tools berikut sudah terinstal di sistem Anda:

Tool Versi Minimum Unduh
Node.js v20.0+ nodejs.org
npm v10.0+ Termasuk dalam Node.js
PostgreSQL v14+ postgresql.org
Git Terbaru git-scm.com

Opsional: Prisma Studio akan tersedia via npm run db:studio untuk visual database explorer.


🚀 Instalasi & Setup

Quick Start (Satu Perintah)

# Clone repository
git clone <repository-url>
cd examhub-portal-pendidik

# Setup otomatis: install deps → generate Prisma → push schema → seed data
npm run setup

Manual Step-by-Step

# 1. Clone dan masuk ke direktori project
git clone <repository-url>
cd examhub-portal-pendidik

# 2. Install dependensi
npm install

# 3. Salin file konfigurasi environment
cp .env.example .env
# Edit .env dan sesuaikan DATABASE_URL serta secret keys

# 4. Generate Prisma Client
npm run db:generate

# 5. Push schema ke database PostgreSQL
npm run db:push

# 6. Seed data demo (akun guru, siswa, ujian contoh)
npm run db:seed

# 7. Jalankan development server
npm run dev

Aplikasi akan berjalan di http://localhost:3000 🚀


⚙️ Konfigurasi Environment

Salin .env.example menjadi .env dan sesuaikan nilainya:

# --- AI (Google Gemini) ---
# Opsional — tanpa API key, sistem akan menggunakan fallback simulasi
GEMINI_API_KEY="your_gemini_api_key_here"
APP_URL="http://localhost:3000"

# --- DATABASE (PostgreSQL) ---
DATABASE_URL="postgresql://USER:PASSWORD@HOST:PORT/DATABASE?schema=public"

# --- AUTH (JWT + Cookie) ---
JWT_SECRET="minimal_64_karakter_secret_key_yang_aman_untuk_produksi"
JWT_EXPIRES_IN="7d"
COOKIE_SECRET="minimal_32_karakter_cookie_secret"

# --- APP ---
NODE_ENV="development"
PORT=3000
Variable Wajib Deskripsi
GEMINI_API_KEY API key Google Gemini. Tanpa ini, fitur AI menggunakan fallback simulasi
DATABASE_URL Connection string PostgreSQL
JWT_SECRET Secret key untuk signing JWT token (min. 64 karakter)
JWT_EXPIRES_IN Masa berlaku token (default: 7d)
COOKIE_SECRET Secret key untuk signed cookies (min. 32 karakter)
PORT Port server (default: 3000)
NODE_ENV development atau production

🗄️ Database

Entity-Relationship Diagram

erDiagram
    User ||--o{ Exam : creates
    User ||--o{ ExamSession : takes
    User ||--o{ CheatLog : triggers
    User ||--o{ ActivityLog : generates

    Exam ||--o{ Question : contains
    Exam ||--o{ ExamClass : "available to"
    Exam ||--o{ ExamEligibility : "restricts"
    Exam ||--o{ ExamSession : hosts
    Exam ||--o{ ActivityLog : "logged in"

    ExamSession ||--o{ StudentAnswer : records
    ExamSession ||--o{ CheatLog : detects

    Question ||--o{ StudentAnswer : "answered by"

    User {
        string id PK
        string email UK
        string name
        enum role "TEACHER | STUDENT | ADMIN"
        string nisn UK
        string className
    }

    Exam {
        string id PK
        string title
        string subject
        enum status "DRAF | TERJADWAL | BERLANGSUNG | SELESAI"
        int durationMinutes
        datetime startTime
        datetime endTime
        boolean shuffleQuestions
        boolean detectTabSwitch
        boolean requireCamera
    }

    Question {
        string id PK
        string questionText
        json options
        string correctOption
        int orderIndex
    }

    ExamSession {
        string id PK
        int score
        int warningsCount
        boolean examLocked
        enum status "NORMAL | WARNING | CHEAT | SELESAI"
        json questionOrder
        json choiceOrders
    }
Loading

Model Database

Model Deskripsi
User Akun pengguna (guru, siswa, admin) dengan role-based access
Exam Data ujian lengkap: judul, jadwal, durasi, konfigurasi anti-cheat
Question Soal pilihan ganda (4 opsi A-D) terkait exam
ExamClass Relasi exam ↔ kelas yang berhak mengikuti
ExamEligibility Kontrol akses per-siswa untuk ujian tertentu
ExamSession Sesi pengerjaan siswa: skor, progress, status curang
StudentAnswer Jawaban siswa per-soal (auto-graded)
CheatLog Log pelanggaran: tab-switch, copy-paste, dll.
ActivityLog Riwayat aktivitas untuk audit trail

🧪 Akun Demo

Setelah menjalankan npm run db:seed, akun-akun berikut tersedia:

Role Email Password Catatan
🔑 Admin admin@examhub.id admin Akses penuh
👨‍🏫 Guru budi@examhub.id admin Budi Santoso, M.Pd
👩‍🏫 Guru sari@examhub.id admin Sari Wulandari, S.Pd
👨‍🎓 Siswa siswa1@examhub.id siswa Ahmad Rizqi (Kelas 12 MIPA 1)
👨‍🎓 Siswa siswa2@examhub.idsiswa10@examhub.id examhub123 9 siswa tambahan

Data demo mencakup 6 ujian (1 berlangsung, 3 terjadwal, 1 selesai, 1 draf) dengan soal lengkap di beberapa mata pelajaran.


📁 Struktur Direktori

examhub-portal-pendidik/
├── 📄 server.ts                  # Entry point: Express + Vite + Socket.io + Gemini AI
├── 📄 vite.config.ts             # Konfigurasi Vite (React, TailwindCSS)
├── 📄 tsconfig.json              # Konfigurasi TypeScript
├── 📄 package.json               # Dependensi & scripts
├── 📄 index.html                 # HTML template (SPA entry)
├── 📄 .env.example               # Template environment variables
│
├── 📂 src/                       # === FRONTEND (React) ===
│   ├── 📄 main.tsx               # React DOM render entry
│   ├── 📄 App.tsx                # Root component & routing logic
│   ├── 📄 index.css              # Global styles (TailwindCSS)
│   ├── 📄 types.ts               # TypeScript interfaces (Exam, Question, etc.)
│   ├── 📄 data.ts                # Initial/fallback data
│   │
│   ├── 📂 components/            # UI Components
│   │   ├── 📄 LandingPage.tsx    # Halaman landing publik
│   │   ├── 📄 LoginPage.tsx      # Halaman login (guru & siswa)
│   │   ├── 📄 DashboardView.tsx  # Dashboard guru: statistik & overview
│   │   ├── 📄 ExamListView.tsx   # Daftar & manajemen ujian
│   │   ├── 📄 UploadAiView.tsx   # AI ExamMaker: buat/edit soal
│   │   ├── 📄 LiveMonitorView.tsx# Monitoring ujian real-time
│   │   ├── 📄 ReportsView.tsx    # Laporan & analisis nilai
│   │   ├── 📄 StudentPortalView.tsx # Portal siswa: daftar & kerjakan ujian
│   │   ├── 📄 Sidebar.tsx        # Navigasi sidebar guru
│   │   └── 📄 Navbar.tsx         # Header navigasi
│   │
│   ├── 📂 context/
│   │   └── 📄 AuthContext.tsx    # React Context untuk autentikasi
│   │
│   ├── 📂 hooks/
│   │   └── 📄 useSocket.ts      # Custom hook Socket.io
│   │
│   └── 📂 services/
│       └── 📄 api.ts            # Centralized REST API client
│
├── 📂 backend/                   # === BACKEND ===
│   ├── 📂 prisma/
│   │   ├── 📄 schema.prisma     # Database schema (9 models, 4 enums)
│   │   └── 📄 seed.ts           # Demo data seeder
│   │
│   └── 📂 src/
│       ├── 📄 db.ts             # Prisma client singleton
│       │
│       ├── 📂 routes/           # Express route handlers
│       │   ├── 📄 auth.ts       # POST /login, /logout, GET /me
│       │   ├── 📄 exams.ts      # CRUD ujian + publish/start/stop/clone
│       │   ├── 📄 questions.ts  # CRUD soal + bulk import
│       │   ├── 📄 monitor.ts    # Live monitor: students, lock/unlock
│       │   ├── 📄 reports.ts    # Laporan: summary, detail, per-siswa
│       │   ├── 📄 student.ts    # Portal siswa: verify, start, answer, submit
│       │   ├── 📄 activities.ts # Activity log feed
│       │   ├── 📄 users.ts      # User management (admin)
│       │   ├── 📄 stats.ts      # Dashboard statistics
│       │   └── 📄 profile.ts    # Update profil & ganti password
│       │
│       ├── 📂 middleware/
│       │   ├── 📄 auth.ts       # JWT verification middleware
│       │   └── 📄 errorHandler.ts # Global error & 404 handler
│       │
│       ├── 📂 socket/
│       │   └── 📄 monitorSocket.ts # Socket.io server: auth, rooms, events
│       │
│       └── 📂 utils/            # Helper utilities
│
└── 📂 assets/                    # Static assets

🔌 API Reference

Semua endpoint berada di prefix /api. Autentikasi menggunakan HTTP-only cookie (examhub_token).

🔐 Auth (/api/auth)

Method Endpoint Deskripsi Auth
POST /api/auth/login Login guru/siswa → set cookie
POST /api/auth/logout Logout → clear cookie
GET /api/auth/me Ambil data user yang sedang login

📝 Exams (/api/exams)

Method Endpoint Deskripsi Auth
GET /api/exams List semua ujian milik guru
GET /api/exams/:id Detail ujian beserta soal
POST /api/exams Buat ujian baru (+ soal inline)
PUT /api/exams/:id Update ujian
DELETE /api/exams/:id Hapus ujian
POST /api/exams/:id/publish Publikasi draf → terjadwal
POST /api/exams/:id/start Mulai ujian → berlangsung
POST /api/exams/:id/stop Hentikan ujian → selesai
POST /api/exams/:id/clone Duplikat ujian

❓ Questions (/api/exams/:examId/questions)

Method Endpoint Deskripsi Auth
GET /api/exams/:examId/questions List soal pada ujian
POST /api/exams/:examId/questions Tambah satu soal
POST /api/exams/:examId/questions/bulk Bulk import soal
PUT /api/exams/:examId/questions/:qid Update soal
DELETE /api/exams/:examId/questions/:qid Hapus soal

👨‍🎓 Student Portal (/api/student)

Method Endpoint Deskripsi Auth
GET /api/student/exams Ujian yang tersedia untuk siswa
POST /api/student/exams/:id/verify Verifikasi password ujian
POST /api/student/exams/:id/start Mulai mengerjakan ujian
POST /api/student/exams/:id/answer Kirim jawaban soal
POST /api/student/exams/:id/submit Submit ujian → auto-grade
POST /api/student/exams/:id/warning Laporkan pelanggaran dari client
POST /api/student/exams/:id/heartbeat Heartbeat status aktif

📊 Monitor (/api/monitor)

Method Endpoint Deskripsi Auth
GET /api/monitor/:examId/students List siswa aktif dalam ujian
POST /api/monitor/:examId/lock/:studentId Kunci ujian siswa (curang)
POST /api/monitor/:examId/unlock/:studentId Buka kunci ujian siswa
POST /api/monitor/:examId/broadcast Broadcast pesan ke semua siswa

📈 Reports (/api/reports)

Method Endpoint Deskripsi Auth
GET /api/reports/exams/:examId Ringkasan laporan ujian
GET /api/reports/exams/:examId/students Daftar siswa + nilai
GET /api/reports/exams/:examId/students/:studentId Detail jawaban siswa

📊 Stats & Others

Method Endpoint Deskripsi Auth
GET /api/stats/dashboard Statistik dashboard guru
GET /api/stats/distribution Distribusi nilai per ujian/mapel
GET /api/stats/student Statistik siswa personal
GET /api/activities Feed aktivitas terkini
PUT /api/profile Update profil user
POST /api/profile/password Ganti password
GET /api/users List user (admin/guru)
POST /api/users Buat user baru
PUT /api/users/:id Update user
DELETE /api/users/:id Hapus user
GET /api/users/classes List kelas yang terdaftar
GET /api/health Health check server

🤖 Fitur AI (Gemini)

ExamHub mengintegrasikan Google Gemini 3.5 Flash untuk dua fitur utama:

1. AI ExamMaker — Generate Soal Otomatis

POST /api/generate-questions
{
  "promptText": "Revolusi Industri di Inggris abad ke-18",
  "numQuestions": 5,
  "mode": "ultimate",
  "difficulty": "HOTS"
}
Mode Deskripsi
pro Analisis dokumen/teks yang diunggah → generate soal dari konten
ultimate Generate soal dari topik bebas dengan tingkat kesulitan terkontrol
Difficulty Level
Mudah Teori mendasar, ingatan fakta langsung
Sedang Analitis konsep, sebab-akibat sederhana
Sulit Penalaran kritis, multi-variabel
HOTS Evaluasi, sintesis, logika kompleks

2. AI Question Polish — Sempurnakan Soal

POST /api/polish-question

Menyempurnakan tata bahasa, menghilangkan ambiguitas, dan meningkatkan kualitas opsi pengecoh agar lebih meyakinkan namun tetap memiliki satu kunci jawaban yang pasti benar.

Catatan: Jika GEMINI_API_KEY tidak dikonfigurasi, sistem secara otomatis menggunakan fallback simulasi dengan soal-soal berkualitas tinggi yang sudah terstruktur (Sejarah, Fisika, Biologi).


🛡️ Sistem Anti-Kecurangan

ExamHub menyediakan 9 parameter proteksi yang dapat dikonfigurasi secara independen per-ujian:

Parameter Deskripsi Default
shuffleQuestions Acak urutan soal per-siswa
shuffleChoices Acak urutan opsi jawaban per-soal
requireFullscreen Paksa mode fullscreen saat ujian
detectTabSwitch Deteksi dan catat perpindahan tab/window
blockRightClickAndCopy Blokir klik kanan dan salin teks
requireCamera Wajibkan akses kamera selama ujian
blockKeyboardShortcuts Blokir shortcut keyboard (Ctrl+C, dll.)
blockPaste Blokir operasi paste
blockSearchSelection Blokir seleksi teks untuk pencarian

Alur Deteksi Kecurangan

Siswa melanggar aturan
    ↓
Client mengirim POST /api/student/exams/:id/warning
    ↓
Server mencatat CheatLog + increment warningsCount
    ↓
Socket.io emit event ke monitor guru (real-time)
    ↓
Guru dapat LOCK ujian siswa dari Live Monitor
    ↓
Siswa yang di-lock tidak bisa melanjutkan ujian

📡 Real-time WebSocket

ExamHub menggunakan Socket.io untuk komunikasi real-time antara guru dan siswa:

Events

Event Arah Deskripsi
monitor_join Client → Server Guru bergabung ke room monitoring ujian
monitor_leave Client → Server Guru meninggalkan room monitoring
student_join_exam Client → Server Siswa mulai mengerjakan ujian
student_leave_exam Client → Server Siswa keluar dari ujian
student_update Server → Client Update status siswa (progres, pelanggaran)
exam_locked Server → Client Notifikasi ujian siswa dikunci
broadcast_message Server → Client Pesan dari guru ke semua siswa

Room System

  • exam:{examId} — Semua peserta (guru + siswa) dalam satu ujian
  • monitor:{examId} — Hanya guru yang memantau ujian
  • student:{userId} — Channel pribadi per-siswa

🏗️ Build & Deploy Produksi

Build

# Build frontend (Vite) + backend (esbuild)
npm run build

Hasilnya tersimpan di folder dist/:

  • dist/index.html + assets → Frontend SPA
  • dist/server.cjs → Backend Express (CommonJS bundle)

Jalankan Produksi

# Pastikan environment variables sudah diatur
npm start
# atau
cross-env NODE_ENV=production node dist/server.cjs

Deploy Checklist

  • Set NODE_ENV=production
  • Gunakan JWT_SECRET dan COOKIE_SECRET yang kuat dan unik
  • Konfigurasi DATABASE_URL ke PostgreSQL produksi
  • (Opsional) Set GEMINI_API_KEY untuk fitur AI
  • Jalankan npm run db:push di server produksi
  • Pertimbangkan reverse proxy (Nginx/Caddy) di depan Express

🧰 Perintah NPM

Perintah Deskripsi
npm run dev Jalankan development server (Express + Vite HMR)
npm run build Build produksi (frontend + backend)
npm start Jalankan server produksi
npm run clean Hapus folder build
npm run lint Type-check dengan TypeScript
npm run setup Setup lengkap: install → generate → push → seed
npm run db:generate Generate Prisma Client
npm run db:migrate Jalankan Prisma migrations
npm run db:push Push schema ke database (tanpa migration)
npm run db:seed Seed database dengan data demo
npm run db:reset Reset database (hapus semua data + re-seed)
npm run db:studio Buka Prisma Studio (visual DB explorer)

🤝 Kontribusi

  1. Fork repository ini
  2. Buat branch fitur: git checkout -b feat/fitur-baru
  3. Commit perubahan: git commit -m "feat: tambah fitur baru"
  4. Push ke branch: git push origin feat/fitur-baru
  5. Buat Pull Request

Konvensi Commit

feat:     Fitur baru
fix:      Perbaikan bug
docs:     Perubahan dokumentasi
style:    Formatting (tanpa perubahan kode)
refactor: Refactoring kode
test:     Menambah/memperbaiki test
chore:    Maintenance (build, deps, dll.)

ExamHub — Dibuat dengan ❤️ untuk pendidikan Indonesia yang lebih baik.

Powered by React, Express, PostgreSQL, Prisma, Socket.io & Google Gemini AI

About

ExamHub adalah platform manajemen ujian full-stack yang menggabungkan kecerdasan buatan Google Gemini untuk pembuatan soal otomatis, monitoring kecurangan real-time via WebSocket, dan portal multi-role (Guru, Siswa, Admin) — semuanya dalam satu aplikasi monolitik yang mudah di-deploy.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors