279 lines
6.5 KiB
Markdown
279 lines
6.5 KiB
Markdown
# 🎯 Fitur Mata Kuliah - Dokumentasi Lengkap
|
||
|
||
## 📋 Overview
|
||
|
||
Fitur **Mata Kuliah** telah ditambahkan pada halaman absensi untuk memungkinkan mahasiswa memilih mata kuliah yang sedang diambil saat melakukan absensi.
|
||
|
||
## ✨ Fitur Baru
|
||
|
||
### 1. **Mata Kuliah Field**
|
||
- **Lokasi**: AttendanceScreen, section "Mata Kuliah"
|
||
- **Tipe Input**: TextField dengan placeholder
|
||
- **Validasi**: Wajib diisi sebelum submit
|
||
|
||
```kotlin
|
||
OutlinedTextField(
|
||
value = mataPelajaran,
|
||
onValueChange = { mataPelajaran = it },
|
||
modifier = Modifier.fillMaxWidth().height(40.dp),
|
||
placeholder = { Text("Masukkan nama mata kuliah", fontSize = 12.sp) },
|
||
label = null,
|
||
singleLine = true,
|
||
enabled = !isLoading
|
||
)
|
||
```
|
||
|
||
### 2. **Submit Validation**
|
||
Sebelum absensi dikirim, sistem melakukan pengecekan:
|
||
|
||
```kotlin
|
||
if (mataPelajaran.isEmpty()) {
|
||
statusMessage = "⚠️ Harap masukkan nama mata kuliah terlebih dahulu"
|
||
return@Button
|
||
}
|
||
```
|
||
|
||
### 3. **Data Storage**
|
||
Mata kuliah disimpan dalam Attendance model:
|
||
|
||
```kotlin
|
||
val attendance = Attendance(
|
||
npm = npm,
|
||
nama = nama,
|
||
latitude = latitude!!,
|
||
longitude = longitude!!,
|
||
timestamp = System.currentTimeMillis(),
|
||
fotoBase64 = "",
|
||
mataPelajaran = mataPelajaran, // ← Mata Kuliah
|
||
status = "pending"
|
||
)
|
||
```
|
||
|
||
## 🎨 UI Design
|
||
|
||
### Mata Kuliah Section
|
||
```
|
||
┌─────────────────────────────┐
|
||
│ ℹ️ Mata Kuliah │
|
||
├─────────────────────────────┤
|
||
│ [Masukkan nama mata kuliah] │
|
||
└─────────────────────────────┘
|
||
```
|
||
|
||
### Design Principles
|
||
- **Icon**: Info icon (ℹ️) dengan warna hijau (#2E7D32)
|
||
- **Background**: Light green (#2E7D32 dengan alpha 10%)
|
||
- **Border**: Rounded corners (8dp)
|
||
- **Height**: 40dp (compact)
|
||
|
||
## 🔄 User Flow
|
||
|
||
### Sebelum Mata Kuliah
|
||
```
|
||
1. Ambil Lokasi ✓
|
||
2. Ambil Foto ✓
|
||
3. Klik KIRIM ABSENSI
|
||
↓ ERROR: "Lokasi harus valid"
|
||
```
|
||
|
||
### Sesudah Mata Kuliah (NEW)
|
||
```
|
||
1. Ambil Lokasi ✓
|
||
2. Ambil Foto ✓
|
||
3. Masukkan Mata Kuliah ✓
|
||
4. Klik KIRIM ABSENSI
|
||
↓ SUCCESS: Absensi terkirim
|
||
```
|
||
|
||
## 📱 Requirement Checklist
|
||
|
||
Sebelum submit absensi, semua ini harus terpenuhi:
|
||
|
||
- [x] Lokasi valid (dalam area absensi)
|
||
- [x] Foto selfie sudah diambil
|
||
- [x] **Mata Kuliah sudah diisi** ← NEW
|
||
- [x] Latitude dan Longitude tersedia
|
||
|
||
## 🗄️ Database Integration
|
||
|
||
### Attendance Table
|
||
```sql
|
||
CREATE TABLE attendance (
|
||
id INTEGER PRIMARY KEY,
|
||
npm TEXT,
|
||
nama TEXT,
|
||
latitude REAL,
|
||
longitude REAL,
|
||
timestamp INTEGER,
|
||
fotoBase64 TEXT,
|
||
mataPelajaran TEXT, -- ← NEW COLUMN
|
||
status TEXT
|
||
)
|
||
```
|
||
|
||
### Model Class
|
||
```kotlin
|
||
data class Attendance(
|
||
val npm: String,
|
||
val nama: String,
|
||
val latitude: Double,
|
||
val longitude: Double,
|
||
val timestamp: Long,
|
||
val fotoBase64: String,
|
||
val mataPelajaran: String, // ← NEW FIELD
|
||
val status: String
|
||
)
|
||
```
|
||
|
||
## 🔌 N8N Webhook Integration
|
||
|
||
Ketika absensi dikirim ke N8N, mata kuliah akan disertakan:
|
||
|
||
```json
|
||
{
|
||
"npm": "2401061140",
|
||
"nama": "Budi",
|
||
"latitude": -6.8955,
|
||
"longitude": 107.6105,
|
||
"timestamp": 1705334400000,
|
||
"fotoBase64": "...",
|
||
"mataPelajaran": "Pemrograman Mobile",
|
||
"status": "pending"
|
||
}
|
||
```
|
||
|
||
## 💾 Data Persistence
|
||
|
||
Mata kuliah disimpan di:
|
||
1. **Local Database** (Room Database)
|
||
2. **N8N Server** (via webhook)
|
||
3. **Cloud Storage** (jika ada)
|
||
|
||
### Reset Setelah Submit
|
||
```kotlin
|
||
repository.sendToN8n(
|
||
onSuccess = {
|
||
isLoading = false
|
||
statusMessage = "✓ Absensi berhasil dikirim!"
|
||
foto = null
|
||
mataPelajaran = "" // ← Reset field
|
||
},
|
||
// ...
|
||
)
|
||
```
|
||
|
||
## 🧪 Testing
|
||
|
||
### Test Case 1: Submit Tanpa Mata Kuliah
|
||
```
|
||
1. Buka AttendanceScreen
|
||
2. Ambil Lokasi ✓
|
||
3. Ambil Foto ✓
|
||
4. Klik KIRIM ABSENSI (tanpa isi mata kuliah)
|
||
✅ Expected: Error message "Harap masukkan nama mata kuliah"
|
||
```
|
||
|
||
### Test Case 2: Submit Dengan Mata Kuliah
|
||
```
|
||
1. Buka AttendanceScreen
|
||
2. Ambil Lokasi ✓
|
||
3. Ambil Foto ✓
|
||
4. Isi Mata Kuliah: "Pemrograman Mobile"
|
||
5. Klik KIRIM ABSENSI
|
||
✅ Expected: Absensi terkirim dengan mata kuliah tersimpan
|
||
```
|
||
|
||
### Test Case 3: Clear Field Setelah Submit
|
||
```
|
||
1. Submit absensi dengan mata kuliah
|
||
2. Lihat SuccessScreen
|
||
3. Kembali ke AbsensiScreen
|
||
✅ Expected: Mata kuliah field kosong (reset)
|
||
```
|
||
|
||
## 🎓 Contoh Mata Kuliah
|
||
|
||
Beberapa contoh mata kuliah yang mungkin dimasukkan:
|
||
- Pemrograman Mobile
|
||
- Pemrograman Web
|
||
- Database
|
||
- Algoritma & Struktur Data
|
||
- Software Engineering
|
||
- UI/UX Design
|
||
- Cloud Computing
|
||
- Machine Learning
|
||
- Cybersecurity
|
||
- Game Development
|
||
|
||
## 🔗 Related Components
|
||
|
||
### AttendanceScreen
|
||
- Location validation
|
||
- Photo capture
|
||
- **Mata Kuliah input** ← NEW
|
||
- Submit handler
|
||
|
||
### Attendance Model
|
||
```kotlin
|
||
data class Attendance(
|
||
val npm: String,
|
||
val nama: String,
|
||
val latitude: Double,
|
||
val longitude: Double,
|
||
val timestamp: Long,
|
||
val fotoBase64: String,
|
||
val mataPelajaran: String, // NEW
|
||
val status: String
|
||
)
|
||
```
|
||
|
||
### AttendanceRepository
|
||
```kotlin
|
||
fun sendToN8n(
|
||
onSuccess: () -> Unit,
|
||
onError: (String) -> Unit,
|
||
attendance: Attendance, // Include mataPelajaran
|
||
foto: Bitmap
|
||
)
|
||
```
|
||
|
||
## 📊 Future Enhancements
|
||
|
||
### Possible Improvements
|
||
- [ ] Dropdown list dengan mata kuliah yang tersedia
|
||
- [ ] Auto-complete dari database
|
||
- [ ] Validasi format mata kuliah
|
||
- [ ] Tampilkan mata kuliah yang sedang diambil dari API
|
||
- [ ] History mata kuliah yang pernah diambil
|
||
- [ ] QR code untuk scanning kode mata kuliah
|
||
|
||
## ⚠️ Important Notes
|
||
|
||
1. **Validasi Client-Side**: Mata kuliah harus non-empty
|
||
2. **Validasi Server-Side**: N8N bisa menambahkan validasi tambahan
|
||
3. **Case Sensitive**: Nama mata kuliah dikirim apa adanya (case sensitive)
|
||
4. **Length**: Tidak ada limit panjang nama, tapi ideally < 100 char
|
||
5. **Special Characters**: Diizinkan (no SQL injection risk, sudah di-sanitize)
|
||
|
||
## 🐛 Troubleshooting
|
||
|
||
### Q: Mata kuliah tidak tersimpan
|
||
**A**: Pastikan:
|
||
- Field tidak kosong saat klik KIRIM ABSENSI
|
||
- Network connection aktif
|
||
- Server N8N berjalan
|
||
|
||
### Q: Field mata kuliah tidak reset setelah submit
|
||
**A**: Cek apakah `onSuccess` callback di-trigger dengan benar
|
||
|
||
### Q: Tampilkan mata kuliah yang dipilih sebelumnya
|
||
**A**: Feature ini bisa ditambahkan dengan menyimpan last input ke preferences
|
||
|
||
## 📚 Documentation Links
|
||
|
||
- [AttendanceScreen Implementation](./UI_IMPLEMENTATION_SUMMARY.md)
|
||
- [Location Testing Guide](./LOCATION_TESTING_GUIDE.md)
|
||
- [N8N Integration](./N8N_WEBHOOK_GUIDE.md)
|
||
- [Database Schema](./MASTER_SUMMARY.md)
|
||
|