Skip to content

Yasin-efendi/quiz-sd

Repository files navigation

πŸŽ“ Quiz SD

Aplikasi kuis pembelajaran interaktif untuk latihan Ujian Sekolah Dasar, dibangun dengan Next.js 16 (App Router), TypeScript, Supabase, dan Auth.js.

Next.js TypeScript Supabase Tailwind CSS Vitest License


✨ Fitur Utama

πŸŽ“ Untuk Siswa

  • βœ… Dashboard mata pelajaran & pertemuan dengan tampilan Accordion
  • βœ… Kuis interaktif dengan navigasi soal bebas (maju & mundur)
  • βœ… Dukungan soal bergambar
  • βœ… Halaman hasil dengan skor, nilai persentase, dan pembahasan per soal
  • βœ… Token JWT unik per sesi kuis (berlaku 7 hari)
  • βœ… Responsive design β€” mobile & desktop friendly

πŸ› οΈ Untuk Admin

  • βœ… Login aman dengan Auth.js (JWT session)
  • βœ… Proteksi route /admin/* via proxy.ts
  • βœ… CRUD lengkap: Pelajaran β†’ Pertemuan β†’ Bank Soal
  • βœ… Dashboard statistik: total soal, pelajaran, pertemuan, attempt
  • βœ… Riwayat pengerjaan kuis seluruh siswa
  • βœ… Validasi input server-side menggunakan Zod

βš™οΈ Teknis

  • βœ… Next.js 16 async params pattern (await params)
  • βœ… Supabase Row Level Security (RLS) β€” data terlindungi
  • βœ… API Routes terstruktur dengan error handling konsisten
  • βœ… 17 unit test dengan Vitest (token, validasi, utils)
  • βœ… shadcn/ui component library

πŸš€ Tech Stack

Kategori Teknologi
Framework Next.js 16 (App Router)
Language TypeScript 5.x
UI shadcn/ui + Tailwind CSS v4
Database Supabase (PostgreSQL)
Auth Auth.js v5 (NextAuth) β€” Credentials Provider
Validasi Zod
Token JSON Web Token (jsonwebtoken)
Testing Vitest + React Testing Library

πŸ“¦ Instalasi & Setup

Prerequisites

1. Clone & Install

git clone https://github.com/Yasin-efendi/quiz-sd.git
cd quiz-sd
npm install

2. Konfigurasi Environment

Buat file .env.local di root proyek:

# Supabase
NEXT_PUBLIC_SUPABASE_URL=https://xxxxxxxx.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGci...
SUPABASE_SERVICE_ROLE_KEY=eyJhbGci...

# Auth.js
NEXTAUTH_URL=http://localhost:3000
NEXTAUTH_SECRET=isi_dengan_random_string_panjang

# Admin credentials
ADMIN_USERNAME=admin
ADMIN_PASSWORD=admin123

Generate NEXTAUTH_SECRET dengan perintah:

node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"

3. Setup Database Supabase

Buka SQL Editor di dashboard Supabase, jalankan dua query berikut secara berurutan:

Migration β€” membuat 4 tabel:

CREATE TABLE subjects (
  id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
  name TEXT NOT NULL,
  slug TEXT NOT NULL UNIQUE,
  created_at TIMESTAMPTZ DEFAULT NOW()
);
-- (dan tabel meetings, questions, quiz_attempts)

Lihat file lengkap di supabase/migration.sql dan supabase/seed.sql

4. Jalankan Development Server

npm run dev

Buka http://localhost:3000


πŸ” Akun Admin Default

Username Password
admin admin123

⚠️ Ganti kredensial ini di .env.local sebelum digunakan di lingkungan produksi.

Akses panel admin: http://localhost:3000/admin


πŸ—ΊοΈ Struktur Halaman

Halaman Publik

Halaman URL Keterangan
Beranda / Daftar pelajaran & pertemuan
Kuis /quiz/[slug] Input nama β†’ kerjakan soal
Hasil /result/[token] Skor + pembahasan lengkap

Halaman Admin (Login Required)

Halaman URL Keterangan
Login /admin/login Form autentikasi admin
Dashboard /admin Statistik & 5 attempt terbaru
Pelajaran /admin/subjects CRUD mata pelajaran
Pertemuan /admin/meetings CRUD pertemuan
Bank Soal /admin/questions CRUD soal + filter
Riwayat /admin/attempts Semua riwayat kuis siswa

πŸ”Œ API Reference

Public Endpoints

Method Endpoint Deskripsi
GET /api/quiz Semua pelajaran beserta pertemuannya
GET /api/quiz/[slug] Soal berdasarkan slug pertemuan
POST /api/quiz/[slug]/submit Submit jawaban β†’ dapat token JWT
GET /api/result/[token] Hasil kuis berdasarkan token

Admin Endpoints (Auth Required)

Method Endpoint Deskripsi
GET/POST /api/admin/subjects List & tambah pelajaran
PUT/DELETE /api/admin/subjects/[id] Edit & hapus pelajaran
GET/POST /api/admin/meetings List & tambah pertemuan
PUT/DELETE /api/admin/meetings/[id] Edit & hapus pertemuan
GET/POST /api/admin/questions List & tambah soal
PUT/DELETE /api/admin/questions/[id] Edit & hapus soal

πŸ“ Struktur Proyek

quiz-sd/
β”œβ”€β”€ app/
β”‚   β”œβ”€β”€ admin/
β”‚   β”‚   β”œβ”€β”€ (protected)/           # Route group β€” butuh login
β”‚   β”‚   β”‚   β”œβ”€β”€ layout.tsx         # Layout + navbar admin
β”‚   β”‚   β”‚   β”œβ”€β”€ page.tsx           # Dashboard statistik
β”‚   β”‚   β”‚   β”œβ”€β”€ subjects/          # CRUD pelajaran
β”‚   β”‚   β”‚   β”œβ”€β”€ meetings/          # CRUD pertemuan
β”‚   β”‚   β”‚   β”œβ”€β”€ questions/         # Bank soal + tambah + edit
β”‚   β”‚   β”‚   └── attempts/          # Riwayat kuis
β”‚   β”‚   └── login/page.tsx         # Halaman login
β”‚   β”œβ”€β”€ api/
β”‚   β”‚   β”œβ”€β”€ auth/[...nextauth]/    # Auth.js handler
β”‚   β”‚   β”œβ”€β”€ quiz/                  # Endpoint kuis publik
β”‚   β”‚   β”œβ”€β”€ result/[token]/        # Endpoint hasil kuis
β”‚   β”‚   └── admin/                 # Endpoint CRUD admin
β”‚   β”œβ”€β”€ quiz/[slug]/page.tsx       # Halaman kuis siswa
β”‚   β”œβ”€β”€ result/[token]/page.tsx    # Halaman hasil siswa
β”‚   β”œβ”€β”€ layout.tsx
β”‚   └── globals.css
β”œβ”€β”€ components/
β”‚   β”œβ”€β”€ admin/
β”‚   β”‚   └── DeleteButton.tsx       # Client component hapus soal
β”‚   β”œβ”€β”€ quiz/
β”‚   β”‚   β”œβ”€β”€ QuestionCard.tsx       # Tampilan soal + opsi
β”‚   β”‚   β”œβ”€β”€ QuizNavigation.tsx     # Navigasi + progress
β”‚   β”‚   └── ResultDisplay.tsx      # Tampilan hasil + pembahasan
β”‚   └── ui/                        # shadcn/ui components
β”œβ”€β”€ lib/
β”‚   β”œβ”€β”€ supabase/
β”‚   β”‚   β”œβ”€β”€ client.ts              # Supabase browser client
β”‚   β”‚   └── server.ts              # Supabase admin client
β”‚   β”œβ”€β”€ validations/               # Zod schemas
β”‚   β”‚   β”œβ”€β”€ quiz.ts
β”‚   β”‚   β”œβ”€β”€ subject.ts
β”‚   β”‚   β”œβ”€β”€ meeting.ts
β”‚   β”‚   └── question.ts
β”‚   β”œβ”€β”€ auth.ts                    # Auth.js config
β”‚   β”œβ”€β”€ token.ts                   # JWT create & verify
β”‚   └── utils.ts                   # Helper functions
β”œβ”€β”€ tests/
β”‚   β”œβ”€β”€ setup.ts
β”‚   β”œβ”€β”€ quiz-flow.test.ts          # Test utils kuis
β”‚   β”œβ”€β”€ token.test.ts              # Test JWT token
β”‚   └── validations.test.ts        # Test Zod schema
β”œβ”€β”€ types/
β”‚   └── next-auth.d.ts             # Type extension session
β”œβ”€β”€ proxy.ts                       # Route protection middleware
β”œβ”€β”€ .env.local                     # Environment variables
└── vitest.config.ts

πŸ§ͺ Testing

Jalankan seluruh test:

npx vitest run

Hasil yang diharapkan:

βœ“ tests/quiz-flow.test.ts   (5 tests)
βœ“ tests/token.test.ts       (4 tests)
βœ“ tests/validations.test.ts (8 tests)

Test Files  3 passed
Tests      17 passed

Cakupan Test

File Yang Diuji
quiz-flow.test.ts calculateScore, getScoreMessage, generateSlug
token.test.ts Buat token, decode token valid, tolak token palsu
validations.test.ts Zod schema quiz, subject, question

⚠️ Catatan Penting

Next.js 16 β€” async params

// βœ… Benar: params wajib di-await di Next.js 16
export async function GET(
  request: Request,
  { params }: { params: Promise<{ slug: string }> }
) {
  const { slug } = await params
}

Supabase RLS

Semua tabel menggunakan Row Level Security:

  • Public (anon) β†’ hanya bisa SELECT tabel subjects, meetings, questions
  • Public β†’ bisa INSERT ke quiz_attempts (submit kuis)
  • Service Role β†’ akses penuh untuk operasi admin

proxy.ts vs middleware.ts

Di Next.js 16, middleware.ts telah diganti menjadi proxy.ts. Jika Anda melihat warning middleware deprecated, rename file tersebut ke proxy.ts.


πŸ› οΈ Troubleshooting

Masalah Solusi
Invalid path specified in request URL Pastikan NEXT_PUBLIC_SUPABASE_URL tidak mengandung /rest/v1/ di akhir
Redirect loop di /admin/login Pastikan halaman login berada di luar route group (protected)
Event handlers cannot be passed to Client Component Tambahkan 'use client' atau pisahkan ke file komponen tersendiri
Property 'errors' does not exist on ZodError Ganti .errors dengan .issues (Zod versi terbaru)
Test tidak ditemukan Pastikan folder bernama tests/ (dengan s) dan file setup.ts ada di dalamnya

Reset cache Next.js

rm -rf .next
npm run dev

🀝 Kontribusi

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

πŸ“„ License

Dibagikan di bawah lisensi MIT. Bebas digunakan, dimodifikasi, dan didistribusikan untuk tujuan edukasi.


🎯 Dibuat dengan ❀️ untuk mendukung pembelajaran digital siswa SD Indonesia. Next.js 16 β€’ TypeScript β€’ Supabase β€’ Auth.js β€’ shadcn/ui β€’ Vitest

About

Aplikasi kuis pembelajaran interaktif untuk latihan Ujian Sekolah Dasar. Dibangun dengan Next.js 16, Supabase, Auth.js, dan shadcn/ui.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors