diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 1b115fe..373ec7b 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -39,6 +39,9 @@ android:screenOrientation="portrait" android:theme="@style/Theme.AppCompat.Light.NoActionBar" android:exported="false" /> + \ No newline at end of file diff --git a/app/src/main/java/com/example/bdkipoc/PinActivity.java b/app/src/main/java/com/example/bdkipoc/PinActivity.java index 4dbf2dd..bd2e784 100644 --- a/app/src/main/java/com/example/bdkipoc/PinActivity.java +++ b/app/src/main/java/com/example/bdkipoc/PinActivity.java @@ -35,6 +35,11 @@ public class PinActivity extends AppCompatActivity { 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; @@ -66,6 +71,7 @@ public class PinActivity extends AppCompatActivity { initializeViews(); setupClickListeners(); setupInitialStates(); + setupSuccessScreen(); } private void setStatusBarColor() { @@ -98,6 +104,11 @@ public class PinActivity extends AppCompatActivity { 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); @@ -113,6 +124,13 @@ public class PinActivity extends AppCompatActivity { 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 -> { @@ -283,7 +301,7 @@ public class PinActivity extends AppCompatActivity { // In real implementation, this would call backend API if (isValidPin(pin)) { - showToast("PIN berhasil diverifikasi!"); + // Don't show toast, show success screen instead handleSuccessfulVerification(); } else { showToast("PIN tidak valid. Silakan coba lagi."); @@ -302,7 +320,66 @@ public class PinActivity extends AppCompatActivity { } private void handleSuccessfulVerification() { - // Return result to calling activity + // Show full screen success message + showSuccessScreen(); + + // Navigate to receipt page after 2-3 seconds + animationHandler.postDelayed(() -> { + navigateToReceiptPage(); + }, 2500); // 2.5 seconds delay + } + + private void showSuccessScreen() { + if (successScreen != null) { + // Set success message + if (successMessage != null) { + successMessage.setText("Pembayaran berhasil!"); + } + + // Show success screen with fade in animation + successScreen.setVisibility(View.VISIBLE); + successScreen.setAlpha(0f); + + ObjectAnimator fadeIn = ObjectAnimator.ofFloat(successScreen, "alpha", 0f, 1f); + fadeIn.setDuration(500); + fadeIn.start(); + + // Add scale animation to success icon + if (successIcon != null) { + ObjectAnimator scaleX = ObjectAnimator.ofFloat(successIcon, "scaleX", 0f, 1f); + ObjectAnimator scaleY = ObjectAnimator.ofFloat(successIcon, "scaleY", 0f, 1f); + + AnimatorSet iconAnimation = new AnimatorSet(); + iconAnimation.playTogether(scaleX, scaleY); + iconAnimation.setDuration(600); + iconAnimation.setStartDelay(200); + iconAnimation.start(); + } + } + } + + 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()); @@ -313,15 +390,21 @@ public class PinActivity extends AppCompatActivity { setResult(RESULT_OK, resultIntent); - // Navigate back or to next screen based on source activity - if ("PaymentActivity".equals(sourceActivity)) { - // Could navigate to payment success screen - showToast("Pembayaran berhasil diproses!"); - } - + // 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(); @@ -370,6 +453,10 @@ public class PinActivity extends AppCompatActivity { @Override public void onBackPressed() { + // Prevent back press when success screen is showing + if (successScreen != null && successScreen.getVisibility() == View.VISIBLE) { + return; + } navigateBack(); } diff --git a/app/src/main/java/com/example/bdkipoc/ReceiptActivity.java b/app/src/main/java/com/example/bdkipoc/ReceiptActivity.java new file mode 100644 index 0000000..2fd4067 --- /dev/null +++ b/app/src/main/java/com/example/bdkipoc/ReceiptActivity.java @@ -0,0 +1,214 @@ +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 Button printButton; + private Button 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 + printButton = findViewById(R.id.print_button); + emailButton = findViewById(R.id.email_button); + finishButton = findViewById(R.id.finish_button); + } + + private void setupClickListeners() { + // Back navigation + backNavigation.setOnClickListener(v -> navigateBack()); + backArrow.setOnClickListener(v -> navigateBack()); + toolbarTitle.setOnClickListener(v -> navigateBack()); + + // Action buttons + printButton.setOnClickListener(v -> handlePrintReceipt()); + emailButton.setOnClickListener(v -> handleEmailReceipt()); + finishButton.setOnClickListener(v -> handleFinish()); + } + + private void loadTransactionData() { + Intent intent = getIntent(); + if (intent != null) { + // Load transaction data from intent + 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"); + String taxPercentageStr = intent.getStringExtra("tax_percentage"); + String serviceFeeStr = intent.getStringExtra("service_fee"); + + // Set merchant info + if (!TextUtils.isEmpty(merchantNameStr)) { + merchantName.setText(merchantNameStr); + } + if (!TextUtils.isEmpty(merchantLocationStr)) { + merchantLocation.setText(merchantLocationStr); + } + + // Set transaction details + if (!TextUtils.isEmpty(transactionId)) { + transactionNumber.setText(transactionId); + } + if (!TextUtils.isEmpty(transactionDateStr)) { + transactionDate.setText(transactionDateStr); + } + if (!TextUtils.isEmpty(paymentMethodStr)) { + paymentMethod.setText(paymentMethodStr); + } + if (!TextUtils.isEmpty(cardTypeStr)) { + cardType.setText(cardTypeStr); + } + if (!TextUtils.isEmpty(taxPercentageStr)) { + taxPercentage.setText(taxPercentageStr); + } + if (!TextUtils.isEmpty(serviceFeeStr)) { + serviceFee.setText(serviceFeeStr); + } + + // Calculate and set amounts + if (!TextUtils.isEmpty(amount)) { + try { + long amountValue = Long.parseLong(amount); + String formattedAmount = formatCurrency(amountValue); + + transactionTotal.setText(formattedAmount); + + // Calculate total with tax and service fee + long serviceFeeLong = TextUtils.isEmpty(serviceFeeStr) ? 0 : Long.parseLong(serviceFeeStr); + long totalWithFee = amountValue + serviceFeeLong; + + finalTotal.setText(formatCurrency(totalWithFee)); + + } catch (NumberFormatException e) { + transactionTotal.setText(amount); + finalTotal.setText(amount); + } + } + + // Set MID and TID (you can customize these) + midText.setText("1234567890"); + tidText.setText("1234567890"); + } + } + + 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() { + // Finish and return to main screen + navigateBack(); + } + + private void navigateBack() { + // You can navigate back to main activity or finish + Intent intent = new Intent(this, PaymentActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(intent); + finish(); + } + + private void showToast(String message) { + android.widget.Toast.makeText(this, message, android.widget.Toast.LENGTH_SHORT).show(); + } + + @Override + public void onBackPressed() { + navigateBack(); + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/button_secondary_background.xml b/app/src/main/res/drawable/button_secondary_background.xml new file mode 100644 index 0000000..1da426f --- /dev/null +++ b/app/src/main/res/drawable/button_secondary_background.xml @@ -0,0 +1,13 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_check_circle.xml b/app/src/main/res/drawable/ic_check_circle.xml new file mode 100644 index 0000000..4eff587 --- /dev/null +++ b/app/src/main/res/drawable/ic_check_circle.xml @@ -0,0 +1,10 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_pin.xml b/app/src/main/res/layout/activity_pin.xml index 048da36..aec771f 100644 --- a/app/src/main/res/layout/activity_pin.xml +++ b/app/src/main/res/layout/activity_pin.xml @@ -255,6 +255,43 @@ app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintVertical_bias="0"/> + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_receipt.xml b/app/src/main/res/layout/activity_receipt.xml new file mode 100644 index 0000000..c3bcd8b --- /dev/null +++ b/app/src/main/res/layout/activity_receipt.xml @@ -0,0 +1,502 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +