diff --git a/app/src/main/java/com/example/bandung_bondowoso/BandungBondowosoApp.kt b/app/src/main/java/com/example/bandung_bondowoso/BandungBondowosoApp.kt index a94b8108a4fbd21c92d7592306e6142cc84c5bac..49bb4de20a98106aad5bb2ff07f61c8347503af4 100644 --- a/app/src/main/java/com/example/bandung_bondowoso/BandungBondowosoApp.kt +++ b/app/src/main/java/com/example/bandung_bondowoso/BandungBondowosoApp.kt @@ -3,6 +3,7 @@ package com.example.bandung_bondowoso import android.app.Application import com.example.bandung_bondowoso.local.AppDatabase import com.example.bandung_bondowoso.remote.ApiClient +import com.example.bandung_bondowoso.repository.BillRepository import com.example.bandung_bondowoso.repository.TransactionRepository import com.example.bandung_bondowoso.repository.UserRepository import com.example.bandung_bondowoso.util.Config @@ -12,6 +13,8 @@ class BandungBondowosoApp : Application() { val transactionRepository by lazy { TransactionRepository(database.transactionDao()) } private val sharedPreferences by lazy { getSharedPreferences(Config.SHARED_PREFERENCES_NAME, MODE_PRIVATE) } private val authService by lazy { ApiClient.pbdApiService } + private val billService by lazy {ApiClient.pbdApiService} val userRepository by lazy { UserRepository(authService, sharedPreferences) } + val billRepository by lazy { BillRepository(billService) } } \ No newline at end of file diff --git a/app/src/main/java/com/example/bandung_bondowoso/model/Item.kt b/app/src/main/java/com/example/bandung_bondowoso/model/Item.kt new file mode 100644 index 0000000000000000000000000000000000000000..decee29ad2ebea99ffa115b59df0ae5adb1072d4 --- /dev/null +++ b/app/src/main/java/com/example/bandung_bondowoso/model/Item.kt @@ -0,0 +1,16 @@ +package com.example.bandung_bondowoso.model + +import com.squareup.moshi.Json + +data class Item( + @field:Json(name = "name") val name: String, + @field:Json(name = "qty") val qty: Int, + @field:Json(name = "price") val price: Float +) +data class Items( + @field:Json(name = "items") val items: List<Item> +) + +data class ItemsResponse( + @field:Json(name = "items") val items: Items +) diff --git a/app/src/main/java/com/example/bandung_bondowoso/remote/BillService.kt b/app/src/main/java/com/example/bandung_bondowoso/remote/BillService.kt index 21f42f696a6daa0a5bf34b81cbfa639f4ff2053d..eeddb336db7309680c852dfcaf67744b37e13a75 100644 --- a/app/src/main/java/com/example/bandung_bondowoso/remote/BillService.kt +++ b/app/src/main/java/com/example/bandung_bondowoso/remote/BillService.kt @@ -1,5 +1,9 @@ package com.example.bandung_bondowoso.remote +import com.example.bandung_bondowoso.model.ItemsResponse +import okhttp3.MultipartBody +import retrofit2.Response interface BillService { - suspend fun upload() + suspend fun upload(token: String, file: MultipartBody.Part) : Response<ItemsResponse> + } \ No newline at end of file diff --git a/app/src/main/java/com/example/bandung_bondowoso/remote/PBDApiService.kt b/app/src/main/java/com/example/bandung_bondowoso/remote/PBDApiService.kt index 6db81152cf91c8d909b6930f463f4e31f6e27104..cdd8abb3efcbfc246673acb6c4817e3c0a3342a7 100644 --- a/app/src/main/java/com/example/bandung_bondowoso/remote/PBDApiService.kt +++ b/app/src/main/java/com/example/bandung_bondowoso/remote/PBDApiService.kt @@ -1,12 +1,16 @@ package com.example.bandung_bondowoso.remote +import com.example.bandung_bondowoso.model.ItemsResponse import com.example.bandung_bondowoso.model.Token import com.example.bandung_bondowoso.model.TokenDetail import com.example.bandung_bondowoso.model.request.LoginRequest +import okhttp3.MultipartBody import retrofit2.Response import retrofit2.http.Body import retrofit2.http.Header +import retrofit2.http.Multipart import retrofit2.http.POST +import retrofit2.http.Part interface PBDApiService : AuthService, BillService { @POST("api/auth/login") @@ -15,6 +19,8 @@ interface PBDApiService : AuthService, BillService { @POST("api/auth/token") override suspend fun token(@Header("Authorization") token: String): Response<TokenDetail> + @Multipart @POST("api/bill/upload") - override suspend fun upload() + override suspend fun upload(@Header("Authorization") token: String, @Part file: MultipartBody.Part): Response<ItemsResponse> + } \ No newline at end of file diff --git a/app/src/main/java/com/example/bandung_bondowoso/repository/BillRepository.kt b/app/src/main/java/com/example/bandung_bondowoso/repository/BillRepository.kt index af335675a13c5bdf751e53db0898171d9365dc3e..6248f6ff8e94095c2463bb7d76b2ba8f00918014 100644 --- a/app/src/main/java/com/example/bandung_bondowoso/repository/BillRepository.kt +++ b/app/src/main/java/com/example/bandung_bondowoso/repository/BillRepository.kt @@ -1,16 +1,49 @@ package com.example.bandung_bondowoso.repository +import android.util.Log +import com.example.bandung_bondowoso.model.ItemsResponse +import com.example.bandung_bondowoso.model.NetworkResult import com.example.bandung_bondowoso.remote.ApiHandler import com.example.bandung_bondowoso.remote.BillService import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.MultipartBody +import okhttp3.RequestBody.Companion.asRequestBody +import java.io.File class BillRepository( private val billService: BillService, private val defaultDispatcher: CoroutineDispatcher = Dispatchers.Default ) : ApiHandler { - suspend fun upload() = withContext(defaultDispatcher) { - billService.upload() + private var currentResponse: ItemsResponse? = null + suspend fun upload(token: String, file: File) = withContext(defaultDispatcher) { + val fileRequest = file.asRequestBody("image/*".toMediaTypeOrNull()) + val request = MultipartBody.Part.createFormData("file", "file.jpg", fileRequest) + val response = safeApiCall { + billService.upload("Bearer $token", request) + } + when(response){ + is NetworkResult.Success -> { + val result = response.data + saveResponse(result) + Log.d("BillRepository", "getting bills: $result") + } + else -> { + Log.d("BillRepository", "Getting Bills: $response") + } + } } + private fun saveResponse(response: ItemsResponse?) { + currentResponse = response + } + + fun getCurrentResponse(): ItemsResponse? { + return currentResponse + } + + + + } \ No newline at end of file diff --git a/app/src/main/java/com/example/bandung_bondowoso/view/login/LoginFragment.kt b/app/src/main/java/com/example/bandung_bondowoso/view/login/LoginFragment.kt index ba86196baf9c11ef13142e4ace8c4e134d378019..550ec82883dc75cf68d6fee11068ef684af89e60 100644 --- a/app/src/main/java/com/example/bandung_bondowoso/view/login/LoginFragment.kt +++ b/app/src/main/java/com/example/bandung_bondowoso/view/login/LoginFragment.kt @@ -3,16 +3,14 @@ package com.example.bandung_bondowoso.view.login import android.content.Intent import android.os.Bundle import android.util.Log -import androidx.fragment.app.Fragment import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.Toast -import androidx.fragment.app.viewModels +import androidx.fragment.app.Fragment +import androidx.fragment.app.activityViewModels import androidx.lifecycle.Observer -import androidx.navigation.fragment.findNavController import com.example.bandung_bondowoso.BandungBondowosoApp -import com.example.bandung_bondowoso.R import com.example.bandung_bondowoso.broadcast.connection.ConnectionChangeListener import com.example.bandung_bondowoso.databinding.FragmentLoginBinding import com.example.bandung_bondowoso.service.JwtCheckerService @@ -30,7 +28,7 @@ class LoginFragment : Fragment(), ConnectionChangeListener { // onDestroyView. private val binding get() = _binding!! - private val loginViewModel: LoginViewModel by viewModels { + private val loginViewModel: LoginViewModel by activityViewModels { LoginViewModelFactory((activity?.application as BandungBondowosoApp).userRepository) } diff --git a/app/src/main/java/com/example/bandung_bondowoso/view/scan/ScanFragment.kt b/app/src/main/java/com/example/bandung_bondowoso/view/scan/ScanFragment.kt index f7953d649ae6ddeba148cd4fa6f2a2f7518def7a..ee86cd55af1493bb6ba089c482d19fb389506766 100644 --- a/app/src/main/java/com/example/bandung_bondowoso/view/scan/ScanFragment.kt +++ b/app/src/main/java/com/example/bandung_bondowoso/view/scan/ScanFragment.kt @@ -9,17 +9,30 @@ import android.view.ViewGroup import android.widget.Toast import androidx.activity.result.contract.ActivityResultContracts import androidx.camera.core.CameraSelector +import androidx.camera.core.ImageCapture +import androidx.camera.core.ImageCaptureException import androidx.camera.view.LifecycleCameraController import androidx.camera.view.PreviewView import androidx.core.content.ContextCompat import androidx.fragment.app.Fragment +import androidx.fragment.app.activityViewModels +import androidx.navigation.Navigation +import com.example.bandung_bondowoso.BandungBondowosoApp +import com.example.bandung_bondowoso.R import com.example.bandung_bondowoso.databinding.FragmentScanBinding +import com.example.bandung_bondowoso.viewmodel.scan.ScanViewModel +import com.example.bandung_bondowoso.viewmodel.scan.ScanViewModelFactory +import java.io.File class ScanFragment : Fragment(){ private var _binding : FragmentScanBinding ? = null private lateinit var cameraController: LifecycleCameraController private val binding get() = _binding!! + private var imageFile: File? = null + private val scanViewModel: ScanViewModel by activityViewModels { + ScanViewModelFactory((activity?.application as BandungBondowosoApp).billRepository) + } override fun onCreateView( inflater: LayoutInflater, @@ -29,6 +42,10 @@ class ScanFragment : Fragment(){ Log.d("ScanFragment", "OnCreateView") _binding = FragmentScanBinding.inflate(inflater, container, false) val root: View = binding.root + binding.shutter.setOnClickListener { + takePhoto() ; +// Navigation.findNavController(root).navigate(R.id.action_navigation_camera_to_result) + } return root; } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { @@ -38,7 +55,6 @@ class ScanFragment : Fragment(){ } else { startCamera() } - _binding!!.shutter.setOnClickListener { takePhoto() } } private fun startCamera(){ @@ -51,8 +67,44 @@ class ScanFragment : Fragment(){ } private fun takePhoto(){ - val previewView: PreviewView = _binding!!.viewFinder - previewView.controller = null + val name = "file" + val outputDirectory = File(requireContext().cacheDir, "camera").apply{ + mkdirs() + } + val imageFile = File(outputDirectory, name) + +// val contentValues = ContentValues().apply{ +// put(MediaStore.MediaColumns.DISPLAY_NAME, name) +// put(MediaStore.MediaColumns.MIME_TYPE, "image/jpeg") +// if(Build.VERSION.SDK_INT > Build.VERSION_CODES.P){ +// put(MediaStore.Images.Media.RELATIVE_PATH, "DCIM/Camera") +// +// } +// } +// val outputOptions = ImageCapture.OutputFileOptions +// .Builder(this.requireActivity().getContentResolver(), +// MediaStore.Images.Media.EXTERNAL_CONTENT_URI, +// contentValues) +// .build() + val outputOptions = ImageCapture.OutputFileOptions.Builder(imageFile).build() + cameraController.takePicture( + outputOptions, + ContextCompat.getMainExecutor(this.requireContext()), + object: ImageCapture.OnImageSavedCallback{ + override fun onError(exc: ImageCaptureException){ + Log.e("PhotoCapture", "Photo captured failed: ${exc.message}", exc) + } + + override fun onImageSaved(outputFileResults: ImageCapture.OutputFileResults) { + Log.d("PhotoCapture", "Photo captured success!") + this@ScanFragment.imageFile = imageFile + Log.d("ImageFile", "ImageFile : ${this@ScanFragment.imageFile.toString()}") + scanViewModel.setUploadFile(this@ScanFragment.imageFile!!) + Log.d("ImageFile scanFragment", "Update image file uploaded") + view?.let { Navigation.findNavController(it).navigate(R.id.action_navigation_camera_to_result)} + } + } + ) } @@ -83,4 +135,4 @@ class ScanFragment : Fragment(){ ContextCompat.checkSelfPermission(context, it) == PackageManager.PERMISSION_GRANTED; } } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/example/bandung_bondowoso/view/scan/ScanHomeFragment.kt b/app/src/main/java/com/example/bandung_bondowoso/view/scan/ScanHomeFragment.kt index cd091ef09797c1d14b55f34b171f2bf5909e9a0f..24563dd0aa04c687b18977404ac5ab56c6022d00 100644 --- a/app/src/main/java/com/example/bandung_bondowoso/view/scan/ScanHomeFragment.kt +++ b/app/src/main/java/com/example/bandung_bondowoso/view/scan/ScanHomeFragment.kt @@ -1,6 +1,10 @@ package com.example.bandung_bondowoso.view.scan +import android.content.ContentResolver +import android.content.Context +import android.net.Uri import android.os.Bundle +import android.provider.MediaStore import android.util.Log import android.view.LayoutInflater import android.view.View @@ -8,25 +12,39 @@ import android.view.ViewGroup import androidx.activity.result.PickVisualMediaRequest import androidx.activity.result.contract.ActivityResultContracts import androidx.fragment.app.Fragment +import androidx.fragment.app.activityViewModels import androidx.navigation.Navigation +import com.example.bandung_bondowoso.BandungBondowosoApp import com.example.bandung_bondowoso.R import com.example.bandung_bondowoso.broadcast.connection.ConnectionChangeListener import com.example.bandung_bondowoso.databinding.FragmentScanHomeBinding import com.example.bandung_bondowoso.util.ConnectionStateMonitor import com.example.bandung_bondowoso.view.network.NoNetworkFragment +import com.example.bandung_bondowoso.viewmodel.scan.ScanViewModel +import com.example.bandung_bondowoso.viewmodel.scan.ScanViewModelFactory +import java.io.File +import java.io.FileOutputStream +import java.io.InputStream +import java.io.OutputStream class ScanHomeFragment: Fragment(), ConnectionChangeListener { private var _binding :FragmentScanHomeBinding ? = null; private val binding get() = _binding!! + private val scanViewModel: ScanViewModel by activityViewModels { + ScanViewModelFactory((activity?.application as BandungBondowosoApp).billRepository) + } + private var imageFile : File? = null private val pickMedia = registerForActivityResult(ActivityResultContracts.PickVisualMedia()) { uri -> if (uri != null) { Log.d("PhotoPicker", "Selected URI: $uri") + imageFile = uriToFile(uri, this.requireContext()) + scanViewModel.setUploadFile(imageFile!!) + Navigation.findNavController(binding.root).navigate(R.id.action_navigation_scan_to_result) } else { Log.d("PhotoPicker", "No photo selected") } } private val connectionStateMonitor = ConnectionStateMonitor(this) - override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -41,16 +59,13 @@ class ScanHomeFragment: Fragment(), ConnectionChangeListener { binding.toGaleriButton.setOnClickListener{ pickImageGallery() } - connectionStateMonitor.enable(requireContext()) - return root; } private fun pickImageGallery(){ pickMedia.launch(PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly)) } - override fun onConnectionChanged(isConnected: Boolean) { activity?.runOnUiThread(Runnable { if (!isConnected) { @@ -74,4 +89,30 @@ class ScanHomeFragment: Fragment(), ConnectionChangeListener { }) } -} \ No newline at end of file + private fun uriToFile(imageUri: Uri, context: Context) : File{ + val contentResolver = context.contentResolver + val file = File(context.cacheDir, contentResolver.getFileName(imageUri)) + val input: InputStream? = contentResolver.openInputStream(imageUri) + val output: OutputStream = FileOutputStream(file) + input?.copyTo(output) + + return file; + } + fun ContentResolver.getFileName(uri: Uri): String{ + var name = "" + val returnCursor = this.query(uri, null, null, null, null) + if (returnCursor != null) { + val nameIndex = returnCursor.getColumnIndex(MediaStore.Images.ImageColumns.DISPLAY_NAME) + returnCursor.moveToFirst() + name = returnCursor.getString(nameIndex) + returnCursor.close() + } + return name + } + + override fun onDestroyView() { + super.onDestroyView() + _binding = null + } + +} diff --git a/app/src/main/java/com/example/bandung_bondowoso/view/scan/ScanResultFragment.kt b/app/src/main/java/com/example/bandung_bondowoso/view/scan/ScanResultFragment.kt new file mode 100644 index 0000000000000000000000000000000000000000..53490aa6e8d5141e1bbe95c6ca8bf0e5cd727256 --- /dev/null +++ b/app/src/main/java/com/example/bandung_bondowoso/view/scan/ScanResultFragment.kt @@ -0,0 +1,79 @@ +package com.example.bandung_bondowoso.view.scan + +import android.os.Bundle +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import androidx.fragment.app.activityViewModels +import androidx.navigation.Navigation +import com.example.bandung_bondowoso.BandungBondowosoApp +import com.example.bandung_bondowoso.R +import com.example.bandung_bondowoso.databinding.FragmentScanResultBinding +import com.example.bandung_bondowoso.viewmodel.login.LoginViewModel +import com.example.bandung_bondowoso.viewmodel.login.LoginViewModelFactory +import com.example.bandung_bondowoso.viewmodel.scan.ScanViewModel +import com.example.bandung_bondowoso.viewmodel.scan.ScanViewModelFactory +import java.io.File + +class ScanResultFragment: Fragment() { + private var _binding: FragmentScanResultBinding ? = null + private val binding get() = _binding!! + + private val scanViewModel: ScanViewModel by activityViewModels { + ScanViewModelFactory((activity?.application as BandungBondowosoApp).billRepository) + } + private val loginViewModel: LoginViewModel by activityViewModels { + LoginViewModelFactory((activity?.application as BandungBondowosoApp).userRepository) + } + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + Log.d("ScanResultFragment", "OnCreateView") + _binding = FragmentScanResultBinding.inflate(inflater, container, false) + val root: View = binding.root + binding.buttonUlang.setOnClickListener { + Navigation.findNavController(root).navigate(R.id.action_navigation_result_to_scan) + } + binding.buttonTidakUlang.setOnClickListener{ + // TO DO : save transaction + Navigation.findNavController(root).navigate(R.id.action_navigation_result_to_transaction) + } + return root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + var token: String? + var file: File? + + scanViewModel.uploadResult.observe(viewLifecycleOwner) { uploadResult -> + var temp = "" + uploadResult?.items?.items?.forEach { item -> + temp += "${item.name} " + temp += "${item.qty * item.price} \n" + } + binding.testAja.text = temp.trim() + } + file = scanViewModel.getUploadFile() + loginViewModel.getToken().observe(viewLifecycleOwner) { userToken -> + token = userToken + Log.d("Token", "Token value: $token") + if(token != null && file != null){ + scanViewModel.upload(token!!, file) + Log.d("ScanResultFragment", "Upload file") + } + } + + } + + + override fun onDestroyView() { + super.onDestroyView() + _binding = null + } +} diff --git a/app/src/main/java/com/example/bandung_bondowoso/viewmodel/login/LoginViewModel.kt b/app/src/main/java/com/example/bandung_bondowoso/viewmodel/login/LoginViewModel.kt index 8a748399fd4d9748ec104ab9ca1caf783d3a1e6d..238e5e1cb3ae12785968bac53e48ef4a638ea5bc 100644 --- a/app/src/main/java/com/example/bandung_bondowoso/viewmodel/login/LoginViewModel.kt +++ b/app/src/main/java/com/example/bandung_bondowoso/viewmodel/login/LoginViewModel.kt @@ -56,5 +56,13 @@ class LoginViewModel(private val userRepository: UserRepository) : ViewModel() { } return email } + fun getToken(): LiveData<String?>{ + val token = MutableLiveData<String?>() + viewModelScope.launch{ + token.value = userRepository.getToken() + } + return token + } + } diff --git a/app/src/main/java/com/example/bandung_bondowoso/viewmodel/scan/ScanViewModel.kt b/app/src/main/java/com/example/bandung_bondowoso/viewmodel/scan/ScanViewModel.kt new file mode 100644 index 0000000000000000000000000000000000000000..a367bdf5ff47bedf1f30860ee4539fd5621956f2 --- /dev/null +++ b/app/src/main/java/com/example/bandung_bondowoso/viewmodel/scan/ScanViewModel.kt @@ -0,0 +1,53 @@ +package com.example.bandung_bondowoso.viewmodel.scan + +import android.util.Log +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.example.bandung_bondowoso.model.ItemsResponse +import com.example.bandung_bondowoso.repository.BillRepository +import kotlinx.coroutines.launch +import java.io.File + +class ScanViewModel(private val billRepository: BillRepository) : ViewModel() { + private val _uploadResult = MutableLiveData<ItemsResponse?>() + val uploadResult: LiveData<ItemsResponse?> = _uploadResult + + private val _uploadFile = MutableLiveData<File?>() + val uploadFile: LiveData<File?> = _uploadFile + + private val _error = MutableLiveData<String?>() + val error: LiveData<String?> = _error + + fun upload(token: String, file: File) { + viewModelScope.launch { + try { + billRepository.upload(token, file) + _uploadResult.value = billRepository.getCurrentResponse() + Log.d("ViewModel", "Uploading..") + } catch (e: Exception) { + Log.d("ViewModel", "Error uploading") + _error.postValue(e.message) + } + } + } + fun getCurrentResponse():ItemsResponse? { + viewModelScope.launch { + val currentResponse = billRepository.getCurrentResponse() + _uploadResult.postValue(currentResponse) + } + return _uploadResult.value; + } + fun getUploadFile() : File?{ + return _uploadFile.value; + } + fun get_UploadResult(): ItemsResponse?{ + return _uploadResult.value; + } + fun setUploadFile(file: File){ + _uploadFile.value = file + } + + +} \ No newline at end of file diff --git a/app/src/main/java/com/example/bandung_bondowoso/viewmodel/scan/ScanViewModelFactory.kt b/app/src/main/java/com/example/bandung_bondowoso/viewmodel/scan/ScanViewModelFactory.kt new file mode 100644 index 0000000000000000000000000000000000000000..9b05449d09a9db16e6e063615d6cbf44052f23af --- /dev/null +++ b/app/src/main/java/com/example/bandung_bondowoso/viewmodel/scan/ScanViewModelFactory.kt @@ -0,0 +1,15 @@ +package com.example.bandung_bondowoso.viewmodel.scan + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider +import com.example.bandung_bondowoso.repository.BillRepository + +class ScanViewModelFactory(private val billRepository: BillRepository) : ViewModelProvider.Factory { + override fun <T : ViewModel> create(modelClass: Class<T>): T { + if (modelClass.isAssignableFrom(ScanViewModel::class.java)) { + @Suppress("UNCHECKED_CAST") + return ScanViewModel(billRepository) as T + } + throw IllegalArgumentException("Unknown ViewModel class") + } +} diff --git a/app/src/main/res/drawable/rounded_button.xml b/app/src/main/res/drawable/rounded_button.xml new file mode 100644 index 0000000000000000000000000000000000000000..390fd78f3e5f70b7572a61c569a217c1585f9cd8 --- /dev/null +++ b/app/src/main/res/drawable/rounded_button.xml @@ -0,0 +1,6 @@ +<!-- rounded_button_background.xml --> +<shape xmlns:android="http://schemas.android.com/apk/res/android" + android:shape="rectangle"> + <solid android:color="@color/md_theme_blue" /> + <corners android:radius="15dp" /> <!-- Adjust the radius to change the roundness --> +</shape> diff --git a/app/src/main/res/layout/fragment_scan_home.xml b/app/src/main/res/layout/fragment_scan_home.xml index 1b4225689c6d7a21babea1df5d56a6d0aa36be7e..ebd34b798e5f7cfce0f05a9f2814f5ed594314c2 100644 --- a/app/src/main/res/layout/fragment_scan_home.xml +++ b/app/src/main/res/layout/fragment_scan_home.xml @@ -81,4 +81,4 @@ android:layout_height="match_parent" android:visibility="gone" /> -</FrameLayout> \ No newline at end of file +</FrameLayout> diff --git a/app/src/main/res/layout/fragment_scan_result.xml b/app/src/main/res/layout/fragment_scan_result.xml new file mode 100644 index 0000000000000000000000000000000000000000..6b61d8ae2303802c420ae299c784fc957eb75be1 --- /dev/null +++ b/app/src/main/res/layout/fragment_scan_result.xml @@ -0,0 +1,98 @@ +<?xml version="1.0" encoding="utf-8"?> +<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + xmlns:app="http://schemas.android.com/apk/res-auto" + android:background="@color/md_theme_primary"> + + <TextView + android:id="@+id/tv_scan_result_title" + style="@style/TextAppearance.HeadlineLarge" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginStart="30dp" + android:layout_marginTop="20dp" + android:text="Hasil Scan" + android:textColor="@color/white" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="430dp" + android:layout_marginStart="30dp" + android:layout_marginEnd="30dp" + android:layout_marginTop="20dp" + android:orientation="vertical" + + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/tv_scan_result_title"> + <TextView + android:id= "@+id/test_aja" + android:textColor="@color/white" + android:layout_width="match_parent" + android:layout_height="match_parent" + /> +<!-- <androidx.recyclerview.widget.RecyclerView--> +<!-- android:id="@+id/rvTransaction"--> +<!-- android:layout_width="match_parent"--> +<!-- android:layout_height="match_parent"--> +<!-- app:layout_constraintEnd_toEndOf="parent"--> +<!-- app:layout_constraintStart_toStartOf="parent"--> +<!-- app:layout_constraintTop_toTopOf="parent" />--> + + </LinearLayout> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="180dp" + android:orientation="vertical" + android:background="@color/white" + app:layout_constraintBottom_toBottomOf="parent" + > + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:text = "Apakah anda ingin mengulang pengambilan foto?" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent" + android:textColor="@color/textColor" + android:layout_marginTop="20dp" + android:layout_marginStart="80dp" + android:layout_marginEnd = "80dp" + android:gravity="center_horizontal" + /> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:gravity="center_horizontal" + android:orientation="horizontal" + android:layout_marginTop="10dp"> + + <androidx.appcompat.widget.AppCompatButton + android:id="@+id/button_tidak_ulang" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="0dp" + android:layout_marginEnd="30dp" + android:background="@drawable/rounded_button" + android:text="Tidak" + android:textColor="@color/white" + app:layout_constraintStart_toStartOf="parent" /> + + <Button + android:id="@+id/button_ulang" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginStart="30dp" + android:layout_marginTop="0dp" + android:background="@drawable/rounded_button" + android:text="Ya" + android:textColor="@color/white" + app:layout_constraintEnd_toEndOf="parent" /> + </LinearLayout> + </LinearLayout> + +</androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file diff --git a/app/src/main/res/navigation/mobile_navigation.xml b/app/src/main/res/navigation/mobile_navigation.xml index 5e4d7bcf2bd3888b99652f21498b93912fec71e1..388197c8cbe8b189ec5445d3bbd41cdc327cf928 100644 --- a/app/src/main/res/navigation/mobile_navigation.xml +++ b/app/src/main/res/navigation/mobile_navigation.xml @@ -19,13 +19,30 @@ android:id="@+id/action_navigation_transaction_to_editTransactionFragment" app:destination="@id/editTransactionFragment" /> </fragment> + <fragment + android:id = "@+id/scan_result" + android:name = "com.example.bandung_bondowoso.view.scan.ScanResultFragment" + android:label = "ScanResult" + tools:layout="@layout/fragment_scan_result"> + <action + android:id = "@+id/action_navigation_result_to_scan" + app:destination="@id/navigation_scan"/> + <action + android:id = "@+id/action_navigation_result_to_transaction" + app:destination="@id/navigation_transaction" /> + + </fragment> <fragment android:id = "@+id/camera_scan" android:name = "com.example.bandung_bondowoso.view.scan.ScanFragment" android:label = "CameraScan" - tools:layout="@layout/fragment_scan" + tools:layout="@layout/fragment_scan"> + <action + android:id = "@+id/action_navigation_camera_to_result" + app:destination="@id/scan_result" /> + </fragment> <fragment android:id="@+id/navigation_scan" android:name="com.example.bandung_bondowoso.view.scan.ScanHomeFragment" @@ -35,6 +52,9 @@ android:id = "@+id/action_navigation_scan_to_camera_scan" app:destination = "@id/camera_scan" /> + <action + android:id = "@+id/action_navigation_scan_to_result" + app:destination="@id/scan_result" /> </fragment> diff --git a/app/src/main/res/values-night/themes.xml b/app/src/main/res/values-night/themes.xml index d5163d3b443b045918a2f93789fdceefbad25206..a3598177e57cf34155c5eafa2c6da739717667c8 100644 --- a/app/src/main/res/values-night/themes.xml +++ b/app/src/main/res/values-night/themes.xml @@ -152,6 +152,9 @@ <item name="android:background">@drawable/bg_button_primary</item> </style> + <style name="buttonStyleShutter" parent="Widget.MaterialComponents.Button"> + <item name="android:background">@drawable/round_button</item> + </style>zz <style name="buttonStyleDanger" parent="Widget.MaterialComponents.Button"> <item name="android:background">@drawable/bg_button_danger</item> <item name="android:textColor">@color/white</item> diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index cafda946330a40d5b83ec312891229bc99ddfb2b..c7170c8d98b4039e9dfb055cf62706cf8fc4da7f 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -167,6 +167,9 @@ <item name="android:background">@drawable/bg_button_primary</item> <item name="android:textColor">@color/white</item> </style> + <style name="buttonStyleShutter" parent="Widget.MaterialComponents.Button"> + <item name="android:background">@drawable/bg_custom_dialog</item> + </style> <style name="buttonStyleDanger" parent="Widget.MaterialComponents.Button"> <item name="android:background">@drawable/bg_button_danger</item>