From edca7f92ec6d3f45ff16086753a77c10a02a4936 Mon Sep 17 00:00:00 2001 From: riz081 Date: Fri, 6 Jun 2025 05:29:37 +0700 Subject: [PATCH] implement history --- app/src/main/AndroidManifest.xml | 6 + .../com/example/bdkipoc/HistoryActivity.java | 415 ++++++++++++++++++ .../bdkipoc/HistoryDetailActivity.java | 204 +++++++++ .../com/example/bdkipoc/MainActivity.java | 2 +- app/src/main/res/layout/activity_history.xml | 174 ++++++++ .../res/layout/activity_history_detail.xml | 45 ++ app/src/main/res/layout/item_history.xml | 69 +++ .../main/res/layout/item_history_detail.xml | 178 ++++++++ 8 files changed, 1092 insertions(+), 1 deletion(-) create mode 100644 app/src/main/java/com/example/bdkipoc/HistoryActivity.java create mode 100644 app/src/main/java/com/example/bdkipoc/HistoryDetailActivity.java create mode 100644 app/src/main/res/layout/activity_history.xml create mode 100644 app/src/main/res/layout/activity_history_detail.xml create mode 100644 app/src/main/res/layout/item_history.xml create mode 100644 app/src/main/res/layout/item_history_detail.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index f293eee..c24742c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -49,6 +49,12 @@ + + \ No newline at end of file diff --git a/app/src/main/java/com/example/bdkipoc/HistoryActivity.java b/app/src/main/java/com/example/bdkipoc/HistoryActivity.java new file mode 100644 index 0000000..3b17901 --- /dev/null +++ b/app/src/main/java/com/example/bdkipoc/HistoryActivity.java @@ -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 historyList; + private ImageView btnBack; + + // Store full data for detail view + private static List 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 getFullHistoryData() { + return new ArrayList<>(fullHistoryData); + } + + // AsyncTask for API call + private class ApiTask extends AsyncTask { + @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 { + + private List historyList; + + public HistoryAdapter(List 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); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/bdkipoc/HistoryDetailActivity.java b/app/src/main/java/com/example/bdkipoc/HistoryDetailActivity.java new file mode 100644 index 0000000..1bc6cec --- /dev/null +++ b/app/src/main/java/com/example/bdkipoc/HistoryDetailActivity.java @@ -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 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 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 { + + private List detailList; + + public HistoryDetailAdapter(List 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(); + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/bdkipoc/MainActivity.java b/app/src/main/java/com/example/bdkipoc/MainActivity.java index 89854f3..d2cf263 100644 --- a/app/src/main/java/com/example/bdkipoc/MainActivity.java +++ b/app/src/main/java/com/example/bdkipoc/MainActivity.java @@ -170,7 +170,7 @@ public class MainActivity extends AppCompatActivity { } else if (cardId == R.id.card_settlement) { startActivity(new Intent(MainActivity.this, SettlementActivity.class)); } else if (cardId == R.id.card_histori) { - Toast.makeText(this, "Histori - Coming Soon", Toast.LENGTH_SHORT).show(); + 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) { diff --git a/app/src/main/res/layout/activity_history.xml b/app/src/main/res/layout/activity_history.xml new file mode 100644 index 0000000..5357dac --- /dev/null +++ b/app/src/main/res/layout/activity_history.xml @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +