diff --git a/app/build.gradle.kts b/app/build.gradle.kts index a3bd951c3e163d1da63123731e15f5743ca1284f..1c8421167432f4e800a185ac8886e4b7d62a3499 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -52,10 +52,19 @@ dependencies { implementation("androidx.legacy:legacy-support-v4:1.0.0") implementation("org.apache.poi:poi:5.2.5") implementation("org.apache.poi:poi-ooxml:5.2.5") + implementation("androidx.concurrent:concurrent-futures-ktx:1.1.0") + implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.4.0") testImplementation("junit:junit:4.13.2") androidTestImplementation("androidx.test.ext:junit:1.1.5") androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1") + val cameraxVersion = "1.3.0-rc01" + implementation("androidx.camera:camera-core:$cameraxVersion") + implementation("androidx.camera:camera-camera2:$cameraxVersion") + implementation("androidx.camera:camera-lifecycle:$cameraxVersion") + implementation("androidx.camera:camera-view:$cameraxVersion") + implementation("androidx.camera:camera-extensions:$cameraxVersion") + // ROOM implementation("androidx.room:room-ktx:2.6.1") annotationProcessor("androidx.room:room-compiler:2.6.1") diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 204ed94e48cb7db2c9a28e5788910b92217d7bb6..3a9e66b67af683a17318e0721aa642ecd6dc7727 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,7 +1,8 @@ <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools"> - + <uses-feature android:name="android.hardware.camera.any" /> + <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> @@ -11,6 +12,7 @@ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> + <application android:name=".BandungBondowosoApp" android:allowBackup="true" diff --git a/app/src/main/java/com/example/bandung_bondowoso/view/notifications/NotificationsFragment.kt b/app/src/main/java/com/example/bandung_bondowoso/view/notifications/NotificationsFragment.kt deleted file mode 100644 index 5b8e91b6a53bf8932275877911583a6258d27d09..0000000000000000000000000000000000000000 --- a/app/src/main/java/com/example/bandung_bondowoso/view/notifications/NotificationsFragment.kt +++ /dev/null @@ -1,44 +0,0 @@ -package com.example.bandung_bondowoso.view.notifications - -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.widget.TextView -import androidx.fragment.app.Fragment -import androidx.fragment.app.viewModels -import androidx.lifecycle.ViewModelProvider -import com.example.bandung_bondowoso.BandungBondowosoApp -import com.example.bandung_bondowoso.R -import com.example.bandung_bondowoso.databinding.FragmentNotificationsBinding -import com.example.bandung_bondowoso.viewmodel.NotificationsViewModel -import com.example.bandung_bondowoso.viewmodel.NotificationsViewModelFactory -import com.example.bandung_bondowoso.viewmodel.login.LoginViewModel -import com.example.bandung_bondowoso.viewmodel.login.LoginViewModelFactory - -class NotificationsFragment : Fragment() { - - private var _binding: FragmentNotificationsBinding? = null - - // This property is only valid between onCreateView and - // onDestroyView. - private val binding get() = _binding!! - - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ): View { - _binding = FragmentNotificationsBinding.inflate(inflater, container, false) - val root: View = binding.root - - val textView: TextView = binding.textNotifications - - return root - } - - override fun onDestroyView() { - super.onDestroyView() - _binding = null - } -} \ No newline at end of file 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 new file mode 100644 index 0000000000000000000000000000000000000000..f7953d649ae6ddeba148cd4fa6f2a2f7518def7a --- /dev/null +++ b/app/src/main/java/com/example/bandung_bondowoso/view/scan/ScanFragment.kt @@ -0,0 +1,86 @@ +package com.example.bandung_bondowoso.view.scan +import android.content.Context +import android.content.pm.PackageManager +import android.os.Bundle +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.Toast +import androidx.activity.result.contract.ActivityResultContracts +import androidx.camera.core.CameraSelector +import androidx.camera.view.LifecycleCameraController +import androidx.camera.view.PreviewView +import androidx.core.content.ContextCompat +import androidx.fragment.app.Fragment +import com.example.bandung_bondowoso.databinding.FragmentScanBinding + + +class ScanFragment : Fragment(){ + private var _binding : FragmentScanBinding ? = null + private lateinit var cameraController: LifecycleCameraController + private val binding get() = _binding!! + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + Log.d("ScanFragment", "OnCreateView") + _binding = FragmentScanBinding.inflate(inflater, container, false) + val root: View = binding.root + return root; + } + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + if (!hasPermission(requireContext())) { + activityResultLauncher.launch(REQUIRED_PERMISSIONS) + } else { + startCamera() + } + _binding!!.shutter.setOnClickListener { takePhoto() } + } + + private fun startCamera(){ + val previewView: PreviewView = _binding!!.viewFinder + cameraController = LifecycleCameraController(requireContext()) + cameraController.bindToLifecycle(this) + cameraController.cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA + previewView.controller = cameraController + + } + + private fun takePhoto(){ + val previewView: PreviewView = _binding!!.viewFinder + previewView.controller = null + + } + + private val activityResultLauncher = registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()){ + permissions -> + var permissionGranted = true + permissions.entries.forEach{ + if(it.key in REQUIRED_PERMISSIONS && it.value == false){ + permissionGranted = false + } + } + if(!permissionGranted) { + Toast.makeText(requireContext(), "Permission request denied", Toast.LENGTH_LONG).show() + }else{ + startCamera() + } + } + + companion object { + private const val TAG = "CameraXApp" + private const val FILENAME_FORMAT = "yyyy-MM-dd-HH-mm-ss-SSS" + private val REQUIRED_PERMISSIONS = + mutableListOf( + android.Manifest.permission.CAMERA + ).toTypedArray() + + fun hasPermission(context: Context) = REQUIRED_PERMISSIONS.all{ + 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 new file mode 100644 index 0000000000000000000000000000000000000000..072e947d4ecf8084c1352c49a3d0eeb02b7e2e22 --- /dev/null +++ b/app/src/main/java/com/example/bandung_bondowoso/view/scan/ScanHomeFragment.kt @@ -0,0 +1,46 @@ +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.activity.result.PickVisualMediaRequest +import androidx.activity.result.contract.ActivityResultContracts +import androidx.fragment.app.Fragment +import androidx.navigation.Navigation +import com.example.bandung_bondowoso.R +import com.example.bandung_bondowoso.databinding.FragmentScanHomeBinding + +class ScanHomeFragment: Fragment() { + private var _binding :FragmentScanHomeBinding ? = null; + private val binding get() = _binding!! + private val pickMedia = registerForActivityResult(ActivityResultContracts.PickVisualMedia()) { uri -> + if (uri != null) { + Log.d("PhotoPicker", "Selected URI: $uri") + } else { + Log.d("PhotoPicker", "No photo selected") + } + } + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + Log.d("ScanHomeFragment", "OnCreateView") + _binding = FragmentScanHomeBinding.inflate(inflater, container, false) + val root: View = binding.root + binding.toScanButton.setOnClickListener { + Navigation.findNavController(root).navigate(R.id.action_navigation_scan_to_camera_scan) + } + binding.toGaleriButton.setOnClickListener{ + pickImageGallery() + } + return root; + } + + private fun pickImageGallery(){ + pickMedia.launch(PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly)) + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/example/bandung_bondowoso/view/twibbon/TwibbonFragment.kt b/app/src/main/java/com/example/bandung_bondowoso/view/twibbon/TwibbonFragment.kt new file mode 100644 index 0000000000000000000000000000000000000000..4702f006af1edfdd925deeb85476c48a7d2b233d --- /dev/null +++ b/app/src/main/java/com/example/bandung_bondowoso/view/twibbon/TwibbonFragment.kt @@ -0,0 +1,143 @@ +package com.example.bandung_bondowoso.view.twibbon + +import android.content.Context +import android.content.pm.PackageManager +import android.os.Bundle +import androidx.fragment.app.Fragment +import android.view.LayoutInflater +import android.view.View +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.Preview +import androidx.camera.lifecycle.ProcessCameraProvider +import androidx.camera.view.LifecycleCameraController +import androidx.camera.view.PreviewView +import androidx.core.content.ContextCompat +import com.example.bandung_bondowoso.databinding.FragmentTwibbonBinding + +class TwibbonFragment : Fragment() { + private var _binding : FragmentTwibbonBinding? = null + private lateinit var cameraController: LifecycleCameraController + private val binding get() = _binding!! + private var freeze = false + private lateinit var imageCapture: ImageCapture + private var selectedImage: View? = null + + companion object { + private val REQUIRED_PERMISSIONS = + mutableListOf( + android.Manifest.permission.CAMERA + ).toTypedArray() + fun hasPermission(context: Context) = TwibbonFragment.REQUIRED_PERMISSIONS.all{ + ContextCompat.checkSelfPermission(context, it) == PackageManager.PERMISSION_GRANTED; + } + } + + private lateinit var preview:Preview + + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + _binding = FragmentTwibbonBinding.inflate(inflater, container, false) + return binding.root; + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + if (!hasPermission(requireContext())) { + requestCameraPermission() + } else { + startCamera() + } + selectedImage = binding.twibbon1 + imageCapture = ImageCapture.Builder().build() + _binding!!.shutter.setOnClickListener { + freeze = !freeze + takePhoto() } + _binding!!.buttonRetake.setOnClickListener { + freeze = false + binding.imageButtonSoobin.visibility = View.VISIBLE + binding.imageButtonFaker.visibility = View.VISIBLE + _binding!!.shutter.visibility = View.VISIBLE + _binding!!.buttonRetake.visibility = View.GONE + startCamera() + } + binding.imageButtonSoobin.setOnClickListener { + binding.twibbon1.visibility = View.VISIBLE + binding.twibbon2.visibility = View.GONE + selectedImage = binding.twibbon1 + } + + binding.imageButtonFaker.setOnClickListener{ + binding.twibbon2.visibility = View.VISIBLE + binding.twibbon1.visibility = View.GONE + selectedImage = binding.twibbon2 + } + } + private fun startCamera(){ + freeze = false + val cameraProviderFuture = ProcessCameraProvider.getInstance(requireContext()) + + cameraProviderFuture.addListener({ + val cameraProvider = cameraProviderFuture.get() + + preview = Preview.Builder().build().also { + it.setSurfaceProvider(binding.viewFinder.surfaceProvider) + } + + val cameraSelector = CameraSelector.DEFAULT_FRONT_CAMERA + binding.viewFinder.implementationMode = PreviewView.ImplementationMode.COMPATIBLE + binding.viewFinder.overlay.add(selectedImage!!) + preview.setSurfaceProvider(binding.viewFinder.surfaceProvider) + imageCapture = ImageCapture.Builder().build() + + try { + cameraProvider.unbindAll() + cameraProvider.bindToLifecycle(this, cameraSelector, preview, imageCapture) + } catch (e: Exception) { + Toast.makeText(requireContext(), "Error starting camera", Toast.LENGTH_SHORT).show() + } + }, ContextCompat.getMainExecutor(requireContext())) + } + + private fun takePhoto() { + if (freeze) { + preview.setSurfaceProvider(null) + _binding!!.shutter.visibility = View.GONE + _binding!!.buttonRetake.visibility = View.VISIBLE + binding.imageButtonSoobin.visibility = View.GONE + binding.imageButtonFaker.visibility = View.GONE + } else { + preview.setSurfaceProvider(binding.viewFinder.surfaceProvider) + _binding!!.shutter.visibility = View.VISIBLE + _binding!!.buttonRetake.visibility = View.GONE + binding.imageButtonSoobin.visibility = View.VISIBLE + binding.imageButtonFaker.visibility = View.VISIBLE + } + } + + private val activityResultLauncher = registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()){ + permissions -> + var permissionGranted = true + permissions.entries.forEach{ + entry -> + if (entry.key in REQUIRED_PERMISSIONS && !entry.value) { + permissionGranted = false + } + } + if(!permissionGranted) { + Toast.makeText(requireContext(), "Permission request denied", Toast.LENGTH_LONG).show() + }else{ + startCamera() + } + } + + private fun requestCameraPermission() { + activityResultLauncher.launch(REQUIRED_PERMISSIONS) + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/example/bandung_bondowoso/viewmodel/NotificationsViewModel.kt b/app/src/main/java/com/example/bandung_bondowoso/viewmodel/NotificationsViewModel.kt deleted file mode 100644 index 57bedf6ef1f5e4a42a747b66adf72763a70fcd61..0000000000000000000000000000000000000000 --- a/app/src/main/java/com/example/bandung_bondowoso/viewmodel/NotificationsViewModel.kt +++ /dev/null @@ -1,69 +0,0 @@ -package com.example.bandung_bondowoso.viewmodel - -import android.content.Context -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.ViewModel -import androidx.lifecycle.ViewModelProvider -import androidx.lifecycle.viewModelScope -import com.example.bandung_bondowoso.model.NetworkResult -import com.example.bandung_bondowoso.model.Token -import com.example.bandung_bondowoso.remote.ApiClient -import com.example.bandung_bondowoso.repository.UserRepository -import com.example.bandung_bondowoso.viewmodel.login.LoginViewModel -import kotlinx.coroutines.launch - -class NotificationsViewModel(private val userRepository: UserRepository) : ViewModel() { - - private val _text = MutableLiveData<String>().apply { - value = "This is notifications Fragment" - } - val text: LiveData<String> = _text - - private val _token = MutableLiveData<Token?>() - val token: LiveData<Token?> = _token - - private val _errorMessage = MutableLiveData<String?>() - val errorMessage: LiveData<String?> = _errorMessage - - private val _responseCode = MutableLiveData<Int>() - val responseCode: LiveData<Int> = _responseCode - - fun login(email: String, password: String) = viewModelScope.launch { - when (val response = userRepository.login(email, password)) { - is NetworkResult.Success -> { - _token.value = response.data - _errorMessage.value = null - _responseCode.value = response.code - } - is NetworkResult.Error -> { - _token.value = null - _responseCode.value = response.code - - if (!response.errorByPaths.isNullOrEmpty()) { - _errorMessage.value = response.errorByPaths.joinToString { - "${it.path}: ${it.message}" - } - } else { - _errorMessage.value = response.errorMsg - } - } - is NetworkResult.Exception -> { - _token.value = null - _errorMessage.value = response.e.message - _responseCode.value = 500 - } - } - } -} - -class NotificationsViewModelFactory(private val userRepository: UserRepository) : ViewModelProvider.Factory { - override fun <T : ViewModel> create(modelClass: Class<T>): T { - if (modelClass.isAssignableFrom(NotificationsViewModel::class.java)) { - @Suppress("UNCHECKED_CAST") - return NotificationsViewModel(userRepository) as T - } - throw IllegalArgumentException("Unknown ViewModel class") - } -} - diff --git a/app/src/main/res/drawable/ic_twibbon_faker.png b/app/src/main/res/drawable/ic_twibbon_faker.png new file mode 100644 index 0000000000000000000000000000000000000000..2f7ab4110c111eb722a713067f5e045e7d06c637 Binary files /dev/null and b/app/src/main/res/drawable/ic_twibbon_faker.png differ diff --git a/app/src/main/res/drawable/ic_twibbon_soobin.png b/app/src/main/res/drawable/ic_twibbon_soobin.png new file mode 100644 index 0000000000000000000000000000000000000000..14d2dad929ae7e0050f1ec926a895a06f43d095c Binary files /dev/null and b/app/src/main/res/drawable/ic_twibbon_soobin.png differ diff --git a/app/src/main/res/drawable/round_button.xml b/app/src/main/res/drawable/round_button.xml new file mode 100644 index 0000000000000000000000000000000000000000..a4c6e5099fbe20b9e073dbea48279d04b6ce8d61 --- /dev/null +++ b/app/src/main/res/drawable/round_button.xml @@ -0,0 +1,13 @@ +<?xml version = "1.0" encoding = "utf-8"?> +<selector xmlns:android = "http://schemas.android.com/apk/res/android"> + <item android:state_pressed = "false"> + <shape android:shape = "oval"> + <solid android:color = "#ffffff"/> + </shape> + </item> + <item android:state_pressed = "true"> + <shape android:shape = "oval"> + <solid android:color = "#ffffff"/> + </shape> + </item> +</selector> \ No newline at end of file diff --git a/app/src/main/res/drawable/round_button_blue.xml b/app/src/main/res/drawable/round_button_blue.xml new file mode 100644 index 0000000000000000000000000000000000000000..93b9c33707ace6d9c3014ede825dcb9c127c1594 --- /dev/null +++ b/app/src/main/res/drawable/round_button_blue.xml @@ -0,0 +1,13 @@ +<?xml version = "1.0" encoding = "utf-8"?> +<selector xmlns:android = "http://schemas.android.com/apk/res/android"> + <item android:state_pressed = "false"> + <shape android:shape = "oval"> + <solid android:color = "@color/md_theme_primary" /> + </shape> + </item> + <item android:state_pressed = "true"> + <shape android:shape = "oval"> + <solid android:color = "@color/md_theme_primary"/> + </shape> + </item> +</selector> \ No newline at end of file diff --git a/app/src/main/res/drawable/scan.png b/app/src/main/res/drawable/scan.png new file mode 100644 index 0000000000000000000000000000000000000000..c838cd68be6b992eaabe1f6e26ce6235cc9e205f Binary files /dev/null and b/app/src/main/res/drawable/scan.png differ diff --git a/app/src/main/res/drawable/twibbon_faker.png b/app/src/main/res/drawable/twibbon_faker.png new file mode 100644 index 0000000000000000000000000000000000000000..c002a4c3b7dfb53c3ae5c38633a092a0c6d2ac6c Binary files /dev/null and b/app/src/main/res/drawable/twibbon_faker.png differ diff --git a/app/src/main/res/drawable/twibbon_soobim.png b/app/src/main/res/drawable/twibbon_soobim.png new file mode 100644 index 0000000000000000000000000000000000000000..cc6a2b3cca00d053074399b92788d9250725c409 Binary files /dev/null and b/app/src/main/res/drawable/twibbon_soobim.png differ diff --git a/app/src/main/res/layout/fragment_notifications.xml b/app/src/main/res/layout/fragment_notifications.xml deleted file mode 100644 index 0da8ca89c6263f24b6d420788ae841fb545d3f61..0000000000000000000000000000000000000000 --- a/app/src/main/res/layout/fragment_notifications.xml +++ /dev/null @@ -1,117 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<androidx.constraintlayout.widget.ConstraintLayout 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" - tools:context=".view.notifications.NotificationsFragment"> - - <TextView - android:id="@+id/text_notifications" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginStart="8dp" - android:layout_marginTop="8dp" - android:layout_marginEnd="8dp" - android:textAlignment="center" - android:textSize="20sp" - app:layout_constraintBottom_toTopOf="@id/text_token" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toTopOf="parent" /> - - <TextView - android:id="@+id/text_token" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginStart="8dp" - android:layout_marginTop="8dp" - android:layout_marginEnd="8dp" - android:textAlignment="center" - android:textSize="20sp" - app:layout_constraintBottom_toTopOf="@id/text_error_message" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toBottomOf="@id/text_notifications" - /> - - <TextView - android:id="@+id/text_error_message" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginStart="8dp" - android:layout_marginTop="8dp" - android:layout_marginEnd="8dp" - android:textAlignment="center" - android:textSize="20sp" - app:layout_constraintBottom_toTopOf="@id/text_response_code" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toBottomOf="@id/text_token" - /> - - <TextView - android:id="@+id/text_response_code" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:layout_marginStart="8dp" - android:layout_marginTop="8dp" - android:layout_marginEnd="8dp" - android:textAlignment="center" - android:textSize="20sp" - app:layout_constraintBottom_toTopOf="@id/button_login" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toBottomOf="@id/text_error_message" - /> - - <Button - android:id="@+id/button_login" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="Login" - app:layout_constraintTop_toBottomOf="@id/text_response_code" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintEnd_toEndOf="parent" - /> - - <Button - android:id="@+id/button_login_wrong_credentials" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="Login Wrong Credentials" - app:layout_constraintTop_toBottomOf="@id/button_login" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintEnd_toEndOf="parent" - /> - - <Button - android:id="@+id/button_login_pass_less_than_8" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="Login Pass Less Than 8" - app:layout_constraintTop_toBottomOf="@id/button_login_wrong_credentials" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintEnd_toEndOf="parent" - /> - - <Button - android:id="@+id/button_login_invalid_email" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="Login Invalid Email" - app:layout_constraintTop_toBottomOf="@id/button_login_pass_less_than_8" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintEnd_toEndOf="parent" - /> - - <Button - android:id="@+id/button_login_invalid_both" - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="Login Invalid Both" - app:layout_constraintTop_toBottomOf="@id/button_login_invalid_email" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintEnd_toEndOf="parent" - /> -</androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_scan.xml b/app/src/main/res/layout/fragment_scan.xml new file mode 100644 index 0000000000000000000000000000000000000000..54ebb32706a503200cf06c7d2597da1787e704fd --- /dev/null +++ b/app/src/main/res/layout/fragment_scan.xml @@ -0,0 +1,52 @@ +<?xml version="1.0" encoding="utf-8"?> +<androidx.constraintlayout.widget.ConstraintLayout 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:background="@color/md_theme_primary" + android:paddingHorizontal="30dp"> + + <TextView + android:id="@+id/tv_scan_title" + style="@style/TextAppearance.HeadlineLarge" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="@dimen/title_top_margin" + android:text="@string/title_scan" + android:textColor="@color/white" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + + <androidx.cardview.widget.CardView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="90dp" + app:cardCornerRadius="50dp" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/tv_scan_title"> + + <androidx.camera.view.PreviewView + android:id="@+id/viewFinder" + android:layout_width="330dp" + android:layout_height="330dp" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintHorizontal_bias="0.476" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintVertical_bias="0.394" /> + </androidx.cardview.widget.CardView> + + <androidx.appcompat.widget.AppCompatButton + android:id="@+id/shutter" + android:layout_width="57dp" + android:layout_height="57dp" + android:layout_marginBottom="112dp" + android:background="@drawable/round_button" + android:elevation="2dp" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintLeft_toLeftOf="parent" + app:layout_constraintRight_toRightOf="parent" /> +</androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_scan_home.xml b/app/src/main/res/layout/fragment_scan_home.xml new file mode 100644 index 0000000000000000000000000000000000000000..53b37e0ea2256f75fb66ecce9900ca11f9fbf7af --- /dev/null +++ b/app/src/main/res/layout/fragment_scan_home.xml @@ -0,0 +1,73 @@ +<?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" + + android:background="@color/md_theme_primary" + xmlns:app="http://schemas.android.com/apk/res-auto"> + <TextView + android:id="@+id/tv_scan_title" + style="@style/TextAppearance.HeadlineLarge" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="@dimen/title_top_margin" + android:layout_marginStart="30dp" + android:text="@string/title_scan" + android:textColor="@color/white" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + + <TextView + android:id = "@+id/tv_scan_deskripsi" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="20dp" + android:text="Tidak perlu masukin manual! Scan saja!!" + android:textColor="@color/white" + android:textSize="16sp" + app:layout_constraintStart_toStartOf="@+id/tv_scan_title" + app:layout_constraintTop_toBottomOf="@+id/tv_scan_title" + tools:layout_editor_absoluteX="1dp" /> + + <ImageView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginStart="0dp" + android:layout_marginTop="0dp" + android:src="@drawable/scan" + app:layout_constraintStart_toStartOf="@+id/tv_scan_title" + app:layout_constraintTop_toBottomOf="@+id/tv_scan_deskripsi" /> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="190dp" + android:background="@color/white" + android:orientation="vertical" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintStart_toStartOf="parent" + tools:layout_editor_absoluteX="60dp"> + + <Button + android:id = "@+id/to_scan_button" + style="@style/buttonStylePrimary" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginStart="30dp" + android:layout_marginTop="25dp" + android:layout_marginEnd="30dp" + android:text="Foto Struk" /> + + <Button + android:id = "@+id/to_galeri_button" + style="@style/buttonStylePrimary" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginStart="30dp" + android:layout_marginTop="10dp" + android:layout_marginEnd="30dp" + android:text="Buka Galeri" /> + </LinearLayout> + + +</androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_twibbon.xml b/app/src/main/res/layout/fragment_twibbon.xml new file mode 100644 index 0000000000000000000000000000000000000000..ac37b109c61ee31b426092faffdb73b47475c0d7 --- /dev/null +++ b/app/src/main/res/layout/fragment_twibbon.xml @@ -0,0 +1,128 @@ +<?xml version="1.0" encoding="utf-8"?> +<androidx.constraintlayout.widget.ConstraintLayout 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:background="@color/md_theme_surface" + android:layout_height="match_parent" + tools:context=".view.twibbon.TwibbonFragment" + > + <TextView + android:id="@+id/tv_title_fragment" + style="@style/TextAppearance.HeadlineLarge" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginStart="@dimen/title_start_margin" + android:layout_marginTop="@dimen/title_top_margin" + android:text="@string/title_twibbon" + android:textColor="@color/md_theme_primary" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + + <androidx.cardview.widget.CardView + android:id="@+id/cardView" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="60dp" + app:cardCornerRadius="50dp" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/tv_title_fragment"> + + <androidx.camera.view.PreviewView + android:id="@+id/viewFinder" + android:layout_width="330dp" + android:layout_height="330dp" + app:layout_constraintBottom_toTopOf="@id/twibbon1" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + + <FrameLayout + android:layout_width="match_parent" + android:layout_height="match_parent" + > + + <ImageView + android:id="@+id/twibbon1" + android:layout_width="330dp" + android:layout_height="330dp" + android:src="@drawable/twibbon_soobim" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + android:contentDescription="@string/cd_twibon_soobin" + app:layout_constraintTop_toBottomOf="@+id/viewFinder" /> + + <ImageView + android:id="@+id/twibbon2" + android:layout_width="330dp" + android:layout_height="330dp" + android:src="@drawable/twibbon_faker" + android:visibility="gone" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + android:contentDescription="@string/cd_twibon_faker" + app:layout_constraintTop_toBottomOf="@+id/viewFinder" /> + </FrameLayout> + + + </androidx.cardview.widget.CardView> + + + <androidx.appcompat.widget.AppCompatButton + android:id="@+id/shutter" + android:layout_width="57dp" + android:layout_height="57dp" + android:layout_marginBottom="112dp" + android:background="@drawable/round_button_blue" + android:elevation="2dp" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintLeft_toLeftOf="parent" + app:layout_constraintRight_toRightOf="parent" + android:text="@string/label_shutter" + android:textColor="@color/md_theme_primary" + android:tooltipText="@string/label_shutter" + /> + + <Button + android:id="@+id/buttonRetake" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginBottom="112dp" + android:text="@string/btn_retake" + android:visibility="gone" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" /> + + <ImageButton + android:id="@+id/imageButtonSoobin" + android:layout_width="72dp" + android:layout_height="72dp" + android:layout_marginStart="76dp" + android:layout_marginTop="72dp" + android:src="@drawable/ic_twibbon_soobin" + android:scaleType="fitCenter" + android:backgroundTint="@color/md_theme_primary" + app:layout_constraintStart_toStartOf="parent" + android:contentDescription="@string/cd_twibon_soobin" + app:layout_constraintTop_toBottomOf="@+id/cardView" /> + + <ImageButton + android:id="@+id/imageButtonFaker" + android:layout_width="72dp" + android:layout_height="72dp" + android:layout_marginTop="72dp" + android:layout_marginEnd="84dp" + android:contentDescription="@string/cd_twibon_faker" + android:src="@drawable/ic_twibbon_faker" + android:backgroundTint="@color/md_theme_primary" + app:layout_constraintEnd_toEndOf="parent" + android:scaleType="fitCenter" + app:layout_constraintHorizontal_bias="0.971" + app:layout_constraintStart_toEndOf="@+id/imageButtonSoobin" + app:layout_constraintTop_toBottomOf="@+id/cardView" /> + +</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 d1f85e9422bc5710f1accea6ba584031704251c0..5e4d7bcf2bd3888b99652f21498b93912fec71e1 100644 --- a/app/src/main/res/navigation/mobile_navigation.xml +++ b/app/src/main/res/navigation/mobile_navigation.xml @@ -20,18 +20,24 @@ app:destination="@id/editTransactionFragment" /> </fragment> - + <fragment + android:id = "@+id/camera_scan" + android:name = "com.example.bandung_bondowoso.view.scan.ScanFragment" + android:label = "CameraScan" + tools:layout="@layout/fragment_scan" + /> <fragment android:id="@+id/navigation_scan" - android:name="com.example.bandung_bondowoso.view.dashboard.DashboardFragment" + android:name="com.example.bandung_bondowoso.view.scan.ScanHomeFragment" android:label="@string/title_scan" - tools:layout="@layout/fragment_dashboard" /> + tools:layout="@layout/fragment_scan_home"> + <action + android:id = "@+id/action_navigation_scan_to_camera_scan" + app:destination = "@id/camera_scan" + /> + </fragment> + - <fragment - android:id="@+id/navigation_twibbon" - android:name="com.example.bandung_bondowoso.view.notifications.NotificationsFragment" - android:label="@string/title_twibbon" - tools:layout="@layout/fragment_notifications" /> <fragment android:id = "@+id/navigation_settings" android:name= "com.example.bandung_bondowoso.view.setting.SettingFragment" @@ -99,6 +105,11 @@ app:popUpToInclusive="true" /> </fragment> + <fragment + android:id="@+id/navigation_twibbon" + android:name="com.example.bandung_bondowoso.view.twibbon.TwibbonFragment" + android:label="fragment_twibbon" + tools:layout="@layout/fragment_twibbon" /> </navigation> \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index d2c0d80060d17f936b4d8fb6d4cb889995c893e3..1581753ef67379a26ff68dcb250f144a23b0e941 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -33,6 +33,8 @@ <string name="cd_transaction_create">Create New Transaction</string> <string name="cd_transaction_modify">Edit/Delete Existing Transaction</string> <string name="cd_transaction_empty">No Transaction Available</string> + <string name="cd_twibon_soobin">Twibon Soobin</string> + <string name="cd_twibon_faker">Twibon Faker</string> <!--Label--> <string name="label_transaction">Judul Transaksi</string> <string name="label_price">Nominal Transaksi</string> @@ -41,6 +43,7 @@ <string name="label_pembelian">Pengeluaran</string> <string name="label_pemasukan">Pemasukan</string> <string name="label_mata_uang">IDR</string> + <string name="label_shutter">Shutter</string> <!--Hint--> <string name="hint_transaction_new">Nama Transaksi</string> <string name="hint_transaction_price">Jumlah Nominal</string> @@ -78,6 +81,7 @@ <string name="login_button_text">Masuk</string> <string name="no_network">OOPS!</string> <string name="img_no_network_description">Tidak ada internet\n</string> + <string name="img_twibbon_preview">Hasil Twibbon</string> <string name="no_network_description">Kamu terputus dari internet. Silahkan cek pengaturan internet kamu</string> <string name="save_transaction">Simpan Daftar Transaksi</string> <string name="file_type">.xlsx/.xls</string> @@ -91,6 +95,7 @@ <string name="okay">Oke</string> <string name="tv_settings_alert_email_no_network">Tidak ada koneksi internet</string> <string name="tv_description_settings_email_no_network">Silahkan cek pengaturan internet kamu</string> + <string name="btn_retake">Retake</string> </resources> \ No newline at end of file