From 4209b193d7dfad44021b2141462a167e9a61bab7 Mon Sep 17 00:00:00 2001 From: riz081 Date: Mon, 30 Jun 2025 14:50:03 +0700 Subject: [PATCH] implement login API dan BantuanActivity Riwayaat API --- app/src/main/AndroidManifest.xml | 4 + .../com/example/bdkipoc/LoginActivity.java | 300 ++++++ .../com/example/bdkipoc/MainActivity.java | 225 +++- .../bdkipoc/bantuan/BantuanActivity.java | 961 ++++++------------ .../res/layout/activity_bantuan_riwayat.xml | 488 --------- .../main/res/layout/activity_bantuan_umum.xml | 498 --------- app/src/main/res/layout/activity_login.xml | 211 ++++ app/src/main/res/layout/activity_main.xml | 131 ++- 8 files changed, 1123 insertions(+), 1695 deletions(-) create mode 100644 app/src/main/java/com/example/bdkipoc/LoginActivity.java delete mode 100644 app/src/main/res/layout/activity_bantuan_riwayat.xml delete mode 100644 app/src/main/res/layout/activity_bantuan_umum.xml create mode 100644 app/src/main/res/layout/activity_login.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 5267bf8..7671da8 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -67,6 +67,10 @@ android:name=".SettlementActivity" android:exported="false" /> + + diff --git a/app/src/main/java/com/example/bdkipoc/LoginActivity.java b/app/src/main/java/com/example/bdkipoc/LoginActivity.java new file mode 100644 index 0000000..19bc1dd --- /dev/null +++ b/app/src/main/java/com/example/bdkipoc/LoginActivity.java @@ -0,0 +1,300 @@ +package com.example.bdkipoc; + +import android.content.Intent; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.text.TextUtils; +import android.util.Log; +import android.view.View; +import android.view.WindowManager; +import android.widget.EditText; +import android.widget.ProgressBar; +import android.widget.Toast; + +import androidx.appcompat.app.AppCompatActivity; + +import com.google.android.material.button.MaterialButton; + +import org.json.JSONObject; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public class LoginActivity extends AppCompatActivity { + + private static final String TAG = "LoginActivity"; + private static final String API_URL = "https://be-edc.msvc.app/users/auth"; + private static final String PREFS_NAME = "LoginPrefs"; + private static final String KEY_TOKEN = "token"; + private static final String KEY_USER_DATA = "user_data"; + private static final String KEY_IS_LOGGED_IN = "is_logged_in"; + + private EditText etIdentifier, etPassword; + private MaterialButton btnLogin; + private ProgressBar progressBar; + private ExecutorService executor; + + @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 + getWindow().setFlags( + WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED, + WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED + ); + + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_login); + + // Check if user is already logged in + if (isUserLoggedIn()) { + navigateToMainActivity(); + return; + } + + initializeViews(); + setupListeners(); + + executor = Executors.newSingleThreadExecutor(); + } + + private void initializeViews() { + etIdentifier = findViewById(R.id.et_identifier); + etPassword = findViewById(R.id.et_password); + btnLogin = findViewById(R.id.btn_login); + progressBar = findViewById(R.id.progress_bar); + } + + private void setupListeners() { + btnLogin.setOnClickListener(v -> { + String identifier = etIdentifier.getText().toString().trim(); + String password = etPassword.getText().toString().trim(); + + if (validateInput(identifier, password)) { + performLogin(identifier, password); + } + }); + } + + private boolean validateInput(String identifier, String password) { + if (TextUtils.isEmpty(identifier)) { + etIdentifier.setError("Email/Username tidak boleh kosong"); + etIdentifier.requestFocus(); + return false; + } + + if (TextUtils.isEmpty(password)) { + etPassword.setError("Password tidak boleh kosong"); + etPassword.requestFocus(); + return false; + } + + if (password.length() < 6) { + etPassword.setError("Password minimal 6 karakter"); + etPassword.requestFocus(); + return false; + } + + return true; + } + + private void performLogin(String identifier, String password) { + setLoadingState(true); + + executor.execute(() -> { + try { + // Create JSON payload + JSONObject jsonPayload = new JSONObject(); + jsonPayload.put("identifier", identifier); + jsonPayload.put("password", password); + + // Setup HTTP connection + URL url = new URL(API_URL); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setRequestMethod("POST"); + connection.setRequestProperty("Content-Type", "application/json"); + connection.setRequestProperty("accept", "*/*"); + connection.setDoOutput(true); + connection.setConnectTimeout(10000); + connection.setReadTimeout(10000); + + // Send request + try (OutputStream os = connection.getOutputStream()) { + byte[] input = jsonPayload.toString().getBytes("utf-8"); + os.write(input, 0, input.length); + } + + // Get response + int responseCode = connection.getResponseCode(); + Log.d(TAG, "Response Code: " + responseCode); + + BufferedReader reader; + if (responseCode >= 200 && responseCode < 300) { + reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); + } else { + reader = new BufferedReader(new InputStreamReader(connection.getErrorStream())); + } + + StringBuilder response = new StringBuilder(); + String line; + while ((line = reader.readLine()) != null) { + response.append(line); + } + reader.close(); + connection.disconnect(); + + Log.d(TAG, "Response: " + response.toString()); + + // Parse response on main thread + runOnUiThread(() -> handleLoginResponse(responseCode, response.toString())); + + } catch (Exception e) { + Log.e(TAG, "Login error: " + e.getMessage(), e); + runOnUiThread(() -> { + setLoadingState(false); + Toast.makeText(this, "Koneksi gagal: " + e.getMessage(), Toast.LENGTH_LONG).show(); + }); + } + }); + } + + private void handleLoginResponse(int responseCode, String responseBody) { + setLoadingState(false); + + try { + JSONObject jsonResponse = new JSONObject(responseBody); + + if (responseCode >= 200 && responseCode < 300) { + // Login successful + String message = jsonResponse.optString("message", ""); + int status = jsonResponse.optInt("status", 0); + + if (status == 200) { + JSONObject result = jsonResponse.getJSONObject("result"); + String token = result.getString("token"); + JSONObject userData = result.getJSONObject("user"); + + // Save login data + saveLoginData(token, userData.toString()); + + Toast.makeText(this, "Login berhasil! " + message, Toast.LENGTH_SHORT).show(); + + // Navigate to MainActivity + navigateToMainActivity(); + } else { + Toast.makeText(this, "Login gagal: " + message, Toast.LENGTH_LONG).show(); + } + } else { + // Login failed + String errorMessage = jsonResponse.optString("message", "Login gagal"); + Toast.makeText(this, errorMessage, Toast.LENGTH_LONG).show(); + Log.e(TAG, "Login failed: " + errorMessage); + } + } catch (Exception e) { + Log.e(TAG, "Error parsing response: " + e.getMessage(), e); + Toast.makeText(this, "Error parsing response", Toast.LENGTH_LONG).show(); + } + } + + private void setLoadingState(boolean isLoading) { + btnLogin.setEnabled(!isLoading); + etIdentifier.setEnabled(!isLoading); + etPassword.setEnabled(!isLoading); + progressBar.setVisibility(isLoading ? View.VISIBLE : View.GONE); + + if (isLoading) { + btnLogin.setText("Memproses..."); + } else { + btnLogin.setText("MASUK"); + } + } + + private void saveLoginData(String token, String userData) { + SharedPreferences prefs = getSharedPreferences(PREFS_NAME, MODE_PRIVATE); + SharedPreferences.Editor editor = prefs.edit(); + editor.putString(KEY_TOKEN, token); + editor.putString(KEY_USER_DATA, userData); + editor.putBoolean(KEY_IS_LOGGED_IN, true); + editor.apply(); + + Log.d(TAG, "Login data saved successfully"); + } + + private boolean isUserLoggedIn() { + SharedPreferences prefs = getSharedPreferences(PREFS_NAME, MODE_PRIVATE); + return prefs.getBoolean(KEY_IS_LOGGED_IN, false); + } + + private void navigateToMainActivity() { + Intent intent = new Intent(LoginActivity.this, MainActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); + startActivity(intent); + finish(); + } + + // Public static methods untuk mengakses data login dari activity lain + public static String getToken(android.content.Context context) { + SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, MODE_PRIVATE); + return prefs.getString(KEY_TOKEN, ""); + } + + public static String getUserData(android.content.Context context) { + SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, MODE_PRIVATE); + return prefs.getString(KEY_USER_DATA, ""); + } + + public static JSONObject getUserDataAsJson(android.content.Context context) { + try { + String userData = getUserData(context); + if (!TextUtils.isEmpty(userData)) { + return new JSONObject(userData); + } + } catch (Exception e) { + Log.e("LoginActivity", "Error parsing user data: " + e.getMessage()); + } + return null; + } + + public static void logout(android.content.Context context) { + SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, MODE_PRIVATE); + SharedPreferences.Editor editor = prefs.edit(); + editor.clear(); + editor.apply(); + + // Navigate back to login + Intent intent = new Intent(context, LoginActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); + context.startActivity(intent); + } + + public static boolean isLoggedIn(android.content.Context context) { + SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, MODE_PRIVATE); + return prefs.getBoolean(KEY_IS_LOGGED_IN, false); + } + + @Override + protected void onDestroy() { + super.onDestroy(); + if (executor != null && !executor.isShutdown()) { + executor.shutdown(); + } + } +} \ 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 b23ba1e..10b22f6 100644 --- a/app/src/main/java/com/example/bdkipoc/MainActivity.java +++ b/app/src/main/java/com/example/bdkipoc/MainActivity.java @@ -8,6 +8,9 @@ import android.widget.TextView; import android.widget.Toast; import android.view.animation.AccelerateDecelerateInterpolator; import android.view.WindowManager; +import android.view.Menu; +import android.view.MenuItem; +import android.util.Log; import androidx.activity.EdgeToEdge; import androidx.appcompat.app.AppCompatActivity; @@ -30,10 +33,18 @@ import com.example.bdkipoc.transaction.ResultTransactionActivity; import com.example.bdkipoc.bantuan.BantuanActivity; +import org.json.JSONObject; + public class MainActivity extends AppCompatActivity { + private static final String TAG = "MainActivity"; private boolean isExpanded = false; // False = showing only 9 main menus, True = showing all 15 menus private MaterialButton btnLainnya; + private MaterialButton logoutButton; + private TextView tvUserName, tvUserRole; + private LinearLayout userInfoSection; + private String authToken; + private JSONObject userData; @Override public void onWindowFocusChanged(boolean hasFocus) { @@ -58,6 +69,17 @@ public class MainActivity extends AppCompatActivity { ); super.onCreate(savedInstanceState); + + // Check if user is logged in + if (!LoginActivity.isLoggedIn(this)) { + // User is not logged in, redirect to login + Intent intent = new Intent(this, LoginActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); + startActivity(intent); + finish(); + return; + } + EdgeToEdge.enable(this); setContentView(R.layout.activity_main); @@ -67,8 +89,20 @@ public class MainActivity extends AppCompatActivity { return insets; }); + // Load user data + loadUserData(); + // Initialize views btnLainnya = findViewById(R.id.btn_lainnya); + logoutButton = findViewById(R.id.logout_button); + tvUserName = findViewById(R.id.tv_user_name); + tvUserRole = findViewById(R.id.tv_user_role); + userInfoSection = findViewById(R.id.user_info_section); + + // Setup logout button + if (logoutButton != null) { + logoutButton.setOnClickListener(v -> performLogout()); + } // Check if we're returning from a completed transaction checkTransactionCompletion(); @@ -78,6 +112,112 @@ public class MainActivity extends AppCompatActivity { // Setup menu listeners setupMenuListeners(); + + // Display user info + displayUserInfo(); + } + + private void loadUserData() { + // Get authentication token + authToken = LoginActivity.getToken(this); + + // Get user data + userData = LoginActivity.getUserDataAsJson(this); + + Log.d(TAG, "Loaded auth token: " + (authToken != null ? "✓" : "✗")); + Log.d(TAG, "Loaded user data: " + (userData != null ? "✓" : "✗")); + + if (userData != null) { + Log.d(TAG, "User: " + userData.optString("name", "Unknown")); + Log.d(TAG, "Email: " + userData.optString("email", "Unknown")); + Log.d(TAG, "Role: " + userData.optString("role", "Unknown")); + } + } + + private void displayUserInfo() { + if (userData != null) { + String userName = userData.optString("name", "User"); + String userRole = userData.optString("role", ""); + + // Display welcome message + String welcomeMessage = "Selamat datang, " + userName; + if (!userRole.isEmpty()) { + welcomeMessage += " (" + userRole + ")"; + } + + // Show welcome toast + Toast.makeText(this, welcomeMessage, Toast.LENGTH_LONG).show(); + + // Update merchant card with user info + if (tvUserName != null) { + tvUserName.setText(userName); + } + if (tvUserRole != null && !userRole.isEmpty()) { + tvUserRole.setText("(" + userRole + ")"); + tvUserRole.setVisibility(View.VISIBLE); + } else if (tvUserRole != null) { + tvUserRole.setVisibility(View.GONE); + } + + // Show user info section in merchant card + if (userInfoSection != null) { + userInfoSection.setVisibility(View.VISIBLE); + } + } + } + + // Method to get auth token for use in other activities + public static String getAuthToken(android.content.Context context) { + return LoginActivity.getToken(context); + } + + // Method to get user data for use in other activities + public static JSONObject getUserData(android.content.Context context) { + return LoginActivity.getUserDataAsJson(context); + } + + @Override + public boolean onCreateOptionsMenu(Menu menu) { + // Menu logout sudah ada di custom toolbar, tidak perlu action bar menu + return false; // Return false to not show action bar menu + } + + @Override + public boolean onOptionsItemSelected(MenuItem item) { + // No longer needed since logout is handled by custom toolbar button + return super.onOptionsItemSelected(item); + } + + private void performLogout() { + // Show confirmation dialog with red theme + androidx.appcompat.app.AlertDialog.Builder builder = new androidx.appcompat.app.AlertDialog.Builder(this); + builder.setTitle("Logout"); + builder.setMessage("Apakah Anda yakin ingin keluar dari aplikasi?"); + builder.setIcon(android.R.drawable.ic_dialog_alert); + + // Set positive button (Ya) + builder.setPositiveButton("Ya", (dialog, which) -> { + // Show logout progress + Toast.makeText(this, "Logging out...", Toast.LENGTH_SHORT).show(); + + // Perform logout + LoginActivity.logout(this); + }); + + // Set negative button (Batal) + builder.setNegativeButton("Batal", (dialog, which) -> { + dialog.dismiss(); + }); + + // Create and show dialog + androidx.appcompat.app.AlertDialog dialog = builder.create(); + dialog.show(); + + // Customize button colors + dialog.getButton(androidx.appcompat.app.AlertDialog.BUTTON_POSITIVE) + .setTextColor(getResources().getColor(android.R.color.holo_red_dark)); + dialog.getButton(androidx.appcompat.app.AlertDialog.BUTTON_NEGATIVE) + .setTextColor(getResources().getColor(android.R.color.black)); } private void setupInitialMenuState() { @@ -161,30 +301,30 @@ public class MainActivity extends AppCompatActivity { CardView cardView = findViewById(cardId); if (cardView != null) { cardView.setOnClickListener(v -> { - // ✅ ENHANCED: Navigate with payment type information + // ✅ ENHANCED: Navigate with payment type information and auth token if (cardId == R.id.card_kartu_kredit) { navigateToCreateTransaction("credit_card", cardId, "Kartu Kredit"); } else if (cardId == R.id.card_kartu_debit) { navigateToCreateTransaction("debit_card", cardId, "Kartu Debit"); } else if (cardId == R.id.card_qris) { - startActivity(new Intent(MainActivity.this, QrisActivity.class)); + startActivityWithAuth(new Intent(MainActivity.this, QrisActivity.class)); // Col-2 } else if (cardId == R.id.card_transfer) { navigateToCreateTransaction("transfer", cardId, "Transfer"); } else if (cardId == R.id.card_uang_elektronik) { navigateToCreateTransaction("e_money", cardId, "Uang Elektronik"); } else if (cardId == R.id.card_cetak_ulang) { - startActivity(new Intent(MainActivity.this, ReprintActivity.class)); + startActivityWithAuth(new Intent(MainActivity.this, ReprintActivity.class)); // Col-3 } else if (cardId == R.id.card_refund) { navigateToCreateTransaction("refund", cardId, "Refund"); } else if (cardId == R.id.card_settlement) { Toast.makeText(this, "Settlement - Coming Soon", Toast.LENGTH_SHORT).show(); } else if (cardId == R.id.card_histori) { - startActivity(new Intent(MainActivity.this, HistoryActivity.class)); + startActivityWithAuth(new Intent(MainActivity.this, HistoryActivity.class)); // Col-4 } else if (cardId == R.id.card_bantuan) { - startActivity(new Intent(MainActivity.this, BantuanActivity.class)); + startActivityWithAuth(new Intent(MainActivity.this, BantuanActivity.class)); } 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_pengaturan) { @@ -243,12 +383,12 @@ public class MainActivity extends AppCompatActivity { if (scanBayarContent != null) { scanBayarContent.setOnClickListener(v -> { // Navigate to QRIS payment activity - startActivity(new Intent(MainActivity.this, QrisActivity.class)); + startActivityWithAuth(new Intent(MainActivity.this, QrisActivity.class)); }); } } - // ✅ NEW: Enhanced navigation method with payment type information + // ✅ NEW: Enhanced navigation method with payment type information and auth token private void navigateToCreateTransaction(String paymentType, int cardMenuId, String cardName) { try { Intent intent = new Intent(MainActivity.this, CreateTransactionActivity.class); @@ -259,21 +399,45 @@ public class MainActivity extends AppCompatActivity { intent.putExtra("CARD_NAME", cardName); intent.putExtra("CALLING_ACTIVITY", "MainActivity"); + // ✅ NEW: Pass authentication data + intent.putExtra("AUTH_TOKEN", authToken); + if (userData != null) { + intent.putExtra("USER_DATA", userData.toString()); + } + // ✅ DEBUG: Log navigation details - android.util.Log.d("MainActivity", "=== NAVIGATING TO CREATE TRANSACTION ==="); - android.util.Log.d("MainActivity", "Payment Type: " + paymentType); - android.util.Log.d("MainActivity", "Card Menu ID: " + cardMenuId); - android.util.Log.d("MainActivity", "Card Name: " + cardName); - android.util.Log.d("MainActivity", "========================================"); + Log.d(TAG, "=== NAVIGATING TO CREATE TRANSACTION ==="); + Log.d(TAG, "Payment Type: " + paymentType); + Log.d(TAG, "Card Menu ID: " + cardMenuId); + Log.d(TAG, "Card Name: " + cardName); + Log.d(TAG, "Auth Token: " + (authToken != null ? "✓" : "✗")); + Log.d(TAG, "========================================"); startActivity(intent); } catch (Exception e) { - android.util.Log.e("MainActivity", "Error navigating to CreateTransaction: " + e.getMessage(), e); + Log.e(TAG, "Error navigating to CreateTransaction: " + e.getMessage(), e); Toast.makeText(this, "Error opening transaction: " + e.getMessage(), Toast.LENGTH_SHORT).show(); } } + // ✅ NEW: Helper method to start activity with authentication data + private void startActivityWithAuth(Intent intent) { + try { + // Add authentication data to intent + intent.putExtra("AUTH_TOKEN", authToken); + if (userData != null) { + intent.putExtra("USER_DATA", userData.toString()); + } + + startActivity(intent); + + } catch (Exception e) { + Log.e(TAG, "Error starting activity: " + e.getMessage(), e); + Toast.makeText(this, "Error opening activity: " + e.getMessage(), Toast.LENGTH_SHORT).show(); + } + } + // ✅ NEW: Helper method to get payment type from card ID (for backward compatibility) private String getPaymentTypeFromCardId(int cardId) { if (cardId == R.id.card_kartu_kredit) { @@ -289,7 +453,7 @@ public class MainActivity extends AppCompatActivity { } else if (cardId == R.id.card_refund) { return "refund"; } else { - android.util.Log.w("MainActivity", "Unknown card ID: " + cardId + ", defaulting to credit_card"); + Log.w(TAG, "Unknown card ID: " + cardId + ", defaulting to credit_card"); return "credit_card"; } } @@ -378,24 +542,35 @@ public class MainActivity extends AppCompatActivity { @Override protected void onResume() { super.onResume(); + + // Check if user is still logged in + if (!LoginActivity.isLoggedIn(this)) { + // User is not logged in, redirect to login + Intent intent = new Intent(this, LoginActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); + startActivity(intent); + finish(); + return; + } + // Clear any transaction completion flags to avoid repeated messages getIntent().removeExtra("transaction_completed"); getIntent().removeExtra("transaction_amount"); // ✅ NEW: Log resume for debugging - android.util.Log.d("MainActivity", "MainActivity resumed"); + Log.d(TAG, "MainActivity resumed"); } @Override protected void onPause() { super.onPause(); - android.util.Log.d("MainActivity", "MainActivity paused"); + Log.d(TAG, "MainActivity paused"); } @Override protected void onDestroy() { super.onDestroy(); - android.util.Log.d("MainActivity", "MainActivity destroyed"); + Log.d(TAG, "MainActivity destroyed"); } // ✅ NEW: Method to handle direct payment type launch (for external calls) @@ -404,6 +579,14 @@ public class MainActivity extends AppCompatActivity { intent.putExtra("PAYMENT_TYPE", paymentType); intent.putExtra("CARD_NAME", cardName); intent.putExtra("CALLING_ACTIVITY", "External"); + + // Add authentication data + intent.putExtra("AUTH_TOKEN", LoginActivity.getToken(context)); + String userData = LoginActivity.getUserData(context); + if (!userData.isEmpty()) { + intent.putExtra("USER_DATA", userData); + } + return intent; } @@ -413,7 +596,7 @@ public class MainActivity extends AppCompatActivity { if (cardView != null) { cardView.performClick(); } else { - android.util.Log.w("MainActivity", "Card not found for ID: " + cardId); + Log.w(TAG, "Card not found for ID: " + cardId); } } @@ -435,7 +618,7 @@ public class MainActivity extends AppCompatActivity { // ✅ NEW: Debug method to log all card IDs and their payment types private void debugCardMappings() { - android.util.Log.d("MainActivity", "=== CARD PAYMENT TYPE MAPPINGS ==="); + Log.d(TAG, "=== CARD PAYMENT TYPE MAPPINGS ==="); int[] cardIds = { R.id.card_kartu_kredit, R.id.card_kartu_debit, R.id.card_qris, @@ -445,10 +628,10 @@ public class MainActivity extends AppCompatActivity { for (int cardId : cardIds) { String paymentType = getPaymentTypeFromCardId(cardId); String cardName = getCardNameFromCardId(cardId); - android.util.Log.d("MainActivity", + Log.d(TAG, "Card ID: " + cardId + " -> Payment Type: " + paymentType + " -> Name: " + cardName); } - android.util.Log.d("MainActivity", "=================================="); + Log.d(TAG, "=================================="); } } \ No newline at end of file diff --git a/app/src/main/java/com/example/bdkipoc/bantuan/BantuanActivity.java b/app/src/main/java/com/example/bdkipoc/bantuan/BantuanActivity.java index 7b7ea19..c1b41c2 100644 --- a/app/src/main/java/com/example/bdkipoc/bantuan/BantuanActivity.java +++ b/app/src/main/java/com/example/bdkipoc/bantuan/BantuanActivity.java @@ -11,9 +11,9 @@ import android.widget.ScrollView; import android.widget.TextView; import androidx.appcompat.app.AppCompatActivity; import androidx.core.content.ContextCompat; -import android.widget.ProgressBar; import com.example.bdkipoc.R; +import com.example.bdkipoc.LoginActivity; import org.json.JSONArray; import org.json.JSONObject; @@ -32,33 +32,22 @@ import java.util.concurrent.Executors; public class BantuanActivity extends AppCompatActivity { - // Tab components + // UI Components private LinearLayout tabUmum, tabRiwayat; private TextView textUmum, textRiwayat; - - // Content containers private ScrollView contentUmum, contentRiwayat; private LinearLayout riwayatContainer; - private ProgressBar progressBar; + private LinearLayout btnForm, btnWhatsApp, backNavigation; - // Bottom buttons - private LinearLayout btnForm, btnWhatsApp; - private LinearLayout backNavigation; - - // Current active tab + // State private boolean isUmumTabActive = true; - - // API and data private List ticketList = new ArrayList<>(); private ExecutorService executor = Executors.newSingleThreadExecutor(); private Handler mainHandler = new Handler(Looper.getMainLooper()); - // Data model class + // ✅ Simplified TicketData class public static class TicketData { - public String createdAt; - public String ticketCode; - public String issueName; - public String status; + public String createdAt, ticketCode, issueName, status; public TicketData(String createdAt, String ticketCode, String issueName, String status) { this.createdAt = createdAt; @@ -71,668 +60,401 @@ public class BantuanActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - android.util.Log.d("BantuanActivity", "=== onCreate START ==="); + + // ✅ Check authentication + if (!LoginActivity.isLoggedIn(this)) { + LoginActivity.logout(this); + return; + } setContentView(R.layout.activity_bantuan); - // Debug network and system info - checkNetworkConnection(); - initViews(); setupListeners(); - - // Set default tab (Umum) as active showUmumTab(); - - // Debug layout hierarchy - debugLayoutHierarchy(); - - // Test basic HTTP connectivity - testSimpleHttpConnection(); - - // Load ticket data from API - android.util.Log.d("BantuanActivity", "Starting API call..."); loadTicketData(); - - android.util.Log.d("BantuanActivity", "=== onCreate END ==="); } private void initViews() { - try { - // Tab components - tabUmum = findViewById(R.id.tab_umum); - tabRiwayat = findViewById(R.id.tab_riwayat); - textUmum = findViewById(R.id.text_umum); - textRiwayat = findViewById(R.id.text_riwayat); - - // Content containers - contentUmum = findViewById(R.id.content_umum); - contentRiwayat = findViewById(R.id.content_riwayat); - - // Create dynamic container for riwayat content - if (contentRiwayat != null) { - View child = contentRiwayat.getChildAt(0); - if (child instanceof LinearLayout) { - riwayatContainer = (LinearLayout) child; - } + // Tabs + tabUmum = findViewById(R.id.tab_umum); + tabRiwayat = findViewById(R.id.tab_riwayat); + textUmum = findViewById(R.id.text_umum); + textRiwayat = findViewById(R.id.text_riwayat); + + // Content + contentUmum = findViewById(R.id.content_umum); + contentRiwayat = findViewById(R.id.content_riwayat); + + // Riwayat container + if (contentRiwayat != null && contentRiwayat.getChildCount() > 0) { + View child = contentRiwayat.getChildAt(0); + if (child instanceof LinearLayout) { + riwayatContainer = (LinearLayout) child; } - - // Bottom buttons - btnForm = findViewById(R.id.btn_form); - btnWhatsApp = findViewById(R.id.btn_whatsapp); - - // Back navigation dari component_appbar - backNavigation = findViewById(R.id.back_navigation); - - // Create progress bar programmatically - progressBar = new ProgressBar(this, null, android.R.attr.progressBarStyleSmall); - progressBar.setVisibility(View.GONE); - - // Debug: Log which views are null - android.util.Log.d("BantuanActivity", "tabUmum: " + (tabUmum != null)); - android.util.Log.d("BantuanActivity", "tabRiwayat: " + (tabRiwayat != null)); - android.util.Log.d("BantuanActivity", "contentUmum: " + (contentUmum != null)); - android.util.Log.d("BantuanActivity", "contentRiwayat: " + (contentRiwayat != null)); - android.util.Log.d("BantuanActivity", "riwayatContainer: " + (riwayatContainer != null)); - - } catch (Exception e) { - e.printStackTrace(); - android.util.Log.e("BantuanActivity", "Error in initViews: " + e.getMessage()); } + + // Buttons + btnForm = findViewById(R.id.btn_form); + btnWhatsApp = findViewById(R.id.btn_whatsapp); + backNavigation = findViewById(R.id.back_navigation); } private void setupListeners() { - // Back navigation listener if (backNavigation != null) { backNavigation.setOnClickListener(v -> onBackPressed()); } - // Tab listeners if (tabUmum != null) { tabUmum.setOnClickListener(v -> showUmumTab()); } + if (tabRiwayat != null) { tabRiwayat.setOnClickListener(v -> showRiwayatTab()); } - // Button listeners if (btnForm != null) { - btnForm.setOnClickListener(v -> { - try { - // Handle form bantuan - untuk sementara bisa tampilkan toast atau dialog - android.widget.Toast.makeText(this, "Form Bantuan akan segera tersedia", android.widget.Toast.LENGTH_SHORT).show(); - } catch (Exception e) { - e.printStackTrace(); - android.widget.Toast.makeText(this, "Error: " + e.getMessage(), android.widget.Toast.LENGTH_SHORT).show(); - } - }); + btnForm.setOnClickListener(v -> + android.widget.Toast.makeText(this, "Form Bantuan akan segera tersedia", + android.widget.Toast.LENGTH_SHORT).show()); } if (btnWhatsApp != null) { - btnWhatsApp.setOnClickListener(v -> { - try { - // Handle WhatsApp CS - bisa buka aplikasi WhatsApp atau web - openWhatsAppCS(); - } catch (Exception e) { - e.printStackTrace(); - android.widget.Toast.makeText(this, "Error membuka WhatsApp: " + e.getMessage(), android.widget.Toast.LENGTH_SHORT).show(); - } - }); + btnWhatsApp.setOnClickListener(v -> openWhatsAppCS()); } } private void showUmumTab() { - try { - if (isUmumTabActive) return; // Avoid unnecessary operations - - isUmumTabActive = true; - - // Update content visibility - if (contentUmum != null) { - contentUmum.setVisibility(View.VISIBLE); - android.util.Log.d("BantuanActivity", "contentUmum set to VISIBLE"); - } - if (contentRiwayat != null) { - contentRiwayat.setVisibility(View.GONE); - android.util.Log.d("BantuanActivity", "contentRiwayat set to GONE"); - } - - // Update tab appearance - updateTabAppearance(); - } catch (Exception e) { - e.printStackTrace(); - android.util.Log.e("BantuanActivity", "Error in showUmumTab: " + e.getMessage()); - } + if (isUmumTabActive) return; + + isUmumTabActive = true; + + if (contentUmum != null) contentUmum.setVisibility(View.VISIBLE); + if (contentRiwayat != null) contentRiwayat.setVisibility(View.GONE); + + updateTabAppearance(); } private void showRiwayatTab() { - try { - android.util.Log.d("BantuanActivity", "=== showRiwayatTab called ==="); - - if (!isUmumTabActive) { - android.util.Log.d("BantuanActivity", "Already on riwayat tab, skipping"); - return; // Avoid unnecessary operations - } - - isUmumTabActive = false; - android.util.Log.d("BantuanActivity", "Switching to riwayat tab"); - - // Update content visibility - if (contentUmum != null) { - contentUmum.setVisibility(View.GONE); - android.util.Log.d("BantuanActivity", "contentUmum set to GONE"); - } - if (contentRiwayat != null) { - contentRiwayat.setVisibility(View.VISIBLE); - android.util.Log.d("BantuanActivity", "contentRiwayat set to VISIBLE"); - } - - // Update tab appearance - updateTabAppearance(); - - // Debug current state - debugLayoutHierarchy(); - - // Populate riwayat content if data is available - if (!ticketList.isEmpty()) { - android.util.Log.d("BantuanActivity", "Ticket data available (" + ticketList.size() + " items), populating content"); - populateRiwayatContent(); - } else { - android.util.Log.w("BantuanActivity", "No ticket data available yet"); - // Show loading or empty message - if (riwayatContainer != null) { - riwayatContainer.removeAllViews(); - TextView loadingText = new TextView(this); - loadingText.setLayoutParams(new LinearLayout.LayoutParams( - LinearLayout.LayoutParams.MATCH_PARENT, - LinearLayout.LayoutParams.WRAP_CONTENT - )); - loadingText.setText("Memuat data..."); - loadingText.setTextSize(16); - loadingText.setGravity(android.view.Gravity.CENTER); - loadingText.setPadding(dpToPx(16), dpToPx(32), dpToPx(16), dpToPx(32)); - loadingText.setTextColor(ContextCompat.getColor(this, android.R.color.darker_gray)); - riwayatContainer.addView(loadingText); - android.util.Log.d("BantuanActivity", "Loading message added to riwayat container"); - } - } - - } catch (Exception e) { - e.printStackTrace(); - android.util.Log.e("BantuanActivity", "Error in showRiwayatTab: " + e.getMessage()); - } + if (!isUmumTabActive) return; - android.util.Log.d("BantuanActivity", "=== showRiwayatTab completed ==="); + isUmumTabActive = false; + + if (contentUmum != null) contentUmum.setVisibility(View.GONE); + if (contentRiwayat != null) contentRiwayat.setVisibility(View.VISIBLE); + + updateTabAppearance(); + + // Load data if available + if (!ticketList.isEmpty()) { + populateRiwayatContent(); + } else { + showLoadingMessage(); + } } private void updateTabAppearance() { - try { - if (isUmumTabActive) { - // Umum tab active - if (tabUmum != null) { - tabUmum.setBackgroundResource(R.drawable.tab_active_bg); - } - if (textUmum != null) { - textUmum.setTextColor(ContextCompat.getColor(this, android.R.color.white)); - } - - // Riwayat tab inactive - if (tabRiwayat != null) { - tabRiwayat.setBackgroundResource(R.drawable.tab_inactive_bg); - } - if (textRiwayat != null) { - textRiwayat.setTextColor(Color.parseColor("#DE0701")); - } - } else { - // Riwayat tab active - if (tabRiwayat != null) { - tabRiwayat.setBackgroundResource(R.drawable.tab_active_bg); - } - if (textRiwayat != null) { - textRiwayat.setTextColor(ContextCompat.getColor(this, android.R.color.white)); - } - - // Umum tab inactive - if (tabUmum != null) { - tabUmum.setBackgroundResource(R.drawable.tab_inactive_bg); - } - if (textUmum != null) { - textUmum.setTextColor(Color.parseColor("#DE0701")); - } - } + if (isUmumTabActive) { + // Umum active + if (tabUmum != null) tabUmum.setBackgroundResource(R.drawable.tab_active_bg); + if (textUmum != null) textUmum.setTextColor(ContextCompat.getColor(this, android.R.color.white)); - android.util.Log.d("BantuanActivity", "Tab appearance updated. isUmumTabActive: " + isUmumTabActive); - } catch (Exception e) { - e.printStackTrace(); - android.util.Log.e("BantuanActivity", "Error in updateTabAppearance: " + e.getMessage()); + // Riwayat inactive + if (tabRiwayat != null) tabRiwayat.setBackgroundResource(R.drawable.tab_inactive_bg); + if (textRiwayat != null) textRiwayat.setTextColor(Color.parseColor("#DE0701")); + } else { + // Riwayat active + if (tabRiwayat != null) tabRiwayat.setBackgroundResource(R.drawable.tab_active_bg); + if (textRiwayat != null) textRiwayat.setTextColor(ContextCompat.getColor(this, android.R.color.white)); + + // Umum inactive + if (tabUmum != null) tabUmum.setBackgroundResource(R.drawable.tab_inactive_bg); + if (textUmum != null) textUmum.setTextColor(Color.parseColor("#DE0701")); } } + // ✅ Simplified API call with new endpoint private void loadTicketData() { - android.util.Log.d("BantuanActivity", "=== START loadTicketData ==="); - showLoading(true); + String authToken = LoginActivity.getToken(this); + if (authToken == null || authToken.isEmpty()) { + LoginActivity.logout(this); + return; + } executor.execute(() -> { HttpURLConnection connection = null; try { - String apiUrl = "https://be-edc.msvc.app/tickets?page=0&limit=10&sortOrder=ASC&sortColumn=ticket_code"; - android.util.Log.d("BantuanActivity", "API URL: " + apiUrl); - - URL url = new URL(apiUrl); + // ✅ Updated API endpoint + URL url = new URL("https://be-edc.msvc.app/tickets/list"); connection = (HttpURLConnection) url.openConnection(); - // Set connection properties connection.setRequestMethod("GET"); - connection.setRequestProperty("accept", "*/*"); - connection.setRequestProperty("User-Agent", "Android-App/1.0"); - connection.setConnectTimeout(15000); // Increase timeout + connection.setRequestProperty("accept", "application/json"); + connection.setRequestProperty("Authorization", "Bearer " + authToken); + connection.setConnectTimeout(15000); connection.setReadTimeout(15000); - connection.setDoInput(true); - - android.util.Log.d("BantuanActivity", "Connection configured, attempting to connect..."); - - // Check if we can connect - connection.connect(); - android.util.Log.d("BantuanActivity", "Connection established"); int responseCode = connection.getResponseCode(); - String responseMessage = connection.getResponseMessage(); - android.util.Log.d("BantuanActivity", "API Response Code: " + responseCode); - android.util.Log.d("BantuanActivity", "API Response Message: " + responseMessage); - if (responseCode == HttpURLConnection.HTTP_OK) { - android.util.Log.d("BantuanActivity", "Reading response..."); - + if (responseCode == 200) { BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); StringBuilder response = new StringBuilder(); String line; - while ((line = reader.readLine()) != null) { response.append(line); } reader.close(); - String responseString = response.toString(); - android.util.Log.d("BantuanActivity", "Response Length: " + responseString.length()); - android.util.Log.d("BantuanActivity", "Response Preview: " + - (responseString.length() > 200 ? responseString.substring(0, 200) + "..." : responseString)); + parseTicketData(response.toString()); - // Parse JSON response - parseTicketData(responseString); - - } else { - // Log error response body - try { - BufferedReader errorReader = new BufferedReader(new InputStreamReader(connection.getErrorStream())); - StringBuilder errorResponse = new StringBuilder(); - String errorLine; - while ((errorLine = errorReader.readLine()) != null) { - errorResponse.append(errorLine); - } - errorReader.close(); - android.util.Log.e("BantuanActivity", "Error Response Body: " + errorResponse.toString()); - } catch (Exception errorEx) { - android.util.Log.e("BantuanActivity", "Cannot read error response: " + errorEx.getMessage()); - } - - android.util.Log.e("BantuanActivity", "API Error: " + responseCode + " - " + responseMessage); + } else if (responseCode == 401) { mainHandler.post(() -> { - showLoading(false); - android.widget.Toast.makeText(this, "Gagal memuat data riwayat: " + responseCode, android.widget.Toast.LENGTH_LONG).show(); + android.widget.Toast.makeText(this, "Session expired. Please login again.", + android.widget.Toast.LENGTH_LONG).show(); + LoginActivity.logout(this); + }); + } else { + mainHandler.post(() -> { + android.widget.Toast.makeText(this, "Failed to load data. Error: " + responseCode, + android.widget.Toast.LENGTH_LONG).show(); }); } - } catch (java.net.UnknownHostException e) { - android.util.Log.e("BantuanActivity", "Network Error - Unknown Host: " + e.getMessage()); - mainHandler.post(() -> { - showLoading(false); - android.widget.Toast.makeText(this, "Tidak dapat terhubung ke server. Periksa koneksi internet.", android.widget.Toast.LENGTH_LONG).show(); - }); - } catch (java.net.SocketTimeoutException e) { - android.util.Log.e("BantuanActivity", "Network Error - Timeout: " + e.getMessage()); - mainHandler.post(() -> { - showLoading(false); - android.widget.Toast.makeText(this, "Koneksi timeout. Coba lagi.", android.widget.Toast.LENGTH_LONG).show(); - }); - } catch (java.net.ConnectException e) { - android.util.Log.e("BantuanActivity", "Network Error - Connection Failed: " + e.getMessage()); - mainHandler.post(() -> { - showLoading(false); - android.widget.Toast.makeText(this, "Gagal terhubung ke server.", android.widget.Toast.LENGTH_LONG).show(); - }); - } catch (java.io.IOException e) { - android.util.Log.e("BantuanActivity", "IO Error: " + e.getMessage()); - e.printStackTrace(); - mainHandler.post(() -> { - showLoading(false); - android.widget.Toast.makeText(this, "Error IO: " + e.getMessage(), android.widget.Toast.LENGTH_LONG).show(); - }); } catch (Exception e) { - android.util.Log.e("BantuanActivity", "General Error: " + e.getMessage()); - e.printStackTrace(); mainHandler.post(() -> { - showLoading(false); - android.widget.Toast.makeText(this, "Error: " + e.getMessage(), android.widget.Toast.LENGTH_LONG).show(); + android.widget.Toast.makeText(this, "Network error: " + e.getMessage(), + android.widget.Toast.LENGTH_LONG).show(); }); } finally { if (connection != null) { connection.disconnect(); - android.util.Log.d("BantuanActivity", "Connection disconnected"); } - android.util.Log.d("BantuanActivity", "=== END loadTicketData ==="); } }); } + // ✅ Simplified JSON parsing private void parseTicketData(String jsonResponse) { try { - android.util.Log.d("BantuanActivity", "=== START parseTicketData ==="); - android.util.Log.d("BantuanActivity", "JSON Response received, length: " + jsonResponse.length()); - - if (jsonResponse == null || jsonResponse.trim().isEmpty()) { - android.util.Log.e("BantuanActivity", "JSON Response is null or empty"); - mainHandler.post(() -> { - showLoading(false); - android.widget.Toast.makeText(this, "Response kosong dari server", android.widget.Toast.LENGTH_SHORT).show(); - }); - return; - } - JSONObject jsonObject = new JSONObject(jsonResponse); - android.util.Log.d("BantuanActivity", "JSON parsed successfully"); - // Check if response has results - if (!jsonObject.has("results")) { - android.util.Log.e("BantuanActivity", "JSON does not contain 'results' field"); - android.util.Log.d("BantuanActivity", "Available keys: " + jsonObject.keys().toString()); - mainHandler.post(() -> { - showLoading(false); - android.widget.Toast.makeText(this, "Format response tidak valid", android.widget.Toast.LENGTH_SHORT).show(); - }); - return; + // Check for different possible response structures + JSONArray dataArray = null; + + if (jsonObject.has("results") && jsonObject.getJSONObject("results").has("data")) { + // Structure: { "results": { "data": [...] } } + dataArray = jsonObject.getJSONObject("results").getJSONArray("data"); + } else if (jsonObject.has("data")) { + // Structure: { "data": [...] } + dataArray = jsonObject.getJSONArray("data"); + } else if (jsonObject.has("tickets")) { + // Structure: { "tickets": [...] } + dataArray = jsonObject.getJSONArray("tickets"); + } else { + // Assume the response is directly an array + dataArray = new JSONArray(jsonResponse); } - JSONObject results = jsonObject.getJSONObject("results"); - android.util.Log.d("BantuanActivity", "Results object extracted"); - - // Check if results has data - if (!results.has("data")) { - android.util.Log.e("BantuanActivity", "Results does not contain 'data' field"); - android.util.Log.d("BantuanActivity", "Available keys in results: " + results.keys().toString()); - mainHandler.post(() -> { - showLoading(false); - android.widget.Toast.makeText(this, "Data tidak ditemukan dalam response", android.widget.Toast.LENGTH_SHORT).show(); - }); - return; - } - - JSONArray dataArray = results.getJSONArray("data"); - android.util.Log.d("BantuanActivity", "Data array extracted, length: " + dataArray.length()); - List newTicketList = new ArrayList<>(); for (int i = 0; i < dataArray.length(); i++) { - try { - JSONObject ticket = dataArray.getJSONObject(i); - android.util.Log.d("BantuanActivity", "Processing ticket " + (i+1) + "/" + dataArray.length()); - - // Extract required fields with null checks - String createdAt = ticket.optString("createdAt", ""); - String ticketCode = ticket.optString("ticket_code", ""); - String status = ticket.optString("status", ""); - - android.util.Log.d("BantuanActivity", "Ticket " + (i+1) + " - createdAt: " + createdAt + ", ticket_code: " + ticketCode + ", status: " + status); - - // Get issue name with null check - String issueName = ""; - if (ticket.has("issue") && !ticket.isNull("issue")) { - JSONObject issue = ticket.getJSONObject("issue"); - issueName = issue.optString("name", "Tidak ada keterangan"); - android.util.Log.d("BantuanActivity", "Ticket " + (i+1) + " - issue name: " + issueName); - } else { - android.util.Log.w("BantuanActivity", "Ticket " + (i+1) + " - issue field is missing or null"); - issueName = "Tidak ada keterangan"; - } - - // Validate required fields - if (createdAt.isEmpty() || ticketCode.isEmpty()) { - android.util.Log.w("BantuanActivity", "Ticket " + (i+1) + " - skipping due to missing required fields"); - continue; - } - + JSONObject ticket = dataArray.getJSONObject(i); + + String createdAt = ticket.optString("createdAt", ticket.optString("created_at", "")); + String ticketCode = ticket.optString("ticket_code", ticket.optString("ticketCode", "")); + String status = ticket.optString("status", ""); + + String issueName = "Tidak ada keterangan"; + if (ticket.has("issue") && !ticket.isNull("issue")) { + JSONObject issue = ticket.getJSONObject("issue"); + issueName = issue.optString("name", issueName); + } else if (ticket.has("issue_name")) { + issueName = ticket.optString("issue_name", issueName); + } else if (ticket.has("title")) { + issueName = ticket.optString("title", issueName); + } + + if (!createdAt.isEmpty() && !ticketCode.isEmpty()) { newTicketList.add(new TicketData(createdAt, ticketCode, issueName, status)); - android.util.Log.d("BantuanActivity", "Ticket " + (i+1) + " added successfully"); - - } catch (Exception ticketException) { - android.util.Log.e("BantuanActivity", "Error processing ticket " + (i+1) + ": " + ticketException.getMessage()); - ticketException.printStackTrace(); - // Continue with next ticket } } - android.util.Log.d("BantuanActivity", "Successfully processed " + newTicketList.size() + " tickets out of " + dataArray.length()); - - // Update UI on main thread mainHandler.post(() -> { - try { - android.util.Log.d("BantuanActivity", "Updating UI with ticket data..."); - ticketList.clear(); - ticketList.addAll(newTicketList); - showLoading(false); - - // If currently on riwayat tab, update the content - if (!isUmumTabActive) { - android.util.Log.d("BantuanActivity", "Currently on riwayat tab, populating content..."); - populateRiwayatContent(); - } else { - android.util.Log.d("BantuanActivity", "Currently on umum tab, data loaded and ready"); - } - - android.widget.Toast.makeText(this, "Data riwayat berhasil dimuat (" + ticketList.size() + " item)", android.widget.Toast.LENGTH_SHORT).show(); - android.util.Log.d("BantuanActivity", "UI update completed successfully"); - - } catch (Exception uiException) { - android.util.Log.e("BantuanActivity", "Error updating UI: " + uiException.getMessage()); - uiException.printStackTrace(); - android.widget.Toast.makeText(this, "Error updating UI: " + uiException.getMessage(), android.widget.Toast.LENGTH_SHORT).show(); + ticketList.clear(); + ticketList.addAll(newTicketList); + + if (!isUmumTabActive) { + populateRiwayatContent(); } + + android.widget.Toast.makeText(this, "Data riwayat berhasil dimuat (" + + ticketList.size() + " item)", android.widget.Toast.LENGTH_SHORT).show(); }); - } catch (org.json.JSONException jsonException) { - android.util.Log.e("BantuanActivity", "JSON Parsing Error: " + jsonException.getMessage()); - android.util.Log.e("BantuanActivity", "Invalid JSON received: " + (jsonResponse.length() > 500 ? jsonResponse.substring(0, 500) + "..." : jsonResponse)); - jsonException.printStackTrace(); - mainHandler.post(() -> { - showLoading(false); - android.widget.Toast.makeText(this, "Error parsing JSON: " + jsonException.getMessage(), android.widget.Toast.LENGTH_LONG).show(); - }); } catch (Exception e) { - android.util.Log.e("BantuanActivity", "General parsing error: " + e.getMessage()); - e.printStackTrace(); mainHandler.post(() -> { - showLoading(false); - android.widget.Toast.makeText(this, "Error parsing data: " + e.getMessage(), android.widget.Toast.LENGTH_SHORT).show(); + android.widget.Toast.makeText(this, "Error parsing data: " + e.getMessage(), + android.widget.Toast.LENGTH_LONG).show(); }); - } finally { - android.util.Log.d("BantuanActivity", "=== END parseTicketData ==="); } } private void populateRiwayatContent() { - android.util.Log.d("BantuanActivity", "=== START populateRiwayatContent ==="); + if (riwayatContainer == null) return; - if (riwayatContainer == null) { - android.util.Log.e("BantuanActivity", "riwayatContainer is null!"); - return; - } + riwayatContainer.removeAllViews(); if (ticketList.isEmpty()) { - android.util.Log.w("BantuanActivity", "ticketList is empty!"); - // Show empty state message - riwayatContainer.removeAllViews(); - - TextView emptyText = new TextView(this); - emptyText.setLayoutParams(new LinearLayout.LayoutParams( - LinearLayout.LayoutParams.MATCH_PARENT, - LinearLayout.LayoutParams.WRAP_CONTENT - )); - emptyText.setText("Belum ada data riwayat"); - emptyText.setTextSize(16); - emptyText.setGravity(android.view.Gravity.CENTER); - emptyText.setPadding(dpToPx(16), dpToPx(32), dpToPx(16), dpToPx(32)); - emptyText.setTextColor(ContextCompat.getColor(this, android.R.color.darker_gray)); - - riwayatContainer.addView(emptyText); - android.util.Log.d("BantuanActivity", "Empty state message added"); + showEmptyMessage(); return; } - try { - android.util.Log.d("BantuanActivity", "Clearing existing content..."); - // Clear existing content - riwayatContainer.removeAllViews(); + for (int i = 0; i < ticketList.size(); i++) { + TicketData ticket = ticketList.get(i); + LinearLayout historyItem = createHistoryItem(ticket); - android.util.Log.d("BantuanActivity", "Creating " + ticketList.size() + " history items..."); - - for (int i = 0; i < ticketList.size(); i++) { - TicketData ticket = ticketList.get(i); - android.util.Log.d("BantuanActivity", "Creating item " + (i+1) + ": " + ticket.ticketCode); + if (historyItem != null) { + riwayatContainer.addView(historyItem); - // Create history item layout - LinearLayout historyItem = createHistoryItem(ticket); - if (historyItem != null) { - riwayatContainer.addView(historyItem); - android.util.Log.d("BantuanActivity", "Item " + (i+1) + " added successfully"); - - // Add separator (except for last item) - if (i < ticketList.size() - 1) { - View separator = new View(this); - separator.setLayoutParams(new LinearLayout.LayoutParams( - LinearLayout.LayoutParams.MATCH_PARENT, - 1 - )); - separator.setBackgroundColor(Color.parseColor("#e0e0e0")); - riwayatContainer.addView(separator); - android.util.Log.d("BantuanActivity", "Separator " + (i+1) + " added"); - } - } else { - android.util.Log.e("BantuanActivity", "Failed to create item " + (i+1)); + // Add separator except for last item + if (i < ticketList.size() - 1) { + View separator = new View(this); + separator.setLayoutParams(new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, 1)); + separator.setBackgroundColor(Color.parseColor("#e0e0e0")); + riwayatContainer.addView(separator); } } - - android.util.Log.d("BantuanActivity", "All items created successfully. Total children in container: " + riwayatContainer.getChildCount()); - - // Force layout refresh - riwayatContainer.requestLayout(); - - } catch (Exception e) { - e.printStackTrace(); - android.util.Log.e("BantuanActivity", "Error populating riwayat content: " + e.getMessage()); - - // Show error message in UI - riwayatContainer.removeAllViews(); - TextView errorText = new TextView(this); - errorText.setLayoutParams(new LinearLayout.LayoutParams( - LinearLayout.LayoutParams.MATCH_PARENT, - LinearLayout.LayoutParams.WRAP_CONTENT - )); - errorText.setText("Error menampilkan data: " + e.getMessage()); - errorText.setTextSize(14); - errorText.setGravity(android.view.Gravity.CENTER); - errorText.setPadding(dpToPx(16), dpToPx(32), dpToPx(16), dpToPx(32)); - errorText.setTextColor(ContextCompat.getColor(this, android.R.color.holo_red_dark)); - riwayatContainer.addView(errorText); } - - android.util.Log.d("BantuanActivity", "=== END populateRiwayatContent ==="); } private LinearLayout createHistoryItem(TicketData ticket) { + LinearLayout mainLayout = new LinearLayout(this); + mainLayout.setLayoutParams(new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.WRAP_CONTENT)); + mainLayout.setOrientation(LinearLayout.VERTICAL); + mainLayout.setPadding(dpToPx(16), dpToPx(16), dpToPx(16), dpToPx(16)); + mainLayout.setBackgroundColor(Color.WHITE); + + // Header (date and status) + LinearLayout headerLayout = new LinearLayout(this); + headerLayout.setLayoutParams(new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.WRAP_CONTENT)); + headerLayout.setOrientation(LinearLayout.HORIZONTAL); + + // Date + TextView dateText = new TextView(this); + LinearLayout.LayoutParams dateParams = new LinearLayout.LayoutParams( + 0, LinearLayout.LayoutParams.WRAP_CONTENT, 1.0f); + dateText.setLayoutParams(dateParams); + dateText.setText(formatDate(ticket.createdAt)); + dateText.setTextSize(16); + dateText.setTypeface(null, android.graphics.Typeface.BOLD); + + // Status + TextView statusText = new TextView(this); + statusText.setLayoutParams(new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.WRAP_CONTENT, + LinearLayout.LayoutParams.WRAP_CONTENT)); + statusText.setText(formatStatus(ticket.status)); + statusText.setTextSize(14); + statusText.setTextColor(getStatusColor(ticket.status)); + + headerLayout.addView(dateText); + headerLayout.addView(statusText); + + // Ticket code + TextView ticketCodeText = new TextView(this); + LinearLayout.LayoutParams ticketParams = new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.WRAP_CONTENT); + ticketParams.setMargins(0, dpToPx(4), 0, 0); + ticketCodeText.setLayoutParams(ticketParams); + ticketCodeText.setText("Nomor tiket: " + ticket.ticketCode); + ticketCodeText.setTextSize(14); + ticketCodeText.setTextColor(ContextCompat.getColor(this, android.R.color.darker_gray)); + + // Issue name + TextView issueText = new TextView(this); + LinearLayout.LayoutParams issueParams = new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.WRAP_CONTENT); + issueParams.setMargins(0, dpToPx(8), 0, 0); + issueText.setLayoutParams(issueParams); + issueText.setText(ticket.issueName); + issueText.setTextSize(16); + + mainLayout.addView(headerLayout); + mainLayout.addView(ticketCodeText); + mainLayout.addView(issueText); + + return mainLayout; + } + + private void showLoadingMessage() { + if (riwayatContainer == null) return; + + riwayatContainer.removeAllViews(); + + TextView loadingText = new TextView(this); + loadingText.setLayoutParams(new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.WRAP_CONTENT)); + loadingText.setText("Memuat data..."); + loadingText.setTextSize(16); + loadingText.setGravity(android.view.Gravity.CENTER); + loadingText.setPadding(dpToPx(16), dpToPx(32), dpToPx(16), dpToPx(32)); + loadingText.setTextColor(ContextCompat.getColor(this, android.R.color.darker_gray)); + + riwayatContainer.addView(loadingText); + } + + private void showEmptyMessage() { + TextView emptyText = new TextView(this); + emptyText.setLayoutParams(new LinearLayout.LayoutParams( + LinearLayout.LayoutParams.MATCH_PARENT, + LinearLayout.LayoutParams.WRAP_CONTENT)); + emptyText.setText("Belum ada data riwayat"); + emptyText.setTextSize(16); + emptyText.setGravity(android.view.Gravity.CENTER); + emptyText.setPadding(dpToPx(16), dpToPx(32), dpToPx(16), dpToPx(32)); + emptyText.setTextColor(ContextCompat.getColor(this, android.R.color.darker_gray)); + + riwayatContainer.addView(emptyText); + } + + private void openWhatsAppCS() { try { - android.util.Log.d("BantuanActivity", "Creating history item for ticket: " + ticket.ticketCode); + JSONObject userData = LoginActivity.getUserDataAsJson(this); + String userName = "User"; + String userEmail = ""; - LinearLayout mainLayout = new LinearLayout(this); - mainLayout.setLayoutParams(new LinearLayout.LayoutParams( - LinearLayout.LayoutParams.MATCH_PARENT, - LinearLayout.LayoutParams.WRAP_CONTENT - )); - mainLayout.setOrientation(LinearLayout.VERTICAL); - mainLayout.setPadding(dpToPx(16), dpToPx(16), dpToPx(16), dpToPx(16)); - mainLayout.setBackgroundColor(Color.WHITE); + if (userData != null) { + userName = userData.optString("name", "User"); + userEmail = userData.optString("email", ""); + } - // Header layout (date and status) - LinearLayout headerLayout = new LinearLayout(this); - headerLayout.setLayoutParams(new LinearLayout.LayoutParams( - LinearLayout.LayoutParams.MATCH_PARENT, - LinearLayout.LayoutParams.WRAP_CONTENT - )); - headerLayout.setOrientation(LinearLayout.HORIZONTAL); + String phoneNumber = "+6281234567890"; // Update with actual CS number + String message = "Halo, saya " + userName; + if (!userEmail.isEmpty()) { + message += " (" + userEmail + ")"; + } + message += " butuh bantuan terkait Payvora PRO"; - // Date TextView - TextView dateText = new TextView(this); - LinearLayout.LayoutParams dateParams = new LinearLayout.LayoutParams( - 0, LinearLayout.LayoutParams.WRAP_CONTENT, 1.0f - ); - dateText.setLayoutParams(dateParams); - String formattedDate = formatDate(ticket.createdAt); - dateText.setText(formattedDate); - dateText.setTextSize(16); - dateText.setTypeface(null, android.graphics.Typeface.BOLD); - android.util.Log.d("BantuanActivity", "Date formatted: " + ticket.createdAt + " -> " + formattedDate); - - // Status TextView - TextView statusText = new TextView(this); - statusText.setLayoutParams(new LinearLayout.LayoutParams( - LinearLayout.LayoutParams.WRAP_CONTENT, - LinearLayout.LayoutParams.WRAP_CONTENT - )); - String formattedStatus = formatStatus(ticket.status); - int statusColor = getStatusColor(ticket.status); - statusText.setText(formattedStatus); - statusText.setTextSize(14); - statusText.setTextColor(statusColor); - android.util.Log.d("BantuanActivity", "Status formatted: " + ticket.status + " -> " + formattedStatus); - - headerLayout.addView(dateText); - headerLayout.addView(statusText); - - // Ticket code TextView - TextView ticketCodeText = new TextView(this); - LinearLayout.LayoutParams ticketParams = new LinearLayout.LayoutParams( - LinearLayout.LayoutParams.MATCH_PARENT, - LinearLayout.LayoutParams.WRAP_CONTENT - ); - ticketParams.setMargins(0, dpToPx(4), 0, 0); - ticketCodeText.setLayoutParams(ticketParams); - ticketCodeText.setText("Nomor tiket: " + ticket.ticketCode); - ticketCodeText.setTextSize(14); - ticketCodeText.setTextColor(ContextCompat.getColor(this, android.R.color.darker_gray)); - - // Issue name TextView - TextView issueText = new TextView(this); - LinearLayout.LayoutParams issueParams = new LinearLayout.LayoutParams( - LinearLayout.LayoutParams.MATCH_PARENT, - LinearLayout.LayoutParams.WRAP_CONTENT - ); - issueParams.setMargins(0, dpToPx(8), 0, 0); - issueText.setLayoutParams(issueParams); - issueText.setText(ticket.issueName); - issueText.setTextSize(16); - - mainLayout.addView(headerLayout); - mainLayout.addView(ticketCodeText); - mainLayout.addView(issueText); - - android.util.Log.d("BantuanActivity", "History item created successfully for: " + ticket.ticketCode); - return mainLayout; + Intent intent = new Intent(Intent.ACTION_VIEW); + intent.setData(android.net.Uri.parse("https://wa.me/" + phoneNumber + "?text=" + + android.net.Uri.encode(message))); + startActivity(intent); } catch (Exception e) { - android.util.Log.e("BantuanActivity", "Error creating history item for ticket " + ticket.ticketCode + ": " + e.getMessage()); - e.printStackTrace(); - return null; + android.widget.Toast.makeText(this, "Error opening WhatsApp: " + e.getMessage(), + android.widget.Toast.LENGTH_SHORT).show(); } } + // ✅ Utility methods private String formatDate(String isoDate) { try { SimpleDateFormat inputFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.getDefault()); @@ -740,38 +462,27 @@ public class BantuanActivity extends AppCompatActivity { Date date = inputFormat.parse(isoDate); return outputFormat.format(date); } catch (Exception e) { - android.util.Log.e("BantuanActivity", "Error formatting date: " + e.getMessage()); - return isoDate.substring(0, 10); // fallback to YYYY-MM-DD + return isoDate.length() > 10 ? isoDate.substring(0, 10) : isoDate; } } private String formatStatus(String status) { switch (status.toLowerCase()) { - case "new": - return "Pengajuan"; - case "on_progres": - return "Proses"; - case "done": - return "Selesai"; - case "cancel": - return "Cancel"; - default: - return status; + case "new": return "Pengajuan"; + case "on_progres": return "Proses"; + case "done": return "Selesai"; + case "cancel": return "Cancel"; + default: return status; } } private int getStatusColor(String status) { switch (status.toLowerCase()) { - case "new": - return ContextCompat.getColor(this, android.R.color.holo_blue_light); - case "on_progres": - return ContextCompat.getColor(this, android.R.color.holo_orange_light); - case "done": - return ContextCompat.getColor(this, android.R.color.holo_green_dark); - case "cancel": - return ContextCompat.getColor(this, android.R.color.holo_red_dark); - default: - return ContextCompat.getColor(this, android.R.color.black); + case "new": return ContextCompat.getColor(this, android.R.color.holo_blue_light); + case "on_progres": return ContextCompat.getColor(this, android.R.color.holo_orange_light); + case "done": return ContextCompat.getColor(this, android.R.color.holo_green_dark); + case "cancel": return ContextCompat.getColor(this, android.R.color.holo_red_dark); + default: return ContextCompat.getColor(this, android.R.color.black); } } @@ -780,106 +491,12 @@ public class BantuanActivity extends AppCompatActivity { return Math.round(dp * density); } - private void showLoading(boolean show) { - android.util.Log.d("BantuanActivity", "Loading state: " + show); - // You can implement a loading indicator here if needed - // For example, you can show/hide a progress bar - } - - // Debug helper methods - private void checkNetworkConnection() { - try { - android.net.ConnectivityManager cm = (android.net.ConnectivityManager) getSystemService(android.content.Context.CONNECTIVITY_SERVICE); - android.net.NetworkInfo activeNetwork = cm.getActiveNetworkInfo(); - boolean isConnected = activeNetwork != null && activeNetwork.isConnectedOrConnecting(); - android.util.Log.d("BantuanActivity", "Network connected: " + isConnected); - - if (activeNetwork != null) { - android.util.Log.d("BantuanActivity", "Network type: " + activeNetwork.getTypeName()); - android.util.Log.d("BantuanActivity", "Network subtype: " + activeNetwork.getSubtypeName()); - } - } catch (Exception e) { - android.util.Log.e("BantuanActivity", "Error checking network: " + e.getMessage()); - } - } - - private void testSimpleHttpConnection() { - android.util.Log.d("BantuanActivity", "Testing simple HTTP connection..."); - executor.execute(() -> { - try { - java.net.URL url = new java.net.URL("https://httpbin.org/get"); - java.net.HttpURLConnection connection = (java.net.HttpURLConnection) url.openConnection(); - connection.setRequestMethod("GET"); - connection.setConnectTimeout(5000); - connection.setReadTimeout(5000); - - int responseCode = connection.getResponseCode(); - android.util.Log.d("BantuanActivity", "Test connection response: " + responseCode); - connection.disconnect(); - - if (responseCode == 200) { - android.util.Log.d("BantuanActivity", "Basic HTTP connection works fine"); - } else { - android.util.Log.w("BantuanActivity", "Basic HTTP connection returned: " + responseCode); - } - } catch (Exception e) { - android.util.Log.e("BantuanActivity", "Test connection failed: " + e.getMessage()); - e.printStackTrace(); - } - }); - } - - private void debugLayoutHierarchy() { - android.util.Log.d("BantuanActivity", "=== Layout Debug Info ==="); - android.util.Log.d("BantuanActivity", "contentRiwayat: " + (contentRiwayat != null ? "OK" : "NULL")); - - if (contentRiwayat != null) { - android.util.Log.d("BantuanActivity", "contentRiwayat visibility: " + contentRiwayat.getVisibility()); - android.util.Log.d("BantuanActivity", "contentRiwayat childCount: " + contentRiwayat.getChildCount()); - - if (contentRiwayat.getChildCount() > 0) { - android.view.View child = contentRiwayat.getChildAt(0); - android.util.Log.d("BantuanActivity", "First child type: " + child.getClass().getSimpleName()); - - if (child instanceof LinearLayout) { - LinearLayout childLinear = (LinearLayout) child; - android.util.Log.d("BantuanActivity", "Child LinearLayout childCount: " + childLinear.getChildCount()); - } - } - } - - android.util.Log.d("BantuanActivity", "riwayatContainer: " + (riwayatContainer != null ? "OK" : "NULL")); - if (riwayatContainer != null) { - android.util.Log.d("BantuanActivity", "riwayatContainer childCount: " + riwayatContainer.getChildCount()); - } - - android.util.Log.d("BantuanActivity", "ticketList size: " + ticketList.size()); - android.util.Log.d("BantuanActivity", "isUmumTabActive: " + isUmumTabActive); - android.util.Log.d("BantuanActivity", "========================="); - } - - private void openWhatsAppCS() { - // Implementasi untuk membuka WhatsApp CS - // Contoh: buka WhatsApp dengan nomor tertentu - try { - String phoneNumber = "+6281234567890"; // Ganti dengan nomor CS yang sesuai - String message = "Halo, saya butuh bantuan terkait Payvora PRO"; - - Intent intent = new Intent(Intent.ACTION_VIEW); - intent.setData(android.net.Uri.parse("https://wa.me/" + phoneNumber + "?text=" + - android.net.Uri.encode(message))); - startActivity(intent); - } catch (Exception e) { - // Fallback jika WhatsApp tidak terinstall - // Bisa tampilkan dialog atau buka browser - e.printStackTrace(); - } - } - @Override - public void onBackPressed() { - super.onBackPressed(); - finish(); + protected void onResume() { + super.onResume(); + if (!LoginActivity.isLoggedIn(this)) { + finish(); + } } @Override diff --git a/app/src/main/res/layout/activity_bantuan_riwayat.xml b/app/src/main/res/layout/activity_bantuan_riwayat.xml deleted file mode 100644 index 703e7fe..0000000 --- a/app/src/main/res/layout/activity_bantuan_riwayat.xml +++ /dev/null @@ -1,488 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/activity_bantuan_umum.xml b/app/src/main/res/layout/activity_bantuan_umum.xml deleted file mode 100644 index 5f0d9d6..0000000 --- a/app/src/main/res/layout/activity_bantuan_umum.xml +++ /dev/null @@ -1,498 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..28cbd1b --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,211 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index d7fd674..0c539b9 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -28,81 +28,180 @@ - + - + + + + + android:layout_marginBottom="8dp" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintEnd_toStartOf="@id/logout_button" + app:layout_constraintHorizontal_bias="0" /> + + android:gravity="center" + android:layout_marginTop="8dp" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toBottomOf="@id/logo_payvora" /> + + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toBottomOf="@id/tv_store_name" /> + + + + + + + + + + + + + android:background="#EEEEEE" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toBottomOf="@id/user_info_section" /> + + android:gravity="center" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toBottomOf="@id/divider"> + android:layout_marginEnd="16dp" /> + android:textSize="14sp" /> + - + + +