diff --git a/app/src/main/java/id/ac/ubharajaya/sistemakademik/data/MataKuliah.kt b/app/src/main/java/id/ac/ubharajaya/sistemakademik/data/MataKuliah.kt
index dd00b9c..d994df2 100644
--- a/app/src/main/java/id/ac/ubharajaya/sistemakademik/data/MataKuliah.kt
+++ b/app/src/main/java/id/ac/ubharajaya/sistemakademik/data/MataKuliah.kt
@@ -1,2 +1,6 @@
package id.ac.ubharajaya.sistemakademik.data
+data class MataKuliah(
+ val kode: String,
+ val nama: String
+)
\ No newline at end of file
diff --git a/app/src/main/java/id/ac/ubharajaya/sistemakademik/data/UserProfile.kt b/app/src/main/java/id/ac/ubharajaya/sistemakademik/data/UserProfile.kt
index ac88714..d83b19c 100644
--- a/app/src/main/java/id/ac/ubharajaya/sistemakademik/data/UserProfile.kt
+++ b/app/src/main/java/id/ac/ubharajaya/sistemakademik/data/UserProfile.kt
@@ -11,6 +11,12 @@ data class AbsensiData(
val longitude: Double,
val timestamp: Long,
val fotoBase64: String,
+
+ // 🔽 FIELD BARU (WAJIB DITARUH SEBELUM DEFAULT VALUE)
+ val kodeMatkul: String,
+ val namaMatkul: String,
+
+ // 🔽 FIELD DENGAN DEFAULT VALUE HARUS PALING BAWAH
val alamat: String = "Alamat tidak tersedia"
)
diff --git a/app/src/main/java/id/ac/ubharajaya/sistemakademik/ui/fragments/AbsensiFragment.kt b/app/src/main/java/id/ac/ubharajaya/sistemakademik/ui/fragments/AbsensiFragment.kt
index af8bbb3..608cb32 100644
--- a/app/src/main/java/id/ac/ubharajaya/sistemakademik/ui/fragments/AbsensiFragment.kt
+++ b/app/src/main/java/id/ac/ubharajaya/sistemakademik/ui/fragments/AbsensiFragment.kt
@@ -11,10 +11,7 @@ import android.util.Base64
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
-import android.widget.Button
-import android.widget.ImageView
-import android.widget.TextView
-import android.widget.Toast
+import android.widget.*
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
@@ -23,6 +20,8 @@ import com.google.android.gms.location.LocationServices
import id.ac.ubharajaya.sistemakademik.R
import id.ac.ubharajaya.sistemakademik.data.AbsensiData
import id.ac.ubharajaya.sistemakademik.data.DataHolder
+import id.ac.ubharajaya.sistemakademik.data.MataKuliah
+import id.ac.ubharajaya.sistemakademik.utils.DummyData
import java.io.ByteArrayOutputStream
class AbsensiFragment : Fragment() {
@@ -31,59 +30,48 @@ class AbsensiFragment : Fragment() {
private lateinit var tvLokasi: TextView
private lateinit var btnAmbilFoto: Button
private lateinit var btnLanjut: Button
+ private lateinit var spinnerMatkul: Spinner
private var foto: Bitmap? = null
private var latitude: Double? = null
private var longitude: Double? = null
+ private var selectedMatkul: MataKuliah? = null
private val fusedLocationClient by lazy {
LocationServices.getFusedLocationProviderClient(requireActivity())
}
- // Permission launcher untuk lokasi
- private val locationPermissionLauncher = registerForActivityResult(
- ActivityResultContracts.RequestPermission()
- ) { granted ->
- if (granted) {
- ambilLokasiGPS()
- } else {
- Toast.makeText(context, "Izin lokasi ditolak", Toast.LENGTH_SHORT).show()
+ // ===== Permission Launcher =====
+ private val locationPermissionLauncher =
+ registerForActivityResult(ActivityResultContracts.RequestPermission()) { granted ->
+ if (granted) ambilLokasiGPS()
+ else Toast.makeText(context, "Izin lokasi ditolak", Toast.LENGTH_SHORT).show()
}
- }
- // Camera launcher
- private val cameraLauncher = registerForActivityResult(
- ActivityResultContracts.StartActivityForResult()
- ) { result ->
- if (result.resultCode == Activity.RESULT_OK) {
- val bitmap = result.data?.extras?.get("data") as? Bitmap
- if (bitmap != null) {
- foto = bitmap
- ivPreview.setImageBitmap(bitmap)
- cekKelengkapanData()
- Toast.makeText(context, "Foto berhasil diambil!", Toast.LENGTH_SHORT).show()
+ private val cameraPermissionLauncher =
+ registerForActivityResult(ActivityResultContracts.RequestPermission()) { granted ->
+ if (granted) bukaKamera()
+ else Toast.makeText(context, "Izin kamera ditolak", Toast.LENGTH_SHORT).show()
+ }
+
+ private val cameraLauncher =
+ registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
+ if (result.resultCode == Activity.RESULT_OK) {
+ val bitmap = result.data?.extras?.get("data") as? Bitmap
+ bitmap?.let {
+ foto = it
+ ivPreview.setImageBitmap(it)
+ cekKelengkapanData()
+ Toast.makeText(context, "Foto berhasil diambil!", Toast.LENGTH_SHORT).show()
+ }
}
}
- }
-
- // Permission launcher untuk kamera
- private val cameraPermissionLauncher = registerForActivityResult(
- ActivityResultContracts.RequestPermission()
- ) { granted ->
- if (granted) {
- bukaKamera()
- } else {
- Toast.makeText(context, "Izin kamera ditolak", Toast.LENGTH_SHORT).show()
- }
- }
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
- ): View? {
- return inflater.inflate(R.layout.fragment_absensi, container, false)
- }
+ ): View = inflater.inflate(R.layout.fragment_absensi, container, false)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
@@ -92,87 +80,106 @@ class AbsensiFragment : Fragment() {
tvLokasi = view.findViewById(R.id.tvLokasi)
btnAmbilFoto = view.findViewById(R.id.btnAmbilFoto)
btnLanjut = view.findViewById(R.id.btnLanjutPreview)
+ spinnerMatkul = view.findViewById(R.id.spinnerMatkul)
- // Cek profile sudah diisi atau belum
- if (DataHolder.userProfile.nama.isEmpty()) {
- Toast.makeText(context, "Isi profile dulu di tab Profil!", Toast.LENGTH_LONG).show()
- }
-
- // Request permission lokasi
+ setupSpinnerMatkul()
requestLocationPermission()
- btnAmbilFoto.setOnClickListener {
- requestCameraPermission()
- }
+ btnAmbilFoto.setOnClickListener { requestCameraPermission() }
btnLanjut.setOnClickListener {
- if (foto != null && latitude != null && longitude != null) {
- simpanDataSementara()
- findNavController().navigate(R.id.action_absensi_to_preview)
- }
+ simpanDataSementara()
+ findNavController().navigate(R.id.action_absensi_to_preview)
}
}
+ // ===== Mata Kuliah =====
+ private fun setupSpinnerMatkul() {
+ val matkulList = DummyData.mataKuliahList
+
+ val adapter = ArrayAdapter(
+ requireContext(),
+ android.R.layout.simple_spinner_dropdown_item,
+ matkulList.map { "${it.kode} - ${it.nama}" }
+ )
+
+ spinnerMatkul.adapter = adapter
+
+ spinnerMatkul.onItemSelectedListener =
+ object : AdapterView.OnItemSelectedListener {
+ override fun onItemSelected(
+ parent: AdapterView<*>, view: View?, position: Int, id: Long
+ ) {
+ selectedMatkul = matkulList[position]
+ cekKelengkapanData()
+ }
+
+ override fun onNothingSelected(parent: AdapterView<*>) {
+ selectedMatkul = null
+ cekKelengkapanData()
+ }
+ }
+ }
+
+ // ===== Location =====
private fun requestLocationPermission() {
- when {
- ContextCompat.checkSelfPermission(
+ if (ContextCompat.checkSelfPermission(
requireContext(),
Manifest.permission.ACCESS_FINE_LOCATION
- ) == PackageManager.PERMISSION_GRANTED -> {
- ambilLokasiGPS()
- }
- else -> {
- locationPermissionLauncher.launch(Manifest.permission.ACCESS_FINE_LOCATION)
- }
+ ) == PackageManager.PERMISSION_GRANTED
+ ) {
+ ambilLokasiGPS()
+ } else {
+ locationPermissionLauncher.launch(Manifest.permission.ACCESS_FINE_LOCATION)
}
}
private fun ambilLokasiGPS() {
- try {
- fusedLocationClient.lastLocation.addOnSuccessListener { location ->
- if (location != null) {
- latitude = location.latitude
- longitude = location.longitude
- tvLokasi.text = "📍 GPS Ready\nLat: ${location.latitude}\nLon: ${location.longitude}"
- cekKelengkapanData()
- } else {
- tvLokasi.text = "❌ Lokasi tidak tersedia\nHidupkan GPS"
- }
+ fusedLocationClient.lastLocation.addOnSuccessListener { location ->
+ if (location != null) {
+ latitude = location.latitude
+ longitude = location.longitude
+ tvLokasi.text =
+ "📍 GPS Ready\nLat: ${location.latitude}\nLon: ${location.longitude}"
+ cekKelengkapanData()
+ } else {
+ tvLokasi.text = "❌ Lokasi tidak tersedia"
}
- } catch (e: SecurityException) {
- Toast.makeText(context, "Error: ${e.message}", Toast.LENGTH_SHORT).show()
}
}
+ // ===== Camera =====
private fun requestCameraPermission() {
- when {
- ContextCompat.checkSelfPermission(
+ if (ContextCompat.checkSelfPermission(
requireContext(),
Manifest.permission.CAMERA
- ) == PackageManager.PERMISSION_GRANTED -> {
- bukaKamera()
- }
- else -> {
- cameraPermissionLauncher.launch(Manifest.permission.CAMERA)
- }
+ ) == PackageManager.PERMISSION_GRANTED
+ ) {
+ bukaKamera()
+ } else {
+ cameraPermissionLauncher.launch(Manifest.permission.CAMERA)
}
}
private fun bukaKamera() {
- val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
- cameraLauncher.launch(intent)
+ cameraLauncher.launch(Intent(MediaStore.ACTION_IMAGE_CAPTURE))
}
+ // ===== Validation =====
private fun cekKelengkapanData() {
- btnLanjut.isEnabled = foto != null && latitude != null && longitude != null
+ btnLanjut.isEnabled =
+ foto != null &&
+ latitude != null &&
+ longitude != null &&
+ selectedMatkul != null
}
+ // ===== Save =====
private fun simpanDataSementara() {
val bitmap = foto ?: return
val lat = latitude ?: return
val lon = longitude ?: return
-
- val fotoBase64 = bitmapToBase64(bitmap)
+ val matkul = selectedMatkul ?: return
DataHolder.currentAbsensi = AbsensiData(
nama = DataHolder.userProfile.nama,
@@ -180,8 +187,10 @@ class AbsensiFragment : Fragment() {
latitude = lat,
longitude = lon,
timestamp = System.currentTimeMillis(),
- fotoBase64 = fotoBase64,
- alamat = "Alamat akan diambil saat preview"
+ fotoBase64 = bitmapToBase64(bitmap),
+ alamat = "Alamat akan diambil saat preview",
+ kodeMatkul = matkul.kode,
+ namaMatkul = matkul.nama
)
}
diff --git a/app/src/main/java/id/ac/ubharajaya/sistemakademik/ui/fragments/PreviewFragment.kt b/app/src/main/java/id/ac/ubharajaya/sistemakademik/ui/fragments/PreviewFragment.kt
index 3a84f2d..29cc891 100644
--- a/app/src/main/java/id/ac/ubharajaya/sistemakademik/ui/fragments/PreviewFragment.kt
+++ b/app/src/main/java/id/ac/ubharajaya/sistemakademik/ui/fragments/PreviewFragment.kt
@@ -123,17 +123,38 @@ class PreviewFragment : Fragment() {
conn.doOutput = true
val json = JSONObject().apply {
+
+ // 1️⃣ HARUS ADA
+ put("timestamp", absensi.timestamp)
+
+ // 2️⃣ IP address (kalau belum ada, kirim dummy)
+ put("ip_addr", "android")
+
+ // 3️⃣ Identitas
put("npm", absensi.npm)
put("nama", absensi.nama)
+
+ // 4️⃣ Lokasi
put("latitude", absensi.latitude)
put("longitude", absensi.longitude)
- put("timestamp", absensi.timestamp)
- put("foto_base64", absensi.fotoBase64)
- put("address", absensi.alamat)
- put("distance_from_campus", 0)
+
+ // 5️⃣ MATA KULIAH (INI YANG KOSONG KEMARIN)
+ put("mata_kuliah", absensi.namaMatkul)
+ // atau kalau mau sekalian kode:
+ // put("mata_kuliah", "${absensi.kodeMatkul} - ${absensi.namaMatkul}")
+
+ // 6️⃣ Photo (boleh string apa aja / URL / label)
+ put("photo", "camera")
+
+ // 7️⃣ Status
put("status", "hadir")
+
+ // 8️⃣ FOTO BASE64
+ put("foto_base64", absensi.fotoBase64)
}
+
+
conn.outputStream.use {
it.write(json.toString().toByteArray())
}
diff --git a/app/src/main/java/id/ac/ubharajaya/sistemakademik/utils/DummyData.kt b/app/src/main/java/id/ac/ubharajaya/sistemakademik/utils/DummyData.kt
index b94cdbb..b854529 100644
--- a/app/src/main/java/id/ac/ubharajaya/sistemakademik/utils/DummyData.kt
+++ b/app/src/main/java/id/ac/ubharajaya/sistemakademik/utils/DummyData.kt
@@ -1,2 +1,11 @@
package id.ac.ubharajaya.sistemakademik.utils
+import id.ac.ubharajaya.sistemakademik.data.MataKuliah
+
+object DummyData {
+ val mataKuliahList = listOf(
+ MataKuliah("IF301", "Pemrograman Mobile"),
+ MataKuliah("IF302", "Kecerdasan Buatan"),
+ MataKuliah("IF303", "Basis Data")
+ )
+}
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_absensi.xml b/app/src/main/res/layout/fragment_absensi.xml
index 56d0dc6..7b4d100 100644
--- a/app/src/main/res/layout/fragment_absensi.xml
+++ b/app/src/main/res/layout/fragment_absensi.xml
@@ -32,6 +32,13 @@
android:textAlignment="center"
android:layout_marginBottom="32dp"/>
+
+
+