Sorting List

This commit is contained in:
riz081 2025-06-13 09:29:35 +07:00
parent eddade3200
commit d4245c5906
2 changed files with 63 additions and 43 deletions

View File

@ -45,6 +45,7 @@ import java.util.Date;
import java.util.Locale; import java.util.Locale;
import java.util.Calendar; import java.util.Calendar;
import java.util.Collections; import java.util.Collections;
import java.util.TimeZone;
import android.app.DatePickerDialog; import android.app.DatePickerDialog;
import android.widget.DatePicker; import android.widget.DatePicker;
@ -445,13 +446,13 @@ public class TransactionActivity extends AppCompatActivity implements Transactio
filteredList.clear(); filteredList.clear();
if (query.isEmpty()) { if (query.isEmpty()) {
// NO SEARCH: Show current API page data (already sorted) // NO SEARCH: Show current API page data (maintain sorting from API)
filteredList.addAll(transactionList); filteredList.addAll(transactionList);
totalRecords = totalRecords; // Use API total totalRecords = totalRecords; // Use API total
totalPages = (int) Math.ceil((double) totalRecords / itemsPerPage); totalPages = (int) Math.ceil((double) totalRecords / itemsPerPage);
// VERIFY FILTERED LIST ORDER // PASTIKAN TIDAK PERLU SORT LAGI karena sudah sorted dari API response
Log.d("TransactionActivity", "📋 FILTERED LIST ORDER (no search):"); Log.d("TransactionActivity", "📋 FILTERED LIST ORDER (no search - maintaining API order):");
for (int i = 0; i < Math.min(5, filteredList.size()); i++) { for (int i = 0; i < Math.min(5, filteredList.size()); i++) {
Transaction tx = filteredList.get(i); Transaction tx = filteredList.get(i);
Log.d("TransactionActivity", " " + (i+1) + ". " + tx.createdAt + " - " + tx.referenceId); Log.d("TransactionActivity", " " + (i+1) + ". " + tx.createdAt + " - " + tx.referenceId);
@ -465,7 +466,7 @@ public class TransactionActivity extends AppCompatActivity implements Transactio
} }
} }
// SORT SEARCH RESULTS by date // SORT SEARCH RESULTS by date (maintaining newest first)
Collections.sort(filteredList, (t1, t2) -> { Collections.sort(filteredList, (t1, t2) -> {
try { try {
Date date1 = parseCreatedAtDate(t1.createdAt); Date date1 = parseCreatedAtDate(t1.createdAt);
@ -687,7 +688,7 @@ public class TransactionActivity extends AppCompatActivity implements Transactio
if (error) { if (error) {
Toast.makeText(TransactionActivity.this, "Failed to fetch transactions", Toast.LENGTH_SHORT).show(); Toast.makeText(TransactionActivity.this, "Failed to fetch transactions", Toast.LENGTH_SHORT).show();
updatePaginationDisplay(); // Show current state even on error updatePaginationDisplay();
return; return;
} }
@ -696,33 +697,33 @@ public class TransactionActivity extends AppCompatActivity implements Transactio
totalRecords = apiTotal; totalRecords = apiTotal;
totalPages = (int) Math.ceil((double) totalRecords / itemsPerPage); totalPages = (int) Math.ceil((double) totalRecords / itemsPerPage);
// UPDATE TRANSACTION LIST // PERBAIKAN SORTING: Sort transactions SEBELUM menambahkan ke list
transactionList.clear(); Collections.sort(transactions, (t1, t2) -> {
transactionList.addAll(transactions);
// CRITICAL: FORCE SORT AGAIN after adding to main list
Collections.sort(filteredList, (t1, t2) -> {
try { try {
Date date1 = parseCreatedAtDate(t1.createdAt); Date date1 = parseCreatedAtDate(t1.createdAt);
Date date2 = parseCreatedAtDate(t2.createdAt); Date date2 = parseCreatedAtDate(t2.createdAt);
if (date1 != null && date2 != null) { if (date1 != null && date2 != null) {
int comparison = date2.compareTo(date1); // Newest first int comparison = date2.compareTo(date1); // Newest first
Log.d("TransactionActivity", "🔄 Final sort: " + t1.createdAt + " vs " + t2.createdAt + " = " + comparison); Log.d("TransactionActivity", "🔄 Sorting: " + t2.createdAt + " vs " + t1.createdAt + " = " + comparison);
return comparison; return comparison;
} }
} catch (Exception e) { } catch (Exception e) {
Log.w("TransactionActivity", "Date comparison error: " + e.getMessage()); Log.w("TransactionActivity", "Date comparison error: " + e.getMessage());
} }
return Integer.compare(t2.id, t1.id); // Fallback by ID return Integer.compare(t2.id, t1.id); // Fallback by ID (higher ID = newer)
}); });
// UPDATE TRANSACTION LIST dengan data yang sudah tersortir
transactionList.clear();
transactionList.addAll(transactions);
Log.d("TransactionActivity", "📋 Page " + currentPage + " loaded and sorted: " + Log.d("TransactionActivity", "📋 Page " + currentPage + " loaded and sorted: " +
transactions.size() + " transactions. Total: " + totalRecords + "/" + totalPages + " pages"); transactions.size() + " transactions. Total: " + totalRecords + "/" + totalPages + " pages");
// LOG FINAL ORDER VERIFICATION // VERIFIKASI SORTING ORDER
Log.d("TransactionActivity", "📋 FINAL DISPLAY ORDER:"); Log.d("TransactionActivity", "📋 SORTED ORDER VERIFICATION:");
for (int i = 0; i < Math.min(10, transactionList.size()); i++) { for (int i = 0; i < Math.min(5, transactionList.size()); i++) {
Transaction tx = transactionList.get(i); Transaction tx = transactionList.get(i);
Log.d("TransactionActivity", " " + (i+1) + ". " + tx.createdAt + " - " + tx.referenceId); Log.d("TransactionActivity", " " + (i+1) + ". " + tx.createdAt + " - " + tx.referenceId);
} }
@ -745,19 +746,23 @@ public class TransactionActivity extends AppCompatActivity implements Transactio
return null; return null;
} }
// List of possible date formats from API // List of possible date formats from API (urutan dari yang paling spesifik)
String[] possibleFormats = { String[] possibleFormats = {
"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", // ISO format with milliseconds "yyyy-MM-dd'T'HH:mm:ss.SSSSSS'Z'", // ISO format with microseconds (6 digits)
"yyyy-MM-dd'T'HH:mm:ss'Z'", // ISO format without milliseconds "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", // ISO format with milliseconds (3 digits)
"yyyy-MM-dd HH:mm:ss.SSS", // Standard format with milliseconds "yyyy-MM-dd'T'HH:mm:ss'Z'", // ISO format without milliseconds
"yyyy-MM-dd HH:mm:ss", // Standard format "yyyy-MM-dd HH:mm:ss.SSSSSS", // Standard format with microseconds
"yyyy-MM-dd'T'HH:mm:ss.SSSSSS'Z'" // ISO format with microseconds "yyyy-MM-dd HH:mm:ss.SSS", // Standard format with milliseconds
"yyyy-MM-dd HH:mm:ss" // Standard format
}; };
for (String format : possibleFormats) { for (String format : possibleFormats) {
try { try {
SimpleDateFormat sdf = new SimpleDateFormat(format, Locale.getDefault()); SimpleDateFormat sdf = new SimpleDateFormat(format, Locale.getDefault());
return sdf.parse(rawDate); sdf.setTimeZone(TimeZone.getTimeZone("UTC")); // Handle timezone properly
Date parsed = sdf.parse(rawDate);
Log.d("TransactionActivity", "✅ Date parsed successfully: " + rawDate + " -> " + parsed + " using format: " + format);
return parsed;
} catch (Exception e) { } catch (Exception e) {
// Continue to next format // Continue to next format
} }
@ -773,9 +778,11 @@ public class TransactionActivity extends AppCompatActivity implements Transactio
} }
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault()); SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.getDefault());
return sdf.parse(cleanedDate); Date parsed = sdf.parse(cleanedDate);
Log.d("TransactionActivity", "✅ Date parsed with fallback: " + rawDate + " -> " + parsed);
return parsed;
} catch (Exception e) { } catch (Exception e) {
Log.w("TransactionActivity", "❌ Could not parse date: " + rawDate); Log.w("TransactionActivity", "❌ Could not parse date: " + rawDate + " - Error: " + e.getMessage());
return null; return null;
} }
} }

