Compare commits
18 Commits
master
...
developmen
Author | SHA1 | Date | |
---|---|---|---|
edca7f92ec | |||
3f189f5975 | |||
5a03fc3aec | |||
a30e767adc | |||
74f95e0374 | |||
1799e7eb0e | |||
2a24016637 | |||
459d9ab0f1 | |||
191966a2e4 | |||
46fb81b6a7 | |||
290f3015d9 | |||
f1228db89a | |||
810964b4be | |||
a7fa40d60a | |||
a07e7a99ac | |||
c55af6141f | |||
6d681f5e41 | |||
1ca26371a1 |
3
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"java.configuration.updateBuildConfiguration": "interactive"
|
||||
}
|
@ -35,6 +35,7 @@ dependencies {
|
||||
implementation libs.activity
|
||||
implementation libs.constraintlayout
|
||||
implementation libs.cardview
|
||||
implementation 'androidx.recyclerview:recyclerview:1.3.0'
|
||||
testImplementation libs.junit
|
||||
androidTestImplementation libs.ext.junit
|
||||
androidTestImplementation libs.espresso.core
|
||||
|
@ -17,6 +17,7 @@
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.BDKIPOC"
|
||||
android:usesCleartextTraffic="true"
|
||||
tools:targetApi="31">
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
@ -33,7 +34,27 @@
|
||||
<activity
|
||||
android:name=".PaymentActivity"
|
||||
android:exported="false" />
|
||||
<activity
|
||||
android:name=".PinActivity"
|
||||
android:screenOrientation="portrait"
|
||||
android:theme="@style/Theme.AppCompat.Light.NoActionBar"
|
||||
android:exported="false" />
|
||||
<activity
|
||||
android:name=".ReceiptActivity"
|
||||
android:exported="false" />
|
||||
<activity
|
||||
android:name=".QrisActivity"
|
||||
android:exported="false" />
|
||||
<activity android:name=".QrisResultActivity" />
|
||||
<activity
|
||||
android:name=".SettlementActivity"
|
||||
android:exported="false" />
|
||||
<activity
|
||||
android:name=".HistoryActivity"
|
||||
android:exported="false" />
|
||||
<activity
|
||||
android:name=".HistoryDetailActivity"
|
||||
android:exported="false" />
|
||||
</application>
|
||||
|
||||
</manifest>
|
415
app/src/main/java/com/example/bdkipoc/HistoryActivity.java
Normal file
@ -0,0 +1,415 @@
|
||||
package com.example.bdkipoc;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.text.NumberFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
public class HistoryActivity extends AppCompatActivity {
|
||||
|
||||
private TextView tvTotalAmount;
|
||||
private TextView tvTotalTransactions;
|
||||
private TextView btnLihatDetailTop;
|
||||
private Button btnLihatDetailBottom;
|
||||
private RecyclerView recyclerView;
|
||||
private HistoryAdapter adapter;
|
||||
private List<HistoryItem> historyList;
|
||||
private ImageView btnBack;
|
||||
|
||||
// Store full data for detail view
|
||||
private static List<HistoryItem> fullHistoryData = new ArrayList<>();
|
||||
|
||||
private String API_URL = "https://be-edc.msvc.app/transactions?page=0&limit=50&sortOrder=DESC&from_date=2025-05-10&to_date=2025-05-21&location_id=0&merchant_id=0&sortColumn=id";
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_history);
|
||||
|
||||
initViews();
|
||||
setupRecyclerView();
|
||||
fetchApiData();
|
||||
setupClickListeners();
|
||||
}
|
||||
|
||||
private void initViews() {
|
||||
tvTotalAmount = findViewById(R.id.tv_total_amount);
|
||||
tvTotalTransactions = findViewById(R.id.tv_total_transactions);
|
||||
btnLihatDetailTop = findViewById(R.id.btn_lihat_detail);
|
||||
btnLihatDetailBottom = findViewById(R.id.btn_lihat_detail_bottom);
|
||||
recyclerView = findViewById(R.id.recycler_view);
|
||||
btnBack = findViewById(R.id.btn_back);
|
||||
|
||||
historyList = new ArrayList<>();
|
||||
}
|
||||
|
||||
private void setupRecyclerView() {
|
||||
adapter = new HistoryAdapter(historyList);
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(this));
|
||||
recyclerView.setAdapter(adapter);
|
||||
}
|
||||
|
||||
private void setupClickListeners() {
|
||||
btnBack.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
finish();
|
||||
}
|
||||
});
|
||||
|
||||
View.OnClickListener detailClickListener = new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
try {
|
||||
Intent intent = new Intent(HistoryActivity.this, HistoryDetailActivity.class);
|
||||
startActivity(intent);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
Toast.makeText(HistoryActivity.this, "Error opening detail", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
btnLihatDetailTop.setOnClickListener(detailClickListener);
|
||||
btnLihatDetailBottom.setOnClickListener(detailClickListener);
|
||||
}
|
||||
|
||||
private void fetchApiData() {
|
||||
new ApiTask().execute(API_URL);
|
||||
}
|
||||
|
||||
private void processApiData(JSONArray dataArray) {
|
||||
try {
|
||||
historyList.clear();
|
||||
fullHistoryData.clear(); // Clear static data
|
||||
|
||||
final long[] totalAmountArray = {0};
|
||||
final int[] totalTransactionsArray = {0};
|
||||
|
||||
for (int i = 0; i < dataArray.length(); i++) {
|
||||
JSONObject item = dataArray.getJSONObject(i);
|
||||
|
||||
String channelCode = item.getString("channel_code");
|
||||
String amount = item.getString("amount");
|
||||
String status = item.getString("status");
|
||||
String transactionDate = item.getString("transaction_date");
|
||||
String referenceId = item.getString("reference_id");
|
||||
|
||||
// Parse amount safely
|
||||
double amountValue = 0;
|
||||
try {
|
||||
amountValue = Double.parseDouble(amount);
|
||||
} catch (NumberFormatException e) {
|
||||
amountValue = 0;
|
||||
}
|
||||
|
||||
// Create history item
|
||||
HistoryItem historyItem = new HistoryItem();
|
||||
historyItem.setTime(formatTime(transactionDate));
|
||||
historyItem.setDate(formatDate(transactionDate));
|
||||
historyItem.setAmount((long) amountValue);
|
||||
historyItem.setChannelName(formatChannelName(channelCode));
|
||||
historyItem.setStatus(status);
|
||||
historyItem.setReferenceId(referenceId);
|
||||
historyItem.setFullDate(transactionDate);
|
||||
historyItem.setChannelCode(channelCode);
|
||||
|
||||
// Add to full data
|
||||
fullHistoryData.add(historyItem);
|
||||
|
||||
// Add first 10 to display list
|
||||
if (i < 10) {
|
||||
historyList.add(historyItem);
|
||||
}
|
||||
|
||||
totalAmountArray[0] += (long) amountValue;
|
||||
totalTransactionsArray[0]++;
|
||||
}
|
||||
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
updateSummary(totalAmountArray[0], totalTransactionsArray[0]);
|
||||
adapter.notifyDataSetChanged();
|
||||
}
|
||||
});
|
||||
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Toast.makeText(HistoryActivity.this, "Error parsing data", Toast.LENGTH_SHORT).show();
|
||||
loadSampleData();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void updateSummary(long totalAmount, int totalTransactions) {
|
||||
tvTotalAmount.setText("RP " + formatCurrency(totalAmount));
|
||||
tvTotalTransactions.setText(String.valueOf(totalTransactions));
|
||||
}
|
||||
|
||||
private void loadSampleData() {
|
||||
historyList.clear();
|
||||
fullHistoryData.clear();
|
||||
|
||||
// Create sample data
|
||||
HistoryItem[] sampleData = {
|
||||
new HistoryItem("03:44", "11-05-2025", 2018619, "Kredit", "FAILED", "197870"),
|
||||
new HistoryItem("03:10", "12-05-2025", 3974866, "QRIS", "SUCCESS", "053059"),
|
||||
new HistoryItem("15:17", "13-05-2025", 2418167, "QRIS", "FAILED", "668320"),
|
||||
new HistoryItem("12:09", "11-05-2025", 3429230, "Debit", "FAILED", "454790"),
|
||||
new HistoryItem("08:39", "10-05-2025", 4656447, "QRIS", "FAILED", "454248"),
|
||||
new HistoryItem("00:35", "12-05-2025", 3507704, "QRIS", "FAILED", "301644"),
|
||||
new HistoryItem("22:43", "13-05-2025", 4277904, "Debit", "SUCCESS", "388709"),
|
||||
new HistoryItem("18:16", "11-05-2025", 4456904, "Debit", "FAILED", "986861")
|
||||
};
|
||||
|
||||
for (HistoryItem item : sampleData) {
|
||||
historyList.add(item);
|
||||
fullHistoryData.add(item);
|
||||
}
|
||||
|
||||
tvTotalAmount.setText("RP 36.166.829");
|
||||
tvTotalTransactions.setText("10");
|
||||
|
||||
adapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
private String formatChannelName(String channelCode) {
|
||||
switch (channelCode) {
|
||||
case "DEBIT":
|
||||
return "Debit";
|
||||
case "QRIS":
|
||||
return "QRIS";
|
||||
case "OTHER":
|
||||
return "Kredit";
|
||||
default:
|
||||
return channelCode.substring(0, 1).toUpperCase() +
|
||||
channelCode.substring(1).toLowerCase();
|
||||
}
|
||||
}
|
||||
|
||||
private String formatTime(String isoDate) {
|
||||
try {
|
||||
SimpleDateFormat inputFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.getDefault());
|
||||
SimpleDateFormat outputFormat = new SimpleDateFormat("HH:mm", Locale.getDefault());
|
||||
Date date = inputFormat.parse(isoDate);
|
||||
return outputFormat.format(date);
|
||||
} catch (ParseException e) {
|
||||
return "00:00";
|
||||
}
|
||||
}
|
||||
|
||||
private String formatDate(String isoDate) {
|
||||
try {
|
||||
SimpleDateFormat inputFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.getDefault());
|
||||
SimpleDateFormat outputFormat = new SimpleDateFormat("dd-MM-yyyy", Locale.getDefault());
|
||||
Date date = inputFormat.parse(isoDate);
|
||||
return outputFormat.format(date);
|
||||
} catch (ParseException e) {
|
||||
return "01-01-2025";
|
||||
}
|
||||
}
|
||||
|
||||
private String formatCurrency(long amount) {
|
||||
NumberFormat formatter = NumberFormat.getNumberInstance(new Locale("id", "ID"));
|
||||
return formatter.format(amount);
|
||||
}
|
||||
|
||||
// Public static method to get full data for detail activity
|
||||
public static List<HistoryItem> getFullHistoryData() {
|
||||
return new ArrayList<>(fullHistoryData);
|
||||
}
|
||||
|
||||
// AsyncTask for API call
|
||||
private class ApiTask extends AsyncTask<String, Void, String> {
|
||||
@Override
|
||||
protected String doInBackground(String... urls) {
|
||||
try {
|
||||
URL url = new URL(urls[0]);
|
||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
connection.setRequestMethod("GET");
|
||||
connection.setConnectTimeout(10000);
|
||||
connection.setReadTimeout(10000);
|
||||
|
||||
int responseCode = connection.getResponseCode();
|
||||
if (responseCode == HttpURLConnection.HTTP_OK) {
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
||||
StringBuilder response = new StringBuilder();
|
||||
String line;
|
||||
|
||||
while ((line = reader.readLine()) != null) {
|
||||
response.append(line);
|
||||
}
|
||||
reader.close();
|
||||
return response.toString();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(String result) {
|
||||
if (result != null) {
|
||||
try {
|
||||
JSONObject jsonResponse = new JSONObject(result);
|
||||
if (jsonResponse.getInt("status") == 200) {
|
||||
JSONObject results = jsonResponse.getJSONObject("results");
|
||||
JSONArray dataArray = results.getJSONArray("data");
|
||||
processApiData(dataArray);
|
||||
} else {
|
||||
Toast.makeText(HistoryActivity.this, "API Error", Toast.LENGTH_SHORT).show();
|
||||
loadSampleData();
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
Toast.makeText(HistoryActivity.this, "JSON Parse Error", Toast.LENGTH_SHORT).show();
|
||||
loadSampleData();
|
||||
}
|
||||
} else {
|
||||
Toast.makeText(HistoryActivity.this, "Network Error", Toast.LENGTH_SHORT).show();
|
||||
loadSampleData();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// HistoryItem class - enhanced with more fields
|
||||
class HistoryItem {
|
||||
private String time;
|
||||
private String date;
|
||||
private long amount;
|
||||
private String channelName;
|
||||
private String status;
|
||||
private String referenceId;
|
||||
private String fullDate;
|
||||
private String channelCode;
|
||||
|
||||
public HistoryItem() {}
|
||||
|
||||
public HistoryItem(String time, String date, long amount, String channelName, String status, String referenceId) {
|
||||
this.time = time;
|
||||
this.date = date;
|
||||
this.amount = amount;
|
||||
this.channelName = channelName;
|
||||
this.status = status;
|
||||
this.referenceId = referenceId;
|
||||
}
|
||||
|
||||
// Getters and Setters
|
||||
public String getTime() { return time; }
|
||||
public void setTime(String time) { this.time = time; }
|
||||
public String getDate() { return date; }
|
||||
public void setDate(String date) { this.date = date; }
|
||||
public long getAmount() { return amount; }
|
||||
public void setAmount(long amount) { this.amount = amount; }
|
||||
public String getChannelName() { return channelName; }
|
||||
public void setChannelName(String channelName) { this.channelName = channelName; }
|
||||
public String getStatus() { return status; }
|
||||
public void setStatus(String status) { this.status = status; }
|
||||
public String getReferenceId() { return referenceId; }
|
||||
public void setReferenceId(String referenceId) { this.referenceId = referenceId; }
|
||||
public String getFullDate() { return fullDate; }
|
||||
public void setFullDate(String fullDate) { this.fullDate = fullDate; }
|
||||
public String getChannelCode() { return channelCode; }
|
||||
public void setChannelCode(String channelCode) { this.channelCode = channelCode; }
|
||||
}
|
||||
|
||||
// HistoryAdapter class - simplified and stable
|
||||
class HistoryAdapter extends RecyclerView.Adapter<HistoryAdapter.HistoryViewHolder> {
|
||||
|
||||
private List<HistoryItem> historyList;
|
||||
|
||||
public HistoryAdapter(List<HistoryItem> historyList) {
|
||||
this.historyList = historyList;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public HistoryViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(parent.getContext())
|
||||
.inflate(R.layout.item_history, parent, false);
|
||||
return new HistoryViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull HistoryViewHolder holder, int position) {
|
||||
HistoryItem item = historyList.get(position);
|
||||
|
||||
holder.tvTime.setText(item.getTime() + ", " + item.getDate());
|
||||
holder.tvAmount.setText("Rp. " + formatCurrency(item.getAmount()));
|
||||
holder.tvChannel.setText(item.getChannelName());
|
||||
|
||||
// Set status color
|
||||
String status = item.getStatus();
|
||||
if ("SUCCESS".equals(status)) {
|
||||
holder.tvStatus.setText("Berhasil");
|
||||
holder.tvStatus.setTextColor(0xFF4CAF50); // Green
|
||||
} else if ("FAILED".equals(status)) {
|
||||
holder.tvStatus.setText("Gagal");
|
||||
holder.tvStatus.setTextColor(0xFFF44336); // Red
|
||||
} else {
|
||||
holder.tvStatus.setText("Tertunda");
|
||||
holder.tvStatus.setTextColor(0xFFFF9800); // Orange
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return historyList != null ? historyList.size() : 0;
|
||||
}
|
||||
|
||||
private String formatCurrency(long amount) {
|
||||
try {
|
||||
NumberFormat formatter = NumberFormat.getNumberInstance(new Locale("id", "ID"));
|
||||
return formatter.format(amount);
|
||||
} catch (Exception e) {
|
||||
return String.valueOf(amount);
|
||||
}
|
||||
}
|
||||
|
||||
static class HistoryViewHolder extends RecyclerView.ViewHolder {
|
||||
TextView tvTime;
|
||||
TextView tvAmount;
|
||||
TextView tvChannel;
|
||||
TextView tvStatus;
|
||||
|
||||
public HistoryViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
tvTime = itemView.findViewById(R.id.tv_time);
|
||||
tvAmount = itemView.findViewById(R.id.tv_amount);
|
||||
tvChannel = itemView.findViewById(R.id.tv_channel);
|
||||
tvStatus = itemView.findViewById(R.id.tv_status);
|
||||
}
|
||||
}
|
||||
}
|
204
app/src/main/java/com/example/bdkipoc/HistoryDetailActivity.java
Normal file
@ -0,0 +1,204 @@
|
||||
package com.example.bdkipoc;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import java.text.NumberFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
public class HistoryDetailActivity extends AppCompatActivity {
|
||||
|
||||
private RecyclerView recyclerView;
|
||||
private HistoryDetailAdapter adapter;
|
||||
private List<HistoryItem> detailList;
|
||||
private ImageView btnBack;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_history_detail);
|
||||
|
||||
initViews();
|
||||
setupRecyclerView();
|
||||
loadData();
|
||||
setupClickListeners();
|
||||
}
|
||||
|
||||
private void initViews() {
|
||||
recyclerView = findViewById(R.id.recycler_view);
|
||||
btnBack = findViewById(R.id.btn_back);
|
||||
detailList = new ArrayList<>();
|
||||
}
|
||||
|
||||
private void setupRecyclerView() {
|
||||
adapter = new HistoryDetailAdapter(detailList);
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(this));
|
||||
recyclerView.setAdapter(adapter);
|
||||
}
|
||||
|
||||
private void setupClickListeners() {
|
||||
btnBack.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
finish();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void loadData() {
|
||||
try {
|
||||
// Get data from HistoryActivity
|
||||
List<HistoryItem> fullData = HistoryActivity.getFullHistoryData();
|
||||
|
||||
if (fullData != null && !fullData.isEmpty()) {
|
||||
detailList.clear();
|
||||
detailList.addAll(fullData);
|
||||
adapter.notifyDataSetChanged();
|
||||
} else {
|
||||
loadSampleDetailData();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
loadSampleDetailData();
|
||||
}
|
||||
}
|
||||
|
||||
private void loadSampleDetailData() {
|
||||
detailList.clear();
|
||||
|
||||
// Create sample detail data
|
||||
HistoryItem[] sampleData = {
|
||||
new HistoryItem("03:44", "11-05-2025", 2018619, "Kredit", "FAILED", "197870"),
|
||||
new HistoryItem("03:10", "12-05-2025", 3974866, "QRIS", "SUCCESS", "053059"),
|
||||
new HistoryItem("15:17", "13-05-2025", 2418167, "QRIS", "FAILED", "668320"),
|
||||
new HistoryItem("12:09", "11-05-2025", 3429230, "Debit", "FAILED", "454790"),
|
||||
new HistoryItem("08:39", "10-05-2025", 4656447, "QRIS", "FAILED", "454248"),
|
||||
new HistoryItem("00:35", "12-05-2025", 3507704, "QRIS", "FAILED", "301644"),
|
||||
new HistoryItem("22:43", "13-05-2025", 4277904, "Debit", "SUCCESS", "388709"),
|
||||
new HistoryItem("18:16", "11-05-2025", 4456904, "Debit", "FAILED", "986861"),
|
||||
new HistoryItem("12:51", "10-05-2025", 3027953, "Kredit", "SUCCESS", "771339"),
|
||||
new HistoryItem("19:50", "14-05-2025", 4399035, "QRIS", "FAILED", "103478")
|
||||
};
|
||||
|
||||
for (HistoryItem item : sampleData) {
|
||||
detailList.add(item);
|
||||
}
|
||||
|
||||
adapter.notifyDataSetChanged();
|
||||
}
|
||||
}
|
||||
|
||||
// HistoryDetailAdapter class - simplified for stability
|
||||
class HistoryDetailAdapter extends RecyclerView.Adapter<HistoryDetailAdapter.DetailViewHolder> {
|
||||
|
||||
private List<HistoryItem> detailList;
|
||||
|
||||
public HistoryDetailAdapter(List<HistoryItem> detailList) {
|
||||
this.detailList = detailList;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public DetailViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(parent.getContext())
|
||||
.inflate(R.layout.item_history_detail, parent, false);
|
||||
return new DetailViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull DetailViewHolder holder, int position) {
|
||||
HistoryItem item = detailList.get(position);
|
||||
|
||||
try {
|
||||
holder.tvReferenceId.setText("Ref: " + item.getReferenceId());
|
||||
holder.tvAmount.setText("Rp. " + formatCurrency(item.getAmount()));
|
||||
holder.tvChannel.setText(item.getChannelName());
|
||||
holder.tvMerchant.setText("TEST MERCHANT");
|
||||
holder.tvTime.setText(formatDateTime(item.getTime(), item.getDate()));
|
||||
holder.tvIssuer.setText("BANK MANDIRI");
|
||||
|
||||
// Set status color
|
||||
String status = item.getStatus();
|
||||
if ("SUCCESS".equals(status)) {
|
||||
holder.tvStatus.setText("Berhasil");
|
||||
holder.tvStatus.setTextColor(0xFF4CAF50); // Green
|
||||
} else if ("FAILED".equals(status)) {
|
||||
holder.tvStatus.setText("Gagal");
|
||||
holder.tvStatus.setTextColor(0xFFF44336); // Red
|
||||
} else {
|
||||
holder.tvStatus.setText("Tertunda");
|
||||
holder.tvStatus.setTextColor(0xFFFF9800); // Orange
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
// Set default values if error occurs
|
||||
holder.tvReferenceId.setText("Ref: " + position);
|
||||
holder.tvAmount.setText("Rp. 0");
|
||||
holder.tvChannel.setText("Unknown");
|
||||
holder.tvMerchant.setText("TEST MERCHANT");
|
||||
holder.tvTime.setText("00:00, 01-01-2025");
|
||||
holder.tvIssuer.setText("UNKNOWN");
|
||||
holder.tvStatus.setText("Tidak Diketahui");
|
||||
holder.tvStatus.setTextColor(0xFF666666);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return detailList != null ? detailList.size() : 0;
|
||||
}
|
||||
|
||||
private String formatCurrency(long amount) {
|
||||
try {
|
||||
NumberFormat formatter = NumberFormat.getNumberInstance(new Locale("id", "ID"));
|
||||
return formatter.format(amount);
|
||||
} catch (Exception e) {
|
||||
return String.valueOf(amount);
|
||||
}
|
||||
}
|
||||
|
||||
private String formatDateTime(String time, String date) {
|
||||
try {
|
||||
return time + ", " + date;
|
||||
} catch (Exception e) {
|
||||
return "00:00, 01-01-2025";
|
||||
}
|
||||
}
|
||||
|
||||
static class DetailViewHolder extends RecyclerView.ViewHolder {
|
||||
TextView tvReferenceId;
|
||||
TextView tvAmount;
|
||||
TextView tvChannel;
|
||||
TextView tvMerchant;
|
||||
TextView tvTime;
|
||||
TextView tvIssuer;
|
||||
TextView tvStatus;
|
||||
|
||||
public DetailViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
try {
|
||||
tvReferenceId = itemView.findViewById(R.id.tv_reference_id);
|
||||
tvAmount = itemView.findViewById(R.id.tv_amount);
|
||||
tvChannel = itemView.findViewById(R.id.tv_channel);
|
||||
tvMerchant = itemView.findViewById(R.id.tv_merchant);
|
||||
tvTime = itemView.findViewById(R.id.tv_time);
|
||||
tvIssuer = itemView.findViewById(R.id.tv_issuer);
|
||||
tvStatus = itemView.findViewById(R.id.tv_status);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,41 +1,267 @@
|
||||
package com.example.bdkipoc;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
import android.view.animation.AccelerateDecelerateInterpolator;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import androidx.activity.EdgeToEdge;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.cardview.widget.CardView;
|
||||
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||
import androidx.core.graphics.Insets;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.core.view.WindowInsetsCompat;
|
||||
|
||||
import com.google.android.material.button.MaterialButton;
|
||||
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
|
||||
private boolean isExpanded = false; // False = showing only 9 main menus, True = showing all 15 menus
|
||||
private MaterialButton btnLainnya;
|
||||
|
||||
@Override
|
||||
public void onWindowFocusChanged(boolean hasFocus) {
|
||||
super.onWindowFocusChanged(hasFocus);
|
||||
if (hasFocus) {
|
||||
getWindow().getDecorView().setSystemUiVisibility(
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
|
||||
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
|
||||
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
||||
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
|
||||
| View.SYSTEM_UI_FLAG_FULLSCREEN
|
||||
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
// Enable hardware acceleration for smoother scrolling
|
||||
getWindow().setFlags(
|
||||
WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED,
|
||||
WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED
|
||||
);
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
EdgeToEdge.enable(this);
|
||||
setContentView(R.layout.activity_main);
|
||||
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
|
||||
|
||||
ViewCompat.setOnApplyWindowInsetsListener(findViewById(android.R.id.content), (v, insets) -> {
|
||||
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
|
||||
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
|
||||
return insets;
|
||||
});
|
||||
|
||||
// Set up click listeners for the cards
|
||||
CardView paymentCard = findViewById(R.id.card_payment);
|
||||
CardView transactionsCard = findViewById(R.id.card_transactions);
|
||||
// Initialize views
|
||||
btnLainnya = findViewById(R.id.btn_lainnya);
|
||||
|
||||
paymentCard.setOnClickListener(v -> {
|
||||
// Launch payment activity
|
||||
startActivity(new android.content.Intent(MainActivity.this, PaymentActivity.class));
|
||||
// Check if we're returning from a completed transaction
|
||||
checkTransactionCompletion();
|
||||
|
||||
// Setup initial state - 9 main menus visible, 6 dummy menus hidden
|
||||
setupInitialMenuState();
|
||||
|
||||
// Setup menu listeners
|
||||
setupMenuListeners();
|
||||
}
|
||||
|
||||
private void setupInitialMenuState() {
|
||||
// 9 main menus should always be visible
|
||||
CardView cardBantuan = findViewById(R.id.card_bantuan);
|
||||
CardView cardInfoToko = findViewById(R.id.card_info_toko);
|
||||
|
||||
if (cardBantuan != null) {
|
||||
cardBantuan.setVisibility(View.VISIBLE);
|
||||
}
|
||||
if (cardInfoToko != null) {
|
||||
cardInfoToko.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
// 6 dummy menus should be hidden initially
|
||||
CardView[] dummyCards = {
|
||||
findViewById(R.id.card_dummy_menu_1),
|
||||
findViewById(R.id.card_dummy_menu_2),
|
||||
findViewById(R.id.card_dummy_menu_3),
|
||||
findViewById(R.id.card_dummy_menu_4),
|
||||
findViewById(R.id.card_dummy_menu_5),
|
||||
findViewById(R.id.card_dummy_menu_6)
|
||||
};
|
||||
|
||||
for (CardView card : dummyCards) {
|
||||
if (card != null) {
|
||||
card.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
// Set initial button text
|
||||
isExpanded = false;
|
||||
btnLainnya.setText("Lainnya");
|
||||
}
|
||||
|
||||
private void checkTransactionCompletion() {
|
||||
Intent intent = getIntent();
|
||||
if (intent != null) {
|
||||
boolean transactionCompleted = intent.getBooleanExtra("transaction_completed", false);
|
||||
String transactionAmount = intent.getStringExtra("transaction_amount");
|
||||
|
||||
if (transactionCompleted) {
|
||||
if (transactionAmount != null) {
|
||||
Toast.makeText(this, "Transaksi berhasil! Jumlah: Rp " + formatCurrency(transactionAmount), Toast.LENGTH_LONG).show();
|
||||
} else {
|
||||
Toast.makeText(this, "Transaksi berhasil diselesaikan!", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String formatCurrency(String amount) {
|
||||
try {
|
||||
long amountValue = Long.parseLong(amount);
|
||||
return String.format("%,d", amountValue).replace(',', '.');
|
||||
} catch (NumberFormatException e) {
|
||||
return amount;
|
||||
}
|
||||
}
|
||||
|
||||
private void setupMenuListeners() {
|
||||
// Card IDs to set up listeners - Total 15 menu items
|
||||
int[] cardIds = {
|
||||
// Row 1 (Always visible - 3 items)
|
||||
R.id.card_kartu_kredit,
|
||||
R.id.card_kartu_debit,
|
||||
R.id.card_qris,
|
||||
// Row 2 (Always visible - 3 items)
|
||||
R.id.card_uang_elektronik,
|
||||
R.id.card_cetak_ulang,
|
||||
R.id.card_settlement,
|
||||
// Row 3 (Always visible - 3 items)
|
||||
R.id.card_histori,
|
||||
R.id.card_bantuan,
|
||||
R.id.card_info_toko,
|
||||
// Row 4 (Hidden initially - 3 items)
|
||||
R.id.card_dummy_menu_1,
|
||||
R.id.card_dummy_menu_2,
|
||||
R.id.card_dummy_menu_3,
|
||||
// Row 5 (Hidden initially - 3 items)
|
||||
R.id.card_dummy_menu_4,
|
||||
R.id.card_dummy_menu_5,
|
||||
R.id.card_dummy_menu_6
|
||||
};
|
||||
|
||||
// Set up click listeners for all cards
|
||||
for (int cardId : cardIds) {
|
||||
CardView cardView = findViewById(cardId);
|
||||
if (cardView != null) {
|
||||
cardView.setOnClickListener(v -> {
|
||||
if (cardId == R.id.card_kartu_kredit) {
|
||||
startActivity(new Intent(MainActivity.this, PaymentActivity.class));
|
||||
} else if (cardId == R.id.card_kartu_debit) {
|
||||
startActivity(new Intent(MainActivity.this, PaymentActivity.class));
|
||||
} else if (cardId == R.id.card_qris) {
|
||||
startActivity(new Intent(MainActivity.this, QrisActivity.class));
|
||||
} else if (cardId == R.id.card_uang_elektronik) {
|
||||
startActivity(new Intent(MainActivity.this, PaymentActivity.class));
|
||||
} else if (cardId == R.id.card_cetak_ulang) {
|
||||
startActivity(new Intent(MainActivity.this, TransactionActivity.class));
|
||||
} else if (cardId == R.id.card_settlement) {
|
||||
startActivity(new Intent(MainActivity.this, SettlementActivity.class));
|
||||
} else if (cardId == R.id.card_histori) {
|
||||
startActivity(new Intent(MainActivity.this, HistoryActivity.class));
|
||||
} else if (cardId == R.id.card_bantuan) {
|
||||
Toast.makeText(this, "Bantuan - Coming Soon", Toast.LENGTH_SHORT).show();
|
||||
} else if (cardId == R.id.card_info_toko) {
|
||||
Toast.makeText(this, "Info Toko - Coming Soon", Toast.LENGTH_SHORT).show();
|
||||
} else if (cardId == R.id.card_dummy_menu_1) {
|
||||
Toast.makeText(this, "Dummy Menu 1 - Coming Soon", Toast.LENGTH_SHORT).show();
|
||||
} else if (cardId == R.id.card_dummy_menu_2) {
|
||||
Toast.makeText(this, "Dummy Menu 2 - Coming Soon", Toast.LENGTH_SHORT).show();
|
||||
} else if (cardId == R.id.card_dummy_menu_3) {
|
||||
Toast.makeText(this, "Dummy Menu 3 - Coming Soon", Toast.LENGTH_SHORT).show();
|
||||
} else if (cardId == R.id.card_dummy_menu_4) {
|
||||
Toast.makeText(this, "Dummy Menu 4 - Coming Soon", Toast.LENGTH_SHORT).show();
|
||||
} else if (cardId == R.id.card_dummy_menu_5) {
|
||||
Toast.makeText(this, "Dummy Menu 5 - Coming Soon", Toast.LENGTH_SHORT).show();
|
||||
} else if (cardId == R.id.card_dummy_menu_6) {
|
||||
Toast.makeText(this, "Dummy Menu 6 - Coming Soon", Toast.LENGTH_SHORT).show();
|
||||
} else {
|
||||
// Fallback for any other cards
|
||||
Toast.makeText(this, "Menu Diklik: " + getResources().getResourceEntryName(cardId), Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Get references to ONLY the dummy cards that need to be toggled
|
||||
CardView[] toggleableCards = {
|
||||
findViewById(R.id.card_dummy_menu_1),
|
||||
findViewById(R.id.card_dummy_menu_2),
|
||||
findViewById(R.id.card_dummy_menu_3),
|
||||
findViewById(R.id.card_dummy_menu_4),
|
||||
findViewById(R.id.card_dummy_menu_5),
|
||||
findViewById(R.id.card_dummy_menu_6)
|
||||
};
|
||||
|
||||
// Set up "Lainnya" button click listener
|
||||
btnLainnya.setOnClickListener(v -> {
|
||||
isExpanded = !isExpanded;
|
||||
|
||||
if (isExpanded) {
|
||||
// Show the 6 dummy menus with animation
|
||||
for (CardView card : toggleableCards) {
|
||||
if (card != null) {
|
||||
card.setVisibility(View.VISIBLE);
|
||||
card.setAlpha(0f);
|
||||
card.animate()
|
||||
.alpha(1f)
|
||||
.setDuration(300)
|
||||
.setInterpolator(new AccelerateDecelerateInterpolator())
|
||||
.start();
|
||||
}
|
||||
}
|
||||
btnLainnya.setText("Tampilkan Lebih Sedikit");
|
||||
} else {
|
||||
// Hide the 6 dummy menus with animation
|
||||
for (CardView card : toggleableCards) {
|
||||
if (card != null) {
|
||||
card.animate()
|
||||
.alpha(0f)
|
||||
.setDuration(300)
|
||||
.setInterpolator(new AccelerateDecelerateInterpolator())
|
||||
.withEndAction(() -> card.setVisibility(View.GONE))
|
||||
.start();
|
||||
}
|
||||
}
|
||||
btnLainnya.setText("Lainnya");
|
||||
}
|
||||
});
|
||||
|
||||
transactionsCard.setOnClickListener(v -> {
|
||||
// Launch transactions activity
|
||||
startActivity(new android.content.Intent(MainActivity.this, TransactionActivity.class));
|
||||
});
|
||||
// Set up scan dan bayar card click listener
|
||||
LinearLayout scanBayarContent = findViewById(R.id.scan_bayar_content);
|
||||
if (scanBayarContent != null) {
|
||||
scanBayarContent.setOnClickListener(v -> {
|
||||
// Navigate to QRIS payment activity
|
||||
startActivity(new Intent(MainActivity.this, QrisActivity.class));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNewIntent(Intent intent) {
|
||||
super.onNewIntent(intent);
|
||||
setIntent(intent);
|
||||
// Check for transaction completion when returning to MainActivity
|
||||
checkTransactionCompletion();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
// Clear any transaction completion flags to avoid repeated messages
|
||||
getIntent().removeExtra("transaction_completed");
|
||||
getIntent().removeExtra("transaction_amount");
|
||||
}
|
||||
}
|
557
app/src/main/java/com/example/bdkipoc/PinActivity.java
Normal file
@ -0,0 +1,557 @@
|
||||
package com.example.bdkipoc;
|
||||
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Color;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
public class PinActivity extends AppCompatActivity {
|
||||
|
||||
// Intent Extra Keys
|
||||
public static final String EXTRA_TITLE = "extra_title";
|
||||
public static final String EXTRA_SUBTITLE = "extra_subtitle";
|
||||
public static final String EXTRA_AMOUNT = "extra_amount";
|
||||
public static final String EXTRA_SOURCE_ACTIVITY = "extra_source_activity";
|
||||
|
||||
// Views
|
||||
private EditText editTextPin;
|
||||
private Button confirmButton;
|
||||
private LinearLayout backNavigation;
|
||||
private ImageView backArrow;
|
||||
private TextView toolbarTitle;
|
||||
|
||||
// Success screen views
|
||||
private View successScreen;
|
||||
private ImageView successIcon;
|
||||
private TextView successMessage;
|
||||
|
||||
// Numpad buttons
|
||||
private TextView btn1, btn2, btn3, btn4, btn5, btn6, btn7, btn8, btn9, btn0, btn000;
|
||||
private ImageView btnDelete;
|
||||
|
||||
// Data
|
||||
private StringBuilder currentPin = new StringBuilder();
|
||||
private static final int MAX_PIN_LENGTH = 6;
|
||||
private static final int MIN_PIN_LENGTH = 4;
|
||||
|
||||
// Extra data from intent
|
||||
private String sourceActivity;
|
||||
private String amount;
|
||||
|
||||
// Animation
|
||||
private Handler animationHandler = new Handler(Looper.getMainLooper());
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
// Set status bar color programmatically
|
||||
setStatusBarColor();
|
||||
|
||||
setContentView(R.layout.activity_pin);
|
||||
|
||||
// Get intent extras
|
||||
getIntentExtras();
|
||||
|
||||
initializeViews();
|
||||
setupClickListeners();
|
||||
setupInitialStates();
|
||||
setupSuccessScreen();
|
||||
}
|
||||
|
||||
private void setStatusBarColor() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
Window window = getWindow();
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
|
||||
window.setStatusBarColor(Color.parseColor("#E31937")); // Red color
|
||||
|
||||
// Make status bar icons white (for dark red background)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
View decorView = window.getDecorView();
|
||||
decorView.setSystemUiVisibility(0); // Clear light status bar flag
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void getIntentExtras() {
|
||||
Intent intent = getIntent();
|
||||
if (intent != null) {
|
||||
sourceActivity = intent.getStringExtra(EXTRA_SOURCE_ACTIVITY);
|
||||
amount = intent.getStringExtra(EXTRA_AMOUNT);
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeViews() {
|
||||
// Main views
|
||||
editTextPin = findViewById(R.id.editTextPin);
|
||||
confirmButton = findViewById(R.id.confirmButton);
|
||||
backNavigation = findViewById(R.id.back_navigation);
|
||||
backArrow = findViewById(R.id.backArrow);
|
||||
toolbarTitle = findViewById(R.id.toolbarTitle);
|
||||
|
||||
// Success screen views
|
||||
successScreen = findViewById(R.id.success_screen);
|
||||
successIcon = findViewById(R.id.success_icon);
|
||||
successMessage = findViewById(R.id.success_message);
|
||||
|
||||
// Numpad buttons
|
||||
btn1 = findViewById(R.id.btn1);
|
||||
btn2 = findViewById(R.id.btn2);
|
||||
btn3 = findViewById(R.id.btn3);
|
||||
btn4 = findViewById(R.id.btn4);
|
||||
btn5 = findViewById(R.id.btn5);
|
||||
btn6 = findViewById(R.id.btn6);
|
||||
btn7 = findViewById(R.id.btn7);
|
||||
btn8 = findViewById(R.id.btn8);
|
||||
btn9 = findViewById(R.id.btn9);
|
||||
btn0 = findViewById(R.id.btn0);
|
||||
btn000 = findViewById(R.id.btn000);
|
||||
btnDelete = findViewById(R.id.btnDelete);
|
||||
}
|
||||
|
||||
private void setupSuccessScreen() {
|
||||
// Initially hide success screen
|
||||
if (successScreen != null) {
|
||||
successScreen.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
private void setupClickListeners() {
|
||||
// Back navigation - entire LinearLayout is clickable
|
||||
backNavigation.setOnClickListener(v -> {
|
||||
addClickAnimation(v);
|
||||
navigateBack();
|
||||
});
|
||||
|
||||
// Individual back arrow (for additional touch area)
|
||||
backArrow.setOnClickListener(v -> {
|
||||
addClickAnimation(v);
|
||||
navigateBack();
|
||||
});
|
||||
|
||||
// Toolbar title (also clickable for back navigation)
|
||||
toolbarTitle.setOnClickListener(v -> {
|
||||
addClickAnimation(v);
|
||||
navigateBack();
|
||||
});
|
||||
|
||||
// Numpad listeners
|
||||
btn1.setOnClickListener(v -> handleNumpadClick(v, "1"));
|
||||
btn2.setOnClickListener(v -> handleNumpadClick(v, "2"));
|
||||
btn3.setOnClickListener(v -> handleNumpadClick(v, "3"));
|
||||
btn4.setOnClickListener(v -> handleNumpadClick(v, "4"));
|
||||
btn5.setOnClickListener(v -> handleNumpadClick(v, "5"));
|
||||
btn6.setOnClickListener(v -> handleNumpadClick(v, "6"));
|
||||
btn7.setOnClickListener(v -> handleNumpadClick(v, "7"));
|
||||
btn8.setOnClickListener(v -> handleNumpadClick(v, "8"));
|
||||
btn9.setOnClickListener(v -> handleNumpadClick(v, "9"));
|
||||
btn0.setOnClickListener(v -> handleNumpadClick(v, "0"));
|
||||
btn000.setOnClickListener(v -> handleNumpadClick(v, "000"));
|
||||
|
||||
// Delete button
|
||||
btnDelete.setOnClickListener(v -> {
|
||||
addClickAnimation(v);
|
||||
deleteLastDigit();
|
||||
});
|
||||
|
||||
// Confirm button
|
||||
confirmButton.setOnClickListener(v -> {
|
||||
if (confirmButton.isEnabled()) {
|
||||
addButtonClickAnimation(v);
|
||||
handleConfirmPin();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void navigateBack() {
|
||||
finish();
|
||||
}
|
||||
|
||||
private void handleNumpadClick(View view, String digit) {
|
||||
addClickAnimation(view);
|
||||
addDigit(digit);
|
||||
}
|
||||
|
||||
private void setupInitialStates() {
|
||||
// Set initial PIN display
|
||||
editTextPin.setText("");
|
||||
|
||||
// Set initial button state
|
||||
updateButtonState();
|
||||
|
||||
// Disable EditText input (only numpad input allowed)
|
||||
editTextPin.setFocusable(false);
|
||||
editTextPin.setClickable(false);
|
||||
editTextPin.setCursorVisible(false);
|
||||
}
|
||||
|
||||
private void addDigit(String digit) {
|
||||
// Validate input length
|
||||
if (currentPin.length() >= MAX_PIN_LENGTH) {
|
||||
showToast("Maksimal " + MAX_PIN_LENGTH + " digit");
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle special case for 000
|
||||
if (digit.equals("000")) {
|
||||
if (currentPin.length() + 3 <= MAX_PIN_LENGTH) {
|
||||
currentPin.append("000");
|
||||
} else {
|
||||
int remainingLength = MAX_PIN_LENGTH - currentPin.length();
|
||||
if (remainingLength > 0) {
|
||||
currentPin.append("0".repeat(remainingLength));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
currentPin.append(digit);
|
||||
}
|
||||
|
||||
updatePinDisplay();
|
||||
updateButtonState();
|
||||
addInputFeedback();
|
||||
}
|
||||
|
||||
private void deleteLastDigit() {
|
||||
if (currentPin.length() > 0) {
|
||||
String current = currentPin.toString();
|
||||
|
||||
// If current ends with 000, remove all three digits
|
||||
if (current.endsWith("000") && current.length() >= 3) {
|
||||
currentPin.delete(currentPin.length() - 3, currentPin.length());
|
||||
} else {
|
||||
currentPin.deleteCharAt(currentPin.length() - 1);
|
||||
}
|
||||
|
||||
updatePinDisplay();
|
||||
updateButtonState();
|
||||
addDeleteFeedback();
|
||||
}
|
||||
}
|
||||
|
||||
private void updatePinDisplay() {
|
||||
String pin = currentPin.toString();
|
||||
|
||||
if (pin.isEmpty()) {
|
||||
editTextPin.setText("");
|
||||
} else {
|
||||
// Convert digits to asterisks for security
|
||||
String maskedPin = "*".repeat(pin.length());
|
||||
editTextPin.setText(maskedPin);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateButtonState() {
|
||||
boolean hasValidPin = currentPin.length() >= MIN_PIN_LENGTH;
|
||||
|
||||
confirmButton.setEnabled(hasValidPin);
|
||||
|
||||
if (hasValidPin) {
|
||||
// Active state
|
||||
confirmButton.setBackgroundResource(R.drawable.button_active_background);
|
||||
confirmButton.setTextColor(Color.WHITE);
|
||||
confirmButton.setAlpha(1.0f);
|
||||
} else {
|
||||
// Inactive state
|
||||
confirmButton.setBackgroundResource(R.drawable.button_inactive_background);
|
||||
confirmButton.setTextColor(Color.parseColor("#999999"));
|
||||
confirmButton.setAlpha(0.6f);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleConfirmPin() {
|
||||
String pin = currentPin.toString();
|
||||
|
||||
if (TextUtils.isEmpty(pin)) {
|
||||
showToast("Masukkan PIN");
|
||||
return;
|
||||
}
|
||||
|
||||
if (pin.length() < MIN_PIN_LENGTH) {
|
||||
showToast("PIN minimal " + MIN_PIN_LENGTH + " digit");
|
||||
return;
|
||||
}
|
||||
|
||||
// Process PIN verification
|
||||
verifyPin(pin);
|
||||
}
|
||||
|
||||
private void verifyPin(String pin) {
|
||||
// Show loading state
|
||||
confirmButton.setText("Memverifikasi...");
|
||||
confirmButton.setEnabled(false);
|
||||
|
||||
// Simulate PIN verification
|
||||
animationHandler.postDelayed(() -> {
|
||||
// For demo purposes, accept any PIN with length >= 4
|
||||
// In real implementation, this would call backend API
|
||||
|
||||
if (isValidPin(pin)) {
|
||||
// Show success screen instead of toast
|
||||
handleSuccessfulVerification();
|
||||
} else {
|
||||
showToast("PIN tidak valid. Silakan coba lagi.");
|
||||
resetPinState();
|
||||
}
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
private boolean isValidPin(String pin) {
|
||||
// Demo validation - in real app, this would validate against backend
|
||||
// For now, reject simple patterns like "1111", "1234", etc.
|
||||
return !pin.equals("1111") &&
|
||||
!pin.equals("1234") &&
|
||||
!pin.equals("0000") &&
|
||||
pin.length() >= MIN_PIN_LENGTH;
|
||||
}
|
||||
|
||||
private void handleSuccessfulVerification() {
|
||||
// Show full screen success message
|
||||
showSuccessScreen();
|
||||
|
||||
// Navigate to receipt page after 2.5 seconds
|
||||
animationHandler.postDelayed(() -> {
|
||||
navigateToReceiptPage();
|
||||
}, 2500);
|
||||
}
|
||||
|
||||
private void showSuccessScreen() {
|
||||
if (successScreen != null) {
|
||||
// Hide all other UI components first
|
||||
hideMainUIComponents();
|
||||
|
||||
// Set success message
|
||||
if (successMessage != null) {
|
||||
successMessage.setText("Pembayaran Berhasil");
|
||||
}
|
||||
|
||||
// Show success screen with fade in animation
|
||||
successScreen.setVisibility(View.VISIBLE);
|
||||
successScreen.setAlpha(0f);
|
||||
|
||||
// Fade in the background
|
||||
ObjectAnimator backgroundFadeIn = ObjectAnimator.ofFloat(successScreen, "alpha", 0f, 1f);
|
||||
backgroundFadeIn.setDuration(500);
|
||||
backgroundFadeIn.start();
|
||||
|
||||
// Add scale and bounce animation to success icon
|
||||
if (successIcon != null) {
|
||||
// Start with invisible icon
|
||||
successIcon.setScaleX(0f);
|
||||
successIcon.setScaleY(0f);
|
||||
successIcon.setAlpha(0f);
|
||||
|
||||
// Scale animation with bounce effect
|
||||
ObjectAnimator scaleX = ObjectAnimator.ofFloat(successIcon, "scaleX", 0f, 1.2f, 1f);
|
||||
ObjectAnimator scaleY = ObjectAnimator.ofFloat(successIcon, "scaleY", 0f, 1.2f, 1f);
|
||||
ObjectAnimator iconFadeIn = ObjectAnimator.ofFloat(successIcon, "alpha", 0f, 1f);
|
||||
|
||||
AnimatorSet iconAnimation = new AnimatorSet();
|
||||
iconAnimation.playTogether(scaleX, scaleY, iconFadeIn);
|
||||
iconAnimation.setDuration(800);
|
||||
iconAnimation.setStartDelay(300);
|
||||
iconAnimation.setInterpolator(new android.view.animation.OvershootInterpolator(1.2f));
|
||||
iconAnimation.start();
|
||||
}
|
||||
|
||||
// Add slide up animation to success message
|
||||
if (successMessage != null) {
|
||||
successMessage.setAlpha(0f);
|
||||
successMessage.setTranslationY(50f);
|
||||
|
||||
ObjectAnimator messageSlideUp = ObjectAnimator.ofFloat(successMessage, "translationY", 50f, 0f);
|
||||
ObjectAnimator messageFadeIn = ObjectAnimator.ofFloat(successMessage, "alpha", 0f, 1f);
|
||||
|
||||
AnimatorSet messageAnimation = new AnimatorSet();
|
||||
messageAnimation.playTogether(messageSlideUp, messageFadeIn);
|
||||
messageAnimation.setDuration(600);
|
||||
messageAnimation.setStartDelay(600);
|
||||
messageAnimation.setInterpolator(new android.view.animation.DecelerateInterpolator());
|
||||
messageAnimation.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void hideMainUIComponents() {
|
||||
// Hide all main UI components to create clean full screen success
|
||||
if (backNavigation != null) {
|
||||
backNavigation.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
// Hide the red header backgrounds
|
||||
View redStatusBar = findViewById(R.id.red_status_bar);
|
||||
View redHeaderBackground = findViewById(R.id.red_header_background);
|
||||
if (redStatusBar != null) {
|
||||
redStatusBar.setVisibility(View.GONE);
|
||||
}
|
||||
if (redHeaderBackground != null) {
|
||||
redHeaderBackground.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
// Hide PIN card
|
||||
View pinCard = findViewById(R.id.pin_card);
|
||||
if (pinCard != null) {
|
||||
pinCard.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
// Hide numpad
|
||||
View numpadGrid = findViewById(R.id.numpad_grid);
|
||||
if (numpadGrid != null) {
|
||||
numpadGrid.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
// Hide confirm button
|
||||
if (confirmButton != null) {
|
||||
confirmButton.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
private void navigateToReceiptPage() {
|
||||
// Create intent to navigate to receipt/struk page
|
||||
Intent intent = new Intent(this, ReceiptActivity.class);
|
||||
|
||||
// Pass transaction data
|
||||
intent.putExtra("transaction_amount", amount);
|
||||
intent.putExtra("pin_verified", true);
|
||||
intent.putExtra("source_activity", sourceActivity);
|
||||
|
||||
// Add transaction details (you can customize these)
|
||||
intent.putExtra("merchant_name", "TOKO KLONTONG PAK EKO");
|
||||
intent.putExtra("merchant_location", "Ciputat Baru, Tangsel");
|
||||
intent.putExtra("transaction_id", generateTransactionId());
|
||||
intent.putExtra("transaction_date", getCurrentDateTime());
|
||||
intent.putExtra("payment_method", "Kartu Kredit");
|
||||
intent.putExtra("card_type", "BCA");
|
||||
intent.putExtra("tax_percentage", "11%");
|
||||
intent.putExtra("service_fee", "500");
|
||||
|
||||
startActivity(intent);
|
||||
|
||||
// Set result for calling activity
|
||||
Intent resultIntent = new Intent();
|
||||
resultIntent.putExtra("pin_verified", true);
|
||||
resultIntent.putExtra("pin_length", currentPin.length());
|
||||
|
||||
if (!TextUtils.isEmpty(amount)) {
|
||||
resultIntent.putExtra(EXTRA_AMOUNT, amount);
|
||||
}
|
||||
|
||||
setResult(RESULT_OK, resultIntent);
|
||||
|
||||
// Finish this activity
|
||||
finish();
|
||||
}
|
||||
|
||||
private String generateTransactionId() {
|
||||
// Generate a simple transaction ID (in real app, this would come from backend)
|
||||
return String.valueOf(System.currentTimeMillis() % 1000000000L);
|
||||
}
|
||||
|
||||
private String getCurrentDateTime() {
|
||||
// Get current date and time (in real app, use proper date formatting)
|
||||
java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("dd MMMM yyyy HH:mm", java.util.Locale.getDefault());
|
||||
return sdf.format(new java.util.Date());
|
||||
}
|
||||
|
||||
private void resetPinState() {
|
||||
currentPin = new StringBuilder();
|
||||
updatePinDisplay();
|
||||
updateButtonState();
|
||||
confirmButton.setText("Konfirmasi");
|
||||
confirmButton.setEnabled(false);
|
||||
}
|
||||
|
||||
// Animation methods
|
||||
private void addClickAnimation(View view) {
|
||||
ObjectAnimator scaleX = ObjectAnimator.ofFloat(view, "scaleX", 1f, 0.95f, 1f);
|
||||
ObjectAnimator scaleY = ObjectAnimator.ofFloat(view, "scaleY", 1f, 0.95f, 1f);
|
||||
|
||||
AnimatorSet animatorSet = new AnimatorSet();
|
||||
animatorSet.playTogether(scaleX, scaleY);
|
||||
animatorSet.setDuration(150);
|
||||
animatorSet.start();
|
||||
}
|
||||
|
||||
private void addButtonClickAnimation(View view) {
|
||||
ObjectAnimator scaleX = ObjectAnimator.ofFloat(view, "scaleX", 1f, 0.98f, 1f);
|
||||
ObjectAnimator scaleY = ObjectAnimator.ofFloat(view, "scaleY", 1f, 0.98f, 1f);
|
||||
|
||||
AnimatorSet animatorSet = new AnimatorSet();
|
||||
animatorSet.playTogether(scaleX, scaleY);
|
||||
animatorSet.setDuration(200);
|
||||
animatorSet.start();
|
||||
}
|
||||
|
||||
private void addInputFeedback() {
|
||||
ObjectAnimator fadeIn = ObjectAnimator.ofFloat(editTextPin, "alpha", 0.7f, 1f);
|
||||
fadeIn.setDuration(200);
|
||||
fadeIn.start();
|
||||
}
|
||||
|
||||
private void addDeleteFeedback() {
|
||||
ObjectAnimator shake = ObjectAnimator.ofFloat(editTextPin, "translationX", 0f, -10f, 10f, 0f);
|
||||
shake.setDuration(300);
|
||||
shake.start();
|
||||
}
|
||||
|
||||
// Utility methods
|
||||
private void showToast(String message) {
|
||||
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
// Prevent back press when success screen is showing
|
||||
if (successScreen != null && successScreen.getVisibility() == View.VISIBLE) {
|
||||
return;
|
||||
}
|
||||
navigateBack();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (animationHandler != null) {
|
||||
animationHandler.removeCallbacksAndMessages(null);
|
||||
}
|
||||
}
|
||||
|
||||
// Public methods for testing
|
||||
public String getCurrentPin() {
|
||||
return currentPin.toString();
|
||||
}
|
||||
|
||||
public boolean isConfirmButtonEnabled() {
|
||||
return confirmButton.isEnabled();
|
||||
}
|
||||
|
||||
// Static helper method to launch PinActivity
|
||||
public static void launch(android.content.Context context, String sourceActivity, String amount) {
|
||||
Intent intent = new Intent(context, PinActivity.class);
|
||||
intent.putExtra(EXTRA_SOURCE_ACTIVITY, sourceActivity);
|
||||
if (!TextUtils.isEmpty(amount)) {
|
||||
intent.putExtra(EXTRA_AMOUNT, amount);
|
||||
}
|
||||
|
||||
// Launch for result if context is an Activity
|
||||
if (context instanceof AppCompatActivity) {
|
||||
((AppCompatActivity) context).startActivityForResult(intent, 100);
|
||||
} else {
|
||||
context.startActivity(intent);
|
||||
}
|
||||
}
|
||||
}
|
690
app/src/main/java/com/example/bdkipoc/QrisActivity.java
Normal file
@ -0,0 +1,690 @@
|
||||
package com.example.bdkipoc;
|
||||
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.view.animation.AccelerateDecelerateInterpolator;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.util.Random;
|
||||
import java.util.UUID;
|
||||
|
||||
public class QrisActivity extends AppCompatActivity {
|
||||
|
||||
// Views
|
||||
private EditText editTextAmount;
|
||||
private Button initiatePaymentButton;
|
||||
private LinearLayout backNavigation;
|
||||
private TextView toolbarTitle;
|
||||
private TextView descriptionText;
|
||||
|
||||
// Numpad buttons
|
||||
private TextView btn1, btn2, btn3, btn4, btn5, btn6, btn7, btn8, btn9, btn0, btn000;
|
||||
private TextView btnDelete; // Changed from ImageView to TextView
|
||||
|
||||
// Only needed views for loading state
|
||||
private ProgressBar progressBar;
|
||||
private TextView statusTextView;
|
||||
private TextView referenceIdTextView;
|
||||
private LinearLayout initialPaymentLayout;
|
||||
|
||||
// Data
|
||||
private StringBuilder currentAmount = new StringBuilder();
|
||||
private static final int MAX_AMOUNT_LENGTH = 12;
|
||||
private String transactionId;
|
||||
private String transactionUuid;
|
||||
private String referenceId;
|
||||
private int amount;
|
||||
private JSONObject midtransResponse;
|
||||
|
||||
// Animation
|
||||
private Handler animationHandler = new Handler(Looper.getMainLooper());
|
||||
|
||||
private static final String BACKEND_BASE = "https://be-edc.msvc.app";
|
||||
private static final String MIDTRANS_CHARGE_URL = "https://api.sandbox.midtrans.com/v2/charge";
|
||||
private static final String MIDTRANS_AUTH = "Basic U0ItTWlkLXNlcnZlci1JM2RJWXdIRzVuamVMeHJCMVZ5endWMUM="; // Replace with your actual key
|
||||
private static final String WEBHOOK_URL = "https://be-edc.msvc.app/webhooks/midtrans";
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
// Set status bar color programmatically
|
||||
setStatusBarColor();
|
||||
|
||||
setContentView(R.layout.activity_qris);
|
||||
|
||||
initializeViews();
|
||||
setupClickListeners();
|
||||
setupInitialStates();
|
||||
|
||||
// Generate reference ID
|
||||
referenceId = "ref-" + generateRandomString(8);
|
||||
referenceIdTextView.setText(referenceId);
|
||||
|
||||
// Initially hide the progress and status views
|
||||
progressBar.setVisibility(View.GONE);
|
||||
statusTextView.setVisibility(View.GONE);
|
||||
initialPaymentLayout.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
private void setStatusBarColor() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
Window window = getWindow();
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
|
||||
window.setStatusBarColor(Color.parseColor("#E31937")); // Red color
|
||||
|
||||
// Make status bar icons white (for dark red background)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
View decorView = window.getDecorView();
|
||||
decorView.setSystemUiVisibility(0); // Clear light status bar flag
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeViews() {
|
||||
// New UI components (similar to PaymentActivity)
|
||||
editTextAmount = findViewById(R.id.editTextAmount);
|
||||
initiatePaymentButton = findViewById(R.id.initiatePaymentButton);
|
||||
backNavigation = findViewById(R.id.back_navigation);
|
||||
toolbarTitle = findViewById(R.id.toolbarTitle);
|
||||
descriptionText = findViewById(R.id.descriptionText);
|
||||
|
||||
// Numpad buttons
|
||||
btn1 = findViewById(R.id.btn1);
|
||||
btn2 = findViewById(R.id.btn2);
|
||||
btn3 = findViewById(R.id.btn3);
|
||||
btn4 = findViewById(R.id.btn4);
|
||||
btn5 = findViewById(R.id.btn5);
|
||||
btn6 = findViewById(R.id.btn6);
|
||||
btn7 = findViewById(R.id.btn7);
|
||||
btn8 = findViewById(R.id.btn8);
|
||||
btn9 = findViewById(R.id.btn9);
|
||||
btn0 = findViewById(R.id.btn0);
|
||||
btn000 = findViewById(R.id.btn000);
|
||||
btnDelete = findViewById(R.id.btnDelete); // Now TextView
|
||||
|
||||
// Only needed views for loading state
|
||||
progressBar = findViewById(R.id.progressBar);
|
||||
statusTextView = findViewById(R.id.statusTextView);
|
||||
referenceIdTextView = findViewById(R.id.referenceIdTextView);
|
||||
|
||||
// Main content layout (replaces initialPaymentLayout)
|
||||
initialPaymentLayout = findViewById(R.id.mainContentLayout);
|
||||
}
|
||||
|
||||
private void setupClickListeners() {
|
||||
// Back navigation
|
||||
backNavigation.setOnClickListener(v -> {
|
||||
addClickAnimation(v);
|
||||
navigateBack();
|
||||
});
|
||||
|
||||
toolbarTitle.setOnClickListener(v -> {
|
||||
addClickAnimation(v);
|
||||
navigateBack();
|
||||
});
|
||||
|
||||
// Numpad listeners
|
||||
btn1.setOnClickListener(v -> handleNumpadClick(v, "1"));
|
||||
btn2.setOnClickListener(v -> handleNumpadClick(v, "2"));
|
||||
btn3.setOnClickListener(v -> handleNumpadClick(v, "3"));
|
||||
btn4.setOnClickListener(v -> handleNumpadClick(v, "4"));
|
||||
btn5.setOnClickListener(v -> handleNumpadClick(v, "5"));
|
||||
btn6.setOnClickListener(v -> handleNumpadClick(v, "6"));
|
||||
btn7.setOnClickListener(v -> handleNumpadClick(v, "7"));
|
||||
btn8.setOnClickListener(v -> handleNumpadClick(v, "8"));
|
||||
btn9.setOnClickListener(v -> handleNumpadClick(v, "9"));
|
||||
btn0.setOnClickListener(v -> handleNumpadClick(v, "0"));
|
||||
btn000.setOnClickListener(v -> handleNumpadClick(v, "000"));
|
||||
|
||||
// Delete button
|
||||
btnDelete.setOnClickListener(v -> {
|
||||
addClickAnimation(v);
|
||||
deleteLastDigit();
|
||||
});
|
||||
|
||||
// Original QRIS buttons - only initiate payment needed
|
||||
initiatePaymentButton.setOnClickListener(v -> {
|
||||
if (initiatePaymentButton.isEnabled()) {
|
||||
addButtonClickAnimation(v);
|
||||
createTransaction();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setupInitialStates() {
|
||||
// Initially hide amount input and show description
|
||||
editTextAmount.setVisibility(View.GONE);
|
||||
descriptionText.setVisibility(View.VISIBLE);
|
||||
|
||||
// Set initial button state
|
||||
updateButtonState();
|
||||
|
||||
// Disable EditText input (only numpad input allowed)
|
||||
editTextAmount.setFocusable(false);
|
||||
editTextAmount.setClickable(false);
|
||||
editTextAmount.setCursorVisible(false);
|
||||
}
|
||||
|
||||
private void navigateBack() {
|
||||
finish();
|
||||
}
|
||||
|
||||
private void handleNumpadClick(View view, String digit) {
|
||||
addClickAnimation(view);
|
||||
addDigit(digit);
|
||||
}
|
||||
|
||||
private void addDigit(String digit) {
|
||||
// Validate input length
|
||||
if (currentAmount.length() >= MAX_AMOUNT_LENGTH) {
|
||||
showToast("Maksimal " + MAX_AMOUNT_LENGTH + " digit");
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle leading zeros
|
||||
if (currentAmount.length() == 0) {
|
||||
if (digit.equals("000")) {
|
||||
// Don't allow 000 as first input
|
||||
return;
|
||||
}
|
||||
currentAmount.append(digit);
|
||||
} else if (currentAmount.length() == 1 && currentAmount.toString().equals("0")) {
|
||||
if (!digit.equals("000")) {
|
||||
// Replace single 0 with new digit
|
||||
currentAmount = new StringBuilder(digit);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
currentAmount.append(digit);
|
||||
}
|
||||
|
||||
updateAmountDisplay();
|
||||
updateButtonState();
|
||||
addInputFeedback();
|
||||
}
|
||||
|
||||
private void deleteLastDigit() {
|
||||
if (currentAmount.length() > 0) {
|
||||
String current = currentAmount.toString();
|
||||
|
||||
// If current ends with 000, remove all three digits
|
||||
if (current.endsWith("000") && current.length() >= 3) {
|
||||
currentAmount.delete(currentAmount.length() - 3, currentAmount.length());
|
||||
} else {
|
||||
currentAmount.deleteCharAt(currentAmount.length() - 1);
|
||||
}
|
||||
|
||||
updateAmountDisplay();
|
||||
updateButtonState();
|
||||
addDeleteFeedback();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateAmountDisplay() {
|
||||
String amount = currentAmount.toString();
|
||||
|
||||
if (amount.isEmpty() || amount.equals("0")) {
|
||||
// Show description text, hide amount input
|
||||
editTextAmount.setVisibility(View.GONE);
|
||||
descriptionText.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
// Show amount input, hide description text
|
||||
String formattedAmount = formatCurrency(amount);
|
||||
editTextAmount.setText(formattedAmount);
|
||||
editTextAmount.setVisibility(View.VISIBLE);
|
||||
descriptionText.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
private String formatCurrency(String amount) {
|
||||
if (TextUtils.isEmpty(amount) || amount.equals("0")) {
|
||||
return "";
|
||||
}
|
||||
|
||||
try {
|
||||
long number = Long.parseLong(amount);
|
||||
return String.format("%,d", number).replace(',', '.');
|
||||
} catch (NumberFormatException e) {
|
||||
return amount;
|
||||
}
|
||||
}
|
||||
|
||||
private void updateButtonState() {
|
||||
boolean hasValidAmount = currentAmount.length() > 0 &&
|
||||
!currentAmount.toString().equals("0") &&
|
||||
!currentAmount.toString().isEmpty();
|
||||
|
||||
initiatePaymentButton.setEnabled(hasValidAmount);
|
||||
|
||||
// Use MaterialButton's backgroundTint property
|
||||
com.google.android.material.button.MaterialButton materialButton =
|
||||
(com.google.android.material.button.MaterialButton) initiatePaymentButton;
|
||||
|
||||
if (hasValidAmount) {
|
||||
// Active state - red background like in the XML
|
||||
materialButton.setBackgroundTintList(android.content.res.ColorStateList.valueOf(Color.parseColor("#DE0701")));
|
||||
materialButton.setTextColor(Color.WHITE);
|
||||
materialButton.setAlpha(1.0f);
|
||||
} else {
|
||||
// Inactive state - gray background
|
||||
materialButton.setBackgroundTintList(android.content.res.ColorStateList.valueOf(Color.parseColor("#E8E8E8")));
|
||||
materialButton.setTextColor(Color.parseColor("#999999"));
|
||||
materialButton.setAlpha(0.6f);
|
||||
}
|
||||
}
|
||||
|
||||
private void createTransaction() {
|
||||
String amountText = currentAmount.toString();
|
||||
|
||||
if (TextUtils.isEmpty(amountText) || amountText.equals("0")) {
|
||||
showToast("Masukkan jumlah pembayaran");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
long amountValue = Long.parseLong(amountText);
|
||||
|
||||
// Validate minimum amount
|
||||
if (amountValue < 1000) {
|
||||
showToast("Minimal pembayaran Rp 1.000");
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate maximum amount
|
||||
if (amountValue > 999999999L) {
|
||||
showToast("Maksimal pembayaran Rp 999.999.999");
|
||||
return;
|
||||
}
|
||||
|
||||
// Set amount for transaction
|
||||
amount = (int) amountValue;
|
||||
|
||||
// Show loading state
|
||||
progressBar.setVisibility(View.VISIBLE);
|
||||
statusTextView.setText("Creating transaction...");
|
||||
statusTextView.setVisibility(View.VISIBLE);
|
||||
initiatePaymentButton.setEnabled(false);
|
||||
|
||||
new CreateTransactionTask().execute();
|
||||
|
||||
} catch (NumberFormatException e) {
|
||||
showToast("Format jumlah tidak valid");
|
||||
}
|
||||
}
|
||||
|
||||
private void displayQrCode(String qrImageUrl) {
|
||||
// This method is no longer needed since we navigate to QrisResultActivity
|
||||
// Keeping it for compatibility but it won't be called
|
||||
}
|
||||
|
||||
private void simulateWebhook() {
|
||||
// This method is no longer needed since we navigate to QrisResultActivity
|
||||
// QrisResultActivity handles webhook simulation
|
||||
}
|
||||
|
||||
private void showSuccessScreen() {
|
||||
// This method is no longer needed since we navigate to QrisResultActivity
|
||||
// QrisResultActivity handles success display
|
||||
}
|
||||
|
||||
private String generateRandomString(int length) {
|
||||
String chars = "abcdefghijklmnopqrstuvwxyz0123456789";
|
||||
StringBuilder sb = new StringBuilder();
|
||||
Random random = new Random();
|
||||
for (int i = 0; i < length; i++) {
|
||||
int index = random.nextInt(chars.length());
|
||||
sb.append(chars.charAt(index));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private String getServerKey() {
|
||||
// MIDTRANS_AUTH = 'Basic base64string'
|
||||
String base64 = MIDTRANS_AUTH.replace("Basic ", "");
|
||||
String decoded = android.util.Base64.decode(base64, android.util.Base64.DEFAULT).toString();
|
||||
// Format is usually 'SB-Mid-server-xxxx:'. Remove trailing colon if present.
|
||||
return decoded.replace(":\n", "");
|
||||
}
|
||||
|
||||
private String generateSignature(String orderId, String statusCode, String grossAmount, String serverKey) {
|
||||
String input = orderId + statusCode + grossAmount + serverKey;
|
||||
try {
|
||||
java.security.MessageDigest md = java.security.MessageDigest.getInstance("SHA-512");
|
||||
byte[] messageDigest = md.digest(input.getBytes());
|
||||
StringBuilder hexString = new StringBuilder();
|
||||
for (byte b : messageDigest) {
|
||||
String hex = Integer.toHexString(0xff & b);
|
||||
if (hex.length() == 1) hexString.append('0');
|
||||
hexString.append(hex);
|
||||
}
|
||||
return hexString.toString();
|
||||
} catch (java.security.NoSuchAlgorithmException e) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
// Animation methods
|
||||
private void addClickAnimation(View view) {
|
||||
ObjectAnimator scaleX = ObjectAnimator.ofFloat(view, "scaleX", 1f, 0.95f, 1f);
|
||||
ObjectAnimator scaleY = ObjectAnimator.ofFloat(view, "scaleY", 1f, 0.95f, 1f);
|
||||
|
||||
AnimatorSet animatorSet = new AnimatorSet();
|
||||
animatorSet.playTogether(scaleX, scaleY);
|
||||
animatorSet.setDuration(150);
|
||||
animatorSet.start();
|
||||
}
|
||||
|
||||
private void addButtonClickAnimation(View view) {
|
||||
ObjectAnimator scaleX = ObjectAnimator.ofFloat(view, "scaleX", 1f, 0.98f, 1f);
|
||||
ObjectAnimator scaleY = ObjectAnimator.ofFloat(view, "scaleY", 1f, 0.98f, 1f);
|
||||
|
||||
AnimatorSet animatorSet = new AnimatorSet();
|
||||
animatorSet.playTogether(scaleX, scaleY);
|
||||
animatorSet.setDuration(200);
|
||||
animatorSet.start();
|
||||
}
|
||||
|
||||
private void addInputFeedback() {
|
||||
ObjectAnimator fadeIn = ObjectAnimator.ofFloat(editTextAmount, "alpha", 0.7f, 1f);
|
||||
fadeIn.setDuration(200);
|
||||
fadeIn.start();
|
||||
}
|
||||
|
||||
private void addDeleteFeedback() {
|
||||
ObjectAnimator shake = ObjectAnimator.ofFloat(editTextAmount, "translationX", 0f, -10f, 10f, 0f);
|
||||
shake.setDuration(300);
|
||||
shake.start();
|
||||
}
|
||||
|
||||
// Utility methods
|
||||
private void showToast(String message) {
|
||||
Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
// Simple back navigation
|
||||
navigateBack();
|
||||
}
|
||||
|
||||
private class CreateTransactionTask extends AsyncTask<Void, Void, Boolean> {
|
||||
private String errorMessage;
|
||||
|
||||
@Override
|
||||
protected Boolean doInBackground(Void... voids) {
|
||||
try {
|
||||
// Generate a UUID for the transaction
|
||||
transactionUuid = UUID.randomUUID().toString();
|
||||
|
||||
// Create transaction JSON payload
|
||||
JSONObject payload = new JSONObject();
|
||||
payload.put("type", "PAYMENT");
|
||||
payload.put("channel_category", "RETAIL_OUTLET");
|
||||
payload.put("channel_code", "QRIS");
|
||||
payload.put("reference_id", referenceId);
|
||||
|
||||
Log.d("MidtransCharge", "Amount for transaction: " + amount);
|
||||
|
||||
payload.put("amount", amount);
|
||||
payload.put("cashflow", "MONEY_IN");
|
||||
payload.put("status", "INIT");
|
||||
payload.put("device_id", 1);
|
||||
payload.put("transaction_uuid", transactionUuid);
|
||||
payload.put("transaction_time_seconds", 0.0);
|
||||
payload.put("device_code", "PB4K252T00021");
|
||||
payload.put("merchant_name", "Marcel Panjaitan");
|
||||
payload.put("mid", "71000026521");
|
||||
payload.put("tid", "73001500");
|
||||
|
||||
// Make the API call
|
||||
URL url = new URI(BACKEND_BASE + "/transactions").toURL();
|
||||
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||
conn.setRequestMethod("POST");
|
||||
conn.setRequestProperty("Content-Type", "application/json");
|
||||
conn.setRequestProperty("Accept", "application/json");
|
||||
conn.setDoOutput(true);
|
||||
|
||||
try (OutputStream os = conn.getOutputStream()) {
|
||||
byte[] input = payload.toString().getBytes("utf-8");
|
||||
os.write(input, 0, input.length);
|
||||
}
|
||||
|
||||
int responseCode = conn.getResponseCode();
|
||||
if (responseCode == 200 || responseCode == 201) {
|
||||
// Read the response
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"));
|
||||
StringBuilder response = new StringBuilder();
|
||||
String responseLine;
|
||||
while ((responseLine = br.readLine()) != null) {
|
||||
response.append(responseLine.trim());
|
||||
}
|
||||
|
||||
// Parse the response to get transaction ID
|
||||
JSONObject jsonResponse = new JSONObject(response.toString());
|
||||
JSONObject data = jsonResponse.getJSONObject("data");
|
||||
transactionId = String.valueOf(data.getInt("id"));
|
||||
|
||||
// Now generate QRIS via Midtrans
|
||||
return generateQris(amount);
|
||||
} else {
|
||||
// Read error response
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getErrorStream(), "utf-8"));
|
||||
StringBuilder response = new StringBuilder();
|
||||
String responseLine;
|
||||
while ((responseLine = br.readLine()) != null) {
|
||||
response.append(responseLine.trim());
|
||||
}
|
||||
errorMessage = "Error creating transaction: " + response.toString();
|
||||
return false;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e("MidtransCharge", "Exception: " + e.getMessage(), e);
|
||||
errorMessage = "Unexpected error: " + e.getMessage();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean generateQris(int amount) {
|
||||
try {
|
||||
// Create QRIS charge JSON payload
|
||||
JSONObject payload = new JSONObject();
|
||||
payload.put("payment_type", "qris");
|
||||
|
||||
JSONObject transactionDetails = new JSONObject();
|
||||
transactionDetails.put("order_id", transactionUuid);
|
||||
transactionDetails.put("gross_amount", amount);
|
||||
payload.put("transaction_details", transactionDetails);
|
||||
|
||||
// Log the request details
|
||||
Log.d("MidtransCharge", "URL: " + MIDTRANS_CHARGE_URL);
|
||||
Log.d("MidtransCharge", "Authorization: " + MIDTRANS_AUTH);
|
||||
Log.d("MidtransCharge", "Accept: application/json");
|
||||
Log.d("MidtransCharge", "Content-Type: application/json");
|
||||
Log.d("MidtransCharge", "X-Override-Notification: " + WEBHOOK_URL);
|
||||
Log.d("MidtransCharge", "Payload: " + payload.toString());
|
||||
|
||||
// Make the API call to Midtrans
|
||||
URL url = new URI(MIDTRANS_CHARGE_URL).toURL();
|
||||
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||
conn.setRequestMethod("POST");
|
||||
conn.setRequestProperty("Accept", "application/json");
|
||||
conn.setRequestProperty("Content-Type", "application/json");
|
||||
conn.setRequestProperty("Authorization", MIDTRANS_AUTH);
|
||||
conn.setRequestProperty("X-Override-Notification", WEBHOOK_URL);
|
||||
conn.setDoOutput(true);
|
||||
|
||||
try (OutputStream os = conn.getOutputStream()) {
|
||||
byte[] input = payload.toString().getBytes("utf-8");
|
||||
os.write(input, 0, input.length);
|
||||
}
|
||||
|
||||
int responseCode = conn.getResponseCode();
|
||||
if (responseCode == 200 || responseCode == 201) {
|
||||
InputStream inputStream = conn.getInputStream();
|
||||
if (inputStream != null) {
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream, "utf-8"));
|
||||
StringBuilder response = new StringBuilder();
|
||||
String responseLine;
|
||||
while ((responseLine = br.readLine()) != null) {
|
||||
response.append(responseLine.trim());
|
||||
}
|
||||
|
||||
// Parse the response
|
||||
midtransResponse = new JSONObject(response.toString());
|
||||
return true;
|
||||
} else {
|
||||
Log.e("MidtransCharge", "HTTP " + responseCode + ": No input stream available");
|
||||
errorMessage = "Error generating QRIS: HTTP " + responseCode + ": No input stream available";
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
InputStream errorStream = conn.getErrorStream();
|
||||
if (errorStream != null) {
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(errorStream, "utf-8"));
|
||||
StringBuilder errorResponse = new StringBuilder();
|
||||
String responseLine;
|
||||
while ((responseLine = br.readLine()) != null) {
|
||||
errorResponse.append(responseLine.trim());
|
||||
}
|
||||
Log.e("MidtransCharge", "HTTP " + responseCode + ": " + errorResponse.toString());
|
||||
errorMessage = "Error generating QRIS: HTTP " + responseCode + ": " + errorResponse.toString();
|
||||
} else {
|
||||
Log.e("MidtransCharge", "HTTP " + responseCode + ": No error stream available");
|
||||
errorMessage = "Error generating QRIS: HTTP " + responseCode + ": No error stream available";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e("MidtransCharge", "Exception: " + e.getMessage(), e);
|
||||
errorMessage = "Unexpected error: " + e.getMessage();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Boolean success) {
|
||||
if (success && midtransResponse != null) {
|
||||
try {
|
||||
// Extract needed values from midtransResponse
|
||||
JSONObject actions = midtransResponse.getJSONArray("actions").getJSONObject(0);
|
||||
String qrImageUrl = actions.getString("url");
|
||||
|
||||
// Extract transaction_id
|
||||
String transactionId = midtransResponse.getString("transaction_id");
|
||||
String transactionTime = midtransResponse.getString("transaction_time");
|
||||
String acquirer = midtransResponse.getString("acquirer");
|
||||
String merchantId = midtransResponse.getString("merchant_id");
|
||||
String exactGrossAmount = midtransResponse.getString("gross_amount");
|
||||
|
||||
// Log everything before launching activity
|
||||
Log.d("MidtransCharge", "Creating QrisResultActivity intent with:");
|
||||
Log.d("MidtransCharge", "qrImageUrl: " + qrImageUrl);
|
||||
Log.d("MidtransCharge", "amount: " + amount);
|
||||
Log.d("MidtransCharge", "referenceId: " + referenceId);
|
||||
Log.d("MidtransCharge", "transactionUuid (orderId): " + transactionUuid);
|
||||
Log.d("MidtransCharge", "transaction_id: " + transactionId);
|
||||
Log.d("MidtransCharge", "exactGrossAmount: " + exactGrossAmount);
|
||||
|
||||
// Launch QrisResultActivity instead of showing QR inline
|
||||
Intent intent = new Intent(QrisActivity.this, QrisResultActivity.class);
|
||||
intent.putExtra("qrImageUrl", qrImageUrl);
|
||||
intent.putExtra("amount", amount);
|
||||
intent.putExtra("referenceId", referenceId);
|
||||
intent.putExtra("orderId", transactionUuid); // Order ID
|
||||
intent.putExtra("transactionId", transactionId); // Actual Midtrans transaction_id
|
||||
intent.putExtra("grossAmount", exactGrossAmount); // Exact gross amount from response
|
||||
intent.putExtra("transactionTime", transactionTime); // For timestamp
|
||||
intent.putExtra("acquirer", acquirer);
|
||||
intent.putExtra("merchantId", merchantId);
|
||||
|
||||
try {
|
||||
startActivity(intent);
|
||||
// Finish this activity so user can't go back to input form
|
||||
finish();
|
||||
} catch (Exception e) {
|
||||
Log.e("MidtransCharge", "Failed to start QrisResultActivity: " + e.getMessage(), e);
|
||||
Toast.makeText(QrisActivity.this, "Error launching QR display: " + e.getMessage(), Toast.LENGTH_LONG).show();
|
||||
resetToInitialState();
|
||||
}
|
||||
|
||||
} catch (JSONException e) {
|
||||
Log.e("MidtransCharge", "QRIS response JSON error: " + e.getMessage(), e);
|
||||
Toast.makeText(QrisActivity.this, "Error processing QRIS response", Toast.LENGTH_LONG).show();
|
||||
resetToInitialState();
|
||||
}
|
||||
} else {
|
||||
String message = (errorMessage != null && !errorMessage.isEmpty()) ? errorMessage : "Unknown error occurred. Please check Logcat for details.";
|
||||
Toast.makeText(QrisActivity.this, message, Toast.LENGTH_LONG).show();
|
||||
resetToInitialState();
|
||||
}
|
||||
progressBar.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
private void resetToInitialState() {
|
||||
// Reset to show the input form again
|
||||
progressBar.setVisibility(View.GONE);
|
||||
statusTextView.setVisibility(View.GONE);
|
||||
initiatePaymentButton.setEnabled(true);
|
||||
updateButtonState();
|
||||
}
|
||||
|
||||
// Remove DownloadImageTask - no longer needed
|
||||
|
||||
// Remove SimulateWebhookTask - no longer needed
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (animationHandler != null) {
|
||||
animationHandler.removeCallbacksAndMessages(null);
|
||||
}
|
||||
}
|
||||
|
||||
// Public methods for testing
|
||||
public String getCurrentAmount() {
|
||||
return currentAmount.toString();
|
||||
}
|
||||
|
||||
public boolean isInitiateButtonEnabled() {
|
||||
return initiatePaymentButton.isEnabled();
|
||||
}
|
||||
}
|
@ -3,16 +3,23 @@ package com.example.bdkipoc;
|
||||
import android.content.Intent;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.BitmapFactory;
|
||||
import android.graphics.Color;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.CountDownTimer;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.Button;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
@ -33,11 +40,23 @@ public class QrisResultActivity extends AppCompatActivity {
|
||||
private ImageView qrImageView;
|
||||
private TextView amountTextView;
|
||||
private TextView referenceTextView;
|
||||
private TextView timerTextView;
|
||||
private TextView qrStatusTextView;
|
||||
private Button downloadQrisButton;
|
||||
private Button checkStatusButton;
|
||||
private Button cancelButton;
|
||||
private TextView statusTextView;
|
||||
private Button returnMainButton;
|
||||
private ProgressBar progressBar;
|
||||
private LinearLayout backNavigation;
|
||||
|
||||
// Timer and QR refresh
|
||||
private CountDownTimer countDownTimer;
|
||||
private long timeLeftInMillis = 60000; // 60 seconds
|
||||
private int qrRefreshCount = 0;
|
||||
private final int MAX_QR_REFRESH = 5; // Maximum 5 refreshes
|
||||
|
||||
// Data variables
|
||||
private String orderId;
|
||||
private String grossAmount;
|
||||
private String referenceId;
|
||||
@ -45,26 +64,102 @@ public class QrisResultActivity extends AppCompatActivity {
|
||||
private String transactionTime;
|
||||
private String acquirer;
|
||||
private String merchantId;
|
||||
private String originalQrImageUrl;
|
||||
private int amount;
|
||||
private String backendBase = "https://be-edc.msvc.app";
|
||||
private String webhookUrl = "https://be-edc.msvc.app/webhooks/midtrans";
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
// Set status bar color programmatically
|
||||
setStatusBarColor();
|
||||
|
||||
setContentView(R.layout.activity_qris_result);
|
||||
|
||||
initializeViews();
|
||||
setupClickListeners();
|
||||
setupData();
|
||||
startTimer();
|
||||
}
|
||||
|
||||
private void setStatusBarColor() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
Window window = getWindow();
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
|
||||
window.setStatusBarColor(Color.parseColor("#E31937")); // Red color
|
||||
|
||||
// Make status bar icons white (for dark red background)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
View decorView = window.getDecorView();
|
||||
decorView.setSystemUiVisibility(0); // Clear light status bar flag
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeViews() {
|
||||
qrImageView = findViewById(R.id.qrImageView);
|
||||
amountTextView = findViewById(R.id.amountTextView);
|
||||
referenceTextView = findViewById(R.id.referenceTextView);
|
||||
timerTextView = findViewById(R.id.timerTextView);
|
||||
qrStatusTextView = findViewById(R.id.qrStatusTextView);
|
||||
downloadQrisButton = findViewById(R.id.downloadQrisButton);
|
||||
checkStatusButton = findViewById(R.id.checkStatusButton);
|
||||
cancelButton = findViewById(R.id.cancelButton);
|
||||
statusTextView = findViewById(R.id.statusTextView);
|
||||
returnMainButton = findViewById(R.id.returnMainButton);
|
||||
progressBar = findViewById(R.id.progressBar);
|
||||
backNavigation = findViewById(R.id.back_navigation);
|
||||
}
|
||||
|
||||
private void setupClickListeners() {
|
||||
// Back navigation
|
||||
if (backNavigation != null) {
|
||||
backNavigation.setOnClickListener(v -> finish());
|
||||
}
|
||||
|
||||
// Cancel button
|
||||
cancelButton.setOnClickListener(v -> {
|
||||
if (countDownTimer != null) {
|
||||
countDownTimer.cancel();
|
||||
}
|
||||
finish();
|
||||
});
|
||||
|
||||
// Download QRIS button (now visible and functional)
|
||||
downloadQrisButton.setOnClickListener(v -> {
|
||||
qrImageView.setDrawingCacheEnabled(true);
|
||||
Bitmap bitmap = qrImageView.getDrawingCache();
|
||||
if (bitmap != null) {
|
||||
saveImageToGallery(bitmap, "qris_code_" + System.currentTimeMillis());
|
||||
}
|
||||
qrImageView.setDrawingCacheEnabled(false);
|
||||
});
|
||||
|
||||
// Check Payment Status button (now visible and functional)
|
||||
checkStatusButton.setOnClickListener(v -> {
|
||||
Toast.makeText(this, "Checking payment status...", Toast.LENGTH_SHORT).show();
|
||||
simulateWebhook();
|
||||
});
|
||||
|
||||
// Return to Main Screen button (now visible and functional)
|
||||
returnMainButton.setOnClickListener(v -> {
|
||||
if (countDownTimer != null) {
|
||||
countDownTimer.cancel();
|
||||
}
|
||||
Intent intent = new Intent(QrisResultActivity.this, MainActivity.class);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
startActivity(intent);
|
||||
finishAffinity();
|
||||
});
|
||||
}
|
||||
|
||||
private void setupData() {
|
||||
Intent intent = getIntent();
|
||||
String qrImageUrl = intent.getStringExtra("qrImageUrl");
|
||||
int amount = intent.getIntExtra("amount", 0);
|
||||
originalQrImageUrl = qrImageUrl; // Store original URL for refresh
|
||||
amount = intent.getIntExtra("amount", 0);
|
||||
referenceId = intent.getStringExtra("referenceId");
|
||||
orderId = intent.getStringExtra("orderId");
|
||||
grossAmount = intent.getStringExtra("grossAmount");
|
||||
@ -75,60 +170,131 @@ public class QrisResultActivity extends AppCompatActivity {
|
||||
|
||||
if (orderId == null || transactionId == null) {
|
||||
Log.e("QrisResultFlow", "orderId or transactionId is null! Intent extras: " + intent.getExtras());
|
||||
android.widget.Toast.makeText(this, "Missing transaction details!", android.widget.Toast.LENGTH_LONG).show();
|
||||
Toast.makeText(this, "Missing transaction details!", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
// Get the exact amount from the grossAmount string value instead of the integer
|
||||
String amountStr = "Amount: " + grossAmount;
|
||||
amountTextView.setText(amountStr);
|
||||
referenceTextView.setText("Reference ID: " + referenceId);
|
||||
// Format and display amount
|
||||
if (grossAmount != null) {
|
||||
String formattedAmount = "RP." + formatCurrency(grossAmount);
|
||||
amountTextView.setText(formattedAmount);
|
||||
} else if (amount > 0) {
|
||||
String formattedAmount = "RP." + formatCurrency(String.valueOf(amount));
|
||||
amountTextView.setText(formattedAmount);
|
||||
}
|
||||
|
||||
// Load QR image
|
||||
new DownloadImageTask(qrImageView).execute(qrImageUrl);
|
||||
// Set reference ID (hidden)
|
||||
if (referenceId != null) {
|
||||
referenceTextView.setText("Reference ID: " + referenceId);
|
||||
}
|
||||
|
||||
// Load initial QR image
|
||||
if (qrImageUrl != null) {
|
||||
loadQrCode(qrImageUrl);
|
||||
}
|
||||
|
||||
// Disable check status button initially
|
||||
checkStatusButton.setEnabled(false);
|
||||
// Start polling for pending payment log
|
||||
pollPendingPaymentLog(orderId);
|
||||
if (orderId != null) {
|
||||
pollPendingPaymentLog(orderId);
|
||||
}
|
||||
}
|
||||
|
||||
// Download QRIS button
|
||||
downloadQrisButton.setOnClickListener(new View.OnClickListener() {
|
||||
private String formatCurrency(String amount) {
|
||||
try {
|
||||
long number = Long.parseLong(amount.replace(".00", ""));
|
||||
return String.format("%,d", number).replace(',', '.');
|
||||
} catch (NumberFormatException e) {
|
||||
return amount;
|
||||
}
|
||||
}
|
||||
|
||||
private void startTimer() {
|
||||
countDownTimer = new CountDownTimer(timeLeftInMillis, 1000) {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
qrImageView.setDrawingCacheEnabled(true);
|
||||
Bitmap bitmap = qrImageView.getDrawingCache();
|
||||
if (bitmap != null) {
|
||||
saveImageToGallery(bitmap, "qris_code_" + System.currentTimeMillis());
|
||||
public void onTick(long millisUntilFinished) {
|
||||
timeLeftInMillis = millisUntilFinished;
|
||||
int seconds = (int) (millisUntilFinished / 1000);
|
||||
timerTextView.setText(String.valueOf(seconds));
|
||||
|
||||
// Update status text based on remaining time
|
||||
if (seconds > 10) {
|
||||
qrStatusTextView.setText("QR Code akan refresh dalam " + seconds + " detik");
|
||||
qrStatusTextView.setTextColor(Color.parseColor("#666666"));
|
||||
} else {
|
||||
qrStatusTextView.setText("QR Code akan refresh dalam " + seconds + " detik");
|
||||
qrStatusTextView.setTextColor(Color.parseColor("#E31937"));
|
||||
}
|
||||
qrImageView.setDrawingCacheEnabled(false);
|
||||
}
|
||||
});
|
||||
|
||||
// Check Payment Status button
|
||||
checkStatusButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
simulateWebhook();
|
||||
public void onFinish() {
|
||||
timerTextView.setText("0");
|
||||
qrStatusTextView.setText("Refreshing QR Code...");
|
||||
qrStatusTextView.setTextColor(Color.parseColor("#E31937"));
|
||||
|
||||
// Auto refresh QR code
|
||||
refreshQrCode();
|
||||
}
|
||||
});
|
||||
}.start();
|
||||
}
|
||||
|
||||
// Return to Main Screen button
|
||||
returnMainButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Intent intent = new Intent(QrisResultActivity.this, com.example.bdkipoc.MainActivity.class);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
startActivity(intent);
|
||||
finishAffinity();
|
||||
private void refreshQrCode() {
|
||||
qrRefreshCount++;
|
||||
|
||||
if (qrRefreshCount >= MAX_QR_REFRESH) {
|
||||
// Max refresh reached, show expired message
|
||||
timerTextView.setText("Expired");
|
||||
qrStatusTextView.setText("QR Code telah expired. Silahkan generate ulang.");
|
||||
qrStatusTextView.setTextColor(Color.parseColor("#E31937"));
|
||||
Toast.makeText(this, "QR Code expired. Please generate new payment.", Toast.LENGTH_LONG).show();
|
||||
return;
|
||||
}
|
||||
|
||||
// Show loading state
|
||||
progressBar.setVisibility(View.VISIBLE);
|
||||
qrStatusTextView.setText("Generating new QR Code... (" + qrRefreshCount + "/" + MAX_QR_REFRESH + ")");
|
||||
|
||||
// Simulate generating new QR code
|
||||
new Thread(() -> {
|
||||
try {
|
||||
// Simulate API call delay
|
||||
Thread.sleep(2000);
|
||||
|
||||
// Generate new QR code (in real app, call Midtrans API again)
|
||||
generateNewQrCode();
|
||||
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
private void generateNewQrCode() {
|
||||
new Handler(Looper.getMainLooper()).post(() -> {
|
||||
progressBar.setVisibility(View.GONE);
|
||||
|
||||
// In real implementation, you would call Midtrans API again
|
||||
// For demo, we'll reload the same QR with a timestamp to show refresh
|
||||
String refreshedUrl = originalQrImageUrl + "?refresh=" + System.currentTimeMillis();
|
||||
loadQrCode(refreshedUrl);
|
||||
|
||||
// Reset timer for new 60 seconds
|
||||
timeLeftInMillis = 60000;
|
||||
startTimer();
|
||||
|
||||
Toast.makeText(this, "QR Code refreshed! (" + qrRefreshCount + "/" + MAX_QR_REFRESH + ")", Toast.LENGTH_SHORT).show();
|
||||
});
|
||||
}
|
||||
|
||||
private void loadQrCode(String qrImageUrl) {
|
||||
new DownloadImageTask(qrImageView).execute(qrImageUrl);
|
||||
}
|
||||
|
||||
private static class DownloadImageTask extends AsyncTask<String, Void, Bitmap> {
|
||||
ImageView bmImage;
|
||||
DownloadImageTask(ImageView bmImage) {
|
||||
this.bmImage = bmImage;
|
||||
}
|
||||
|
||||
protected Bitmap doInBackground(String... urls) {
|
||||
String urlDisplay = urls[0];
|
||||
Bitmap bitmap = null;
|
||||
@ -144,6 +310,7 @@ public class QrisResultActivity extends AppCompatActivity {
|
||||
}
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
protected void onPostExecute(Bitmap result) {
|
||||
if (result != null) {
|
||||
bmImage.setImageBitmap(result);
|
||||
@ -157,12 +324,12 @@ public class QrisResultActivity extends AppCompatActivity {
|
||||
String savedImageURL = android.provider.MediaStore.Images.Media.insertImage(
|
||||
getContentResolver(), bitmap, fileName, "QRIS Payment QR Code");
|
||||
if (savedImageURL != null) {
|
||||
android.widget.Toast.makeText(this, "QRIS saved to gallery", android.widget.Toast.LENGTH_SHORT).show();
|
||||
Toast.makeText(this, "QRIS saved to gallery", Toast.LENGTH_SHORT).show();
|
||||
} else {
|
||||
android.widget.Toast.makeText(this, "Failed to save QRIS", android.widget.Toast.LENGTH_SHORT).show();
|
||||
Toast.makeText(this, "Failed to save QRIS", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
android.widget.Toast.makeText(this, "Error saving QRIS: " + e.getMessage(), android.widget.Toast.LENGTH_LONG).show();
|
||||
Toast.makeText(this, "Error saving QRIS: " + e.getMessage(), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
|
||||
@ -216,9 +383,9 @@ public class QrisResultActivity extends AppCompatActivity {
|
||||
progressBar.setVisibility(View.GONE);
|
||||
if (logFound) {
|
||||
checkStatusButton.setEnabled(true);
|
||||
android.widget.Toast.makeText(QrisResultActivity.this, "Pending payment log found!", android.widget.Toast.LENGTH_SHORT).show();
|
||||
Toast.makeText(QrisResultActivity.this, "Pending payment log found!", Toast.LENGTH_SHORT).show();
|
||||
} else {
|
||||
android.widget.Toast.makeText(QrisResultActivity.this, "Pending payment log NOT found.", android.widget.Toast.LENGTH_LONG).show();
|
||||
Toast.makeText(QrisResultActivity.this, "Pending payment log NOT found.", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
}).start();
|
||||
@ -273,15 +440,52 @@ public class QrisResultActivity extends AppCompatActivity {
|
||||
}
|
||||
new Handler(Looper.getMainLooper()).post(() -> {
|
||||
progressBar.setVisibility(View.GONE);
|
||||
// Proceed to show status/result
|
||||
qrImageView.setVisibility(View.GONE);
|
||||
amountTextView.setVisibility(View.GONE);
|
||||
referenceTextView.setVisibility(View.GONE);
|
||||
downloadQrisButton.setVisibility(View.GONE);
|
||||
checkStatusButton.setVisibility(View.GONE);
|
||||
statusTextView.setVisibility(View.VISIBLE);
|
||||
returnMainButton.setVisibility(View.VISIBLE);
|
||||
// Show success state
|
||||
showSuccessState();
|
||||
});
|
||||
}).start();
|
||||
}
|
||||
}
|
||||
|
||||
private void showSuccessState() {
|
||||
// Stop timer
|
||||
if (countDownTimer != null) {
|
||||
countDownTimer.cancel();
|
||||
}
|
||||
|
||||
// Hide QR section and show success
|
||||
qrImageView.setVisibility(View.GONE);
|
||||
amountTextView.setVisibility(View.GONE);
|
||||
timerTextView.setVisibility(View.GONE);
|
||||
qrStatusTextView.setVisibility(View.GONE);
|
||||
downloadQrisButton.setVisibility(View.GONE);
|
||||
checkStatusButton.setVisibility(View.GONE);
|
||||
cancelButton.setVisibility(View.GONE);
|
||||
|
||||
// Show success message
|
||||
statusTextView.setText("Payment Successful!");
|
||||
statusTextView.setTextColor(Color.parseColor("#4CAF50"));
|
||||
statusTextView.setTextSize(24);
|
||||
statusTextView.setVisibility(View.VISIBLE);
|
||||
returnMainButton.setVisibility(View.VISIBLE);
|
||||
returnMainButton.setText("Back to Main");
|
||||
returnMainButton.setBackgroundColor(Color.parseColor("#4CAF50"));
|
||||
|
||||
Toast.makeText(this, "Payment completed successfully!", Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (countDownTimer != null) {
|
||||
countDownTimer.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
if (countDownTimer != null) {
|
||||
countDownTimer.cancel();
|
||||
}
|
||||
super.onBackPressed();
|
||||
}
|
||||
}
|
208
app/src/main/java/com/example/bdkipoc/ReceiptActivity.java
Normal file
@ -0,0 +1,208 @@
|
||||
package com.example.bdkipoc;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.graphics.Color;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.Button;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
public class ReceiptActivity extends AppCompatActivity {
|
||||
|
||||
// Views
|
||||
private LinearLayout backNavigation;
|
||||
private ImageView backArrow;
|
||||
private TextView toolbarTitle;
|
||||
|
||||
// Receipt details
|
||||
private TextView merchantName;
|
||||
private TextView merchantLocation;
|
||||
private TextView midText;
|
||||
private TextView tidText;
|
||||
private TextView transactionNumber;
|
||||
private TextView transactionDate;
|
||||
private TextView paymentMethod;
|
||||
private TextView cardType;
|
||||
private TextView transactionTotal;
|
||||
private TextView taxPercentage;
|
||||
private TextView serviceFee;
|
||||
private TextView finalTotal;
|
||||
|
||||
// Action buttons
|
||||
private LinearLayout printButton;
|
||||
private LinearLayout emailButton;
|
||||
private Button finishButton;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
// Set status bar color
|
||||
setStatusBarColor();
|
||||
|
||||
setContentView(R.layout.activity_receipt);
|
||||
|
||||
initializeViews();
|
||||
setupClickListeners();
|
||||
loadTransactionData();
|
||||
}
|
||||
|
||||
private void setStatusBarColor() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
Window window = getWindow();
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);
|
||||
window.setStatusBarColor(Color.parseColor("#E31937")); // Red color
|
||||
|
||||
// Make status bar icons white (for dark red background)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||
View decorView = window.getDecorView();
|
||||
decorView.setSystemUiVisibility(0); // Clear light status bar flag
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void initializeViews() {
|
||||
// Navigation
|
||||
backNavigation = findViewById(R.id.back_navigation);
|
||||
backArrow = findViewById(R.id.backArrow);
|
||||
toolbarTitle = findViewById(R.id.toolbarTitle);
|
||||
|
||||
// Receipt details
|
||||
merchantName = findViewById(R.id.merchant_name);
|
||||
merchantLocation = findViewById(R.id.merchant_location);
|
||||
midText = findViewById(R.id.mid_text);
|
||||
tidText = findViewById(R.id.tid_text);
|
||||
transactionNumber = findViewById(R.id.transaction_number);
|
||||
transactionDate = findViewById(R.id.transaction_date);
|
||||
paymentMethod = findViewById(R.id.payment_method);
|
||||
cardType = findViewById(R.id.card_type);
|
||||
transactionTotal = findViewById(R.id.transaction_total);
|
||||
taxPercentage = findViewById(R.id.tax_percentage);
|
||||
serviceFee = findViewById(R.id.service_fee);
|
||||
finalTotal = findViewById(R.id.final_total);
|
||||
|
||||
// Action buttons - Updated to LinearLayout
|
||||
printButton = findViewById(R.id.print_button);
|
||||
emailButton = findViewById(R.id.email_button);
|
||||
finishButton = findViewById(R.id.finish_button);
|
||||
}
|
||||
|
||||
private void setupClickListeners() {
|
||||
// Back navigation - Goes back to previous activity (PaymentActivity)
|
||||
backNavigation.setOnClickListener(v -> navigateBackToPrevious());
|
||||
backArrow.setOnClickListener(v -> navigateBackToPrevious());
|
||||
toolbarTitle.setOnClickListener(v -> navigateBackToPrevious());
|
||||
|
||||
// Action buttons
|
||||
printButton.setOnClickListener(v -> handlePrintReceipt());
|
||||
emailButton.setOnClickListener(v -> handleEmailReceipt());
|
||||
finishButton.setOnClickListener(v -> handleFinish());
|
||||
}
|
||||
|
||||
private void loadTransactionData() {
|
||||
Intent intent = getIntent();
|
||||
if (intent != null) {
|
||||
// Data dari TransactionActivity
|
||||
String amount = intent.getStringExtra("transaction_amount");
|
||||
String merchantNameStr = intent.getStringExtra("merchant_name");
|
||||
String merchantLocationStr = intent.getStringExtra("merchant_location");
|
||||
String transactionId = intent.getStringExtra("transaction_id");
|
||||
String transactionDateStr = intent.getStringExtra("transaction_date");
|
||||
String paymentMethodStr = intent.getStringExtra("payment_method");
|
||||
String cardTypeStr = intent.getStringExtra("card_type");
|
||||
|
||||
// Set data ke view
|
||||
merchantName.setText(merchantNameStr != null ? merchantNameStr : "TOKO KLONTONG PAK EKO");
|
||||
merchantLocation.setText(merchantLocationStr != null ? merchantLocationStr : "Ciputat Baru, Tangsel");
|
||||
transactionNumber.setText(transactionId != null ? transactionId : "3429483635");
|
||||
transactionDate.setText(transactionDateStr != null ? transactionDateStr : "13 Januari 2025 13:46");
|
||||
paymentMethod.setText(paymentMethodStr != null ? paymentMethodStr : "Kartu Kredit");
|
||||
cardType.setText(cardTypeStr != null ? cardTypeStr : "BCA");
|
||||
|
||||
// Format nominal
|
||||
if (amount != null) {
|
||||
try {
|
||||
long amountValue = Long.parseLong(amount);
|
||||
transactionTotal.setText(formatCurrency(amountValue));
|
||||
|
||||
// Hitung total akhir (contoh: tambah pajak 11% dan biaya layanan 500)
|
||||
long tax = (long) (amountValue * 0.11);
|
||||
long serviceFeeValue = 500;
|
||||
long total = amountValue + tax + serviceFeeValue;
|
||||
|
||||
taxPercentage.setText(formatCurrency(tax) + " (11%)");
|
||||
serviceFee.setText(formatCurrency(serviceFeeValue));
|
||||
finalTotal.setText(formatCurrency(total));
|
||||
|
||||
} catch (NumberFormatException e) {
|
||||
transactionTotal.setText(amount);
|
||||
finalTotal.setText(amount);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String formatCurrency(long amount) {
|
||||
return String.format("%,d", amount).replace(',', '.');
|
||||
}
|
||||
|
||||
private void handlePrintReceipt() {
|
||||
// Handle print receipt action
|
||||
// In real app, this would integrate with printer
|
||||
showToast("Mencetak struk...");
|
||||
}
|
||||
|
||||
private void handleEmailReceipt() {
|
||||
// Handle email receipt action
|
||||
// In real app, this would open email intent
|
||||
showToast("Mengirim email...");
|
||||
}
|
||||
|
||||
private void handleFinish() {
|
||||
// Navigate to MainActivity/Home Page when "Selesai" button is pressed
|
||||
navigateToHomePage();
|
||||
}
|
||||
|
||||
private void navigateBackToPrevious() {
|
||||
// Navigate back to PaymentActivity (previous activity)
|
||||
Intent intent = new Intent(this, PaymentActivity.class);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
startActivity(intent);
|
||||
finish();
|
||||
}
|
||||
|
||||
private void navigateToHomePage() {
|
||||
// Navigate to MainActivity/Home Page when "Selesai" button is pressed
|
||||
Intent intent = new Intent(this, MainActivity.class);
|
||||
|
||||
// Clear all previous activities from the stack and start fresh
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
|
||||
// Optional: Add success message to show in MainActivity
|
||||
intent.putExtra("transaction_completed", true);
|
||||
intent.putExtra("transaction_amount", getIntent().getStringExtra("transaction_amount"));
|
||||
|
||||
startActivity(intent);
|
||||
finish();
|
||||
|
||||
// Show success message
|
||||
showToast("Transaksi berhasil diselesaikan!");
|
||||
}
|
||||
|
||||
private void showToast(String message) {
|
||||
android.widget.Toast.makeText(this, message, android.widget.Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
// Back button behavior - goes back to previous activity
|
||||
navigateBackToPrevious();
|
||||
}
|
||||
}
|
354
app/src/main/java/com/example/bdkipoc/SettlementActivity.java
Normal file
@ -0,0 +1,354 @@
|
||||
package com.example.bdkipoc;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.text.NumberFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
public class SettlementActivity extends AppCompatActivity {
|
||||
|
||||
private TextView tvTotalAmount;
|
||||
private TextView tvTotalTransactions;
|
||||
private RecyclerView recyclerView;
|
||||
private SettlementAdapter adapter;
|
||||
private List<SettlementItem> settlementList;
|
||||
private ImageView btnBack;
|
||||
|
||||
private String API_URL = "https://be-edc.msvc.app/transactions/performa-chanel-pembayaran?from_date=2025-01-01&to_date=2025-06-04&location_id=0&merchant_id=0";
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_settlement);
|
||||
|
||||
initViews();
|
||||
setupRecyclerView();
|
||||
fetchApiData();
|
||||
setupClickListeners();
|
||||
}
|
||||
|
||||
private void fetchApiData() {
|
||||
// Execute network call in background thread
|
||||
new ApiTask().execute(API_URL);
|
||||
}
|
||||
|
||||
private void processApiData(JSONArray dataArray) {
|
||||
try {
|
||||
settlementList.clear();
|
||||
|
||||
final long[] totalAmountArray = {0}; // Using array to make it effectively final
|
||||
final int[] totalTransactionsArray = {0}; // Using array to make it effectively final
|
||||
|
||||
// Process each channel individually (no grouping)
|
||||
for (int i = 0; i < dataArray.length(); i++) {
|
||||
JSONObject item = dataArray.getJSONObject(i);
|
||||
|
||||
String channelCode = item.getString("channel_code");
|
||||
int transactions = item.getInt("total_transactions");
|
||||
long maxAmount = item.getLong("max_transastions");
|
||||
|
||||
// Use channel code directly as display name with some formatting
|
||||
String displayName = formatChannelName(channelCode);
|
||||
int iconResource = getChannelIcon(channelCode);
|
||||
|
||||
settlementList.add(new SettlementItem(
|
||||
displayName,
|
||||
maxAmount,
|
||||
transactions,
|
||||
iconResource
|
||||
));
|
||||
|
||||
totalAmountArray[0] += maxAmount;
|
||||
totalTransactionsArray[0] += transactions;
|
||||
}
|
||||
|
||||
// Update UI on main thread
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
updateSummary(totalAmountArray[0], totalTransactionsArray[0]);
|
||||
adapter.notifyDataSetChanged();
|
||||
}
|
||||
});
|
||||
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Toast.makeText(SettlementActivity.this, "Error parsing data", Toast.LENGTH_SHORT).show();
|
||||
loadSampleData(); // Fallback to sample data
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void updateSummary(long totalAmount, int totalTransactions) {
|
||||
tvTotalAmount.setText(formatCurrency(totalAmount));
|
||||
tvTotalTransactions.setText(String.valueOf(totalTransactions));
|
||||
}
|
||||
|
||||
private void initViews() {
|
||||
tvTotalAmount = findViewById(R.id.tv_total_amount);
|
||||
tvTotalTransactions = findViewById(R.id.tv_total_transactions);
|
||||
recyclerView = findViewById(R.id.recycler_view);
|
||||
btnBack = findViewById(R.id.btn_back);
|
||||
|
||||
settlementList = new ArrayList<>();
|
||||
}
|
||||
|
||||
private void setupRecyclerView() {
|
||||
adapter = new SettlementAdapter(settlementList);
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(this));
|
||||
recyclerView.setAdapter(adapter);
|
||||
}
|
||||
|
||||
private void setupClickListeners() {
|
||||
btnBack.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
finish();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void loadSampleData() {
|
||||
// Sample data as fallback
|
||||
settlementList.clear();
|
||||
|
||||
settlementList.add(new SettlementItem("Kartu Kredit", 200000, 13, android.R.drawable.ic_menu_recent_history));
|
||||
settlementList.add(new SettlementItem("Kartu Debit", 200000, 13, android.R.drawable.ic_menu_manage));
|
||||
settlementList.add(new SettlementItem("Transfer", 200000, 13, android.R.drawable.ic_menu_send));
|
||||
settlementList.add(new SettlementItem("Uang Elektronik", 200000, 13, android.R.drawable.ic_menu_gallery));
|
||||
settlementList.add(new SettlementItem("QRIS", 200000, 13, android.R.drawable.ic_menu_camera));
|
||||
|
||||
// Update summary
|
||||
tvTotalAmount.setText(formatCurrency(3506500));
|
||||
tvTotalTransactions.setText("65");
|
||||
|
||||
adapter.notifyDataSetChanged();
|
||||
}
|
||||
|
||||
private String formatChannelName(String channelCode) {
|
||||
// Format channel code to be more readable
|
||||
switch (channelCode) {
|
||||
case "GO-PAY":
|
||||
return "GoPay";
|
||||
case "SHOPEEPAY":
|
||||
return "ShopeePay";
|
||||
case "LINKAJA":
|
||||
return "LinkAja";
|
||||
case "MASTERCARD":
|
||||
return "Mastercard";
|
||||
case "VISA":
|
||||
return "Visa";
|
||||
case "QRIS":
|
||||
return "QRIS";
|
||||
case "DANA":
|
||||
return "Dana";
|
||||
case "OVO":
|
||||
return "OVO";
|
||||
case "DEBIT":
|
||||
return "Kartu Debit";
|
||||
case "GPN":
|
||||
return "GPN";
|
||||
case "OTHER":
|
||||
return "Lainnya";
|
||||
default:
|
||||
// Capitalize first letter and make rest lowercase
|
||||
return channelCode.substring(0, 1).toUpperCase() +
|
||||
channelCode.substring(1).toLowerCase();
|
||||
}
|
||||
}
|
||||
|
||||
private String getChannelDisplayName(String channelCode) {
|
||||
// Deprecated - keeping for backward compatibility
|
||||
return formatChannelName(channelCode);
|
||||
}
|
||||
|
||||
private int getChannelIcon(String channelCode) {
|
||||
// Dynamic icon assignment based on channel type
|
||||
switch (channelCode) {
|
||||
case "DEBIT":
|
||||
return android.R.drawable.ic_menu_manage;
|
||||
case "VISA":
|
||||
case "MASTERCARD":
|
||||
return android.R.drawable.ic_menu_recent_history;
|
||||
case "QRIS":
|
||||
return android.R.drawable.ic_menu_camera;
|
||||
case "DANA":
|
||||
case "GO-PAY":
|
||||
case "OVO":
|
||||
case "SHOPEEPAY":
|
||||
case "LINKAJA":
|
||||
return android.R.drawable.ic_menu_gallery;
|
||||
case "GPN":
|
||||
return android.R.drawable.ic_menu_send;
|
||||
case "OTHER":
|
||||
return android.R.drawable.ic_menu_info_details;
|
||||
default:
|
||||
return android.R.drawable.ic_menu_help;
|
||||
}
|
||||
}
|
||||
|
||||
private String formatCurrency(long amount) {
|
||||
NumberFormat formatter = NumberFormat.getNumberInstance(new Locale("id", "ID"));
|
||||
return formatter.format(amount);
|
||||
}
|
||||
|
||||
// Deprecated helper class - no longer needed
|
||||
// private static class ChannelData { ... }
|
||||
|
||||
// AsyncTask for API call
|
||||
private class ApiTask extends AsyncTask<String, Void, String> {
|
||||
@Override
|
||||
protected String doInBackground(String... urls) {
|
||||
try {
|
||||
URL url = new URL(urls[0]);
|
||||
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
connection.setRequestMethod("GET");
|
||||
connection.setConnectTimeout(5000);
|
||||
connection.setReadTimeout(5000);
|
||||
|
||||
int responseCode = connection.getResponseCode();
|
||||
if (responseCode == HttpURLConnection.HTTP_OK) {
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
|
||||
StringBuilder response = new StringBuilder();
|
||||
String line;
|
||||
|
||||
while ((line = reader.readLine()) != null) {
|
||||
response.append(line);
|
||||
}
|
||||
reader.close();
|
||||
return response.toString();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(String result) {
|
||||
if (result != null) {
|
||||
try {
|
||||
JSONObject jsonResponse = new JSONObject(result);
|
||||
if (jsonResponse.getInt("status") == 200) {
|
||||
JSONArray dataArray = jsonResponse.getJSONArray("data");
|
||||
processApiData(dataArray);
|
||||
} else {
|
||||
Toast.makeText(SettlementActivity.this, "API Error", Toast.LENGTH_SHORT).show();
|
||||
loadSampleData();
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
Toast.makeText(SettlementActivity.this, "JSON Parse Error", Toast.LENGTH_SHORT).show();
|
||||
loadSampleData();
|
||||
}
|
||||
} else {
|
||||
Toast.makeText(SettlementActivity.this, "Network Error", Toast.LENGTH_SHORT).show();
|
||||
loadSampleData();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SettlementItem class - combined in same file
|
||||
class SettlementItem {
|
||||
private String channelName;
|
||||
private long amount;
|
||||
private int transactionCount;
|
||||
private int iconResource;
|
||||
|
||||
public SettlementItem() {}
|
||||
|
||||
public SettlementItem(String channelName, long amount, int transactionCount, int iconResource) {
|
||||
this.channelName = channelName;
|
||||
this.amount = amount;
|
||||
this.transactionCount = transactionCount;
|
||||
this.iconResource = iconResource;
|
||||
}
|
||||
|
||||
// Getters and Setters
|
||||
public String getChannelName() { return channelName; }
|
||||
public void setChannelName(String channelName) { this.channelName = channelName; }
|
||||
public long getAmount() { return amount; }
|
||||
public void setAmount(long amount) { this.amount = amount; }
|
||||
public int getTransactionCount() { return transactionCount; }
|
||||
public void setTransactionCount(int transactionCount) { this.transactionCount = transactionCount; }
|
||||
public int getIconResource() { return iconResource; }
|
||||
public void setIconResource(int iconResource) { this.iconResource = iconResource; }
|
||||
}
|
||||
|
||||
// SettlementAdapter class - combined in same file
|
||||
class SettlementAdapter extends RecyclerView.Adapter<SettlementAdapter.SettlementViewHolder> {
|
||||
|
||||
private List<SettlementItem> settlementList;
|
||||
|
||||
public SettlementAdapter(List<SettlementItem> settlementList) {
|
||||
this.settlementList = settlementList;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public SettlementViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
View view = LayoutInflater.from(parent.getContext())
|
||||
.inflate(R.layout.item_settlement, parent, false);
|
||||
return new SettlementViewHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull SettlementViewHolder holder, int position) {
|
||||
SettlementItem item = settlementList.get(position);
|
||||
|
||||
holder.ivIcon.setImageResource(item.getIconResource());
|
||||
holder.tvChannelName.setText(item.getChannelName());
|
||||
holder.tvAmount.setText("Rp. " + formatCurrency(item.getAmount()));
|
||||
holder.tvTransactionCount.setText(item.getTransactionCount() + " Transaksi");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return settlementList.size();
|
||||
}
|
||||
|
||||
private String formatCurrency(long amount) {
|
||||
NumberFormat formatter = NumberFormat.getNumberInstance(new Locale("id", "ID"));
|
||||
return formatter.format(amount);
|
||||
}
|
||||
|
||||
static class SettlementViewHolder extends RecyclerView.ViewHolder {
|
||||
ImageView ivIcon;
|
||||
TextView tvChannelName;
|
||||
TextView tvAmount;
|
||||
TextView tvTransactionCount;
|
||||
|
||||
public SettlementViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
ivIcon = itemView.findViewById(R.id.iv_icon);
|
||||
tvChannelName = itemView.findViewById(R.id.tv_channel_name);
|
||||
tvAmount = itemView.findViewById(R.id.tv_amount);
|
||||
tvTransactionCount = itemView.findViewById(R.id.tv_transaction_count);
|
||||
}
|
||||
}
|
||||
}
|
@ -2,15 +2,21 @@ package com.example.bdkipoc;
|
||||
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.text.Editable;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.Toast;
|
||||
import android.content.Intent;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
import com.google.android.material.floatingactionbutton.FloatingActionButton;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
@ -25,67 +31,173 @@ import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
public class TransactionActivity extends AppCompatActivity {
|
||||
public class TransactionActivity extends AppCompatActivity implements TransactionAdapter.OnPrintClickListener {
|
||||
private RecyclerView recyclerView;
|
||||
private TransactionAdapter adapter;
|
||||
private List<Transaction> transactionList;
|
||||
private List<Transaction> filteredList;
|
||||
private ProgressBar progressBar;
|
||||
private FloatingActionButton refreshButton;
|
||||
private EditText searchEditText;
|
||||
private ImageButton searchButton;
|
||||
|
||||
// Pagination variables
|
||||
private int page = 0;
|
||||
private final int limit = 10;
|
||||
private boolean isLoading = false;
|
||||
private boolean isLastPage = false;
|
||||
private List<Transaction> transactionList = new ArrayList<>();
|
||||
private String currentSearchQuery = "";
|
||||
private boolean isRefreshing = false;
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_transaction);
|
||||
|
||||
// Set up the toolbar as the action bar
|
||||
androidx.appcompat.widget.Toolbar toolbar = findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
// Initialize views
|
||||
initViews();
|
||||
|
||||
// Enable the back button in the action bar
|
||||
// Setup toolbar
|
||||
setupToolbar();
|
||||
|
||||
// Setup RecyclerView
|
||||
setupRecyclerView();
|
||||
|
||||
// Setup search functionality
|
||||
setupSearch();
|
||||
|
||||
// Load initial data
|
||||
loadTransactions(0);
|
||||
}
|
||||
|
||||
private void initViews() {
|
||||
recyclerView = findViewById(R.id.recyclerView);
|
||||
progressBar = findViewById(R.id.progressBar);
|
||||
searchEditText = findViewById(R.id.searchEditText);
|
||||
searchButton = findViewById(R.id.searchButton);
|
||||
}
|
||||
|
||||
private void setupToolbar() {
|
||||
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
if (getSupportActionBar() != null) {
|
||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||
getSupportActionBar().setDisplayShowHomeEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
recyclerView = findViewById(R.id.recyclerView);
|
||||
progressBar = findViewById(R.id.progressBar);
|
||||
refreshButton = findViewById(R.id.refreshButton);
|
||||
|
||||
adapter = new TransactionAdapter(transactionList);
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(this));
|
||||
private void setupRecyclerView() {
|
||||
transactionList = new ArrayList<>();
|
||||
filteredList = new ArrayList<>();
|
||||
|
||||
adapter = new TransactionAdapter(filteredList);
|
||||
adapter.setPrintClickListener(this);
|
||||
|
||||
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
|
||||
recyclerView.setLayoutManager(layoutManager);
|
||||
recyclerView.setAdapter(adapter);
|
||||
|
||||
refreshButton.setOnClickListener(v -> refreshTransactions());
|
||||
|
||||
// Add scroll listener for pagination
|
||||
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
|
||||
@Override
|
||||
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
|
||||
super.onScrolled(recyclerView, dx, dy);
|
||||
if (!recyclerView.canScrollVertically(1) && !isLoading && !isLastPage) {
|
||||
|
||||
// Pagination: Load more when reaching the bottom
|
||||
if (!recyclerView.canScrollVertically(1) && !isLoading && !isLastPage && currentSearchQuery.isEmpty()) {
|
||||
loadTransactions(page + 1);
|
||||
}
|
||||
|
||||
// Detect scroll to top for refresh gesture (double tap on top)
|
||||
LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
|
||||
if (layoutManager != null && layoutManager.findFirstCompletelyVisibleItemPosition() == 0 && dy < 0) {
|
||||
// User is at top and scrolling up, enable refresh on search button long press
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
loadTransactions(0);
|
||||
private void setupSearch() {
|
||||
// Search button click listener
|
||||
searchButton.setOnClickListener(v -> performSearch());
|
||||
|
||||
// Search button long press for refresh
|
||||
searchButton.setOnLongClickListener(v -> {
|
||||
refreshTransactions();
|
||||
Toast.makeText(this, "Refreshing data...", Toast.LENGTH_SHORT).show();
|
||||
return true;
|
||||
});
|
||||
|
||||
// Search EditText listener
|
||||
searchEditText.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
currentSearchQuery = s.toString().trim();
|
||||
filterTransactions(currentSearchQuery);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {}
|
||||
});
|
||||
}
|
||||
|
||||
private void refreshTransactions() {
|
||||
if (isRefreshing) return;
|
||||
|
||||
isRefreshing = true;
|
||||
// Clear search when refreshing
|
||||
searchEditText.setText("");
|
||||
currentSearchQuery = "";
|
||||
page = 0;
|
||||
isLastPage = false;
|
||||
transactionList.clear();
|
||||
filteredList.clear();
|
||||
adapter.notifyDataSetChanged();
|
||||
loadTransactions(0);
|
||||
}
|
||||
|
||||
private void performSearch() {
|
||||
String query = searchEditText.getText().toString().trim();
|
||||
currentSearchQuery = query;
|
||||
filterTransactions(query);
|
||||
|
||||
// Hide keyboard
|
||||
searchEditText.clearFocus();
|
||||
}
|
||||
|
||||
private void filterTransactions(String query) {
|
||||
filteredList.clear();
|
||||
|
||||
if (query.isEmpty()) {
|
||||
filteredList.addAll(transactionList);
|
||||
} else {
|
||||
for (Transaction transaction : transactionList) {
|
||||
if (transaction.referenceId.toLowerCase().contains(query.toLowerCase()) ||
|
||||
transaction.amount.contains(query)) {
|
||||
filteredList.add(transaction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
adapter.notifyDataSetChanged();
|
||||
|
||||
// Scroll to top after filtering
|
||||
if (!filteredList.isEmpty()) {
|
||||
recyclerView.scrollToPosition(0);
|
||||
}
|
||||
}
|
||||
|
||||
private void loadTransactions(int pageToLoad) {
|
||||
isLoading = true;
|
||||
progressBar.setVisibility(View.VISIBLE);
|
||||
if (pageToLoad == 0) {
|
||||
progressBar.setVisibility(View.VISIBLE);
|
||||
}
|
||||
new FetchTransactionsTask(pageToLoad).execute();
|
||||
}
|
||||
|
||||
@ -149,33 +261,73 @@ public class TransactionActivity extends AppCompatActivity {
|
||||
@Override
|
||||
protected void onPostExecute(List<Transaction> transactions) {
|
||||
isLoading = false;
|
||||
isRefreshing = false;
|
||||
progressBar.setVisibility(View.GONE);
|
||||
|
||||
if (error) {
|
||||
Toast.makeText(TransactionActivity.this, "Failed to fetch transactions", Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
|
||||
if (pageToLoad == 0) {
|
||||
transactionList.clear();
|
||||
}
|
||||
transactionList.addAll(transactions);
|
||||
adapter.notifyDataSetChanged();
|
||||
|
||||
// Update filtered list based on current search
|
||||
filterTransactions(currentSearchQuery);
|
||||
|
||||
page = pageToLoad;
|
||||
if (transactionList.size() >= total) {
|
||||
isLastPage = true;
|
||||
}
|
||||
|
||||
// Scroll to top if it's a refresh
|
||||
if (pageToLoad == 0 && !filteredList.isEmpty()) {
|
||||
recyclerView.scrollToPosition(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(android.view.MenuItem item) {
|
||||
public void onPrintClick(Transaction transaction) {
|
||||
// Buka ReceiptActivity dengan data transaksi
|
||||
Intent intent = new Intent(this, ReceiptActivity.class);
|
||||
|
||||
// Format data sesuai kebutuhan ReceiptActivity
|
||||
intent.putExtra("transaction_id", transaction.referenceId);
|
||||
intent.putExtra("transaction_amount", transaction.amount.replace("Rp. ", "").replace(".", ""));
|
||||
intent.putExtra("transaction_date", formatDate(transaction.createdAt)); // Format tanggal jika perlu
|
||||
intent.putExtra("payment_method", "Kartu " + transaction.channelCode); // Contoh: "Kartu BCA"
|
||||
intent.putExtra("card_type", transaction.channelCategory);
|
||||
intent.putExtra("merchant_name", transaction.merchantName);
|
||||
intent.putExtra("merchant_location", "Lokasi Merchant"); // Tambahkan jika ada di data
|
||||
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
private String formatDate(String rawDate) {
|
||||
try {
|
||||
SimpleDateFormat inputFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
|
||||
SimpleDateFormat outputFormat = new SimpleDateFormat("dd MMMM yyyy HH:mm", new Locale("id", "ID"));
|
||||
Date date = inputFormat.parse(rawDate);
|
||||
return outputFormat.format(date);
|
||||
} catch (Exception e) {
|
||||
return rawDate; // Fallback ke format asli jika parsing gagal
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if (item.getItemId() == android.R.id.home) {
|
||||
// Handle the back button click
|
||||
finish();
|
||||
return true;
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
// Transaction model class
|
||||
static class Transaction {
|
||||
int id;
|
||||
String type;
|
||||
@ -201,4 +353,4 @@ public class TransactionActivity extends AppCompatActivity {
|
||||
this.merchantName = merchantName;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -4,6 +4,7 @@ import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
import android.widget.LinearLayout;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
@ -14,11 +15,20 @@ import java.util.Locale;
|
||||
|
||||
public class TransactionAdapter extends RecyclerView.Adapter<TransactionAdapter.TransactionViewHolder> {
|
||||
private List<TransactionActivity.Transaction> transactionList;
|
||||
private OnPrintClickListener printClickListener;
|
||||
|
||||
public interface OnPrintClickListener {
|
||||
void onPrintClick(TransactionActivity.Transaction transaction);
|
||||
}
|
||||
|
||||
public TransactionAdapter(List<TransactionActivity.Transaction> transactionList) {
|
||||
this.transactionList = transactionList;
|
||||
}
|
||||
|
||||
public void setPrintClickListener(OnPrintClickListener listener) {
|
||||
this.printClickListener = listener;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public TransactionViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
@ -30,19 +40,30 @@ public class TransactionAdapter extends RecyclerView.Adapter<TransactionAdapter.
|
||||
public void onBindViewHolder(@NonNull TransactionViewHolder holder, int position) {
|
||||
TransactionActivity.Transaction t = transactionList.get(position);
|
||||
|
||||
// Set reference ID
|
||||
holder.referenceId.setText(t.referenceId);
|
||||
|
||||
// Format the amount as Indonesian Rupiah
|
||||
try {
|
||||
double amountValue = Double.parseDouble(t.amount);
|
||||
NumberFormat rupiahFormat = NumberFormat.getCurrencyInstance(new Locale.Builder().setLanguage("id").setRegion("ID").build());
|
||||
holder.amount.setText(rupiahFormat.format(amountValue));
|
||||
NumberFormat rupiahFormat = NumberFormat.getInstance(new Locale("id", "ID"));
|
||||
holder.amount.setText("Rp. " + rupiahFormat.format(amountValue));
|
||||
} catch (NumberFormatException e) {
|
||||
holder.amount.setText("Rp " + t.amount);
|
||||
holder.amount.setText("Rp. " + t.amount);
|
||||
}
|
||||
|
||||
holder.status.setText(t.status);
|
||||
holder.referenceId.setText(t.referenceId);
|
||||
holder.merchantName.setText(t.merchantName);
|
||||
holder.createdAt.setText(t.createdAt.replace("T", " ").substring(0, 19));
|
||||
|
||||
holder.itemView.setOnClickListener(v -> {
|
||||
if (printClickListener != null) {
|
||||
printClickListener.onPrintClick(t);
|
||||
}
|
||||
});
|
||||
|
||||
// Set click listener for print button
|
||||
holder.printSection.setOnClickListener(v -> {
|
||||
if (printClickListener != null) {
|
||||
printClickListener.onPrintClick(t);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -51,14 +72,14 @@ public class TransactionAdapter extends RecyclerView.Adapter<TransactionAdapter.
|
||||
}
|
||||
|
||||
static class TransactionViewHolder extends RecyclerView.ViewHolder {
|
||||
TextView amount, status, referenceId, merchantName, createdAt;
|
||||
TextView amount, referenceId;
|
||||
LinearLayout printSection;
|
||||
|
||||
public TransactionViewHolder(@NonNull View itemView) {
|
||||
super(itemView);
|
||||
amount = itemView.findViewById(R.id.textAmount);
|
||||
status = itemView.findViewById(R.id.textStatus);
|
||||
referenceId = itemView.findViewById(R.id.textReferenceId);
|
||||
merchantName = itemView.findViewById(R.id.textMerchantName);
|
||||
createdAt = itemView.findViewById(R.id.textCreatedAt);
|
||||
printSection = itemView.findViewById(R.id.printSection);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
4
app/src/main/res/anim/fade_in.xml
Normal file
@ -0,0 +1,4 @@
|
||||
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:duration="300"
|
||||
android:fromAlpha="0.0"
|
||||
android:toAlpha="1.0" />
|
4
app/src/main/res/anim/fade_out.xml
Normal file
@ -0,0 +1,4 @@
|
||||
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:duration="300"
|
||||
android:fromAlpha="1.0"
|
||||
android:toAlpha="0.0" />
|
14
app/src/main/res/anim/scale_in.xml
Normal file
@ -0,0 +1,14 @@
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<scale
|
||||
android:duration="200"
|
||||
android:fromXScale="0.8"
|
||||
android:fromYScale="0.8"
|
||||
android:pivotX="50%"
|
||||
android:pivotY="50%"
|
||||
android:toXScale="1.0"
|
||||
android:toYScale="1.0" />
|
||||
<alpha
|
||||
android:duration="200"
|
||||
android:fromAlpha="0.0"
|
||||
android:toAlpha="1.0" />
|
||||
</set>
|
14
app/src/main/res/anim/scale_out.xml
Normal file
@ -0,0 +1,14 @@
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<scale
|
||||
android:duration="200"
|
||||
android:fromXScale="1.0"
|
||||
android:fromYScale="1.0"
|
||||
android:pivotX="50%"
|
||||
android:pivotY="50%"
|
||||
android:toXScale="0.8"
|
||||
android:toYScale="0.8" />
|
||||
<alpha
|
||||
android:duration="200"
|
||||
android:fromAlpha="1.0"
|
||||
android:toAlpha="0.0" />
|
||||
</set>
|
10
app/src/main/res/anim/slide_in_left.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<translate
|
||||
android:duration="300"
|
||||
android:fromXDelta="-100%p"
|
||||
android:toXDelta="0" />
|
||||
<alpha
|
||||
android:duration="300"
|
||||
android:fromAlpha="0.0"
|
||||
android:toAlpha="1.0" />
|
||||
</set>
|
10
app/src/main/res/anim/slide_in_right.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<translate
|
||||
android:duration="300"
|
||||
android:fromXDelta="100%p"
|
||||
android:toXDelta="0" />
|
||||
<alpha
|
||||
android:duration="300"
|
||||
android:fromAlpha="0.0"
|
||||
android:toAlpha="1.0" />
|
||||
</set>
|
10
app/src/main/res/anim/slide_out_left.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<translate
|
||||
android:duration="300"
|
||||
android:fromXDelta="0"
|
||||
android:toXDelta="-100%p" />
|
||||
<alpha
|
||||
android:duration="300"
|
||||
android:fromAlpha="1.0"
|
||||
android:toAlpha="0.0" />
|
||||
</set>
|
10
app/src/main/res/anim/slide_out_right.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<set xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<translate
|
||||
android:duration="300"
|
||||
android:fromXDelta="0"
|
||||
android:toXDelta="100%p" />
|
||||
<alpha
|
||||
android:duration="300"
|
||||
android:fromAlpha="1.0"
|
||||
android:toAlpha="0.0" />
|
||||
</set>
|
6
app/src/main/res/drawable/button_active_background.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="#DE0701" />
|
||||
<corners android:radius="8dp" />
|
||||
</shape>
|
5
app/src/main/res/drawable/button_background_selector.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@drawable/button_active_background" android:state_enabled="true"/>
|
||||
<item android:drawable="@drawable/button_inactive_background" android:state_enabled="false"/>
|
||||
</selector>
|
9
app/src/main/res/drawable/button_finish_background.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
|
||||
<solid android:color="#3498DB" />
|
||||
|
||||
<corners android:radius="8dp" />
|
||||
|
||||
</shape>
|
6
app/src/main/res/drawable/button_inactive_background.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="#ECEFF0" />
|
||||
<corners android:radius="8dp" />
|
||||
</shape>
|
13
app/src/main/res/drawable/button_secondary_background.xml
Normal file
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
|
||||
<solid android:color="#F5F5F5" />
|
||||
|
||||
<stroke
|
||||
android:width="1dp"
|
||||
android:color="#E0E0E0" />
|
||||
|
||||
<corners android:radius="8dp" />
|
||||
|
||||
</shape>
|
6
app/src/main/res/drawable/card_background.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:shape="rectangle">
|
||||
<solid android:color="#3498DB" />
|
||||
<corners android:radius="12dp" />
|
||||
<stroke android:width="0dp" />
|
||||
</shape>
|
BIN
app/src/main/res/drawable/ic_arrow_back.png
Normal file
After Width: | Height: | Size: 220 B |
10
app/src/main/res/drawable/ic_backspace.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<!-- res/drawable/icons/ic_backspace.xml -->
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#333333"
|
||||
android:pathData="M22,3H7c-0.69,0 -1.23,0.35 -1.59,0.88L0,12l5.41,8.11c0.36,0.53 0.9,0.89 1.59,0.89h15c1.1,0 2,-0.9 2,-2V5c0,-1.1 -0.9,-2 -2,-2zM19,15.59L17.59,17 14,13.41 10.41,17 9,15.59 12.59,12 9,8.41 10.41,7 14,10.59 17.59,7 19,8.41 15.41,12 19,15.59z"/>
|
||||
</vector>
|
BIN
app/src/main/res/drawable/ic_card_insert.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
10
app/src/main/res/drawable/ic_check_circle.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24"
|
||||
android:tint="?attr/colorOnPrimary">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM10,17l-5,-5 1.41,-1.41L10,14.17l7.59,-7.59L19,8l-9,9z"/>
|
||||
</vector>
|
BIN
app/src/main/res/drawable/ic_credit_card.png
Normal file
After Width: | Height: | Size: 606 B |
BIN
app/src/main/res/drawable/ic_debit_card.png
Normal file
After Width: | Height: | Size: 2.6 KiB |
10
app/src/main/res/drawable/ic_e_money.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#000000"
|
||||
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8zM11,16h2v-1h1c0.55,0 1,-0.45 1,-1v-3c0,-0.55 -0.45,-1 -1,-1h-3v-1h4V8h-2V7h-2v1h-1c-0.55,0 -1,0.45 -1,1v3c0,0.55 0.45,1 1,1h3v1H9v2h2v1z"/>
|
||||
</vector>
|
BIN
app/src/main/res/drawable/ic_email.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
app/src/main/res/drawable/ic_help.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
app/src/main/res/drawable/ic_history.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
app/src/main/res/drawable/ic_logo_icon.png
Normal file
After Width: | Height: | Size: 11 KiB |
10
app/src/main/res/drawable/ic_notifications.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:pathData="M12,22c1.1,0 2,-0.9 2,-2h-4c0,1.1 0.9,2 2,2zM18,16v-5c0,-3.07 -1.64,-5.64 -4.5,-6.32L13.5,4c0,-0.83 -0.67,-1.5 -1.5,-1.5s-1.5,0.67 -1.5,1.5v0.68C7.63,5.36 6,7.92 6,11v5l-2,2v1h16v-1l-2,-2z"/>
|
||||
</vector>
|
BIN
app/src/main/res/drawable/ic_print.png
Normal file
After Width: | Height: | Size: 586 B |
10
app/src/main/res/drawable/ic_qr_code.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:pathData="M3,11h8L11,3L3,3v8zM5,5h4v4L5,9L5,5zM13,3v8h8L21,3h-8zM19,9h-4L15,5h4v4zM3,21h8v-8L3,13v8zM5,15h4v4L5,19v-4zM13,13v8h8v-8h-8zM19,19h-4v-4h4v4z"/>
|
||||
</vector>
|
BIN
app/src/main/res/drawable/ic_qris.png
Normal file
After Width: | Height: | Size: 607 B |
BIN
app/src/main/res/drawable/ic_refund.png
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
app/src/main/res/drawable/ic_reprint.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
10
app/src/main/res/drawable/ic_settlement.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#000000"
|
||||
android:pathData="M19,3h-4.18C14.4,1.84 13.3,1 12,1c-1.3,0 -2.4,0.84 -2.82,2L5,3c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h14c1.1,0 2,-0.9 2,-2L21,5c0,-1.1 -0.9,-2 -2,-2zM12,3c0.55,0 1,0.45 1,1s-0.45,1 -1,1 -1,-0.45 -1,-1 0.45,-1 1,-1zM12,7c1.66,0 3,1.34 3,3s-1.34,3 -3,3 -3,-1.34 -3,-3 1.34,-3 3,-3zM18,19L6,19v-1.4c0,-2 4,-3.1 6,-3.1s6,1.1 6,3.1L18,19z"/>
|
||||
</vector>
|
BIN
app/src/main/res/drawable/ic_store_info.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
app/src/main/res/drawable/ic_success_payment.png
Normal file
After Width: | Height: | Size: 4.0 KiB |
10
app/src/main/res/drawable/ic_transfer.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#000000"
|
||||
android:pathData="M16,17.01V10h-2v7.01h-3L15,20l4,-3h-3zM9,3L5,6h3v7.01h2V6h3L9,3z"/>
|
||||
</vector>
|
5
app/src/main/res/drawable/search_background.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#f5f5f5" />
|
||||
<corners android:radius="4dp" />
|
||||
<stroke android:width="1dp" android:color="#e0e0e0" />
|
||||
</shape>
|
4
app/src/main/res/drawable/search_button_background.xml
Normal file
@ -0,0 +1,4 @@
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<solid android:color="#666666" />
|
||||
<corners android:radius="4dp" />
|
||||
</shape>
|
11
app/src/main/res/font/inter.xml
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<font-family xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<font
|
||||
app:font="@font/inter_regular"
|
||||
app:fontWeight="400"
|
||||
app:fontStyle="normal"/>
|
||||
<font
|
||||
app:font="@font/inter_medium"
|
||||
app:fontWeight="500"
|
||||
app:fontStyle="normal"/>
|
||||
</font-family>
|
BIN
app/src/main/res/font/inter_medium.ttf
Normal file
BIN
app/src/main/res/font/inter_regular.ttf
Normal file
174
app/src/main/res/layout/activity_history.xml
Normal file
@ -0,0 +1,174 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#F5F5F5"
|
||||
android:orientation="vertical">
|
||||
|
||||
<!-- Header with red background -->
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="200dp"
|
||||
android:background="#E53E3E">
|
||||
|
||||
<!-- Back button -->
|
||||
<ImageView
|
||||
android:id="@+id/btn_back"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="24dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:padding="4dp"
|
||||
android:src="@android:drawable/ic_menu_revert"
|
||||
android:tint="@android:color/white" />
|
||||
|
||||
<!-- Title -->
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_toEndOf="@id/btn_back"
|
||||
android:text="Kembali"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="16sp" />
|
||||
|
||||
<!-- History Card -->
|
||||
<androidx.cardview.widget.CardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="120dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="64dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
app:cardCornerRadius="12dp"
|
||||
app:cardElevation="4dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#4299E1"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Transaksi Hari Ini"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="2dp"
|
||||
android:text="Total Transaksi"
|
||||
android:textColor="#E0FFFFFF"
|
||||
android:textSize="12sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_total_amount"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:text="RP 4.500.000"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="2dp"
|
||||
android:text="Jumlah Transaksi"
|
||||
android:textColor="#E0FFFFFF"
|
||||
android:textSize="12sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_total_transactions"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="30"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/btn_lihat_detail"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:padding="8dp"
|
||||
android:text="Lihat Detail"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="12sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<!-- Content -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:text="Transaksi Terbaru"
|
||||
android:textColor="#333333"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<!-- Transaction List -->
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Bottom Button -->
|
||||
<Button
|
||||
android:id="@+id/btn_lihat_detail_bottom"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:layout_margin="16dp"
|
||||
android:background="#6B46C1"
|
||||
android:text="Lihat Detail"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
</LinearLayout>
|
45
app/src/main/res/layout/activity_history_detail.xml
Normal file
@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#F5F5F5"
|
||||
android:orientation="vertical">
|
||||
|
||||
<!-- Header -->
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="56dp"
|
||||
android:background="#E53E3E"
|
||||
android:padding="16dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/btn_back"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:src="@android:drawable/ic_menu_revert"
|
||||
android:tint="@android:color/white" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true"
|
||||
android:text="Detail Transaksi"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<!-- Content -->
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="16dp" />
|
||||
|
||||
</LinearLayout>
|
@ -1,92 +1,701 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<ScrollView
|
||||
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:id="@+id/main"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".MainActivity">
|
||||
android:fillViewport="true"
|
||||
android:overScrollMode="never"
|
||||
android:scrollbars="none"
|
||||
android:background="#FFFFFF">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title_text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/main_title"
|
||||
android:textSize="24sp"
|
||||
android:layout_marginTop="32dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#FFFFFF"
|
||||
tools:context=".MainActivity">
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/card_payment"
|
||||
android:layout_width="140dp"
|
||||
android:layout_height="140dp"
|
||||
android:layout_marginTop="64dp"
|
||||
app:cardCornerRadius="8dp"
|
||||
app:cardElevation="4dp"
|
||||
app:cardBackgroundColor="@color/light_blue"
|
||||
app:layout_constraintEnd_toStartOf="@+id/card_transactions"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/title_text">
|
||||
|
||||
<LinearLayout
|
||||
<!-- Status Bar Area -->
|
||||
<View
|
||||
android:id="@+id/status_bar_background"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
android:layout_height="24dp"
|
||||
android:background="#E31937"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
<ImageView
|
||||
android:layout_width="64dp"
|
||||
android:layout_height="64dp"
|
||||
android:src="@android:drawable/ic_menu_send"
|
||||
android:contentDescription="@string/payment"
|
||||
app:tint="@color/primary_blue" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="@string/payment2"
|
||||
android:textColor="@color/primary_blue"
|
||||
android:textStyle="bold" />
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/card_transactions"
|
||||
android:layout_width="140dp"
|
||||
android:layout_height="140dp"
|
||||
app:cardCornerRadius="8dp"
|
||||
app:cardElevation="4dp"
|
||||
app:cardBackgroundColor="@color/light_gray"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/card_payment"
|
||||
app:layout_constraintTop_toTopOf="@+id/card_payment">
|
||||
|
||||
<LinearLayout
|
||||
<!-- Red Background Header -->
|
||||
<View
|
||||
android:id="@+id/red_header_background"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="center"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
android:layout_height="100dp"
|
||||
android:background="#E31937"
|
||||
app:layout_constraintTop_toBottomOf="@id/status_bar_background"/>
|
||||
|
||||
<ImageView
|
||||
android:layout_width="64dp"
|
||||
android:layout_height="64dp"
|
||||
android:src="@android:drawable/ic_menu_recent_history"
|
||||
android:contentDescription="@string/transactions"
|
||||
app:tint="@color/accent_teal" />
|
||||
<!-- Merchant Card -->
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/merchant_card"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="16dp"
|
||||
app:cardCornerRadius="12dp"
|
||||
app:cardElevation="4dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/status_bar_background">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="@string/transactions2"
|
||||
android:textColor="@color/accent_teal"
|
||||
android:textStyle="bold" />
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
<ImageView
|
||||
android:layout_width="144dp"
|
||||
android:layout_height="36dp"
|
||||
android:src="@drawable/ic_logo_icon"
|
||||
android:scaleType="fitStart"
|
||||
android:adjustViewBounds="true"
|
||||
android:layout_marginBottom="8dp"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="TOKO KLONTONG PAK EKO"
|
||||
android:textColor="#061D28"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
android:layout_gravity="center_horizontal"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:text="Ciputat Baru, Tangsel"
|
||||
android:textColor="#9FA4A9"
|
||||
android:textSize="14sp"
|
||||
android:layout_gravity="center_horizontal"/>
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginTop="12dp"
|
||||
android:layout_marginBottom="12dp"
|
||||
android:background="#EEEEEE"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="MID: 12345678901"
|
||||
android:textColor="#9FA4A9"
|
||||
android:textSize="14sp"
|
||||
android:layout_marginEnd="16dp"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="TID: 12345678901"
|
||||
android:textColor="#9FA4A9"
|
||||
android:textSize="14sp"/>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<!-- Menu Grid -->
|
||||
<GridLayout
|
||||
android:id="@+id/menu_grid"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:columnCount="3"
|
||||
android:rowCount="5"
|
||||
android:background="@android:color/white"
|
||||
android:padding="8dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/merchant_card">
|
||||
|
||||
<!-- Row 1: Kartu Kredit, Kartu Debit, QRIS -->
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/card_kartu_kredit"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_columnWeight="1"
|
||||
android:layout_rowWeight="1"
|
||||
android:layout_margin="8dp"
|
||||
app:cardCornerRadius="12dp"
|
||||
app:cardElevation="2dp"
|
||||
app:cardBackgroundColor="#F3F4F3">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center"
|
||||
android:padding="16dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:src="@drawable/ic_credit_card"
|
||||
android:tint="#E31937"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="Kartu Kredit"
|
||||
style="@style/MenuCardTitle"/>
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/card_kartu_debit"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_columnWeight="1"
|
||||
android:layout_rowWeight="1"
|
||||
android:layout_margin="8dp"
|
||||
app:cardCornerRadius="12dp"
|
||||
app:cardElevation="2dp"
|
||||
app:cardBackgroundColor="#F3F4F3">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center"
|
||||
android:padding="16dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:src="@drawable/ic_debit_card"
|
||||
android:tint="#E31937"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="Kartu Debit"
|
||||
style="@style/MenuCardTitle"/>
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/card_qris"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_columnWeight="1"
|
||||
android:layout_rowWeight="1"
|
||||
android:layout_margin="8dp"
|
||||
app:cardCornerRadius="12dp"
|
||||
app:cardElevation="2dp"
|
||||
app:cardBackgroundColor="#F3F4F3">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center"
|
||||
android:padding="16dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:src="@drawable/ic_qris"
|
||||
android:tint="#E31937"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="QRIS"
|
||||
style="@style/MenuCardTitle"/>
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<!-- Row 2: Uang Elektronik, Cetak Ulang, Settlement -->
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/card_uang_elektronik"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_columnWeight="1"
|
||||
android:layout_rowWeight="1"
|
||||
android:layout_margin="8dp"
|
||||
app:cardCornerRadius="12dp"
|
||||
app:cardElevation="2dp"
|
||||
app:cardBackgroundColor="#F3F4F3">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center"
|
||||
android:padding="16dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:src="@drawable/ic_e_money"
|
||||
android:tint="#E31937"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="Uang Elektronik"
|
||||
style="@style/MenuCardTitle"/>
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/card_cetak_ulang"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_columnWeight="1"
|
||||
android:layout_rowWeight="1"
|
||||
android:layout_margin="8dp"
|
||||
app:cardCornerRadius="12dp"
|
||||
app:cardElevation="2dp"
|
||||
app:cardBackgroundColor="#F3F4F3">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center"
|
||||
android:padding="16dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:src="@drawable/ic_reprint"
|
||||
android:tint="#E31937"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="Cetak Ulang"
|
||||
style="@style/MenuCardTitle"/>
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/card_settlement"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_columnWeight="1"
|
||||
android:layout_rowWeight="1"
|
||||
android:layout_margin="8dp"
|
||||
app:cardCornerRadius="12dp"
|
||||
app:cardElevation="2dp"
|
||||
app:cardBackgroundColor="#F3F4F3">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center"
|
||||
android:padding="16dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:src="@drawable/ic_settlement"
|
||||
android:tint="#E31937"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="Settlement"
|
||||
style="@style/MenuCardTitle"/>
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<!-- Row 3: Histori, Bantuan, Info Toko -->
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/card_histori"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_columnWeight="1"
|
||||
android:layout_rowWeight="1"
|
||||
android:layout_margin="8dp"
|
||||
app:cardCornerRadius="12dp"
|
||||
app:cardElevation="2dp"
|
||||
app:cardBackgroundColor="#F3F4F3">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center"
|
||||
android:padding="16dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:src="@drawable/ic_history"
|
||||
android:tint="#E31937"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="Histori"
|
||||
style="@style/MenuCardTitle"/>
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/card_bantuan"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_columnWeight="1"
|
||||
android:layout_rowWeight="1"
|
||||
android:layout_margin="8dp"
|
||||
android:visibility="visible"
|
||||
app:cardCornerRadius="12dp"
|
||||
app:cardElevation="2dp"
|
||||
app:cardBackgroundColor="#F3F4F3">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center"
|
||||
android:padding="16dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:src="@drawable/ic_help"
|
||||
android:tint="#E31937"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="Bantuan"
|
||||
style="@style/MenuCardTitle"/>
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/card_info_toko"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_columnWeight="1"
|
||||
android:layout_rowWeight="1"
|
||||
android:layout_margin="8dp"
|
||||
android:visibility="visible"
|
||||
app:cardCornerRadius="12dp"
|
||||
app:cardElevation="2dp"
|
||||
app:cardBackgroundColor="#F3F4F3">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center"
|
||||
android:padding="16dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:src="@drawable/ic_store_info"
|
||||
android:tint="#E31937"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="Info Toko"
|
||||
style="@style/MenuCardTitle"/>
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<!-- Row 4: Dummy Menu 1, 2, 3 (Hidden initially) -->
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/card_dummy_menu_1"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_columnWeight="1"
|
||||
android:layout_rowWeight="1"
|
||||
android:layout_margin="8dp"
|
||||
android:visibility="gone"
|
||||
app:cardCornerRadius="12dp"
|
||||
app:cardElevation="2dp"
|
||||
app:cardBackgroundColor="#F3F4F3">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center"
|
||||
android:padding="16dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:src="@drawable/ic_qr_code"
|
||||
android:tint="#E31937"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="Dummy Menu 1"
|
||||
style="@style/MenuCardTitle"/>
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/card_dummy_menu_2"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_columnWeight="1"
|
||||
android:layout_rowWeight="1"
|
||||
android:layout_margin="8dp"
|
||||
android:visibility="gone"
|
||||
app:cardCornerRadius="12dp"
|
||||
app:cardElevation="2dp"
|
||||
app:cardBackgroundColor="#F3F4F3">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center"
|
||||
android:padding="16dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:src="@drawable/ic_qr_code"
|
||||
android:tint="#E31937"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="Dummy Menu 2"
|
||||
style="@style/MenuCardTitle"/>
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/card_dummy_menu_3"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_columnWeight="1"
|
||||
android:layout_rowWeight="1"
|
||||
android:layout_margin="8dp"
|
||||
android:visibility="gone"
|
||||
app:cardCornerRadius="12dp"
|
||||
app:cardElevation="2dp"
|
||||
app:cardBackgroundColor="#F3F4F3">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center"
|
||||
android:padding="16dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:src="@drawable/ic_qr_code"
|
||||
android:tint="#E31937"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="Dummy Menu 3"
|
||||
style="@style/MenuCardTitle"/>
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<!-- Row 5: Dummy Menu 4, 5, 6 (Hidden initially) -->
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/card_dummy_menu_4"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_columnWeight="1"
|
||||
android:layout_rowWeight="1"
|
||||
android:layout_margin="8dp"
|
||||
android:visibility="gone"
|
||||
app:cardCornerRadius="12dp"
|
||||
app:cardElevation="2dp"
|
||||
app:cardBackgroundColor="#F3F4F3">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center"
|
||||
android:padding="16dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:src="@drawable/ic_qr_code"
|
||||
android:tint="#E31937"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="Dummy Menu 4"
|
||||
style="@style/MenuCardTitle"/>
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/card_dummy_menu_5"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_columnWeight="1"
|
||||
android:layout_rowWeight="1"
|
||||
android:layout_margin="8dp"
|
||||
android:visibility="gone"
|
||||
app:cardCornerRadius="12dp"
|
||||
app:cardElevation="2dp"
|
||||
app:cardBackgroundColor="#F3F4F3">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center"
|
||||
android:padding="16dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:src="@drawable/ic_qr_code"
|
||||
android:tint="#E31937"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="Dummy Menu 5"
|
||||
style="@style/MenuCardTitle"/>
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/card_dummy_menu_6"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_columnWeight="1"
|
||||
android:layout_rowWeight="1"
|
||||
android:layout_margin="8dp"
|
||||
android:visibility="gone"
|
||||
app:cardCornerRadius="12dp"
|
||||
app:cardElevation="2dp"
|
||||
app:cardBackgroundColor="#F3F4F3">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center"
|
||||
android:padding="16dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:src="@drawable/ic_qr_code"
|
||||
android:tint="#E31937"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="Dummy Menu 6"
|
||||
style="@style/MenuCardTitle"/>
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
</GridLayout>
|
||||
|
||||
<!-- Lainnya Button -->
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/btn_lainnya"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Tampilkan Lebih Sedikit"
|
||||
android:textColor="#DE0701"
|
||||
android:backgroundTint="#FFFFFF"
|
||||
android:textAllCaps="false"
|
||||
app:strokeColor="#DE0701"
|
||||
app:strokeWidth="1dp"
|
||||
app:cornerRadius="8dp"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:layout_marginTop="8dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/menu_grid"/>
|
||||
|
||||
<!-- Scan dan Bayar Card -->
|
||||
<androidx.cardview.widget.CardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginLeft="16dp"
|
||||
android:layout_marginRight="16dp"
|
||||
android:layout_marginTop="24dp"
|
||||
android:layout_marginBottom="24dp"
|
||||
app:cardCornerRadius="12dp"
|
||||
app:cardBackgroundColor="#E31937"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/btn_lainnya"
|
||||
app:layout_constraintVertical_bias="0">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/scan_bayar_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:src="@drawable/ic_qr_code"
|
||||
android:tint="@android:color/white"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginStart="16dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="SCAN DAN BAYAR"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Terima pembayaran dengan QRIS secara mudah"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="12sp"/>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</ScrollView>
|
@ -1,227 +1,268 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<ScrollView
|
||||
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:layout_height="match_parent"
|
||||
android:fillViewport="true"
|
||||
android:overScrollMode="never"
|
||||
android:scrollbars="none"
|
||||
android:background="#FFFFFF">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:background="?attr/colorPrimary"
|
||||
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
|
||||
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
|
||||
app:title="QRIS Payment" />
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<androidx.core.widget.NestedScrollView
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
||||
android:background="#FFFFFF"
|
||||
tools:context=".PaymentActivity">
|
||||
|
||||
<LinearLayout
|
||||
<!-- Red Status Bar (Override purple) -->
|
||||
<View
|
||||
android:id="@+id/red_status_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
android:layout_height="24dp"
|
||||
android:background="#E31937"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBar"
|
||||
<!-- Red Background Header (Extended height untuk back navigation) -->
|
||||
<View
|
||||
android:id="@+id/red_header_background"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="160dp"
|
||||
android:background="#E31937"
|
||||
app:layout_constraintTop_toBottomOf="@id/red_status_bar"/>
|
||||
|
||||
<!-- Back Navigation (Positioned closer to status bar/appbar) -->
|
||||
<LinearLayout
|
||||
android:id="@+id/back_navigation"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:padding="8dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/red_status_bar">
|
||||
|
||||
<!-- Back Arrow -->
|
||||
<ImageView
|
||||
android:id="@+id/backArrow"
|
||||
android:layout_width="16dp"
|
||||
android:layout_height="16dp"
|
||||
android:src="@drawable/ic_arrow_back"
|
||||
android:contentDescription="Back" />
|
||||
|
||||
<!-- Title Text -->
|
||||
<TextView
|
||||
android:id="@+id/toolbarTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:visibility="gone" />
|
||||
android:layout_marginStart="8dp"
|
||||
android:text="Kembali"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="12sp"
|
||||
android:fontFamily="@font/inter"
|
||||
android:textStyle="normal" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Payment Card -->
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/paymentCard"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="191dp"
|
||||
android:layout_margin="16dp"
|
||||
android:layout_marginTop="5dp"
|
||||
app:cardBackgroundColor="#3498DB"
|
||||
app:cardCornerRadius="12dp"
|
||||
app:cardElevation="8dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/back_navigation">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:padding="20dp">
|
||||
|
||||
<!-- Title -->
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="TOTAL PEMBAYARAN"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="@font/inter"
|
||||
android:layout_marginBottom="24dp" />
|
||||
|
||||
<!-- Amount Input Section -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginBottom="8dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="RP"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="@font/inter"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_gravity="bottom" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/editTextAmount"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:background="@android:color/transparent"
|
||||
android:textColor="@android:color/white"
|
||||
android:textColorHint="#80FFFFFF"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="@font/inter"
|
||||
android:hint=""
|
||||
android:inputType="none"
|
||||
android:focusable="false"
|
||||
android:clickable="false"
|
||||
android:cursorVisible="false"
|
||||
android:text=""
|
||||
android:gravity="start"
|
||||
android:paddingBottom="4dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- White Underline -->
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="2dp"
|
||||
android:background="@android:color/white"
|
||||
android:layout_marginBottom="16dp" />
|
||||
|
||||
<!-- Description -->
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Pastikan kembali nominal pembayaran pelanggan Anda"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="12sp"
|
||||
android:fontFamily="@font/inter"
|
||||
android:alpha="0.9" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<!-- Numpad -->
|
||||
<GridLayout
|
||||
android:id="@+id/numpad_grid"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:columnCount="3"
|
||||
android:rowCount="4"
|
||||
android:layout_marginTop="24dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/paymentCard">
|
||||
|
||||
<!-- Row 1: 1, 2, 3 -->
|
||||
<TextView
|
||||
android:id="@+id/btn1"
|
||||
style="@style/NumpadButton"
|
||||
android:text="1" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/statusTextView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:gravity="center"
|
||||
android:text="Ready to make a payment"
|
||||
android:textSize="18sp" />
|
||||
android:id="@+id/btn2"
|
||||
style="@style/NumpadButton"
|
||||
android:text="2" />
|
||||
|
||||
<!-- Initial Payment Form -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
<TextView
|
||||
android:id="@+id/btn3"
|
||||
style="@style/NumpadButton"
|
||||
android:text="3" />
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp"
|
||||
app:cardBackgroundColor="@color/light_blue"
|
||||
app:cardCornerRadius="8dp"
|
||||
app:cardElevation="4dp">
|
||||
<!-- Row 2: 4, 5, 6 -->
|
||||
<TextView
|
||||
android:id="@+id/btn4"
|
||||
style="@style/NumpadButton"
|
||||
android:text="4" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
<TextView
|
||||
android:id="@+id/btn5"
|
||||
style="@style/NumpadButton"
|
||||
android:text="5" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Amount"
|
||||
android:textColor="@color/primary_blue"
|
||||
android:textSize="16sp" />
|
||||
<TextView
|
||||
android:id="@+id/btn6"
|
||||
style="@style/NumpadButton"
|
||||
android:text="6" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/editTextAmount"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:hint="Enter amount"
|
||||
android:inputType="number"
|
||||
android:maxLength="12"
|
||||
android:importantForAutofill="no"
|
||||
android:singleLine="true"
|
||||
android:textColor="@color/primary_blue"
|
||||
android:textSize="24sp"
|
||||
android:textStyle="bold"
|
||||
android:gravity="end" />
|
||||
<!-- Row 3: 7, 8, 9 -->
|
||||
<TextView
|
||||
android:id="@+id/btn7"
|
||||
style="@style/NumpadButton"
|
||||
android:text="7" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="Reference ID"
|
||||
android:textColor="@color/primary_blue"
|
||||
android:textSize="16sp" />
|
||||
<TextView
|
||||
android:id="@+id/btn8"
|
||||
style="@style/NumpadButton"
|
||||
android:text="8" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/referenceIdTextView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="ref-abcd1234"
|
||||
android:textColor="@color/primary_blue"
|
||||
android:textSize="16sp" />
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
<TextView
|
||||
android:id="@+id/btn9"
|
||||
style="@style/NumpadButton"
|
||||
android:text="9" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/initiatePaymentButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp"
|
||||
android:backgroundTint="@color/primary_blue"
|
||||
android:text="Start Payment" />
|
||||
</LinearLayout>
|
||||
<!-- Row 4: 000, 0, Delete -->
|
||||
<TextView
|
||||
android:id="@+id/btn000"
|
||||
style="@style/NumpadButton"
|
||||
android:text="000" />
|
||||
|
||||
<!-- QR Code and Payment Details -->
|
||||
<LinearLayout
|
||||
android:id="@+id/paymentDetailsLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone">
|
||||
<TextView
|
||||
android:id="@+id/btn0"
|
||||
style="@style/NumpadButton"
|
||||
android:text="0" />
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp"
|
||||
app:cardCornerRadius="8dp"
|
||||
app:cardElevation="4dp">
|
||||
<ImageView
|
||||
android:id="@+id/btnDelete"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="60dp"
|
||||
android:layout_columnWeight="1"
|
||||
android:layout_margin="8dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:src="@drawable/ic_backspace"
|
||||
android:scaleType="center"
|
||||
android:contentDescription="Delete" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_horizontal"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
</GridLayout>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/qrCodeImageView"
|
||||
android:layout_width="250dp"
|
||||
android:layout_height="250dp"
|
||||
android:contentDescription="QRIS Code"
|
||||
android:scaleType="fitCenter" />
|
||||
<!-- Confirmation Button (UPDATED: Menggunakan MaterialButton) -->
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/confirmButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:text="Konfirmasi"
|
||||
android:textColor="#FFFFFF"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="@font/inter"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginTop="24dp"
|
||||
android:layout_marginBottom="24dp"
|
||||
android:enabled="false"
|
||||
app:backgroundTint="#DE0701"
|
||||
app:cornerRadius="8dp"
|
||||
app:rippleColor="#B3000000"
|
||||
app:layout_constraintTop_toBottomOf="@id/numpad_grid"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintVertical_bias="1" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:gravity="center"
|
||||
android:text="Scan with your banking app or e-wallet to pay"
|
||||
android:textSize="14sp" />
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<Button
|
||||
android:id="@+id/simulatePaymentButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp"
|
||||
android:backgroundTint="@color/accent_green"
|
||||
android:text="Confirm Payment" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Payment Success -->
|
||||
<LinearLayout
|
||||
android:id="@+id/paymentSuccessLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:visibility="gone">
|
||||
|
||||
<androidx.cardview.widget.CardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp"
|
||||
app:cardBackgroundColor="@color/light_gray"
|
||||
app:cardCornerRadius="8dp"
|
||||
app:cardElevation="4dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center_horizontal"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="64dp"
|
||||
android:layout_height="64dp"
|
||||
android:contentDescription="Success Icon"
|
||||
android:src="@android:drawable/ic_dialog_info"
|
||||
android:tint="@color/accent_green" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:gravity="center"
|
||||
android:text="Payment Successful!"
|
||||
android:textColor="@color/accent_green"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:gravity="center"
|
||||
android:text="Your transaction has been completed successfully."
|
||||
android:textSize="14sp" />
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<Button
|
||||
android:id="@+id/returnToMainButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="8dp"
|
||||
android:backgroundTint="@color/primary_blue"
|
||||
android:text="Return to Main" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</androidx.core.widget.NestedScrollView>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</ScrollView>
|
298
app/src/main/res/layout/activity_pin.xml
Normal file
@ -0,0 +1,298 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView
|
||||
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:fillViewport="true"
|
||||
android:overScrollMode="never"
|
||||
android:scrollbars="none"
|
||||
android:background="#F5F5F5">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#FFFFFF"
|
||||
tools:context=".PinActivity">
|
||||
|
||||
<!-- Red Status Bar (Override purple) -->
|
||||
<View
|
||||
android:id="@+id/red_status_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="24dp"
|
||||
android:background="#E31937"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
<!-- Red Background Header (Extended height untuk back navigation) -->
|
||||
<View
|
||||
android:id="@+id/red_header_background"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="160dp"
|
||||
android:background="#E31937"
|
||||
app:layout_constraintTop_toBottomOf="@id/red_status_bar"/>
|
||||
|
||||
<!-- Header with Back Navigation -->
|
||||
<LinearLayout
|
||||
android:id="@+id/back_navigation"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:padding="8dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/red_status_bar">
|
||||
|
||||
<!-- Back Arrow -->
|
||||
<ImageView
|
||||
android:id="@+id/backArrow"
|
||||
android:layout_width="16dp"
|
||||
android:layout_height="16dp"
|
||||
android:src="@drawable/ic_arrow_back"
|
||||
android:contentDescription="Back" />
|
||||
|
||||
<!-- Title Text -->
|
||||
<TextView
|
||||
android:id="@+id/toolbarTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:text="Kembali"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="12sp"
|
||||
android:fontFamily="@font/inter"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- PIN Card -->
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/pin_card"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="191dp"
|
||||
android:layout_margin="16dp"
|
||||
android:layout_marginTop="5dp"
|
||||
app:cardBackgroundColor="#3498DB"
|
||||
app:cardCornerRadius="12dp"
|
||||
app:cardElevation="8dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/back_navigation">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:padding="20dp">
|
||||
|
||||
<!-- Title Text -->
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="SILAKAN MASUKAN PIN"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="@font/inter"
|
||||
android:layout_marginBottom="24dp"
|
||||
android:gravity="center"
|
||||
android:textAlignment="center"/>
|
||||
|
||||
<!-- PIN Input Display -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:gravity="center">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="@font/inter"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_gravity="center_vertical" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/editTextPin"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:background="@android:color/transparent"
|
||||
android:textColor="@android:color/white"
|
||||
android:textColorHint="#80FFFFFF"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="@font/inter"
|
||||
android:hint=""
|
||||
android:inputType="none"
|
||||
android:focusable="false"
|
||||
android:clickable="false"
|
||||
android:cursorVisible="false"
|
||||
android:text=""
|
||||
android:gravity="center"
|
||||
android:textAlignment="center"
|
||||
android:paddingBottom="4dp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- White Underline -->
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="2dp"
|
||||
android:background="@android:color/white"
|
||||
android:layout_marginBottom="16dp" />
|
||||
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<!-- Numpad Grid -->
|
||||
<GridLayout
|
||||
android:id="@+id/numpad_grid"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:columnCount="3"
|
||||
android:rowCount="4"
|
||||
android:layout_margin="16dp"
|
||||
android:layout_marginTop="32dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/pin_card">
|
||||
|
||||
<!-- Row 1: 1, 2, 3 -->
|
||||
<TextView
|
||||
android:id="@+id/btn1"
|
||||
style="@style/NumpadButton"
|
||||
android:text="1"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/btn2"
|
||||
style="@style/NumpadButton"
|
||||
android:text="2"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/btn3"
|
||||
style="@style/NumpadButton"
|
||||
android:text="3"/>
|
||||
|
||||
<!-- Row 2: 4, 5, 6 -->
|
||||
<TextView
|
||||
android:id="@+id/btn4"
|
||||
style="@style/NumpadButton"
|
||||
android:text="4"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/btn5"
|
||||
style="@style/NumpadButton"
|
||||
android:text="5"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/btn6"
|
||||
style="@style/NumpadButton"
|
||||
android:text="6"/>
|
||||
|
||||
<!-- Row 3: 7, 8, 9 -->
|
||||
<TextView
|
||||
android:id="@+id/btn7"
|
||||
style="@style/NumpadButton"
|
||||
android:text="7"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/btn8"
|
||||
style="@style/NumpadButton"
|
||||
android:text="8"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/btn9"
|
||||
style="@style/NumpadButton"
|
||||
android:text="9"/>
|
||||
|
||||
<!-- Row 4: 000, 0, Delete -->
|
||||
<TextView
|
||||
android:id="@+id/btn000"
|
||||
style="@style/NumpadButton"
|
||||
android:text="000"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/btn0"
|
||||
style="@style/NumpadButton"
|
||||
android:text="0"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_columnWeight="1"
|
||||
android:layout_margin="8dp"
|
||||
android:gravity="center">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/btnDelete"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:src="@drawable/ic_backspace"
|
||||
android:background="?android:attr/selectableItemBackgroundBorderless"
|
||||
android:padding="12dp"
|
||||
android:tint="#666666"/>
|
||||
</LinearLayout>
|
||||
</GridLayout>
|
||||
|
||||
<!-- Confirmation Button -->
|
||||
<Button
|
||||
android:id="@+id/confirmButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:layout_margin="16dp"
|
||||
android:layout_marginTop="32dp"
|
||||
android:text="Konfirmasi"
|
||||
android:textColor="#999999"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
android:background="@drawable/button_inactive_background"
|
||||
android:enabled="false"
|
||||
android:alpha="0.6"
|
||||
app:layout_constraintTop_toBottomOf="@id/numpad_grid"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintVertical_bias="0"/>
|
||||
|
||||
<!-- Success Screen (Full Screen Overlay) - IMPROVED VERSION -->
|
||||
<LinearLayout
|
||||
android:id="@+id/success_screen"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center"
|
||||
android:background="#E31937"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent">
|
||||
|
||||
<!-- Success Icon -->
|
||||
<ImageView
|
||||
android:id="@+id/success_icon"
|
||||
android:layout_width="120dp"
|
||||
android:layout_height="120dp"
|
||||
android:src="@drawable/ic_success_payment"
|
||||
android:layout_marginBottom="32dp"
|
||||
android:scaleType="centerInside"/>
|
||||
|
||||
<!-- Success Message -->
|
||||
<TextView
|
||||
android:id="@+id/success_message"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Pembayaran Berhasil"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="24sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="@font/inter"
|
||||
android:gravity="center"
|
||||
android:letterSpacing="0.02"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</ScrollView>
|
306
app/src/main/res/layout/activity_qris.xml
Normal file
@ -0,0 +1,306 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView
|
||||
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:fillViewport="true"
|
||||
android:overScrollMode="never"
|
||||
android:scrollbars="none"
|
||||
android:background="#FFFFFF">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#FFFFFF"
|
||||
tools:context=".QrisActivity">
|
||||
|
||||
<!-- Red Status Bar -->
|
||||
<View
|
||||
android:id="@+id/red_status_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="24dp"
|
||||
android:background="#E31937"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
<!-- Red Background Header -->
|
||||
<View
|
||||
android:id="@+id/red_header_background"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="160dp"
|
||||
android:background="#E31937"
|
||||
app:layout_constraintTop_toBottomOf="@id/red_status_bar"/>
|
||||
|
||||
<!-- Back Navigation -->
|
||||
<LinearLayout
|
||||
android:id="@+id/back_navigation"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginBottom="5dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:padding="8dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/red_status_bar">
|
||||
|
||||
<!-- Back Arrow -->
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="‹"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
android:layout_marginEnd="8dp" />
|
||||
|
||||
<!-- Title Text -->
|
||||
<TextView
|
||||
android:id="@+id/toolbarTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Kembali"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="12sp"
|
||||
android:textStyle="normal" />
|
||||
|
||||
<!-- Hidden back arrow for Java compatibility -->
|
||||
<ImageView
|
||||
android:id="@+id/backArrow"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
android:visibility="gone" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Payment Card -->
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/paymentCard"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="191dp"
|
||||
android:layout_margin="16dp"
|
||||
android:layout_marginTop="5dp"
|
||||
app:cardBackgroundColor="#3498DB"
|
||||
app:cardCornerRadius="12dp"
|
||||
app:cardElevation="8dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/back_navigation">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:padding="20dp">
|
||||
|
||||
<!-- Title -->
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="TOTAL PEMBAYARAN"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
android:layout_marginBottom="24dp"
|
||||
android:gravity="center" />
|
||||
|
||||
<!-- RP Label -->
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="RP"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold"
|
||||
android:layout_marginBottom="8dp" />
|
||||
|
||||
<!-- Amount Input Field (initially hidden) -->
|
||||
<EditText
|
||||
android:id="@+id/editTextAmount"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@android:color/transparent"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold"
|
||||
android:inputType="none"
|
||||
android:focusable="false"
|
||||
android:clickable="false"
|
||||
android:cursorVisible="false"
|
||||
android:text=""
|
||||
android:gravity="start"
|
||||
android:paddingBottom="4dp"
|
||||
android:visibility="gone" />
|
||||
|
||||
<!-- Description Text (always visible initially) -->
|
||||
<TextView
|
||||
android:id="@+id/descriptionText"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Pastikan kembali nominal pembayaran pelanggan Anda"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="12sp"
|
||||
android:alpha="0.9"
|
||||
android:layout_marginBottom="8dp" />
|
||||
|
||||
<!-- White Underline -->
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="2dp"
|
||||
android:background="@android:color/white" />
|
||||
|
||||
<!-- Hidden Reference ID for internal use -->
|
||||
<TextView
|
||||
android:id="@+id/referenceIdTextView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="ref-abcd1234"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="12sp"
|
||||
android:visibility="gone" />
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<!-- Main Content Layout -->
|
||||
<LinearLayout
|
||||
android:id="@+id/mainContentLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintTop_toBottomOf="@id/paymentCard"
|
||||
app:layout_constraintBottom_toTopOf="@id/initiatePaymentButton">
|
||||
|
||||
<!-- Numpad -->
|
||||
<GridLayout
|
||||
android:id="@+id/numpad_grid"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:columnCount="3"
|
||||
android:rowCount="4"
|
||||
android:layout_marginTop="8dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp">
|
||||
|
||||
<!-- Row 1: 1, 2, 3 -->
|
||||
<TextView
|
||||
android:id="@+id/btn1"
|
||||
style="@style/NumpadButton"
|
||||
android:text="1" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/btn2"
|
||||
style="@style/NumpadButton"
|
||||
android:text="2" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/btn3"
|
||||
style="@style/NumpadButton"
|
||||
android:text="3" />
|
||||
|
||||
<!-- Row 2: 4, 5, 6 -->
|
||||
<TextView
|
||||
android:id="@+id/btn4"
|
||||
style="@style/NumpadButton"
|
||||
android:text="4" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/btn5"
|
||||
style="@style/NumpadButton"
|
||||
android:text="5" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/btn6"
|
||||
style="@style/NumpadButton"
|
||||
android:text="6" />
|
||||
|
||||
<!-- Row 3: 7, 8, 9 -->
|
||||
<TextView
|
||||
android:id="@+id/btn7"
|
||||
style="@style/NumpadButton"
|
||||
android:text="7" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/btn8"
|
||||
style="@style/NumpadButton"
|
||||
android:text="8" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/btn9"
|
||||
style="@style/NumpadButton"
|
||||
android:text="9" />
|
||||
|
||||
<!-- Row 4: 000, 0, Delete -->
|
||||
<TextView
|
||||
android:id="@+id/btn000"
|
||||
style="@style/NumpadButton"
|
||||
android:text="000" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/btn0"
|
||||
style="@style/NumpadButton"
|
||||
android:text="0" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/btnDelete"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="60dp"
|
||||
android:layout_columnWeight="1"
|
||||
android:layout_margin="8dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:gravity="center"
|
||||
android:text="⌫"
|
||||
android:textColor="@android:color/black"
|
||||
android:textSize="28sp"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:contentDescription="Delete" />
|
||||
</GridLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Confirmation Button -->
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/initiatePaymentButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:text="Konfirmasi"
|
||||
android:textColor="#FFFFFF"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginTop="24dp"
|
||||
android:layout_marginBottom="24dp"
|
||||
android:enabled="false"
|
||||
app:backgroundTint="#DE0701"
|
||||
app:cornerRadius="8dp"
|
||||
app:rippleColor="#B3000000"
|
||||
app:layout_constraintBottom_toBottomOf="parent" />
|
||||
|
||||
<!-- Progress Bar (For create transaction loading) -->
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<!-- Status Text (For create transaction status) -->
|
||||
<TextView
|
||||
android:id="@+id/statusTextView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="16dp"
|
||||
android:gravity="center"
|
||||
android:text="Ready to make a payment"
|
||||
android:textSize="18sp"
|
||||
android:textColor="@android:color/black"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintTop_toBottomOf="@id/progressBar"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</ScrollView>
|
@ -1,82 +1,223 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:padding="24dp"
|
||||
android:background="#181824"
|
||||
>
|
||||
android:background="#FFFFFF">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/amountTextView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/amount"
|
||||
android:textColor="#2D5DA1"
|
||||
android:textSize="20sp"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginTop="16dp"/>
|
||||
<!-- Red Status Bar -->
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="44dp"
|
||||
android:background="#E31937" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/referenceTextView"
|
||||
android:layout_width="wrap_content"
|
||||
<!-- Header with Back Navigation -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/reference_id"
|
||||
android:textColor="#2D5DA1"
|
||||
android:background="#E31937"
|
||||
android:paddingBottom="16dp">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/back_navigation"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_marginStart="16dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:padding="8dp"
|
||||
android:clickable="true"
|
||||
android:focusable="true">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="‹"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
android:layout_marginEnd="8dp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Kembali"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="14sp" />
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
<!-- White Card Container -->
|
||||
<androidx.cardview.widget.CardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="16dp"
|
||||
android:layout_marginTop="0dp"
|
||||
app:cardCornerRadius="16dp"
|
||||
app:cardElevation="8dp"
|
||||
app:cardBackgroundColor="@android:color/white">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="24dp"
|
||||
android:gravity="center_horizontal">
|
||||
|
||||
<!-- Generate QR Title -->
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Generate QR"
|
||||
android:textColor="@android:color/black"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
android:layout_marginBottom="24dp" />
|
||||
|
||||
<!-- QRIS Logo Text -->
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="QRIS"
|
||||
android:textColor="@android:color/black"
|
||||
android:textSize="32sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="monospace"
|
||||
android:layout_marginBottom="24dp" />
|
||||
|
||||
<!-- QR Code -->
|
||||
<ImageView
|
||||
android:id="@+id/qrImageView"
|
||||
android:layout_width="200dp"
|
||||
android:layout_height="200dp"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:contentDescription="QRIS QR Code"
|
||||
android:scaleType="fitCenter"
|
||||
android:background="#F0F0F0"
|
||||
android:layout_marginBottom="24dp" />
|
||||
|
||||
<!-- Amount Display -->
|
||||
<TextView
|
||||
android:id="@+id/amountTextView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="RP.200.000"
|
||||
android:textColor="@android:color/black"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold"
|
||||
android:layout_marginBottom="16dp" />
|
||||
|
||||
<!-- Timer/Counter -->
|
||||
<TextView
|
||||
android:id="@+id/timerTextView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="60"
|
||||
android:textColor="#E31937"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
android:layout_marginBottom="24dp" />
|
||||
|
||||
<!-- QR Refresh Status -->
|
||||
<TextView
|
||||
android:id="@+id/qrStatusTextView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="QR Code akan refresh dalam"
|
||||
android:textColor="#666666"
|
||||
android:textSize="12sp"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:visibility="visible" />
|
||||
|
||||
<!-- Action Buttons Section -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginTop="16dp">
|
||||
|
||||
<!-- Download QRIS Button -->
|
||||
<Button
|
||||
android:id="@+id/downloadQrisButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:text="Download QRIS"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="14sp"
|
||||
android:background="#4CAF50"
|
||||
android:visibility="visible" />
|
||||
|
||||
<!-- Check Payment Status Button -->
|
||||
<Button
|
||||
android:id="@+id/checkStatusButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:text="Check Payment Status"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="14sp"
|
||||
android:background="#2196F3"
|
||||
android:visibility="visible" />
|
||||
|
||||
<!-- Return to Main Button -->
|
||||
<Button
|
||||
android:id="@+id/returnMainButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:text="Return to Main"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="14sp"
|
||||
android:background="#FF9800"
|
||||
android:visibility="visible" />
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Hidden views for compatibility -->
|
||||
<TextView
|
||||
android:id="@+id/referenceTextView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Reference ID: ref-12345"
|
||||
android:textColor="@android:color/black"
|
||||
android:textSize="14sp"
|
||||
android:visibility="gone" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/statusTextView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Payment Status Success"
|
||||
android:textColor="@android:color/black"
|
||||
android:textSize="18sp"
|
||||
android:visibility="gone" />
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<!-- Spacer to push button to bottom -->
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1" />
|
||||
|
||||
<!-- Bottom Cancel Button -->
|
||||
<Button
|
||||
android:id="@+id/cancelButton"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:layout_margin="16dp"
|
||||
android:text="Batalkan"
|
||||
android:textColor="#E31937"
|
||||
android:textSize="16sp"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:layout_marginTop="8dp"/>
|
||||
android:textStyle="normal"
|
||||
android:background="@android:color/transparent"
|
||||
style="?android:attr/borderlessButtonStyle" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/qrImageView"
|
||||
android:layout_width="280dp"
|
||||
android:layout_height="280dp"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginTop="16dp"
|
||||
android:contentDescription="@string/qr_code"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/downloadQrisButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/download_qris"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginTop="16dp"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/checkStatusButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/check_payment_status"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginTop="16dp"/>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBar"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/statusTextView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/payment_status_success"
|
||||
android:textColor="#2D5DA1"
|
||||
android:textSize="20sp"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginTop="24dp"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/returnMainButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/return_main"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginTop="24dp"
|
||||
android:visibility="gone"/>
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
547
app/src/main/res/layout/activity_receipt.xml
Normal file
@ -0,0 +1,547 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView
|
||||
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:fillViewport="true"
|
||||
android:overScrollMode="never"
|
||||
android:scrollbars="none"
|
||||
android:background="#F5F5F5">
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#F5F5F5"
|
||||
tools:context=".ReceiptActivity">
|
||||
|
||||
<!-- Red Status Bar (Override purple) -->
|
||||
<View
|
||||
android:id="@+id/red_status_bar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="24dp"
|
||||
android:background="#E31937"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
<!-- Red Background Header -->
|
||||
<View
|
||||
android:id="@+id/red_header_background"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="120dp"
|
||||
android:background="#E31937"
|
||||
app:layout_constraintTop_toBottomOf="@id/red_status_bar"/>
|
||||
|
||||
<!-- Header with Back Navigation -->
|
||||
<LinearLayout
|
||||
android:id="@+id/back_navigation"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:padding="8dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/red_status_bar">
|
||||
|
||||
<!-- Back Arrow -->
|
||||
<ImageView
|
||||
android:id="@+id/backArrow"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:src="@drawable/ic_arrow_back"
|
||||
android:tint="@android:color/white"
|
||||
android:contentDescription="Kembali" />
|
||||
|
||||
<!-- Title Text -->
|
||||
<TextView
|
||||
android:id="@+id/toolbarTitle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:text="Kembali"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="16sp"
|
||||
android:fontFamily="@font/inter"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Receipt Card - Positioned to overlap header by half -->
|
||||
<androidx.cardview.widget.CardView
|
||||
android:id="@+id/receipt_card"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginTop="60dp"
|
||||
app:cardBackgroundColor="@android:color/white"
|
||||
app:cardCornerRadius="12dp"
|
||||
app:cardElevation="8dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/red_status_bar">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="20dp">
|
||||
|
||||
<!-- Header Section -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center"
|
||||
android:layout_marginBottom="16dp">
|
||||
|
||||
<!-- EDC Merchant Logo/Text -->
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="EDC "
|
||||
android:textColor="#E31937"
|
||||
android:textSize="24sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="@font/inter"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Merchant"
|
||||
android:textColor="#3F51B5"
|
||||
android:textSize="24sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="@font/inter"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="BANK BRI"
|
||||
android:textColor="#333333"
|
||||
android:textSize="12sp"
|
||||
android:fontFamily="@font/inter"
|
||||
android:layout_marginTop="2dp"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Merchant Info -->
|
||||
<TextView
|
||||
android:id="@+id/merchant_name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="TOKO KLONTONG PAK EKO"
|
||||
android:textColor="#333333"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="@font/inter"
|
||||
android:gravity="center"
|
||||
android:layout_marginBottom="4dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/merchant_location"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Ciputat Baru, Tangsel"
|
||||
android:textColor="#666666"
|
||||
android:textSize="14sp"
|
||||
android:fontFamily="@font/inter"
|
||||
android:gravity="center"
|
||||
android:layout_marginBottom="16dp"/>
|
||||
|
||||
<!-- Separator Line -->
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="#E0E0E0"
|
||||
android:layout_marginBottom="16dp"/>
|
||||
|
||||
<!-- Transaction Details -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginBottom="8dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="MID: "
|
||||
android:textColor="#666666"
|
||||
android:textSize="12sp"
|
||||
android:fontFamily="@font/inter"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/mid_text"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="1234567890"
|
||||
android:textColor="#333333"
|
||||
android:textSize="12sp"
|
||||
android:fontFamily="@font/inter"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="TID: "
|
||||
android:textColor="#666666"
|
||||
android:textSize="12sp"
|
||||
android:fontFamily="@font/inter"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tid_text"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="1234567890"
|
||||
android:textColor="#333333"
|
||||
android:textSize="12sp"
|
||||
android:fontFamily="@font/inter"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Separator Line -->
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="#E0E0E0"
|
||||
android:layout_marginVertical="12dp"/>
|
||||
|
||||
<!-- Transaction Number -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginBottom="8dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="Nomor transaksi"
|
||||
android:textColor="#666666"
|
||||
android:textSize="14sp"
|
||||
android:fontFamily="@font/inter"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/transaction_number"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="3429483635"
|
||||
android:textColor="#333333"
|
||||
android:textSize="14sp"
|
||||
android:fontFamily="@font/inter"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Transaction Date -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginBottom="8dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="Tanggal transaksi"
|
||||
android:textColor="#666666"
|
||||
android:textSize="14sp"
|
||||
android:fontFamily="@font/inter"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/transaction_date"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="13 Januari 2025 13:46"
|
||||
android:textColor="#333333"
|
||||
android:textSize="14sp"
|
||||
android:fontFamily="@font/inter"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Payment Method -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginBottom="8dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="Metode pembayaran"
|
||||
android:textColor="#666666"
|
||||
android:textSize="14sp"
|
||||
android:fontFamily="@font/inter"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/payment_method"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Kartu Kredit"
|
||||
android:textColor="#333333"
|
||||
android:textSize="14sp"
|
||||
android:fontFamily="@font/inter"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Card Type -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginBottom="16dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="Jenis Kartu"
|
||||
android:textColor="#666666"
|
||||
android:textSize="14sp"
|
||||
android:fontFamily="@font/inter"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/card_type"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="BCA"
|
||||
android:textColor="#333333"
|
||||
android:textSize="14sp"
|
||||
android:fontFamily="@font/inter"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Separator Line -->
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="#E0E0E0"
|
||||
android:layout_marginBottom="16dp"/>
|
||||
|
||||
<!-- Transaction Amount -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginBottom="8dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="Total transaksi"
|
||||
android:textColor="#666666"
|
||||
android:textSize="14sp"
|
||||
android:fontFamily="@font/inter"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/transaction_total"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="3.500.000"
|
||||
android:textColor="#333333"
|
||||
android:textSize="14sp"
|
||||
android:fontFamily="@font/inter"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Tax -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginBottom="8dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="Pajak (%)"
|
||||
android:textColor="#666666"
|
||||
android:textSize="14sp"
|
||||
android:fontFamily="@font/inter"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tax_percentage"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="11%"
|
||||
android:textColor="#333333"
|
||||
android:textSize="14sp"
|
||||
android:fontFamily="@font/inter"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Service Fee -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginBottom="16dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="Biaya Layanan"
|
||||
android:textColor="#666666"
|
||||
android:textSize="14sp"
|
||||
android:fontFamily="@font/inter"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/service_fee"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="500"
|
||||
android:textColor="#333333"
|
||||
android:textSize="14sp"
|
||||
android:fontFamily="@font/inter"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Separator Line -->
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="2dp"
|
||||
android:background="#E0E0E0"
|
||||
android:layout_marginBottom="16dp"/>
|
||||
|
||||
<!-- Final Total -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginBottom="20dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="TOTAL"
|
||||
android:textColor="#333333"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="@font/inter"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/final_total"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="3.506.500"
|
||||
android:textColor="#333333"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold"
|
||||
android:fontFamily="@font/inter"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
<!-- Action Buttons (Print & Email) -->
|
||||
<LinearLayout
|
||||
android:id="@+id/action_buttons_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginTop="24dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/receipt_card">
|
||||
|
||||
<!-- Print Button -->
|
||||
<LinearLayout
|
||||
android:id="@+id/print_button"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="56dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center"
|
||||
android:background="@drawable/button_secondary_background"
|
||||
android:clickable="true"
|
||||
android:focusable="true">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:src="@drawable/ic_print"
|
||||
android:tint="#666666"
|
||||
android:layout_marginEnd="8dp"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Cetak Ulang"
|
||||
android:textColor="#666666"
|
||||
android:textSize="14sp"
|
||||
android:fontFamily="@font/inter"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Email Button -->
|
||||
<LinearLayout
|
||||
android:id="@+id/email_button"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="56dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginStart="8dp"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center"
|
||||
android:background="@drawable/button_secondary_background"
|
||||
android:clickable="true"
|
||||
android:focusable="true">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:src="@drawable/ic_email"
|
||||
android:tint="#666666"
|
||||
android:layout_marginEnd="8dp"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Email"
|
||||
android:textColor="#666666"
|
||||
android:textSize="14sp"
|
||||
android:fontFamily="@font/inter"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Finish Button -->
|
||||
<Button
|
||||
android:id="@+id/finish_button"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="56dp"
|
||||
android:layout_marginHorizontal="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_marginBottom="24dp"
|
||||
android:text="Selesai"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
android:background="@drawable/button_finish_background"
|
||||
android:fontFamily="@font/inter"
|
||||
app:layout_constraintTop_toBottomOf="@id/action_buttons_container"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintVertical_bias="0"/>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</ScrollView>
|
160
app/src/main/res/layout/activity_settlement.xml
Normal file
@ -0,0 +1,160 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#F5F5F5"
|
||||
android:orientation="vertical">
|
||||
|
||||
<!-- Header with solid red background -->
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="200dp"
|
||||
android:background="#E53E3E">
|
||||
|
||||
<!-- Back button -->
|
||||
<ImageView
|
||||
android:id="@+id/btn_back"
|
||||
android:layout_width="24dp"
|
||||
android:layout_height="24dp"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="24dp"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:padding="4dp"
|
||||
android:src="@android:drawable/ic_menu_revert"
|
||||
android:tint="@android:color/white" />
|
||||
|
||||
<!-- Title -->
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:layout_toEndOf="@id/btn_back"
|
||||
android:text="Kembali"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="16sp" />
|
||||
|
||||
<!-- Settlement Card -->
|
||||
<androidx.cardview.widget.CardView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="120dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_marginTop="64dp"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_marginBottom="16dp"
|
||||
app:cardCornerRadius="12dp"
|
||||
app:cardElevation="4dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#4299E1"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="SETTLEMENT"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="2dp"
|
||||
android:text="Rekap dan kirim transaksi hari ini"
|
||||
android:textColor="#E0FFFFFF"
|
||||
android:textSize="12sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_total_amount"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="3.506.500"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="24sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Jumlah Transaksi"
|
||||
android:textColor="#E0FFFFFF"
|
||||
android:textSize="12sp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_total_transactions"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="65"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
</LinearLayout>
|
||||
</androidx.cardview.widget.CardView>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<!-- Content -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:text="Informasi Ringkasan Transaksi Hari Ini"
|
||||
android:textColor="#333333"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:text="Pastikan Anda melakukan settlement untuk menyelesaikan transaksi harian."
|
||||
android:textColor="#666666"
|
||||
android:textSize="12sp" />
|
||||
|
||||
<!-- Transaction List -->
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recycler_view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Bottom Button -->
|
||||
<Button
|
||||
android:id="@+id/btn_continue"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:layout_margin="16dp"
|
||||
android:background="#E53E3E"
|
||||
android:text="Selanjutnya"
|
||||
android:textColor="@android:color/white"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
</LinearLayout>
|
@ -12,10 +12,10 @@
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:background="?attr/colorPrimary"
|
||||
android:background="#F44336"
|
||||
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
|
||||
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
|
||||
app:title="Transactions History" />
|
||||
app:title="CETAK ULANG STRUK" />
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
@ -23,9 +23,42 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp"
|
||||
android:background="#f5f5f5"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
||||
|
||||
<!-- Search Section -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:padding="16dp"
|
||||
android:background="@android:color/white"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/searchEditText"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_weight="1"
|
||||
android:background="@drawable/search_background"
|
||||
android:hint="Cari dengan nomor struk..."
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp"
|
||||
android:textSize="14sp"
|
||||
android:textColorHint="#999999" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/searchButton"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:background="@drawable/search_button_background"
|
||||
android:src="@android:drawable/ic_menu_search"
|
||||
android:contentDescription="Search"
|
||||
app:tint="@android:color/white" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progressBar"
|
||||
android:layout_width="wrap_content"
|
||||
@ -38,17 +71,8 @@
|
||||
android:id="@+id/recyclerView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginTop="8dp" />
|
||||
android:background="@android:color/white" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/refreshButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|end"
|
||||
android:layout_margin="16dp"
|
||||
android:contentDescription="Refresh"
|
||||
android:src="@android:drawable/ic_popup_sync"
|
||||
app:tint="@android:color/white" />
|
||||
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
69
app/src/main/res/layout/item_history.xml
Normal file
@ -0,0 +1,69 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@android:color/white"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:orientation="horizontal"
|
||||
android:padding="16dp">
|
||||
|
||||
<!-- Left Content -->
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="09:00, 07-05-2025"
|
||||
android:textColor="#333333"
|
||||
android:textSize="14sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_amount"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="4dp"
|
||||
android:text="Rp. 78.000"
|
||||
android:textColor="#333333"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Center Content -->
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="16dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_channel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Kredit"
|
||||
android:textColor="#333333"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Right Content -->
|
||||
<TextView
|
||||
android:id="@+id/tv_status"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginStart="16dp"
|
||||
android:text="Berhasil"
|
||||
android:textColor="#4CAF50"
|
||||
android:textSize="12sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
</LinearLayout>
|
178
app/src/main/res/layout/item_history_detail.xml
Normal file
@ -0,0 +1,178 @@
|
||||
<?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:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="8dp"
|
||||
app:cardCornerRadius="8dp"
|
||||
app:cardElevation="2dp">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="16dp">
|
||||
|
||||
<!-- Header Row -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_reference_id"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="Ref: 197870"
|
||||
android:textColor="#333333"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_status"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="SUCCESS"
|
||||
android:textColor="#4CAF50"
|
||||
android:textSize="12sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Amount -->
|
||||
<TextView
|
||||
android:id="@+id/tv_amount"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="Rp. 2.018.619"
|
||||
android:textColor="#333333"
|
||||
android:textSize="18sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<!-- Details Grid -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="12dp"
|
||||
android:orientation="vertical">
|
||||
|
||||
<!-- Row 1 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Channel"
|
||||
android:textColor="#666666"
|
||||
android:textSize="12sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_channel"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Other Payment"
|
||||
android:textColor="#333333"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Waktu"
|
||||
android:textColor="#666666"
|
||||
android:textSize="12sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="16/05/2025 05:40"
|
||||
android:textColor="#333333"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Row 2 -->
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Merchant"
|
||||
android:textColor="#666666"
|
||||
android:textSize="12sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_merchant"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="TEST MERCHANT"
|
||||
android:textColor="#333333"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Issuer"
|
||||
android:textColor="#666666"
|
||||
android:textSize="12sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_issuer"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="BANK MANDIRI"
|
||||
android:textColor="#333333"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.cardview.widget.CardView>
|
70
app/src/main/res/layout/item_settlement.xml
Normal file
@ -0,0 +1,70 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@android:color/white"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:orientation="horizontal"
|
||||
android:padding="16dp">
|
||||
|
||||
<!-- Icon -->
|
||||
<ImageView
|
||||
android:id="@+id/iv_icon"
|
||||
android:layout_width="40dp"
|
||||
android:layout_height="40dp"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:background="#F7FAFC"
|
||||
android:padding="8dp"
|
||||
android:src="@android:drawable/ic_menu_gallery"
|
||||
android:tint="#E53E3E" />
|
||||
|
||||
<!-- Content -->
|
||||
<LinearLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_weight="1"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_channel_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Kartu Kredit"
|
||||
android:textColor="#333333"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Amount and Count -->
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_amount"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end"
|
||||
android:text="Rp. 200.000"
|
||||
android:textColor="#333333"
|
||||
android:textSize="14sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_transaction_count"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="end"
|
||||
android:layout_marginTop="2dp"
|
||||
android:text="13 Transaksi"
|
||||
android:textColor="#666666"
|
||||
android:textSize="12sp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
@ -1,44 +1,76 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="vertical"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="12dp"
|
||||
android:background="@android:color/white"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:elevation="2dp">
|
||||
android:orientation="vertical"
|
||||
android:background="@android:color/white">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textAmount"
|
||||
android:layout_width="wrap_content"
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Amount"
|
||||
android:textStyle="bold"
|
||||
android:textSize="18sp" />
|
||||
android:orientation="horizontal"
|
||||
android:padding="16dp"
|
||||
android:gravity="center_vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textStatus"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Status"
|
||||
android:textColor="#4CAF50"
|
||||
android:textStyle="bold" />
|
||||
<!-- Kolom 1: Reference ID -->
|
||||
<TextView
|
||||
android:id="@+id/textReferenceId"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="ref-eowu3pin"
|
||||
android:textColor="#333333"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textReferenceId"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Reference ID" />
|
||||
<!-- Kolom 2: Amount -->
|
||||
<TextView
|
||||
android:id="@+id/textAmount"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="Rp. 1.111"
|
||||
android:textColor="#666666"
|
||||
android:textSize="14sp"
|
||||
android:textAlignment="textEnd" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textMerchantName"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Merchant Name" />
|
||||
<!-- Kolom 3: Print Button -->
|
||||
<LinearLayout
|
||||
android:id="@+id/printSection"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:orientation="horizontal"
|
||||
android:gravity="center_vertical|end"
|
||||
android:background="?android:attr/selectableItemBackground"
|
||||
android:padding="8dp"
|
||||
android:clickable="true"
|
||||
android:focusable="true">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/textCreatedAt"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Created At" />
|
||||
</LinearLayout>
|
||||
<ImageView
|
||||
android:layout_width="16dp"
|
||||
android:layout_height="16dp"
|
||||
android:src="@drawable/ic_print"
|
||||
android:layout_marginEnd="8dp"
|
||||
app:tint="#666666" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Cetak Ulang"
|
||||
android:textColor="#666666"
|
||||
android:textSize="14sp" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<!-- Bottom Border -->
|
||||
<View
|
||||
android:id="@+id/bottomBorder"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="#e0e0e0" />
|
||||
|
||||
</LinearLayout>
|
43
app/src/main/res/layout/modal_layout.xml
Normal file
@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- res/layout/modal_layout.xml -->
|
||||
<androidx.cardview.widget.CardView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="32dp"
|
||||
app:cardCornerRadius="16dp"
|
||||
app:cardElevation="8dp"
|
||||
app:cardBackgroundColor="#FFFFFF">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:padding="32dp"
|
||||
android:gravity="center">
|
||||
|
||||
<!-- Card Icon -->
|
||||
<ImageView
|
||||
android:layout_width="80dp"
|
||||
android:layout_height="80dp"
|
||||
android:src="@drawable/ic_card_insert"
|
||||
android:layout_marginBottom="24dp"
|
||||
android:scaleType="fitCenter"
|
||||
android:adjustViewBounds="true"/>
|
||||
|
||||
<!-- Main Text -->
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Silakan Tempelkan / Gesekkan / Masukkan Kartu ke Perangkat"
|
||||
android:textColor="#333333"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="normal"
|
||||
android:textAlignment="center"
|
||||
android:gravity="center"
|
||||
android:lineSpacingExtra="4dp"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.cardview.widget.CardView>
|
48
app/src/main/res/values/styles.xml
Normal file
@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<!-- Style yang sudah ada -->
|
||||
<style name="MenuCardTitle">
|
||||
<item name="fontFamily">@font/inter</item>
|
||||
<item name="android:textSize">12sp</item>
|
||||
<item name="android:textColor">#DD0701</item>
|
||||
<item name="android:textAlignment">center</item>
|
||||
<item name="android:lineSpacingExtra">0dp</item>
|
||||
<item name="android:lineSpacingMultiplier">1.0</item>
|
||||
<item name="android:letterSpacing">0</item>
|
||||
<item name="android:textStyle">normal</item>
|
||||
</style>
|
||||
|
||||
<!-- Style baru untuk Toolbar Title -->
|
||||
<style name="ToolbarTitleStyle">
|
||||
<item name="fontFamily">@font/inter</item>
|
||||
<item name="android:textSize">18sp</item>
|
||||
<item name="android:textStyle">bold</item>
|
||||
<item name="android:lineSpacingExtra">6dp</item>
|
||||
<item name="android:lineSpacingMultiplier">1.0</item>
|
||||
<item name="android:letterSpacing">0</item>
|
||||
<item name="android:textColor">@android:color/white</item>
|
||||
</style>
|
||||
|
||||
<!-- Custom Toolbar Theme -->
|
||||
<style name="CustomToolbarTheme" parent="ThemeOverlay.AppCompat.Dark.ActionBar">
|
||||
<item name="android:textAppearance">@style/ToolbarTitleStyle</item>
|
||||
<item name="titleTextAppearance">@style/ToolbarTitleStyle</item>
|
||||
</style>
|
||||
|
||||
<!-- Numpad Button Style -->
|
||||
<style name="NumpadButton">
|
||||
<item name="android:layout_width">0dp</item>
|
||||
<item name="android:layout_height">60dp</item>
|
||||
<item name="android:layout_columnWeight">1</item>
|
||||
<item name="android:layout_margin">8dp</item>
|
||||
<item name="android:background">?attr/selectableItemBackgroundBorderless</item>
|
||||
<item name="android:textSize">28sp</item>
|
||||
<item name="android:textColor">#333333</item>
|
||||
<item name="android:textStyle">normal</item>
|
||||
<item name="android:fontFamily">@font/inter</item>
|
||||
<item name="android:gravity">center</item>
|
||||
<item name="android:clickable">true</item>
|
||||
<item name="android:focusable">true</item>
|
||||
</style>
|
||||
|
||||
</resources>
|