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 db50b89..da778e9 100644 --- a/app/src/main/java/com/example/bdkipoc/bantuan/BantuanActivity.java +++ b/app/src/main/java/com/example/bdkipoc/bantuan/BantuanActivity.java @@ -24,6 +24,8 @@ import java.net.HttpURLConnection; import java.net.URL; import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; import java.util.Date; import java.util.List; import java.util.Locale; @@ -45,15 +47,44 @@ public class BantuanActivity extends AppCompatActivity { private ExecutorService executor = Executors.newSingleThreadExecutor(); private Handler mainHandler = new Handler(Looper.getMainLooper()); - // ✅ Simplified TicketData class + // ✅ Enhanced TicketData class with date parsing public static class TicketData { public String createdAt, ticketCode, issueName, status; + public Date parsedDate; // Added for sorting public TicketData(String createdAt, String ticketCode, String issueName, String status) { this.createdAt = createdAt; this.ticketCode = ticketCode; this.issueName = issueName; this.status = status; + this.parsedDate = parseDate(createdAt); + } + + // Parse date from ISO format to Date object + private Date parseDate(String dateString) { + try { + // Try different date formats + SimpleDateFormat[] formats = { + new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.getDefault()), + new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.getDefault()), + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()), + new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()) + }; + + for (SimpleDateFormat format : formats) { + try { + return format.parse(dateString); + } catch (Exception e) { + // Continue to next format + } + } + + // If all parsing fails, return current date + return new Date(); + + } catch (Exception e) { + return new Date(); // Fallback to current date + } } } @@ -234,7 +265,7 @@ public class BantuanActivity extends AppCompatActivity { }); } - // ✅ Simplified JSON parsing + // ✅ Enhanced JSON parsing with sorting private void parseTicketData(String jsonResponse) { try { JSONObject jsonObject = new JSONObject(jsonResponse); @@ -280,6 +311,9 @@ public class BantuanActivity extends AppCompatActivity { } } + // ✅ Sort by date - newest first + sortTicketsByDate(newTicketList); + mainHandler.post(() -> { ticketList.clear(); ticketList.addAll(newTicketList); @@ -300,6 +334,26 @@ public class BantuanActivity extends AppCompatActivity { } } + // ✅ New method to sort tickets by date (newest first) + private void sortTicketsByDate(List tickets) { + Collections.sort(tickets, new Comparator() { + @Override + public int compare(TicketData ticket1, TicketData ticket2) { + // Sort by parsedDate in descending order (newest first) + if (ticket1.parsedDate == null && ticket2.parsedDate == null) { + return 0; + } else if (ticket1.parsedDate == null) { + return 1; // null dates go to the end + } else if (ticket2.parsedDate == null) { + return -1; // null dates go to the end + } else { + // Compare dates in descending order (newest first) + return ticket2.parsedDate.compareTo(ticket1.parsedDate); + } + } + }); + } + private void populateRiwayatContent() { if (riwayatContainer == null) return; @@ -310,9 +364,10 @@ public class BantuanActivity extends AppCompatActivity { return; } + // ✅ Data is already sorted, just populate the UI for (int i = 0; i < ticketList.size(); i++) { TicketData ticket = ticketList.get(i); - LinearLayout historyItem = createHistoryItem(ticket); + LinearLayout historyItem = createHistoryItem(ticket, i); if (historyItem != null) { riwayatContainer.addView(historyItem); @@ -329,7 +384,8 @@ public class BantuanActivity extends AppCompatActivity { } } - private LinearLayout createHistoryItem(TicketData ticket) { + // ✅ Enhanced createHistoryItem with position indicator + private LinearLayout createHistoryItem(TicketData ticket, int position) { LinearLayout mainLayout = new LinearLayout(this); mainLayout.setLayoutParams(new LinearLayout.LayoutParams( LinearLayout.LayoutParams.MATCH_PARENT, @@ -345,12 +401,18 @@ public class BantuanActivity extends AppCompatActivity { LinearLayout.LayoutParams.WRAP_CONTENT)); headerLayout.setOrientation(LinearLayout.HORIZONTAL); - // Date + // Date with "Terbaru" indicator for first item 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)); + + String dateDisplay = formatDate(ticket.createdAt); + if (position == 0) { + dateDisplay += " (Terbaru)"; + dateText.setTextColor(Color.parseColor("#DE0701")); + } + dateText.setText(dateDisplay); dateText.setTextSize(16); dateText.setTypeface(null, android.graphics.Typeface.BOLD); @@ -498,6 +560,8 @@ public class BantuanActivity extends AppCompatActivity { if (!LoginActivity.isLoggedIn(this)) { finish(); } + // ✅ Refresh data when returning from form + loadTicketData(); } @Override diff --git a/app/src/main/java/com/example/bdkipoc/bantuan/BantuanFormActivity.java b/app/src/main/java/com/example/bdkipoc/bantuan/BantuanFormActivity.java index f422d39..feea10c 100644 --- a/app/src/main/java/com/example/bdkipoc/bantuan/BantuanFormActivity.java +++ b/app/src/main/java/com/example/bdkipoc/bantuan/BantuanFormActivity.java @@ -20,6 +20,7 @@ import androidx.activity.result.contract.ActivityResultContracts; import com.example.bdkipoc.R; import com.example.bdkipoc.LoginActivity; +import android.util.Log; import org.json.JSONArray; import org.json.JSONObject; @@ -39,12 +40,16 @@ import java.util.concurrent.Executors; public class BantuanFormActivity extends AppCompatActivity { + private static final String TAG = "BantuanFormActivity"; + // UI Components private EditText etTicketCode; private Spinner spinnerSource, spinnerIssue, spinnerMerchant, spinnerAssign, spinnerResolvedDate; private TextView tvStatus; private Button btnKirim; private LinearLayout backNavigation; + private LinearLayout successScreen; + private LinearLayout mainContent; // Data private String selectedResolvedDate = ""; @@ -97,6 +102,10 @@ public class BantuanFormActivity extends AppCompatActivity { } private void initViews() { + // Main content containers + mainContent = findViewById(R.id.main_content); + successScreen = findViewById(R.id.success_screen); + // Form fields etTicketCode = findViewById(R.id.et_ticket_code); @@ -223,6 +232,39 @@ public class BantuanFormActivity extends AppCompatActivity { }); } + private void showSuccessScreen() { + Log.d(TAG, "Showing success screen"); + + // Hide main content and show success screen + if (mainContent != null) { + mainContent.setVisibility(View.GONE); + } + if (successScreen != null) { + successScreen.setVisibility(View.VISIBLE); + } + + // Navigate back to BantuanActivity after 2 seconds + new Handler(Looper.getMainLooper()).postDelayed(() -> { + navigateToBantuanActivity(); + }, 2000); + } + + private void navigateToBantuanActivity() { + Log.d(TAG, "Navigating back to BantuanActivity"); + + try { + // Create intent to BantuanActivity + Intent intent = new Intent(this, Class.forName("com.example.bdkipoc.bantuan.BantuanActivity")); + intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(intent); + finish(); + } catch (ClassNotFoundException e) { + Log.e(TAG, "BantuanActivity class not found", e); + // Fallback: just finish current activity + finish(); + } + } + private void loadUsers() { String authToken = LoginActivity.getToken(this); if (authToken == null || authToken.isEmpty()) { @@ -579,9 +621,12 @@ public class BantuanFormActivity extends AppCompatActivity { private void submitForm() { if (!validateForm()) { + Log.w(TAG, "Form validation failed"); return; } + Log.d(TAG, "Form validation passed, preparing data..."); + // Disable button and show loading btnKirim.setEnabled(false); btnKirim.setText("Mengirim..."); @@ -593,6 +638,33 @@ public class BantuanFormActivity extends AppCompatActivity { int merchantId = getMerchantId(spinnerMerchant.getSelectedItemPosition()); int assignId = getAssignId(spinnerAssign.getSelectedItemPosition()); + // Validate IDs + if (sourceId == 0) { + Log.e(TAG, "Invalid source ID: " + sourceId + ", position: " + spinnerSource.getSelectedItemPosition()); + Toast.makeText(this, "Error: Source tidak valid", Toast.LENGTH_SHORT).show(); + btnKirim.setEnabled(true); + btnKirim.setText("Kirim Sekarang"); + return; + } + + if (issueId == 0) { + Log.e(TAG, "Invalid issue ID: " + issueId + ", position: " + spinnerIssue.getSelectedItemPosition()); + Toast.makeText(this, "Error: Issue tidak valid", Toast.LENGTH_SHORT).show(); + btnKirim.setEnabled(true); + btnKirim.setText("Kirim Sekarang"); + return; + } + + if (assignId == 0) { + Log.e(TAG, "Invalid assign ID: " + assignId + ", position: " + spinnerAssign.getSelectedItemPosition()); + Toast.makeText(this, "Error: Assign To tidak valid", Toast.LENGTH_SHORT).show(); + btnKirim.setEnabled(true); + btnKirim.setText("Kirim Sekarang"); + return; + } + + Log.d(TAG, "All IDs validated successfully"); + submitToAPI(ticketCode, sourceId, issueId, merchantId, assignId, selectedResolvedDate); } @@ -641,8 +713,17 @@ public class BantuanFormActivity extends AppCompatActivity { private void submitToAPI(String ticketCode, int sourceId, int issueId, int merchantId, int assignId, String resolvedAt) { + Log.d(TAG, "Starting API submission..."); + Log.d(TAG, "Ticket Code: " + ticketCode); + Log.d(TAG, "Source ID: " + sourceId); + Log.d(TAG, "Issue ID: " + issueId); + Log.d(TAG, "Merchant ID: " + merchantId); + Log.d(TAG, "Assign ID: " + assignId); + Log.d(TAG, "Resolved At: " + resolvedAt); + String authToken = LoginActivity.getToken(this); if (authToken == null || authToken.isEmpty()) { + Log.e(TAG, "Auth token is null or empty"); mainHandler.post(() -> { btnKirim.setEnabled(true); btnKirim.setText("Kirim Sekarang"); @@ -651,6 +732,8 @@ public class BantuanFormActivity extends AppCompatActivity { return; } + Log.d(TAG, "Auth token obtained: " + authToken.substring(0, Math.min(authToken.length(), 10)) + "..."); + executor.execute(() -> { HttpURLConnection connection = null; try { @@ -675,13 +758,18 @@ public class BantuanFormActivity extends AppCompatActivity { payload.put("assigned_to", assignId); payload.put("resolved_at", resolvedAt); + String jsonPayload = payload.toString(); + Log.d(TAG, "JSON Payload: " + jsonPayload); + // Send request try (OutputStream os = connection.getOutputStream()) { - byte[] input = payload.toString().getBytes("utf-8"); + byte[] input = jsonPayload.getBytes("utf-8"); os.write(input, 0, input.length); + Log.d(TAG, "Request sent successfully"); } int responseCode = connection.getResponseCode(); + Log.d(TAG, "Response Code: " + responseCode); // Read response BufferedReader reader; @@ -698,6 +786,9 @@ public class BantuanFormActivity extends AppCompatActivity { } reader.close(); + String responseBody = response.toString(); + Log.d(TAG, "Response Body: " + responseBody); + // Handle response mainHandler.post(() -> { btnKirim.setEnabled(true); @@ -705,30 +796,34 @@ public class BantuanFormActivity extends AppCompatActivity { if (responseCode >= 200 && responseCode < 300) { // Success + Log.d(TAG, "Request successful"); try { - JSONObject responseJson = new JSONObject(response.toString()); + JSONObject responseJson = new JSONObject(responseBody); String message = responseJson.optString("message", "Tiket berhasil dibuat"); - Toast.makeText(this, message, Toast.LENGTH_LONG).show(); - - // Clear form - clearForm(); + // Show success screen instead of toast + showSuccessScreen(); } catch (Exception e) { - Toast.makeText(this, "Tiket berhasil dikirim!", Toast.LENGTH_LONG).show(); - clearForm(); + Log.e(TAG, "Error parsing success response", e); + // Show success screen even if parsing fails + showSuccessScreen(); } } else if (responseCode == 401) { + Log.e(TAG, "Unauthorized - token expired"); Toast.makeText(this, "Session expired. Please login again.", Toast.LENGTH_LONG).show(); LoginActivity.logout(this); } else { // Error + Log.e(TAG, "Request failed with code: " + responseCode); + Log.e(TAG, "Error response: " + responseBody); try { - JSONObject errorJson = new JSONObject(response.toString()); + JSONObject errorJson = new JSONObject(responseBody); String errorMessage = errorJson.optString("message", "Gagal mengirim tiket"); Toast.makeText(this, errorMessage, Toast.LENGTH_LONG).show(); } catch (Exception e) { + Log.e(TAG, "Error parsing error response", e); Toast.makeText(this, "Gagal mengirim tiket. Error: " + responseCode, Toast.LENGTH_LONG).show(); } @@ -736,6 +831,7 @@ public class BantuanFormActivity extends AppCompatActivity { }); } catch (Exception e) { + Log.e(TAG, "Network error during submission", e); mainHandler.post(() -> { btnKirim.setEnabled(true); btnKirim.setText("Kirim Sekarang"); diff --git a/app/src/main/res/layout/activity_bantuan_form.xml b/app/src/main/res/layout/activity_bantuan_form.xml index b2a20ae..5361c84 100644 --- a/app/src/main/res/layout/activity_bantuan_form.xml +++ b/app/src/main/res/layout/activity_bantuan_form.xml @@ -1,234 +1,284 @@ - - - - - - + + android:layout_height="match_parent" + android:orientation="vertical" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent"> - + + + + + android:layout_height="0dp" + android:layout_weight="1" + android:paddingHorizontal="16dp" + android:paddingTop="16dp"> - - + android:orientation="vertical"> - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + android:layout_marginBottom="16dp" + app:cardCornerRadius="12dp" + app:cardElevation="2dp" + app:cardBackgroundColor="@android:color/white"> + android:orientation="vertical" + android:padding="20dp"> + + + + + android:textColor="#666666" + android:layout_marginBottom="24dp" + android:lineSpacingExtra="2dp" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + - + - - + - + + - - - +