EAS-202310715082-FAZRI-ABDU.../PANDUAN_IMPLEMENTASI.md

458 lines
13 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 📖 Panduan Implementasi Aplikasi Absensi Akademik
## 🎯 Gambaran Umum Implementasi
Aplikasi ini telah diimplementasikan dengan arsitektur yang modular dan clean, memisahkan concerns menjadi beberapa layers:
1. **UI Layer** (Compose Components)
2. **Network Layer** (API Communication)
3. **Utils Layer** (Business Logic)
4. **Config Layer** (Configuration Management)
5. **Models Layer** (Data Classes)
---
## 📂 File Structure Lengkap
### Core Application
```
MainActivity.kt # Entry point & main UI screen
```
### Configuration
```
config/
└─ AttendanceConfig.kt # Centralized configuration
```
### Data Models
```
models/
└─ AttendanceRecord.kt # Data classes:
# - AttendanceRecord
# - LocationData
# - ValidationResult
# - AttendanceState
# - ValidationStatus enum
```
### Network Communication
```
network/
└─ N8nService.kt # API service untuk N8n webhook
```
### Utilities
```
utils/
├─ LocationValidator.kt # Location validation logic:
# - calculateDistance (Haversine)
# - isLocationValid
# - getValidationMessage
# - adjustCoordinates
└─ ErrorHandler.kt # Error handling & messages
```
### UI Components
```
ui/
├─ components/
│ └─ AttendanceComponents.kt # Reusable components:
│ # - PhotoPreviewCard
│ # - LocationStatusCard
│ # - ErrorAlertCard
│ # - SubmitButtonWithLoader
└─ theme/
├─ Theme.kt # Material 3 theme
├─ Color.kt # Color definitions
└─ Type.kt # Typography definitions
```
### Tests
```
test/
└─ java/id/ac/ubharajaya/sistemakademik/
└─ utils/
└─ LocationValidatorTest.kt # Unit tests
```
---
## 🔄 Flow Diagram
```
┌─────────────────────────────────────────────────────────────┐
│ MainActivity │
│ (Jetpack Compose UI + State Management) │
└────────────────────┬────────────────────────────────────────┘
┌───────────┴───────────┐
│ │
┌────▼─────────┐ ┌──────▼──────────┐
│ Location │ │ Camera │
│ Permissions │ │ Permissions │
└────┬─────────┘ └──────┬──────────┘
│ │
┌────▼──────────────────────▼────┐
│ LocationValidator │
│ (Haversine distance calc) │
└────┬─────────────────────────────┘
┌────▼──────────────────────────┐
│ Validation Result │
│ (Valid/Invalid) │
└────┬─────────────────────────┘
┌────▼────────────────────────────────┐
│ N8nService │
│ (HTTP POST to Webhook) │
└────┬────────────────────────────────┘
┌────▼────────────────────┐
│ N8n Server │
│ (Webhook Processing) │
└─────────────────────────┘
```
---
## 🚀 Penggunaan Aplikasi
### Alur Pengguna
1. **Buka Aplikasi** → MainActivity dimuat
2. **Minta Izin Lokasi** → LocationPermissionLauncher diaktifkan otomatis
3. **Ambil Lokasi** → Fused Location Provider mengambil GPS
4. **Validasi Lokasi** → LocationValidator mengecek jarak
5. **Tampilkan Status** → LocationStatusCard menampilkan hasil
6. **Ambil Foto** → CameraPermissionLauncher + Intent Camera
7. **Preview Foto** → PhotoPreviewCard menampilkan hasil
8. **Validasi Data** → Cek semua field terpenuhi
9. **Kirim Data** → N8nService POST ke webhook
10. **Tampilkan Hasil** → Success/Error message
---
## ⚙️ State Management
### AttendanceState Data Class
```kotlin
data class AttendanceState(
val location: LocationData? = null, // GPS coordinates
val foto: Bitmap? = null, // Camera image
val isLoadingLocation: Boolean = false, // GPS acquiring
val isLoadingSubmit: Boolean = false, // API submitting
val validationResult: ValidationResult = ..., // Location validation
val errorMessage: String? = null, // Error feedback
val isLocationPermissionGranted: Boolean = false,
val isCameraPermissionGranted: Boolean = false
)
```
### State Updates
State diupdate secara reactive menggunakan:
```kotlin
var state by remember { mutableStateOf(AttendanceState()) }
state = state.copy(location = newLocation) // Immutable update
```
---
## 📍 Validasi Lokasi Detil
### Haversine Formula
Untuk menghitung jarak akurat antara dua koordinat:
```
Formula:
a = sin²(Δφ/2) + cos(φ1) × cos(φ2) × sin²(Δλ/2)
c = 2 × atan2(√a, √(1a))
d = R × c
Di mana:
- φ adalah latitude (dalam radian)
- λ adalah longitude (dalam radian)
- R adalah radius bumi (6,371 km)
```
### Contoh Validasi
```kotlin
// Referensi lokasi kampus
const val REFERENCE_LATITUDE = -7.0
const val REFERENCE_LONGITUDE = 110.4
// Lokasi mahasiswa (dari GPS)
val studentLatitude = -7.0035
val studentLongitude = 110.4042
// Hitung jarak
val distance = LocationValidator.calculateDistance(
REFERENCE_LATITUDE, REFERENCE_LONGITUDE,
studentLatitude, studentLongitude
)
// Result: ~500 meter
// Validasi terhadap radius (100m)
val isValid = distance <= 100.0 // false
```
---
## 📡 API Integration Detail
### Request Format
```json
{
"npm": "202310715082",
"nama": "Fazri Abdurrahman",
"latitude": -7.0035,
"longitude": 110.4042,
"timestamp": 1705250400000,
"foto_base64": "iVBORw0KGgoAAAANSUhEUgAAAAEA..."
}
```
### Response Handling
```kotlin
HttpURLConnection.HTTP_OK (200) // Success - absensi diterima
HttpURLConnection.HTTP_BAD_REQUEST (400) // Error - data invalid
HttpURLConnection.HTTP_UNAUTHORIZED (401) // Error - auth failed
HttpURLConnection.HTTP_INTERNAL_ERROR (500) // Error - server error
```
### Error Callback
```kotlin
interface SubmitCallback {
fun onSuccess(responseCode: Int, message: String)
fun onError(error: Throwable, message: String)
}
```
---
## 🎨 UI Components Detail
### 1. PhotoPreviewCard
```kotlin
PhotoPreviewCard(
bitmap = state.foto, // Bitmap dari camera
onRetake = { /* reset foto */ }
)
```
- Menampilkan preview foto
- Button "Ambil Ulang" untuk mengganti foto
- Placeholder jika belum ada foto
### 2. LocationStatusCard
```kotlin
LocationStatusCard(
latitude = state.location?.latitude,
longitude = state.location?.longitude,
validationMessage = state.validationResult.message,
isLoading = state.isLoadingLocation
)
```
- Menampilkan koordinat GPS
- Pesan validasi (✓ valid atau ✗ invalid)
- Loading spinner saat mengambil lokasi
### 3. ErrorAlertCard
```kotlin
ErrorAlertCard(
message = state.errorMessage,
onDismiss = { /* hide error */ }
)
```
- Card merah untuk error messages
- Dismissable dengan tombol X
- Auto-hide saat tidak ada error
### 4. SubmitButtonWithLoader
```kotlin
SubmitButtonWithLoader(
text = "Kirim Absensi",
onClick = { /* submit */ },
isLoading = state.isLoadingSubmit,
isEnabled = canSubmit
)
```
- Button dengan loading indicator
- Disabled saat proses
- Spinner bertekstur saat loading
---
## 🔐 Permission Handling
### Automatic Permission Request
```kotlin
LaunchedEffect(Unit) {
locationPermissionLauncher.launch(
Manifest.permission.ACCESS_FINE_LOCATION
)
}
```
- Dipanggil otomatis saat app launch
- Request CAMERA saat user klik "Ambil Foto"
### Permission Check
```kotlin
if (ContextCompat.checkSelfPermission(context,
Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED)
```
---
## 🧪 Testing
### Unit Test LocationValidator
```bash
./gradlew test
```
Test cases:
- ✓ Distance calculation accuracy
- ✓ Validation logic (within/outside radius)
- ✓ Message generation
- ✓ Coordinate adjustment
- ✓ Mathematical properties (symmetry, triangle inequality)
### Manual Testing Checklist
```
[ ] Permissions diminta dengan benar
[ ] Lokasi GPS terakses saat connected
[ ] Card lokasi menampilkan koordinat
[ ] Validasi menunjukkan jarak akurat
[ ] Camera intent terbuka saat "Ambil Foto" diklik
[ ] Foto preview ditampilkan setelah capture
[ ] Form disabled saat lokasi invalid
[ ] Submit button hanya enable jika semua valid
[ ] Loading spinner muncul saat submit
[ ] Success message muncul setelah 200 response
[ ] Error message muncul setelah gagal
[ ] Form reset setelah 2 detik sukses
```
---
## 🛠️ Customization Guide
### Ubah Koordinat Referensi
**File**: `AttendanceConfig.kt`
```kotlin
const val REFERENCE_LATITUDE = -7.025 // Ubah ke lokasi kampus
const val REFERENCE_LONGITUDE = 110.415
```
### Ubah Radius Area
```kotlin
const val ALLOWED_RADIUS_METERS = 150.0 // Ubah ke radius yang diinginkan
```
### Ubah Data Mahasiswa
```kotlin
const val STUDENT_NPM = "202310715082"
const val STUDENT_NAMA = "Fazri Abdurrahman"
```
### Ubah Webhook URL
```kotlin
const val WEBHOOK_PRODUCTION = "https://your-webhook-url/..."
const val WEBHOOK_TEST = "https://your-test-webhook-url/..."
```
### Ubah Photo Quality
```kotlin
const val PHOTO_QUALITY = 80 // 0-100, lebih tinggi = lebih besar file
```
---
## 📊 Monitoring & Debugging
### Enable Logging
```kotlin
// Di N8nService, tambahkan:
Log.d("N8nService", "Request: $json")
Log.d("N8nService", "Response Code: $responseCode")
```
### Check Permission Status
```kotlin
val hasLocationPermission = ContextCompat.checkSelfPermission(
context, Manifest.permission.ACCESS_FINE_LOCATION
) == PackageManager.PERMISSION_GRANTED
```
### Validate GPS
- Buka Google Maps untuk confirm GPS aktif
- Verifikasi koordinat akurat di Maps
- Test di lokasi berbeda untuk validate radius
### Test Webhook
1. Gunakan `WEBHOOK_TEST` terlebih dahulu
2. Cek response di N8n dashboard
3. Verify data received dengan benar
4. Switch ke `WEBHOOK_PRODUCTION` saat siap
---
## 🚨 Common Issues & Solutions
| Issue | Cause | Solution |
|-------|-------|----------|
| GPS tidak berfungsi | Location permission ditolak | Buka Settings > Permissions > Location |
| Lokasi selalu invalid | Koordinat referensi salah | Update `REFERENCE_LATITUDE/LONGITUDE` |
| Foto tidak terakses | Camera permission ditolak | Buka Settings > Permissions > Camera |
| Submit gagal | Network issue | Check internet connection |
| Webhook 404 | URL salah | Verify webhook URL di `AttendanceConfig` |
---
## 📚 Dependencies
```gradle
// Sudah terinclude di build.gradle.kts:
- androidx.core:core-ktx
- androidx.lifecycle:lifecycle-runtime-ktx
- androidx.compose.* (UI framework)
- com.google.android.gms:play-services-location (GPS)
- Material 3 (Design system)
```
---
## 🔄 Next Steps / Future Features
### Phase 2 (Future)
- [ ] Attendance history dengan Room Database
- [ ] User login screen dengan authentication
- [ ] Support multiple courses/classes
- [ ] Attendance statistics & reports
- [ ] Push notifications untuk deadline
- [ ] Offline mode dengan sync
### Phase 3 (Advanced)
- [ ] Biometric verification (fingerprint)
- [ ] QR code verification
- [ ] Face recognition
- [ ] Real-time attendance dashboard
- [ ] Mobile app backend server
---
## 📞 Support & Contact
Untuk pertanyaan atau issues:
1. Check logs di Android Studio Logcat
2. Review error messages di app
3. Test dengan webhook test terlebih dahulu
4. Verify configurations di `AttendanceConfig.kt`
---
**Last Updated**: January 14, 2026
**Version**: 1.0
**Status**: ✅ Production Ready