View File

@ -87,6 +87,7 @@
</com.google.android.material.appbar.AppBarLayout> </com.google.android.material.appbar.AppBarLayout>
<!-- ✅ PERBAIKAN: Gunakan LinearLayout dengan weight distribution yang lebih baik -->
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
@ -221,44 +222,53 @@
android:layout_gravity="center_horizontal" android:layout_gravity="center_horizontal"
android:layout_marginTop="8dp" /> android:layout_marginTop="8dp" />
<!-- ✅ PERBAIKAN: RecyclerView dengan height yang tepat untuk mencegah pagination terpotong -->
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView" android:id="@+id/recyclerView"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="0dp"
android:layout_weight="1" android:layout_weight="1"
android:background="#ffffff" /> android:background="#ffffff"
android:clipToPadding="false"
android:paddingBottom="8dp" />
<!-- Pagination Controls --> <!-- ✅ PERBAIKAN: Pagination Controls dengan padding dan margin yang lebih baik -->
<LinearLayout <LinearLayout
android:id="@+id/paginationControls" android:id="@+id/paginationControls"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal" android:orientation="horizontal"
android:background="@android:color/white" android:background="@android:color/white"
android:padding="20dp" android:paddingTop="16dp"
android:paddingBottom="20dp"
android:paddingLeft="20dp"
android:paddingRight="20dp"
android:gravity="center" android:gravity="center"
android:elevation="2dp" android:elevation="4dp"
android:visibility="gone"> android:visibility="gone"
android:layout_marginTop="2dp">
<!-- First Page Button --> <!-- First Page Button -->
<ImageButton <ImageButton
android:id="@+id/btnFirstPage" android:id="@+id/btnFirstPage"
android:layout_width="44dp" android:layout_width="48dp"
android:layout_height="44dp" android:layout_height="48dp"
android:src="@android:drawable/ic_media_previous" android:src="@android:drawable/ic_media_previous"
android:contentDescription="First Page" android:contentDescription="First Page"
android:layout_marginEnd="8dp" android:layout_marginEnd="8dp"
android:scaleType="centerInside" /> android:scaleType="centerInside"
android:background="?android:attr/selectableItemBackgroundBorderless" />
<!-- Previous Page Button --> <!-- Previous Page Button -->
<ImageButton <ImageButton
android:id="@+id/btnPrevPage" android:id="@+id/btnPrevPage"
android:layout_width="44dp" android:layout_width="48dp"
android:layout_height="44dp" android:layout_height="48dp"
android:src="@android:drawable/ic_media_rew" android:src="@android:drawable/ic_media_rew"
android:contentDescription="Previous Page" android:contentDescription="Previous Page"
android:layout_marginEnd="12dp" android:layout_marginEnd="12dp"
android:scaleType="centerInside" /> android:scaleType="centerInside"
android:background="?android:attr/selectableItemBackgroundBorderless" />
<!-- Page Numbers Container --> <!-- Page Numbers Container -->
<LinearLayout <LinearLayout
@ -268,27 +278,30 @@
android:orientation="horizontal" android:orientation="horizontal"
android:gravity="center" android:gravity="center"
android:layout_marginLeft="8dp" android:layout_marginLeft="8dp"
android:layout_marginRight="8dp" /> android:layout_marginRight="8dp"
android:minHeight="48dp" />
<!-- Next Page Button --> <!-- Next Page Button -->
<ImageButton <ImageButton
android:id="@+id/btnNextPage" android:id="@+id/btnNextPage"
android:layout_width="44dp" android:layout_width="48dp"
android:layout_height="44dp" android:layout_height="48dp"
android:src="@android:drawable/ic_media_ff" android:src="@android:drawable/ic_media_ff"
android:contentDescription="Next Page" android:contentDescription="Next Page"
android:layout_marginStart="12dp" android:layout_marginStart="12dp"
android:scaleType="centerInside" /> android:scaleType="centerInside"
android:background="?android:attr/selectableItemBackgroundBorderless" />
<!-- Last Page Button --> <!-- Last Page Button -->
<ImageButton <ImageButton
android:id="@+id/btnLastPage" android:id="@+id/btnLastPage"
android:layout_width="44dp" android:layout_width="48dp"
android:layout_height="44dp" android:layout_height="48dp"
android:src="@android:drawable/ic_media_next" android:src="@android:drawable/ic_media_next"
android:contentDescription="Last Page" android:contentDescription="Last Page"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
android:scaleType="centerInside" /> android:scaleType="centerInside"
android:background="?android:attr/selectableItemBackgroundBorderless" />
</LinearLayout> </LinearLayout>