From d861c278a24483da135c75893daf9c335c58cba8 Mon Sep 17 00:00:00 2001
From: MooN <56061215+MgKyawLay@users.noreply.github.com>
Date: Sun, 9 Nov 2025 16:32:15 +0630
Subject: [PATCH] qr_generate
---
.idea/copilot.data.migration.agent.xml | 6 +
.idea/copilot.data.migration.ask.xml | 6 +
.idea/copilot.data.migration.edit.xml | 6 +
app/build.gradle | 3 +-
.../main/java/com/utsmm/kbz/MainFragment.java | 53 +--
.../utsmm/kbz/ui/adapters/QRPayAdapter.java | 68 +++
.../utsmm/kbz/ui/qr_pay/QRPayFragment.java | 387 ++++++++++++++++++
.../com/utsmm/kbz/ui/qr_pay/QRPayItem.java | 11 +
.../utsmm/kbz/ui/qr_pay/QRPayViewModel.java | 17 +
app/src/main/res/layout/fragment_qr_pay.xml | 42 ++
.../main/res/layout/item_qr_pay_button.xml | 63 +++
.../main/res/navigation/mobile_navigation.xml | 15 +-
gradle/libs.versions.toml | 6 +
13 files changed, 657 insertions(+), 26 deletions(-)
create mode 100644 .idea/copilot.data.migration.agent.xml
create mode 100644 .idea/copilot.data.migration.ask.xml
create mode 100644 .idea/copilot.data.migration.edit.xml
create mode 100644 app/src/main/java/com/utsmm/kbz/ui/adapters/QRPayAdapter.java
create mode 100644 app/src/main/java/com/utsmm/kbz/ui/qr_pay/QRPayFragment.java
create mode 100644 app/src/main/java/com/utsmm/kbz/ui/qr_pay/QRPayItem.java
create mode 100644 app/src/main/java/com/utsmm/kbz/ui/qr_pay/QRPayViewModel.java
create mode 100644 app/src/main/res/layout/fragment_qr_pay.xml
create mode 100644 app/src/main/res/layout/item_qr_pay_button.xml
diff --git a/.idea/copilot.data.migration.agent.xml b/.idea/copilot.data.migration.agent.xml
new file mode 100644
index 0000000..4ea72a9
--- /dev/null
+++ b/.idea/copilot.data.migration.agent.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/copilot.data.migration.ask.xml b/.idea/copilot.data.migration.ask.xml
new file mode 100644
index 0000000..7ef04e2
--- /dev/null
+++ b/.idea/copilot.data.migration.ask.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/copilot.data.migration.edit.xml b/.idea/copilot.data.migration.edit.xml
new file mode 100644
index 0000000..8648f94
--- /dev/null
+++ b/.idea/copilot.data.migration.edit.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
index f1b546e..94f6fad 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -88,7 +88,8 @@ kapt {
dependencies {
implementation fileTree(include: ['*.jar', '*.aar'], dir: 'libs')
-
+ implementation libs.androidx.lifecycle.livedata.ktx
+ implementation libs.androidx.lifecycle.viewmodel.ktx
def nav_version = "2.3.2"
diff --git a/app/src/main/java/com/utsmm/kbz/MainFragment.java b/app/src/main/java/com/utsmm/kbz/MainFragment.java
index 795be0a..ca08238 100644
--- a/app/src/main/java/com/utsmm/kbz/MainFragment.java
+++ b/app/src/main/java/com/utsmm/kbz/MainFragment.java
@@ -849,31 +849,38 @@ public class MainFragment extends DataBindingFragment {
}
}
- public void onClickQRPay() {
-
- String mmqrIp = SystemParamsOperation.getInstance().getSecHostIpAddress();
-
- if (mainViewModel.payDetailSingle.getValue() != null) {
- mainViewModel.startReversal(mainViewModel.payDetailSingle.getValue());
- }
-// else if (TMSUtil.getInstance().checkSecHostParams().isStatus() == ValidityStatus.FAILURE) {
-// showDeclineDialog(getResourceString(R.string.txt_please_download_config)+"\n"+TMSUtil.getInstance().checkSecHostParams().getMessage());
-// }
- else if (!Connectivity.isConnectedWifi(getContext()) && !Connectivity.isConnectedMobile(getContext())) {
- showSingleInfoDialog(getResourceString(R.string.txt_please_enable_internet));
- }
-// else if (!isValidDomain(mmqrIp)) {
-// showDeclineDialog(getResourceString(R.string.txt_please_check_mmqr_ip));
-// }
- else {
- CurrencyType currencyType = TMSUtil.getInstance().currencyTextToCurrencyType(SystemParamsOperation.getInstance().getSecHostCurrency());
- sharedViewModel.set_currencyText(currencyType.name);
- processBatch();
- sharedViewModel.transactionsType.setValue(TransactionsType.MMQR);
- navigateToAmount();
- }
+ public void onClickQRPay(){
+ // navigate to new QR Pay fragment
+ routeId = R.id.action_nav_main_to_qrFragment;
+ safeNavigateToRouteId();
}
+// public void onClickQRPay() {
+//
+// String mmqrIp = SystemParamsOperation.getInstance().getSecHostIpAddress();
+//
+// if (mainViewModel.payDetailSingle.getValue() != null) {
+// mainViewModel.startReversal(mainViewModel.payDetailSingle.getValue());
+// }
+//// else if (TMSUtil.getInstance().checkSecHostParams().isStatus() == ValidityStatus.FAILURE) {
+//// showDeclineDialog(getResourceString(R.string.txt_please_download_config)+"\n"+TMSUtil.getInstance().checkSecHostParams().getMessage());
+//// }
+// else if (!Connectivity.isConnectedWifi(getContext()) && !Connectivity.isConnectedMobile(getContext())) {
+// showSingleInfoDialog(getResourceString(R.string.txt_please_enable_internet));
+// }
+//// else if (!isValidDomain(mmqrIp)) {
+//// showDeclineDialog(getResourceString(R.string.txt_please_check_mmqr_ip));
+//// }
+// else {
+// CurrencyType currencyType = TMSUtil.getInstance().currencyTextToCurrencyType(SystemParamsOperation.getInstance().getSecHostCurrency());
+// sharedViewModel.set_currencyText(currencyType.name);
+// processBatch();
+// sharedViewModel.transactionsType.setValue(TransactionsType.MMQR);
+// navigateToAmount();
+//
+// }
+// }
+
public void onClickSettlement() {
if (mainViewModel.payDetailSingle.getValue() != null) {
diff --git a/app/src/main/java/com/utsmm/kbz/ui/adapters/QRPayAdapter.java b/app/src/main/java/com/utsmm/kbz/ui/adapters/QRPayAdapter.java
new file mode 100644
index 0000000..ce980c2
--- /dev/null
+++ b/app/src/main/java/com/utsmm/kbz/ui/adapters/QRPayAdapter.java
@@ -0,0 +1,68 @@
+package com.utsmm.kbz.ui.adapters;
+
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+import androidx.databinding.DataBindingUtil;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.utsmm.kbz.R;
+import com.utsmm.kbz.databinding.ItemQrPayButtonBinding;
+import com.utsmm.kbz.ui.qr_pay.QRPayItem;
+
+import java.util.List;
+
+public class QRPayAdapter extends RecyclerView.Adapter {
+
+ public interface OnItemClickListener {
+ void onItemClick(int position);
+ }
+
+ private final List items;
+ private final OnItemClickListener listener;
+
+ public QRPayAdapter(List item, OnItemClickListener listener) {
+ this.items = item;
+ this.listener = listener;
+ }
+
+ @NonNull
+ @Override
+ public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ ItemQrPayButtonBinding binding = DataBindingUtil.inflate(
+ LayoutInflater.from(parent.getContext()),
+ R.layout.item_qr_pay_button,
+ parent,
+ false
+ );
+ return new ViewHolder(binding);
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
+ QRPayItem item = items.get(position);
+ holder.binding.setText(item.title);
+ holder.binding.setIcon(item.icon);
+ holder.binding.btnItem.setOnClickListener(v -> {
+ if(listener != null){
+ listener.onItemClick(position);
+ }
+ });
+ }
+
+ @Override
+ public int getItemCount() {
+ return items == null ? 0 : items.size();
+ }
+
+ public static class ViewHolder extends RecyclerView.ViewHolder {
+ final ItemQrPayButtonBinding binding;
+ public ViewHolder(@NonNull ItemQrPayButtonBinding binding) {
+ super(binding.getRoot());
+ this.binding = binding;
+ }
+ }
+}
+
diff --git a/app/src/main/java/com/utsmm/kbz/ui/qr_pay/QRPayFragment.java b/app/src/main/java/com/utsmm/kbz/ui/qr_pay/QRPayFragment.java
new file mode 100644
index 0000000..64908eb
--- /dev/null
+++ b/app/src/main/java/com/utsmm/kbz/ui/qr_pay/QRPayFragment.java
@@ -0,0 +1,387 @@
+package com.utsmm.kbz.ui.qr_pay;
+
+import androidx.lifecycle.Observer;
+import androidx.lifecycle.ViewModelProvider;
+import androidx.navigation.fragment.NavHostFragment;
+
+import com.utsmm.kbz.BR;
+import com.utsmm.kbz.MainViewModel;
+import com.utsmm.kbz.R;
+import com.utsmm.kbz.config.Constants;
+import com.utsmm.kbz.ui.adapters.QRPayAdapter;
+import com.utsmm.kbz.ui.core_viewmodel.SharedViewModel;
+import com.utsmm.kbz.util.Connectivity;
+import com.utsmm.kbz.util.tms.TMSUtil;
+import com.utsmyanmar.baselib.util.DataBindingConfig;
+import com.utsmyanmar.baselib.fragment.DataBindingFragment;
+import com.utsmyanmar.paylibs.model.PayDetail;
+import com.utsmyanmar.paylibs.utils.POSUtil;
+import com.utsmyanmar.paylibs.utils.core_utils.SystemParamsOperation;
+import com.utsmyanmar.paylibs.utils.enums.CurrencyType;
+import com.utsmyanmar.paylibs.utils.iso_utils.TransactionsType;
+
+import java.util.Date;
+import java.util.List;
+
+public class QRPayFragment extends DataBindingFragment {
+
+ private MainViewModel mainViewModel;
+ private SharedViewModel sharedViewModel;
+ private static final int hostId = Constants.NAV_HOST_ID;
+ private int routeId;
+ private static final int currentId = R.id.dashboardTransFragment;
+
+ public static QRPayFragment newInstance() {
+ return new QRPayFragment();
+ }
+
+ private QRPayViewModel vm;
+ private Observer observeLastTrans;
+ private PayDetail lastPay;
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ setToolBarTitleWithBackIcon("QR Pay");
+ }
+
+ @Override
+ protected void initViewModel() {
+ vm = new ViewModelProvider(this).get(QRPayViewModel.class);
+ mainViewModel = new ViewModelProvider(requireActivity()).get(MainViewModel.class);
+ sharedViewModel = new ViewModelProvider(requireActivity()).get(SharedViewModel.class);
+ }
+
+ @Override
+ protected DataBindingConfig getDataBindingConfig() {
+
+ List features = List.of(
+ new QRPayItem("Generate QR", R.drawable.ic_qr_pay),
+ new QRPayItem("Refund", R.drawable.ic_refund),
+ new QRPayItem("History", R.drawable.ic_history)
+ );
+
+ QRPayAdapter adapter = new QRPayAdapter(features, position -> {
+ QRPayItem selectedBtn = features.get(position);
+ switch (selectedBtn.title){
+ case "Generate QR":
+ onClickQRPay();
+ break;
+ case "Refund":
+
+ break;
+ case "History":
+
+ break;
+ }
+ });
+
+ DataBindingConfig config = new DataBindingConfig(R.layout.fragment_qr_pay, BR.vm, vm);
+ config.addBindingParam(BR.adapter, adapter);
+ return config;
+ }
+
+ @Override
+ protected int currentId() {
+ return currentId;
+ }
+
+ @Override
+ protected int hostId() {
+ return hostId;
+ }
+
+ @Override
+ protected int routeId() {
+ return routeId;
+ }
+
+ public void onClickQRPay() {
+
+ String mmqrIp = SystemParamsOperation.getInstance().getSecHostIpAddress();
+
+ if (mainViewModel.payDetailSingle.getValue() != null) {
+ mainViewModel.startReversal(mainViewModel.payDetailSingle.getValue());
+ }
+// else if (TMSUtil.getInstance().checkSecHostParams().isStatus() == ValidityStatus.FAILURE) {
+// showDeclineDialog(getResourceString(R.string.txt_please_download_config)+"\n"+TMSUtil.getInstance().checkSecHostParams().getMessage());
+// }
+ else if (!Connectivity.isConnectedWifi(getContext()) && !Connectivity.isConnectedMobile(getContext())) {
+ showSingleInfoDialog(getResourceString(R.string.txt_please_enable_internet));
+ }
+// else if (!isValidDomain(mmqrIp)) {
+// showDeclineDialog(getResourceString(R.string.txt_please_check_mmqr_ip));
+// }
+ else {
+ CurrencyType currencyType = TMSUtil.getInstance().currencyTextToCurrencyType(SystemParamsOperation.getInstance().getSecHostCurrency());
+ sharedViewModel.set_currencyText(currencyType.name);
+ processBatch();
+ sharedViewModel.transactionsType.setValue(TransactionsType.MMQR);
+ navigateToAmount();
+ }
+ }
+
+ private void processBatch() {
+ calculateLastTransaction();
+ mainViewModel.observeSettlementPOS();
+ observeLastTrans = payDetail -> {
+
+ if(payDetail == null) {
+ return;
+ }
+
+// SystemParamsOperation.getInstance().saveSerialNumber(payDetail.getVoucherNo());
+// SystemParamsOperation.getInstance().saveInvoiceNumber(payDetail.getInvoiceNo());
+
+ if(lastPay != null) {
+ Date lastPayDate = POSUtil.getInstance().getDateByString(lastPay.getTransDate());
+ Date observePayDate = POSUtil.getInstance().getDateByString(payDetail.getTransDate());
+
+ if(lastPayDate.compareTo(observePayDate) < 0) {
+ payDetail = lastPay;
+ }
+ }
+
+// LogUtil.d(TAG,"TransDetail :"+payDetail.getTransType() + "- Trans Time :"+payDetail.getTransDate());
+
+ if(payDetail.getTransactionType() == TransactionsType.SETTLEMENT.value){
+ return;
+ }
+
+ /*
+ * saving for api post request, to send in next time.
+ * */
+ SystemParamsOperation.getInstance().setLastTransTime(String.valueOf(payDetail.getTransNum()));
+ SystemParamsOperation.getInstance().setLastTransName(payDetail.getTransType());
+
+
+ String lastTransDate = payDetail.getTransDate();
+ String lastTransTime = payDetail.getTransTime();
+
+ Date today = POSUtil.getInstance().getCurrentDate();
+ Date transDate;
+ Date current = new Date(System.currentTimeMillis());
+ String configTimer = SystemParamsOperation.getInstance().getClearBatchTime();
+// LogUtil.d(TAG,"Config Time :" + configTimer);
+ String configTime = "23:00";
+ int configDay = 10;
+
+ String configRawDay = SystemParamsOperation.getInstance().getClearBatchDay();
+
+ if(configRawDay != null && !configRawDay.trim().isEmpty()) {
+ try {
+ configDay = Integer.parseInt(configRawDay);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ }
+
+
+ if(configTimer != null && !configTimer.trim().isEmpty() && checkValidTime(configTimer.trim())) {
+ configTime = configTimer.trim();
+ }
+ Date configDateTime = POSUtil.getInstance().getDateTime(configTime);
+ Date yesterdayConfigDateTime = POSUtil.getInstance().getYesterdayConfigDateTime(configTime);
+
+ transDate = POSUtil.getInstance().getDateByString(lastTransDate);
+
+ Date yesterdayDate = POSUtil.getInstance().getYesterdayDate();
+
+ if(today.compareTo(transDate) == 0) {
+
+// LogUtil.d(TAG,"Last Trans is Today!");
+// LogUtil.d(TAG,"date current :!"+current);
+// LogUtil.d(TAG,"date config :!"+configDateTime);
+
+ // Today
+ if(current.compareTo(configDateTime) > 0) {
+ // clear batch and force update param
+
+// LogUtil.d(TAG,"Last Trans is Today! Config time is passed!");
+// if (!SystemParamsOperation.getInstance().isClearBatch()) {
+ if (checkSyncTrans() || !SystemParamsOperation.getInstance().isClearBatch() ) {
+// LogUtil.d(TAG,"Clearing....");
+ if(!SystemParamsOperation.getInstance().getSettlementStatus()) {
+ clearBatchAndDownload(configDay,payDetail);
+ }
+ }
+
+
+ } else {
+// LogUtil.d(TAG,"Last Trans is Today! Config time is not passed yet.....");
+ SystemParamsOperation.getInstance().setClearBatch(false);
+ }
+
+ } else {
+// LogUtil.d(TAG,"Last Trans is Before Today!");
+ Date yest;
+ if(configTime.equals("00:00")) {
+ yest = configDateTime;
+ } else {
+ yest = yesterdayConfigDateTime;
+ }
+
+
+ Date lastTransDateTime = POSUtil.getInstance().getDateByTransDateTime(lastTransDate,lastTransTime);
+// LogUtil.d(TAG,"Compare Result : "+lastTransDateTime.compareTo(yest));
+
+ if(yest.compareTo(lastTransDateTime) < 0) {
+// LogUtil.d(TAG,"Trans is yesterday, but after config time, no action!");
+ } else {
+// LogUtil.d(TAG,"Trans is yesterday, before config time,");
+// if(!checkSyncTrans()) {
+// LogUtil.d(TAG,"Clearing....");
+ if(!SystemParamsOperation.getInstance().getSettlementStatus()) {
+ clearBatchAndDownload(configDay,payDetail);
+ }
+// }
+ }
+
+
+
+ }
+ };
+ if(mainViewModel.lastTrans.hasActiveObservers()) {
+ mainViewModel.lastTrans.removeObserver(observeLastTrans);
+ }
+ mainViewModel.lastTrans.observe(getViewLifecycleOwner(),observeLastTrans);
+ }
+
+ private void calculateLastTransaction() {
+ mainViewModel.allTrans.observe(getViewLifecycleOwner(), new Observer>() {
+ @Override
+ public void onChanged(List payDetails) {
+ if(payDetails == null || payDetails.isEmpty()) {
+ return;
+ }
+ PayDetail tempPay = payDetails.get(0);
+ for (int i = 0; i < payDetails.size() ; i++) {
+
+ Date tempDate = POSUtil.getInstance().getDateByString(tempPay.getTransDate());
+ Date indexDate = POSUtil.getInstance().getDateByString(payDetails.get(i).getTransDate());
+
+ if(tempDate.compareTo(indexDate) > 0) {
+ // if before
+ tempPay = payDetails.get(i);
+ }
+ }
+
+ lastPay = tempPay;
+
+// LogUtil.d(TAG,"Transaction Name : "+tempPay.getTransType());
+// LogUtil.d(TAG,"Transaction Type : "+tempPay.getTransactionType());
+// LogUtil.d(TAG,"Transaction Amount : "+tempPay.getAmount());
+// LogUtil.d(TAG,"Transaction Date/Time : "+tempPay.getTransDate()+"/"+tempPay.getTransTime());
+// LogUtil.d(TAG,"RRN/Trace : "+tempPay.getReferNo()+"/"+tempPay.getVoucherNo());
+// LogUtil.d(TAG,"Transaction is canceled : "+tempPay.isCanceled());
+// LogUtil.d(TAG,"Transaction settlement config : "+tempPay.isSettlementEnabled());
+// LogUtil.d(TAG,"----------------------------------------------------------");
+ }
+ });
+ }
+
+ private boolean checkSyncTrans() {
+ String transDateString = SystemParamsOperation.getInstance().getSyncTransDate();
+ Date today = POSUtil.getInstance().getCurrentDate();
+ if(transDateString == null || transDateString.isEmpty()) {
+ return true;
+ }
+ Date transDate = POSUtil.getInstance().getDateByString(transDateString);
+ return today.compareTo(transDate) == 0;
+
+ }
+
+ private void clearBatchAndDownload(int configDay,PayDetail payDetail) {
+
+
+ Date yesterday = POSUtil.getInstance().getYesterdayDate();
+ Date lastInputDay = POSUtil.getInstance().getLastInputDay(configDay);
+ mainViewModel.settlementPOS.observe(getViewLifecycleOwner(), list -> {
+
+ Date transDate;
+
+ if(list == null || list.size() == 0) {
+ return;
+ }
+
+ for (PayDetail pay:list) {
+ /*
+ * To Hold One day transaction!
+ * */
+
+ transDate = POSUtil.getInstance().getDateByString(pay.getTransDate());
+
+ if (pay.getTransactionType() == TransactionsType.SALE.value) {
+ if(lastInputDay.compareTo(transDate) > 0) {
+ mainViewModel.deletePayDetail(pay);
+ }
+ } else {
+ if(yesterday.compareTo(transDate) > 0 ) {
+ mainViewModel.deletePayDetail(pay);
+ }
+ }
+
+
+ }
+
+ });
+
+ mainViewModel.deleteTrans.observe(getViewLifecycleOwner(), lists -> {
+ Date transDate;
+ if(lists == null || lists.size() == 0) {
+ return;
+ }
+
+ for (PayDetail pay:lists) {
+ /*
+ * To Hold One day transaction!
+ * */
+
+ transDate = POSUtil.getInstance().getDateByString(pay.getTransDate());
+// LogUtil.d(TAG,"Trans Type : "+pay.getTransType()+"<=====> Trans Date :"+pay.getTransDate());
+// LogUtil.d(TAG,"Yesterday Date: "+yesterday.toString());
+// LogUtil.d(TAG,"Compare result :"+yesterday.compareTo(transDate));
+
+ if(yesterday.compareTo(transDate) > 0) {
+ mainViewModel.deletePayDetail(pay);
+ }
+
+ }
+ });
+
+ mainViewModel.preAuthTrans.observe(getViewLifecycleOwner(), lists -> {
+ Date transDate;
+ if(lists == null || lists.size() == 0) {
+ return;
+ }
+
+ for (PayDetail pay:lists) {
+
+ transDate = POSUtil.getInstance().getDateByString(pay.getTransDate());
+
+ if (lastInputDay.compareTo(transDate) > 0) {
+ mainViewModel.deletePayDetail(pay);
+ }
+
+
+ }
+ });
+
+ /*
+ *
+ * Need to think about his problem .... Nov 7, 2024
+ * */
+ if(!SystemParamsOperation.getInstance().isClearBatch()) {
+// downloadParams(payDetail.getTransType(),String.valueOf(payDetail.getTransNum()),TMSUpdate.UPDATE,false);
+ }
+
+ }
+
+ private void navigateToAmount() {
+// routeId = R.id.action_nav_main_to_inputAmountFragment;
+// safeNavigateToRouteId();
+ NavHostFragment.findNavController(this)
+ .navigate(R.id.action_qrFragment_to_inputAmountFragment);
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/utsmm/kbz/ui/qr_pay/QRPayItem.java b/app/src/main/java/com/utsmm/kbz/ui/qr_pay/QRPayItem.java
new file mode 100644
index 0000000..e7af619
--- /dev/null
+++ b/app/src/main/java/com/utsmm/kbz/ui/qr_pay/QRPayItem.java
@@ -0,0 +1,11 @@
+package com.utsmm.kbz.ui.qr_pay;
+
+public class QRPayItem {
+ public String title;
+ public int icon;
+
+ public QRPayItem(String title, int icon) {
+ this.title = title;
+ this.icon = icon;
+ }
+}
diff --git a/app/src/main/java/com/utsmm/kbz/ui/qr_pay/QRPayViewModel.java b/app/src/main/java/com/utsmm/kbz/ui/qr_pay/QRPayViewModel.java
new file mode 100644
index 0000000..0adab25
--- /dev/null
+++ b/app/src/main/java/com/utsmm/kbz/ui/qr_pay/QRPayViewModel.java
@@ -0,0 +1,17 @@
+package com.utsmm.kbz.ui.qr_pay;
+
+import androidx.lifecycle.ViewModel;
+
+public class QRPayViewModel extends ViewModel {
+ public void generateQR(){
+
+ }
+
+ public void refundQR(){
+
+ }
+
+ public void historyQR(){
+
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_qr_pay.xml b/app/src/main/res/layout/fragment_qr_pay.xml
new file mode 100644
index 0000000..0c09527
--- /dev/null
+++ b/app/src/main/res/layout/fragment_qr_pay.xml
@@ -0,0 +1,42 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/item_qr_pay_button.xml b/app/src/main/res/layout/item_qr_pay_button.xml
new file mode 100644
index 0000000..d84fe47
--- /dev/null
+++ b/app/src/main/res/layout/item_qr_pay_button.xml
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ 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 8085dac..d9e88da 100644
--- a/app/src/main/res/navigation/mobile_navigation.xml
+++ b/app/src/main/res/navigation/mobile_navigation.xml
@@ -141,6 +141,9 @@
+
-
-
+
+
+
+
\ No newline at end of file
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index af7dd89..efb2740 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -12,6 +12,9 @@ coreKtx = "1.17.0"
hilt = "2.51.1"
androidx-hilt = "1.2.0"
nav = "2.5.0"
+legacySupportV4 = "1.0.0"
+lifecycleLivedataKtx = "2.9.4"
+lifecycleViewmodelKtx = "2.9.4"
[libraries]
junit = { group = "junit", name = "junit", version.ref = "junit" }
@@ -25,6 +28,9 @@ core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx"
hilt-android = { group = "com.google.dagger", name = "hilt-android", version.ref = "hilt" }
hilt-compiler = { group = "com.google.dagger", name = "hilt-compiler", version.ref = "hilt" }
androidx-hilt-compiler = { group = "androidx.hilt", name = "hilt-compiler", version.ref = "androidx-hilt" }
+androidx-legacy-support-v4 = { group = "androidx.legacy", name = "legacy-support-v4", version.ref = "legacySupportV4" }
+androidx-lifecycle-livedata-ktx = { group = "androidx.lifecycle", name = "lifecycle-livedata-ktx", version.ref = "lifecycleLivedataKtx" }
+androidx-lifecycle-viewmodel-ktx = { group = "androidx.lifecycle", name = "lifecycle-viewmodel-ktx", version.ref = "lifecycleViewmodelKtx" }
[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }