Error Handler

This commit is contained in:
202310715297 RAIHAN ARIQ MUZAKKI 2026-01-14 01:09:07 +07:00
parent be950a83da
commit 085ea807c9
4 changed files with 478 additions and 813 deletions

View File

@ -63,4 +63,5 @@ dependencies {
androidTestImplementation(libs.androidx.compose.ui.test.junit4) androidTestImplementation(libs.androidx.compose.ui.test.junit4)
debugImplementation(libs.androidx.compose.ui.tooling) debugImplementation(libs.androidx.compose.ui.tooling)
debugImplementation(libs.androidx.compose.ui.test.manifest) debugImplementation(libs.androidx.compose.ui.test.manifest)
} }

View File

@ -0,0 +1,92 @@
package id.ac.ubharajaya.sistemakademik
import androidx.compose.foundation.layout.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Lock
import androidx.compose.material.icons.filled.Warning
import androidx.compose.material.icons.filled.WifiOff
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
// 1. Tampilan Error Full Screen (Misal saat gagal load list)
@Composable
fun FullScreenErrorState(
message: String,
onRetry: () -> Unit,
modifier: Modifier = Modifier
) {
Column(
modifier = modifier.fillMaxSize().padding(32.dp),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Icon(
imageVector = if (message.contains("internet")) Icons.Default.WifiOff else Icons.Default.Warning,
contentDescription = null,
modifier = Modifier.size(64.dp),
tint = MaterialTheme.colorScheme.error
)
Spacer(modifier = Modifier.height(16.dp))
Text(
text = "Ups, Terjadi Masalah",
style = MaterialTheme.typography.titleLarge
)
Spacer(modifier = Modifier.height(8.dp))
Text(
text = message,
style = MaterialTheme.typography.bodyMedium,
textAlign = TextAlign.Center,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
Spacer(modifier = Modifier.height(24.dp))
Button(onClick = onRetry) {
Text("Coba Lagi")
}
}
}
// 2. Dialog Error (Misal saat gagal submit absen)
@Composable
fun ErrorDialog(
message: String,
onDismiss: () -> Unit
) {
AlertDialog(
onDismissRequest = onDismiss,
title = { Text("Gagal") },
text = { Text(message) },
confirmButton = {
TextButton(onClick = onDismiss) {
Text("OK")
}
},
icon = {
Icon(Icons.Default.Warning, contentDescription = null, tint = MaterialTheme.colorScheme.error)
}
)
}
// 3. Session Expired Dialog (Khusus Logout)
@Composable
fun SessionExpiredDialog(
onConfirm: () -> Unit
) {
AlertDialog(
onDismissRequest = {}, // Tidak bisa dicancel
title = { Text("Sesi Berakhir") },
text = { Text("Token akses Anda sudah kadaluarsa. Silakan login kembali untuk melanjutkan.") },
confirmButton = {
Button(onClick = onConfirm) {
Text("Login Ulang")
}
},
icon = {
Icon(Icons.Default.Lock, contentDescription = null)
}
)
}

View File

@ -0,0 +1,43 @@
package id.ac.ubharajaya.sistemakademik
import org.json.JSONObject
import java.net.ConnectException
import java.net.SocketTimeoutException
import java.net.UnknownHostException
object ErrorHandler {
// Menerjemahkan Exception Java ke Pesan Manusia
fun parseException(e: Exception): String {
return when (e) {
is UnknownHostException -> "🚫 Tidak ada koneksi internet. Periksa wifi/data Anda."
is SocketTimeoutException -> "⏳ Waktu habis. Server tidak merespons (Timeout)."
is ConnectException -> "🔌 Gagal terhubung ke server. Server mungkin sedang offline."
else -> "⚠️ Terjadi kesalahan: ${e.message}"
}
}
// Menerjemahkan Response Code HTTP
fun parseHttpError(responseCode: Int, errorBody: String): String {
// Coba ambil pesan error spesifik dari JSON server (jika ada)
val serverMessage = try {
val json = JSONObject(errorBody)
json.optString("error", "")
} catch (e: Exception) {
""
}
if (serverMessage.isNotEmpty()) return serverMessage
// Jika tidak ada pesan JSON, gunakan pesan default berdasarkan kode
return when (responseCode) {
400 -> "❌ Permintaan tidak valid (Bad Request)."
401 -> "🔒 Sesi telah berakhir. Silakan login kembali."
403 -> "⛔ Anda tidak memiliki akses ke fitur ini."
404 -> "🔍 Data atau alamat tidak ditemukan."
500 -> "🔥 Terjadi kesalahan internal pada server."
502, 503 -> "🚧 Server sedang dalam perbaikan (Maintenance)."
else -> "⚠️ Terjadi kesalahan (Kode: $responseCode)."
}
}
}