CRUD tugas anak + validasi ortu + foto bukti
1. Executive Summary & Core Concept
Tujuan Modul: Sistem manajemen tugas harian + kuis edukatif berbasis AI + Otomatisasi Terjadwal (Scheduled AI Tasks). Ortu atur jadwal rutin, AI generate tugas/kuis otomatis tiap hari berdasarkan profil anak + skala kesulitan. Tanpa intervensi manual tiap hari.
Visual Mockup (Android Material 3):
2. Spesifikasi Teknis & Integrasi Sistem
3. Schema DB — Table Baru
3a. JadwalTugasAI
model JadwalTugasAI {
id String @id @default(cuid())
anakIds String // JSON array ["anak1","anak2"] — 1 jadwal bisa untuk multiple anak
ortuId String
tema String
kesulitan Int @default(3) // skala 1-5
jamKirim String // format HH:mm
hariAktif String @default('[1,2,3,4,5]') // ISO weekday: Senin-Jumat
rewardToken Int @default(10)
autoApprove Boolean @default(false)
aktif Boolean @default(false)
maxRetry Int @default(3) // max retry per hari per anak, 0 = unlimited
notifPref String @default('["ai_generate","anak_selesai","anak_buka"]') // ortu pilih notifikasi
lastRun DateTime?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([ortuId])
}
Catatan: 1 jadwal untuk multiple anak (anakIds = JSON array). Cron generate soal terpisah per anak (profil beda = soal beda), tapi 1 entry jadwal.
3b. Tugas
model Tugas {
id String @id @default(cuid())
anakId String
anak Anak @relation(fields: [anakId], references: [id], onDelete: Cascade)
ortuId String
judul String
deskripsi String @default("")
type String @default("manual") // manual | ai_quiz | ai_scheduled
soal String @default("[]") // JSON array soal untuk type ai_*
status String @default("pending") // pending | doing | done | approved | expired
rewardToken Int @default(0)
tokenDiklaim Int @default(0) // token yang sudah diklaim (berdasarkan skor terbaik)
jadwalId String?
waktuMulai DateTime? // saat anak buka tugas
waktuExpire DateTime? // waktuMulai + 24jam, auto-expire kalau tidak selesai
createdAt DateTime @default(now())
selesaiAt DateTime?
approvedAt DateTime?
@@index([anakId])
@@index([ortuId])
@@index([status])
}
3c. KuisSession
model KuisSession {
id String @id @default(cuid())
tugasId String
tugas Tugas @relation(fields: [tugasId], references: [id], onDelete: Cascade)
anakId String
urutanSoal String // JSON [3,1,5,2,4] shuffle index soal
urutanOpsi String // JSON [[2,0,3,1],...] shuffle opsi per soal
jawaban String @default("[]") // JSON [{soalIdx, opsiIdx}] locked saat dipilih
skor Int? // 0-100
benarCount Int?
totalSoal Int?
durasiDetik Int? // total waktu pengerjaan
status String @default("aktif") // aktif | selesai | reviewed
mulaiAt DateTime @default(now())
selesaiAt DateTime?
@@index([tugasId])
@@index([anakId])
}
4. Prompt Template (Gemini 2.5 Flash)
System: You are an educational quiz generator for children. Generate multiple-choice questions that are child-safe, age-appropriate, and contain NO violence, adult themes, or inappropriate content. Explanations must be simple enough for the target age to understand.
User: Generate [jumlah] multiple choice questions about [tema] for a [umur] year old student in [kelas], in [bahasa]. Difficulty level [1-5].
Difficulty guide:
Level 1: Simple recall, single-step, obvious answers.
Level 2: Basic application, single operation.
Level 3: Multi-step or word problems with context.
Level 4: Requires reasoning or combining concepts.
Level 5: Complex multi-step, advanced reasoning, near grade-level ceiling.
Return JSON array only, no markdown:
[
{
"question": "Sari punya 12 permen. Dia memberi 4 permen kepada Andi. Berapa permen Sari sekarang?",
"options": ["6", "8", "7", "9"],
"answer_index": 1,
"explanation": "12 - 4 = 8. Sari memberi 4 permen, jadi sisanya 8."
}
]
Safety: All content must be child-safe. No violence, adult themes, scary content, or inappropriate language.
Explanation: Must be simple enough for [umur] year old to understand. Use short sentences and concrete examples.
5. Fitur Utama & Actionable Checklist
A. Manajemen Tugas Manual (APK Ortu)
B. AI Quiz Generator (APK Ortu)
C. Scheduled AI Tasks [BARU]
D. Sisi Klien Anak (APK Anak)
6. Quiz Flow (Kuis Session)
6a. Mulai Kuis
6b. Lock Per-Soal
6c. Submit
6d. Review Mode
- Jawaban anak (benar = hijau, salah = merah)
- Jawaban benar (highlight)
- Pembahasan/explanation text dari Gemini (simple, age-appropriate)
6e. Retry & Token Balance
6f. Token & Approval
6g. Time Limit (Opsional)
7. Token & Reward Integration
8. Adaptive Difficulty (Opsional, Post-MVP)
9. Progress Tracking (Opsional, Post-MVP)
10. Streak & Gamification (Opsional, Post-MVP)
11. Tier Gating
12. Pitfall
13. Alur Cron
Setiap menit:
1. SELECT * FROM JadwalTugasAI WHERE aktif=true AND hariAktif contains today_weekday
2. Filter jamKirim = current HH:mm (timezone ortu)
3. Filter lastRun < today (sudah jalan hari ini? skip)
4. Untuk tiap jadwal:
a. Parse anakIds -> loop per anak
b. Fetch profil anak (tanggalLahir -> umur, kelas)
c. Call Gemini: generate soal berdasarkan tema + kesulitan + profil + bahasa
d. Validate output: parse JSON, cek answer_index valid, cek explanation ada
e. Content moderation: keyword filter + safety check
f. Dedup check: hash soal, skip kalau duplikat 30 hari
g. INSERT ke tabel Tugas (type: ai_scheduled, soal: JSON, rewardToken dari jadwal)
h. Update lastRun = now
i. Notifikasi push ke APK anak (FCM) — cek notifPref ortu
j. Notifikasi push ke APK ortu (info: AI generate tugas baru) — cek notifPref
5. Error handling: log + skip, jangan block jadwal lain
Tugas = pekerjaan rumah/aktivitas yang ortu assign ke anak.
Flow:
1. Ortu buat tugas (judul, deskripsi, tokenReward, deadline)
2. Anak lihat tugas PENDING
3. Anak kerjakan → kirim foto bukti → status DIKUMPULKAN
4. Ortu validasi: SELESAI (token masuk) atau DITOLAK
Status: PENDING → DIKUMPULKAN → SELESAI/DITOLAK
Model: Tugas — anakId, judul, deskripsi, tokenReward, fotoBuktiUrl, status, validasiOrtu, deadline
API:
GET /api/tugas — list semua tugas anak ortuPOST /api/tugas — buat tugasPATCH /api/tugas/[id] — validasi (selesai/tolak)App ortu: LayarTugas.kt — list tugas per anak, form buat, validasi foto
App anak: lihat tugas, kirim foto bukti
⚠ deadline field ada di model+API tapi belum dipakai di UI app ortu
⚠ Foto bukti: upload mechanism belum fully implemented di app anak