diff --git a/app/src/main/java/com/example/bondoyap/ui/scanner/ScanResultFragment.kt b/app/src/main/java/com/example/bondoyap/ui/scanner/ScanResultFragment.kt index 2c8cd56b2bc9b5253d1525752e0beb0af6f95ba2..96f2ba070db2124c6497759326fab0e7b1419f4d 100644 --- a/app/src/main/java/com/example/bondoyap/ui/scanner/ScanResultFragment.kt +++ b/app/src/main/java/com/example/bondoyap/ui/scanner/ScanResultFragment.kt @@ -7,7 +7,9 @@ import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels +import androidx.recyclerview.widget.LinearLayoutManager import com.example.bondoyap.databinding.FragmentScanResultBinding +import com.example.bondoyap.ui.scanner.listAdapter.ScanResultListAdapter class ScanResultFragment : Fragment() { @@ -16,7 +18,7 @@ class ScanResultFragment : Fragment() { private var _binding: FragmentScanResultBinding? = null private val binding get() = _binding!! - + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -26,8 +28,13 @@ class ScanResultFragment : Fragment() { val root: View = binding.root val scannerViewModel: ScannerViewModel by activityViewModels() + + val recyclerView = binding.recyclerView + val adapter = ScanResultListAdapter() + recyclerView.adapter = adapter + recyclerView.layoutManager = LinearLayoutManager(requireContext()) scannerViewModel.items?.let { items -> - binding.responseText.text = items.toString() + adapter.submitList(items) Log.d("Scan Result", "Result Received: $items") } diff --git a/app/src/main/java/com/example/bondoyap/ui/scanner/ScannerFragment.kt b/app/src/main/java/com/example/bondoyap/ui/scanner/ScannerFragment.kt index a438d4a2f36abb6790d689d07a1ed3bd562860f5..51117c1a9f9a916a690cbf4c58bd47a86c5debf1 100644 --- a/app/src/main/java/com/example/bondoyap/ui/scanner/ScannerFragment.kt +++ b/app/src/main/java/com/example/bondoyap/ui/scanner/ScannerFragment.kt @@ -61,7 +61,7 @@ class ScannerFragment : Fragment() { private lateinit var contentResolver: ContentResolver private lateinit var apiClient: ApiClient - + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -109,7 +109,8 @@ class ScannerFragment : Fragment() { } } - val pickImageIntent = Intent(Intent.ACTION_PICK, MediaStore.Images.Media.INTERNAL_CONTENT_URI) + val pickImageIntent = + Intent(Intent.ACTION_PICK, MediaStore.Images.Media.INTERNAL_CONTENT_URI) pickImageLauncher = registerForActivityResult( ActivityResultContracts.RequestPermission() ) { isGranted -> @@ -150,7 +151,7 @@ class ScannerFragment : Fragment() { val cameraProviderFuture = ProcessCameraProvider.getInstance(requireContext()) cameraProviderFuture.addListener({ val cameraProvider = cameraProviderFuture.get() - + val preview = Preview.Builder().build().also { mPreview -> if (!frozenPreview) { mPreview.setSurfaceProvider(binding.previewView.surfaceProvider) @@ -158,17 +159,17 @@ class ScannerFragment : Fragment() { mPreview.setSurfaceProvider(null) } } - + val imageCapture = ImageCapture.Builder() .setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY) .build() - + val cameraSelector = if (isBackCamera) { CameraSelector.DEFAULT_BACK_CAMERA } else { CameraSelector.DEFAULT_FRONT_CAMERA } - + try { cameraProvider?.unbindAll() cameraProvider?.bindToLifecycle(this, cameraSelector, preview, imageCapture) @@ -183,7 +184,7 @@ class ScannerFragment : Fragment() { cameraImageFile = tempFile Log.d("CameraX", "Image captured: $uriImg") } - + override fun onError(exception: ImageCaptureException) { Log.e( "CameraX", @@ -226,7 +227,8 @@ class ScannerFragment : Fragment() { call: Call<BillResponse>, response: Response<BillResponse> ) { if (response.isSuccessful) { - val billResponse = response.body() ?: throw Exception("Bill Response is Empty") + val billResponse = + response.body() ?: throw Exception("Bill Response is Empty") Log.d("Bill Upload", "Server Response: $billResponse") navigateScanResult(billResponse.items) } else { @@ -245,7 +247,7 @@ class ScannerFragment : Fragment() { private fun navigateScanResult(items: Items) { val scannerViewModel: ScannerViewModel by activityViewModels() - scannerViewModel.items = items + scannerViewModel.items = items.items navController.navigate(R.id.action_to_scanResultFragment) } } \ No newline at end of file diff --git a/app/src/main/java/com/example/bondoyap/ui/scanner/ScannerViewModel.kt b/app/src/main/java/com/example/bondoyap/ui/scanner/ScannerViewModel.kt index 1f6abcae221dc32705cca9dcae7f275717acc31c..3e659568fd7e9ca0d091f8b24e1c7703777b3dc6 100644 --- a/app/src/main/java/com/example/bondoyap/ui/scanner/ScannerViewModel.kt +++ b/app/src/main/java/com/example/bondoyap/ui/scanner/ScannerViewModel.kt @@ -3,13 +3,14 @@ package com.example.bondoyap.ui.scanner import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel -import com.example.bondoyap.service.api.data.Items +import com.example.bondoyap.service.api.data.Item class ScannerViewModel : ViewModel() { - var items: Items? = null + var items: List<Item>? = null private val _text = MutableLiveData<String>().apply { value = "This is Scanner Fragment" } val text: LiveData<String> = _text + } \ No newline at end of file diff --git a/app/src/main/java/com/example/bondoyap/ui/scanner/listAdapter/ItemDiffCallback.kt b/app/src/main/java/com/example/bondoyap/ui/scanner/listAdapter/ItemDiffCallback.kt new file mode 100644 index 0000000000000000000000000000000000000000..15e214aa61d0894a9bc13b086ea6c9845571a7de --- /dev/null +++ b/app/src/main/java/com/example/bondoyap/ui/scanner/listAdapter/ItemDiffCallback.kt @@ -0,0 +1,17 @@ +package com.example.bondoyap.ui.scanner.listAdapter + +import androidx.recyclerview.widget.DiffUtil +import com.example.bondoyap.service.api.data.Item + +class ItemDiffCallback : DiffUtil.ItemCallback<Item>() { + override fun areItemsTheSame(oldItem: Item, newItem: Item): Boolean { + val isNameSame = oldItem.name == newItem.name + val isQuantitySame = oldItem.quantity == newItem.quantity + val isPriceSame = oldItem.price == newItem.price + return isNameSame && isQuantitySame && isPriceSame + } + + override fun areContentsTheSame(oldItem: Item, newItem: Item): Boolean { + return oldItem == newItem + } +} diff --git a/app/src/main/java/com/example/bondoyap/ui/scanner/listAdapter/ItemViewHolder.kt b/app/src/main/java/com/example/bondoyap/ui/scanner/listAdapter/ItemViewHolder.kt new file mode 100644 index 0000000000000000000000000000000000000000..113bfe4879247955c2213e9ea067e5eaa1666f38 --- /dev/null +++ b/app/src/main/java/com/example/bondoyap/ui/scanner/listAdapter/ItemViewHolder.kt @@ -0,0 +1,31 @@ +package com.example.bondoyap.ui.scanner.listAdapter + +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.cardview.widget.CardView +import androidx.recyclerview.widget.RecyclerView +import com.example.bondoyap.R +import com.example.bondoyap.service.api.data.Item + +class ItemViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + fun bind(item: Item) { + val itemName: TextView = itemView.findViewById(R.id.item_name) + val itemQuantity: TextView = itemView.findViewById(R.id.item_quantity) + val itemPrice: TextView = itemView.findViewById(R.id.item_price) + + itemName.text = item.name + itemQuantity.text = item.quantity.toString() + itemPrice.text = item.price.toString() + } + + companion object { + fun create(parent: ViewGroup): ItemViewHolder { + val view: View = LayoutInflater.from(parent.context) + .inflate(R.layout.recyclerview_scan_result, parent, false) + return ItemViewHolder(view) + } + } +} diff --git a/app/src/main/java/com/example/bondoyap/ui/scanner/listAdapter/ScanResultListAdapter.kt b/app/src/main/java/com/example/bondoyap/ui/scanner/listAdapter/ScanResultListAdapter.kt new file mode 100644 index 0000000000000000000000000000000000000000..d60897087cbdcf1d42dc7263bc9495e249317a7e --- /dev/null +++ b/app/src/main/java/com/example/bondoyap/ui/scanner/listAdapter/ScanResultListAdapter.kt @@ -0,0 +1,17 @@ +package com.example.bondoyap.ui.scanner.listAdapter + +import android.view.ViewGroup +import androidx.recyclerview.widget.ListAdapter +import com.example.bondoyap.service.api.data.Item + +class ScanResultListAdapter : + ListAdapter<Item, ItemViewHolder>(ItemDiffCallback()) { + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ItemViewHolder { + return ItemViewHolder.create(parent) + } + + override fun onBindViewHolder(holder: ItemViewHolder, position: Int) { + val currentItem = getItem(position) + holder.bind(currentItem) + } +} diff --git a/app/src/main/res/layout/fragment_scan_result.xml b/app/src/main/res/layout/fragment_scan_result.xml index d59cbfc674110a5cb51b3330eb1e21f707cd6570..972c342f9703685caafa1ddf6265ee9e7d1cc188 100644 --- a/app/src/main/res/layout/fragment_scan_result.xml +++ b/app/src/main/res/layout/fragment_scan_result.xml @@ -1,17 +1,39 @@ <?xml version="1.0" encoding="utf-8"?> -<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" +<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" + android:orientation="vertical" tools:context=".ui.scanner.ScanResultFragment"> - <TextView - android:id="@+id/response_text" + <androidx.recyclerview.widget.RecyclerView + android:id="@+id/recycler_view" android:layout_width="match_parent" - android:layout_height="match_parent" - android:textAlignment="center" - app:layout_constraintLeft_toLeftOf="parent" - app:layout_constraintRight_toLeftOf="parent" /> + android:layout_height="0dp" + android:layout_weight="1" /> -</RelativeLayout> \ No newline at end of file + <!-- TODO: fix relative to bottom nav bar --> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginBottom="72dp" + android:orientation="horizontal"> + + <Button + android:id="@+id/cancel_button" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:text="@string/cancel_button" /> + + <Button + android:id="@+id/save_button" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:text="@string/save_button" /> + + </LinearLayout> + +</LinearLayout> diff --git a/app/src/main/res/layout/recyclerview_scan_result.xml b/app/src/main/res/layout/recyclerview_scan_result.xml new file mode 100644 index 0000000000000000000000000000000000000000..c172e9daa24a17d34ac12b0e3de9263d366866c3 --- /dev/null +++ b/app/src/main/res/layout/recyclerview_scan_result.xml @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="utf-8"?> +<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + android:id="@+id/card_view" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_margin="8dp" + app:cardBackgroundColor="#af5eff" + app:cardCornerRadius="8dp" + app:cardElevation="4dp"> + + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical" + android:padding="16dp"> + + <TextView + android:id="@+id/item_name" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textSize="16sp" /> + + <TextView + android:id="@+id/item_quantity" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textSize="16sp" /> + + <TextView + android:id="@+id/item_price" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:textSize="16sp" /> + </LinearLayout> + +</androidx.cardview.widget.CardView>