diff --git a/android/app/src/main/java/com/example/petstoremobile/api/SaleApi.java b/android/app/src/main/java/com/example/petstoremobile/api/SaleApi.java index c7261b16..fa11f100 100644 --- a/android/app/src/main/java/com/example/petstoremobile/api/SaleApi.java +++ b/android/app/src/main/java/com/example/petstoremobile/api/SaleApi.java @@ -16,13 +16,14 @@ public interface SaleApi { Call> getAllSales( @Query("page") int page, @Query("size") int size, - @Query("query") String query, + @Query("q") String query, @Query("paymentMethod") String paymentMethod, - @Query("sortBy") String sortBy); + @Query("storeId") Long storeId, + @Query("sort") String sort); @GET("api/v1/sales/{id}") Call getSaleById(@Path("id") Long id); @POST("api/v1/sales") Call createSale(@Body SaleDTO sale); -} \ No newline at end of file +} diff --git a/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/AdoptionFragment.java b/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/AdoptionFragment.java index f4757314..55b540ed 100644 --- a/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/AdoptionFragment.java +++ b/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/AdoptionFragment.java @@ -26,6 +26,7 @@ import com.example.petstoremobile.fragments.ListFragment; import com.example.petstoremobile.utils.BulkDeleteHandler; import com.example.petstoremobile.utils.Resource; import com.example.petstoremobile.utils.SpinnerUtils; +import com.example.petstoremobile.utils.UIUtils; import com.example.petstoremobile.viewmodels.AdoptionViewModel; import com.example.petstoremobile.utils.EventDecorator; import com.example.petstoremobile.viewmodels.StoreViewModel; @@ -141,20 +142,24 @@ public class AdoptionFragment extends Fragment implements AdoptionAdapter.OnAdop * Sets up the filter toggle button to show/hide the filter layout. */ private void setupFilterToggle() { - binding.btnToggleFilterAdoption.setOnClickListener(v -> { - if (binding.layoutFilterAdoption.getVisibility() == View.GONE) { - binding.layoutFilterAdoption.setVisibility(View.VISIBLE); - binding.btnToggleFilterAdoption.setImageResource(android.R.drawable.ic_menu_close_clear_cancel); - } else { - binding.layoutFilterAdoption.setVisibility(View.GONE); - binding.btnToggleFilterAdoption.setImageResource(android.R.drawable.ic_menu_search); + UIUtils.setupFilterToggle(binding.btnToggleFilterAdoption, binding.layoutFilterAdoption, + binding.etSearchAdoption, binding.spinnerStatusAdoption, binding.spinnerStoreAdoption); - // Reset filters when closing + binding.btnToggleFilterAdoption.setOnClickListener(v -> { + boolean isVisible = binding.layoutFilterAdoption.getVisibility() == View.VISIBLE; + binding.layoutFilterAdoption.setVisibility(isVisible ? View.GONE : View.VISIBLE); + + binding.btnToggleFilterAdoption.setImageResource(isVisible ? + android.R.drawable.ic_menu_search : + android.R.drawable.ic_menu_close_clear_cancel); + + if (isVisible) { binding.etSearchAdoption.setText(""); binding.spinnerStatusAdoption.setSelection(0); binding.spinnerStoreAdoption.setSelection(0); selectedCalendarDay = null; binding.calendarViewAdoption.clearSelection(); + loadAdoptions(); } }); } diff --git a/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/AnalyticsFragment.java b/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/AnalyticsFragment.java index a1e49971..54dce187 100644 --- a/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/AnalyticsFragment.java +++ b/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/AnalyticsFragment.java @@ -75,7 +75,7 @@ public class AnalyticsFragment extends Fragment { tvAvgTransaction.setText("..."); tvTotalItems.setText("..."); - RetrofitClient.getSaleApi(requireContext()).getAllSales(0, 1000, null, null, null) + RetrofitClient.getSaleApi(requireContext()).getAllSales(0, 1000, null, null, null, "saleDate,desc") .enqueue(new Callback>() { public void onResponse(Call> c, Response> r) { diff --git a/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/AppointmentFragment.java b/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/AppointmentFragment.java index f7aed714..3907f5de 100644 --- a/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/AppointmentFragment.java +++ b/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/AppointmentFragment.java @@ -27,6 +27,7 @@ import com.example.petstoremobile.fragments.ListFragment; import com.example.petstoremobile.utils.BulkDeleteHandler; import com.example.petstoremobile.utils.Resource; import com.example.petstoremobile.utils.SpinnerUtils; +import com.example.petstoremobile.utils.UIUtils; import com.example.petstoremobile.viewmodels.AppointmentViewModel; import com.example.petstoremobile.utils.EventDecorator; import com.example.petstoremobile.viewmodels.AuthViewModel; @@ -171,21 +172,26 @@ public class AppointmentFragment extends Fragment implements AppointmentAdapter. * Sets up the filter toggle button to show/hide the filter layout. */ private void setupFilterToggle() { + UIUtils.setupFilterToggle(binding.btnToggleFilter, binding.layoutFilter, binding.etSearchAppointment, + binding.spinnerStatus, binding.spinnerStore); + + // Add additional reset logic for elements specific to this fragment binding.btnToggleFilter.setOnClickListener(v -> { - if (binding.layoutFilter.getVisibility() == View.GONE) { - binding.layoutFilter.setVisibility(View.VISIBLE); - binding.btnToggleFilter.setImageResource(android.R.drawable.ic_menu_close_clear_cancel); - } else { - binding.layoutFilter.setVisibility(View.GONE); - binding.btnToggleFilter.setImageResource(android.R.drawable.ic_menu_search); + boolean isVisible = binding.layoutFilter.getVisibility() == View.VISIBLE; + binding.layoutFilter.setVisibility(isVisible ? View.GONE : View.VISIBLE); + + binding.btnToggleFilter.setImageResource(isVisible ? + android.R.drawable.ic_menu_search : + android.R.drawable.ic_menu_close_clear_cancel); - // Reset filters when closing + if (isVisible) { binding.etSearchAppointment.setText(""); binding.spinnerStatus.setSelection(0); binding.spinnerStore.setSelection(0); binding.btnMyAppointments.setChecked(false); selectedCalendarDay = null; binding.calendarView.clearSelection(); + loadAppointmentData(); } }); } @@ -214,10 +220,11 @@ public class AppointmentFragment extends Fragment implements AppointmentAdapter. */ private void updateCalendarDecorators() { HashSet datesWithAppointments = new HashSet<>(); + SimpleDateFormat displayFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()); for (AppointmentDTO appointment : appointmentList) { try { //Get the appointment date - Date date = dateFormat.parse(appointment.getAppointmentDate()); + Date date = displayFormat.parse(appointment.getAppointmentDate()); //if the date is not null, add it to the hashset if (date != null) { Calendar cal = Calendar.getInstance(); diff --git a/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/InventoryFragment.java b/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/InventoryFragment.java index bf78e2b8..6db1cbb4 100644 --- a/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/InventoryFragment.java +++ b/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/InventoryFragment.java @@ -24,6 +24,7 @@ import com.example.petstoremobile.dtos.InventoryDTO; import com.example.petstoremobile.dtos.StoreDTO; import com.example.petstoremobile.fragments.ListFragment; import com.example.petstoremobile.utils.BulkDeleteHandler; +import com.example.petstoremobile.utils.UIUtils; import com.example.petstoremobile.viewmodels.InventoryViewModel; import com.example.petstoremobile.utils.Resource; import com.example.petstoremobile.utils.SpinnerUtils; @@ -115,19 +116,7 @@ public class InventoryFragment extends Fragment implements InventoryAdapter.OnIn * Sets up the filter toggle button to show/hide the filter layout. */ private void setupFilterToggle() { - binding.btnToggleFilter.setOnClickListener(v -> { - if (binding.layoutFilter.getVisibility() == View.GONE) { - binding.layoutFilter.setVisibility(View.VISIBLE); - binding.btnToggleFilter.setImageResource(android.R.drawable.ic_menu_close_clear_cancel); - } else { - binding.layoutFilter.setVisibility(View.GONE); - binding.btnToggleFilter.setImageResource(android.R.drawable.ic_menu_search); - - // Reset filters when closing - binding.etSearchInventory.setText(""); - binding.spinnerStore.setSelection(0); - } - }); + UIUtils.setupFilterToggle(binding.btnToggleFilter, binding.layoutFilter, binding.etSearchInventory, binding.spinnerStore); } /** diff --git a/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/PetFragment.java b/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/PetFragment.java index 096f1212..88031831 100644 --- a/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/PetFragment.java +++ b/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/PetFragment.java @@ -27,6 +27,7 @@ import com.example.petstoremobile.fragments.ListFragment; import com.example.petstoremobile.utils.BulkDeleteHandler; import com.example.petstoremobile.utils.Resource; import com.example.petstoremobile.utils.SpinnerUtils; +import com.example.petstoremobile.utils.UIUtils; import com.example.petstoremobile.viewmodels.PetViewModel; import com.example.petstoremobile.viewmodels.StoreViewModel; @@ -126,21 +127,8 @@ public class PetFragment extends Fragment implements PetAdapter.OnPetClickListen * Sets up the filter toggle button to show/hide the filter layout. */ private void setupFilterToggle() { - binding.btnToggleFilter.setOnClickListener(v -> { - if (binding.layoutFilter.getVisibility() == View.GONE) { - binding.layoutFilter.setVisibility(View.VISIBLE); - binding.btnToggleFilter.setImageResource(android.R.drawable.ic_menu_close_clear_cancel); - } else { - binding.layoutFilter.setVisibility(View.GONE); - binding.btnToggleFilter.setImageResource(android.R.drawable.ic_menu_search); - - // Reset filters when closing - binding.etSearchPet.setText(""); - binding.spinnerStatus.setSelection(0); - binding.spinnerSpecies.setSelection(0); - binding.spinnerStore.setSelection(0); - } - }); + UIUtils.setupFilterToggle(binding.btnToggleFilter, binding.layoutFilter, binding.etSearchPet, + binding.spinnerStatus, binding.spinnerSpecies, binding.spinnerStore); } /** diff --git a/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/ProductFragment.java b/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/ProductFragment.java index b2c28fee..099238f5 100644 --- a/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/ProductFragment.java +++ b/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/ProductFragment.java @@ -25,6 +25,7 @@ import com.example.petstoremobile.dtos.ProductDTO; import com.example.petstoremobile.fragments.ListFragment; import com.example.petstoremobile.utils.Resource; import com.example.petstoremobile.utils.SpinnerUtils; +import com.example.petstoremobile.utils.UIUtils; import com.example.petstoremobile.viewmodels.ProductViewModel; import java.util.ArrayList; @@ -104,19 +105,8 @@ public class ProductFragment extends Fragment implements ProductAdapter.OnProduc * Sets up the filter toggle button to show/hide the filter layout. */ private void setupFilterToggle() { - binding.btnToggleFilter.setOnClickListener(v -> { - if (binding.layoutFilter.getVisibility() == View.GONE) { - binding.layoutFilter.setVisibility(View.VISIBLE); - binding.btnToggleFilter.setImageResource(android.R.drawable.ic_menu_close_clear_cancel); - } else { - binding.layoutFilter.setVisibility(View.GONE); - binding.btnToggleFilter.setImageResource(android.R.drawable.ic_menu_search); - - // Reset filters when closing - binding.etSearchProduct.setText(""); - binding.spinnerCategory.setSelection(0); - } - }); + UIUtils.setupFilterToggle(binding.btnToggleFilter, binding.layoutFilter, + binding.etSearchProduct, binding.spinnerCategory); } /** diff --git a/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/ProductSupplierFragment.java b/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/ProductSupplierFragment.java index 578aa7a9..befec0e7 100644 --- a/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/ProductSupplierFragment.java +++ b/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/ProductSupplierFragment.java @@ -26,6 +26,7 @@ import com.example.petstoremobile.fragments.ListFragment; import com.example.petstoremobile.utils.BulkDeleteHandler; import com.example.petstoremobile.utils.Resource; import com.example.petstoremobile.utils.SpinnerUtils; +import com.example.petstoremobile.utils.UIUtils; import com.example.petstoremobile.viewmodels.ProductSupplierViewModel; import com.example.petstoremobile.viewmodels.ProductViewModel; import com.example.petstoremobile.viewmodels.SupplierViewModel; @@ -125,20 +126,8 @@ public class ProductSupplierFragment extends Fragment * Sets up the filter toggle button to show/hide the filter layout. */ private void setupFilterToggle() { - binding.btnToggleFilter.setOnClickListener(v -> { - if (binding.layoutFilter.getVisibility() == View.GONE) { - binding.layoutFilter.setVisibility(View.VISIBLE); - binding.btnToggleFilter.setImageResource(android.R.drawable.ic_menu_close_clear_cancel); - } else { - binding.layoutFilter.setVisibility(View.GONE); - binding.btnToggleFilter.setImageResource(android.R.drawable.ic_menu_search); - - // Reset filters when closing - binding.etSearchPS.setText(""); - binding.spinnerProduct.setSelection(0); - binding.spinnerSupplier.setSelection(0); - } - }); + UIUtils.setupFilterToggle(binding.btnToggleFilter, binding.layoutFilter, binding.etSearchPS, + binding.spinnerProduct, binding.spinnerSupplier); } /** diff --git a/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/PurchaseOrderFragment.java b/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/PurchaseOrderFragment.java index 9a758cb8..e5b90002 100644 --- a/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/PurchaseOrderFragment.java +++ b/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/PurchaseOrderFragment.java @@ -24,6 +24,7 @@ import com.example.petstoremobile.dtos.StoreDTO; import com.example.petstoremobile.fragments.ListFragment; import com.example.petstoremobile.utils.Resource; import com.example.petstoremobile.utils.SpinnerUtils; +import com.example.petstoremobile.utils.UIUtils; import com.example.petstoremobile.viewmodels.PurchaseOrderViewModel; import com.example.petstoremobile.viewmodels.StoreViewModel; @@ -100,19 +101,7 @@ public class PurchaseOrderFragment extends Fragment * Sets up the filter toggle button to show/hide the filter layout. */ private void setupFilterToggle() { - binding.btnToggleFilter.setOnClickListener(v -> { - if (binding.layoutFilter.getVisibility() == View.GONE) { - binding.layoutFilter.setVisibility(View.VISIBLE); - binding.btnToggleFilter.setImageResource(android.R.drawable.ic_menu_close_clear_cancel); - } else { - binding.layoutFilter.setVisibility(View.GONE); - binding.btnToggleFilter.setImageResource(android.R.drawable.ic_menu_search); - - // Reset filters when closing - binding.etSearchPO.setText(""); - binding.spinnerStore.setSelection(0); - } - }); + UIUtils.setupFilterToggle(binding.btnToggleFilter, binding.layoutFilter, binding.etSearchPO, binding.spinnerStore); } /** diff --git a/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/SaleFragment.java b/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/SaleFragment.java index 5908a5d8..3bb27748 100644 --- a/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/SaleFragment.java +++ b/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/SaleFragment.java @@ -20,13 +20,15 @@ import com.example.petstoremobile.R; import com.example.petstoremobile.adapters.SaleAdapter; import com.example.petstoremobile.databinding.FragmentSaleBinding; import com.example.petstoremobile.dtos.SaleDTO; +import com.example.petstoremobile.dtos.StoreDTO; import com.example.petstoremobile.fragments.ListFragment; import com.example.petstoremobile.utils.Resource; import com.example.petstoremobile.utils.SpinnerUtils; +import com.example.petstoremobile.utils.UIUtils; import com.example.petstoremobile.viewmodels.SaleViewModel; +import com.example.petstoremobile.viewmodels.StoreViewModel; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import dagger.hilt.android.AndroidEntryPoint; @@ -35,12 +37,14 @@ import dagger.hilt.android.AndroidEntryPoint; public class SaleFragment extends Fragment implements SaleAdapter.OnSaleClickListener { private static final String TAG = "SaleFragment"; - private static final int PAGE_SIZE = 20; + private static final int PAGE_SIZE = 200; private FragmentSaleBinding binding; private final List saleList = new ArrayList<>(); + private final List storeList = new ArrayList<>(); private SaleAdapter adapter; private SaleViewModel saleViewModel; + private StoreViewModel storeViewModel; // Pagination private int currentPage = 0; @@ -58,9 +62,11 @@ public class SaleFragment extends Fragment implements SaleAdapter.OnSaleClickLis public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); saleViewModel = new ViewModelProvider(this).get(SaleViewModel.class); + storeViewModel = new ViewModelProvider(this).get(StoreViewModel.class); setupRecyclerView(); setupSearch(); + setupStoreFilter(); setupPaymentMethodFilter(); setupSwipeRefresh(); setupFilterToggle(); @@ -83,26 +89,35 @@ public class SaleFragment extends Fragment implements SaleAdapter.OnSaleClickLis NavHostFragment.findNavController(this).navigate(R.id.nav_refund)); } + @Override + public void onResume() { + super.onResume(); + loadStoreData(); + } + private void setupFilterToggle() { - binding.btnToggleFilter.setOnClickListener(v -> { - if (binding.layoutFilter.getVisibility() == View.GONE) { - binding.layoutFilter.setVisibility(View.VISIBLE); - binding.btnToggleFilter.setImageResource(android.R.drawable.ic_menu_close_clear_cancel); - } else { - binding.layoutFilter.setVisibility(View.GONE); - binding.btnToggleFilter.setImageResource(android.R.drawable.ic_menu_search); - binding.etSearchSale.setText(""); - binding.spinnerPaymentMethod.setSelection(0); + UIUtils.setupFilterToggle(binding.btnToggleFilter, binding.layoutFilter, binding.etSearchSale, + binding.spinnerPaymentMethod, binding.spinnerStore); + } + + private void setupStoreFilter() { + SpinnerUtils.setupFilterSpinner(binding.spinnerStore, () -> loadSales(true)); + } + + private void loadStoreData() { + storeViewModel.getAllStores(0, 100).observe(getViewLifecycleOwner(), resource -> { + if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) { + storeList.clear(); + storeList.addAll(resource.data.getContent()); + SpinnerUtils.populateWhiteSpinner(requireContext(), binding.spinnerStore, storeList, + StoreDTO::getStoreName, "Stores", null, StoreDTO::getStoreId); } }); } private void setupPaymentMethodFilter() { - List paymentMethods = Arrays.asList("Cash", "Card"); - SpinnerUtils.populateWhiteSpinner(requireContext(), binding.spinnerPaymentMethod, paymentMethods, - s -> s, "All Payments", null, s -> (long) s.hashCode()); - - SpinnerUtils.setupFilterSpinner(binding.spinnerPaymentMethod, () -> loadSales(true)); + String[] paymentMethods = {"Payments", "Cash", "Card"}; + SpinnerUtils.setupStringFilterSpinner(requireContext(), binding.spinnerPaymentMethod, paymentMethods, () -> loadSales(true)); } @Override @@ -121,12 +136,13 @@ public class SaleFragment extends Fragment implements SaleAdapter.OnSaleClickLis public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { if (dy <= 0) return; LinearLayoutManager lm = (LinearLayoutManager) binding.recyclerViewSales.getLayoutManager(); - if (lm == null) return; - int visible = lm.getChildCount(); - int total = lm.getItemCount(); - int firstVis = lm.findFirstVisibleItemPosition(); - if (!isLoading && !isLastPage && (visible + firstVis) >= total - 3) { - loadSales(false); + if (lm != null) { + int visible = lm.getChildCount(); + int total = lm.getItemCount(); + int firstVis = lm.findFirstVisibleItemPosition(); + if (!isLoading && !isLastPage && (visible + firstVis) >= total - 3) { + loadSales(false); + } } } }); @@ -163,7 +179,12 @@ public class SaleFragment extends Fragment implements SaleAdapter.OnSaleClickLis paymentMethod = (String) binding.spinnerPaymentMethod.getSelectedItem(); } - saleViewModel.getAllSales(currentPage, PAGE_SIZE, query, paymentMethod, "saleDate,desc").observe(getViewLifecycleOwner(), resource -> { + Long storeId = null; + if (binding.spinnerStore.getSelectedItemPosition() > 0 && !storeList.isEmpty()) { + storeId = storeList.get(binding.spinnerStore.getSelectedItemPosition() - 1).getStoreId(); + } + + saleViewModel.getAllSales(currentPage, PAGE_SIZE, query, paymentMethod, storeId, "saleDate,desc").observe(getViewLifecycleOwner(), resource -> { if (resource == null) return; switch (resource.status) { @@ -186,7 +207,9 @@ public class SaleFragment extends Fragment implements SaleAdapter.OnSaleClickLis isLoading = false; binding.swipeRefreshSale.setRefreshing(false); Log.e(TAG, "Error loading sales: " + resource.message); - Toast.makeText(getContext(), "Failed to load sales: " + resource.message, Toast.LENGTH_SHORT).show(); + if (getContext() != null) { + Toast.makeText(getContext(), "Failed to load sales: " + resource.message, Toast.LENGTH_SHORT).show(); + } break; } }); diff --git a/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/ServiceFragment.java b/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/ServiceFragment.java index 0923e4b1..c6d32f84 100644 --- a/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/ServiceFragment.java +++ b/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/ServiceFragment.java @@ -24,6 +24,7 @@ import com.example.petstoremobile.dtos.ServiceDTO; import com.example.petstoremobile.fragments.ListFragment; import com.example.petstoremobile.utils.BulkDeleteHandler; import com.example.petstoremobile.utils.Resource; +import com.example.petstoremobile.utils.UIUtils; import com.example.petstoremobile.viewmodels.ServiceViewModel; import java.util.ArrayList; @@ -113,18 +114,7 @@ public class ServiceFragment extends Fragment implements ServiceAdapter.OnServic * Sets up the filter toggle button to show/hide the filter layout. */ private void setupFilterToggle() { - binding.btnToggleFilter.setOnClickListener(v -> { - if (binding.layoutFilter.getVisibility() == View.GONE) { - binding.layoutFilter.setVisibility(View.VISIBLE); - binding.btnToggleFilter.setImageResource(android.R.drawable.ic_menu_close_clear_cancel); - } else { - binding.layoutFilter.setVisibility(View.GONE); - binding.btnToggleFilter.setImageResource(android.R.drawable.ic_menu_search); - - // Reset filters when closing - binding.etSearchService.setText(""); - } - }); + UIUtils.setupFilterToggle(binding.btnToggleFilter, binding.layoutFilter, binding.etSearchService); } /** diff --git a/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/StaffFragment.java b/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/StaffFragment.java index 63879d9c..06747de3 100644 --- a/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/StaffFragment.java +++ b/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/StaffFragment.java @@ -18,6 +18,7 @@ import com.example.petstoremobile.api.RetrofitClient; import com.example.petstoremobile.dtos.EmployeeDTO; import com.example.petstoremobile.dtos.PageResponse; import com.example.petstoremobile.fragments.ListFragment; +import com.example.petstoremobile.utils.UIUtils; import com.google.android.material.floatingactionbutton.FloatingActionButton; import java.util.*; import retrofit2.*; @@ -50,13 +51,7 @@ public class StaffFragment extends Fragment implements EmployeeAdapter.OnEmploye hamburger.setOnClickListener(v -> openDrawer()); ImageButton btnToggleFilter = view.findViewById(R.id.btnToggleFilterStaff); - btnToggleFilter.setOnClickListener(v -> { - if (layoutFilter.getVisibility() == View.VISIBLE) { - layoutFilter.setVisibility(View.GONE); - } else { - layoutFilter.setVisibility(View.VISIBLE); - } - }); + UIUtils.setupFilterToggle(btnToggleFilter, layoutFilter, etSearch); return view; } diff --git a/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/SupplierFragment.java b/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/SupplierFragment.java index 6d6f28ac..ce255f17 100644 --- a/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/SupplierFragment.java +++ b/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/SupplierFragment.java @@ -24,6 +24,7 @@ import com.example.petstoremobile.dtos.SupplierDTO; import com.example.petstoremobile.fragments.ListFragment; import com.example.petstoremobile.utils.BulkDeleteHandler; import com.example.petstoremobile.utils.Resource; +import com.example.petstoremobile.utils.UIUtils; import com.example.petstoremobile.viewmodels.SupplierViewModel; import java.util.ArrayList; @@ -104,18 +105,7 @@ public class SupplierFragment extends Fragment implements SupplierAdapter.OnSupp * Sets up the filter toggle button to show/hide the filter layout. */ private void setupFilterToggle() { - binding.btnToggleFilter.setOnClickListener(v -> { - if (binding.layoutFilter.getVisibility() == View.GONE) { - binding.layoutFilter.setVisibility(View.VISIBLE); - binding.btnToggleFilter.setImageResource(android.R.drawable.ic_menu_close_clear_cancel); - } else { - binding.layoutFilter.setVisibility(View.GONE); - binding.btnToggleFilter.setImageResource(android.R.drawable.ic_menu_search); - - // Reset search when closing - binding.etSearchSupplier.setText(""); - } - }); + UIUtils.setupFilterToggle(binding.btnToggleFilter, binding.layoutFilter, binding.etSearchSupplier); } /** diff --git a/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/detailfragments/RefundFragment.java b/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/detailfragments/RefundFragment.java index 3249e8d2..a90f9c12 100644 --- a/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/detailfragments/RefundFragment.java +++ b/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/detailfragments/RefundFragment.java @@ -101,7 +101,7 @@ public class RefundFragment extends Fragment { } private void loadAllSales() { - RetrofitClient.getSaleApi(requireContext()).getAllSales(0, 1000, null, null, null) + RetrofitClient.getSaleApi(requireContext()).getAllSales(0, 1000, null, null, null, "saleDate,desc") .enqueue(new Callback>() { public void onResponse(Call> c, Response> r) { diff --git a/android/app/src/main/java/com/example/petstoremobile/repositories/SaleRepository.java b/android/app/src/main/java/com/example/petstoremobile/repositories/SaleRepository.java index 370b28a9..4f436163 100644 --- a/android/app/src/main/java/com/example/petstoremobile/repositories/SaleRepository.java +++ b/android/app/src/main/java/com/example/petstoremobile/repositories/SaleRepository.java @@ -20,8 +20,8 @@ public class SaleRepository extends BaseRepository { this.saleApi = saleApi; } - public LiveData>> getAllSales(int page, int size, String query, String paymentMethod, String sortBy) { - return executeCall(saleApi.getAllSales(page, size, query, paymentMethod, sortBy)); + public LiveData>> getAllSales(int page, int size, String query, String paymentMethod, Long storeId, String sortBy) { + return executeCall(saleApi.getAllSales(page, size, query, paymentMethod, storeId, sortBy)); } public LiveData> getSaleById(Long id) { diff --git a/android/app/src/main/java/com/example/petstoremobile/utils/UIUtils.java b/android/app/src/main/java/com/example/petstoremobile/utils/UIUtils.java index 22b8d4e0..b1ab7ad2 100644 --- a/android/app/src/main/java/com/example/petstoremobile/utils/UIUtils.java +++ b/android/app/src/main/java/com/example/petstoremobile/utils/UIUtils.java @@ -2,7 +2,12 @@ package com.example.petstoremobile.utils; import android.telephony.PhoneNumberFormattingTextWatcher; import android.text.InputFilter; +import android.view.View; import android.widget.EditText; +import android.widget.ImageButton; +import android.widget.Spinner; + +import com.example.petstoremobile.R; /** * Utility class for shared UI component logic and formatting. @@ -15,4 +20,26 @@ public class UIUtils { editText.addTextChangedListener(new PhoneNumberFormattingTextWatcher("CA")); editText.setFilters(new InputFilter[]{new InputFilter.LengthFilter(14)}); } + + /** + * Sets up a toggle for a filter layout, including icon changes and field resets. + */ + public static void setupFilterToggle(ImageButton btnToggle, View layoutFilter, EditText etSearch, Spinner... spinners) { + btnToggle.setOnClickListener(v -> { + boolean isVisible = layoutFilter.getVisibility() == View.VISIBLE; + layoutFilter.setVisibility(isVisible ? View.GONE : View.VISIBLE); + + // Use Android default icons or app-specific ones if available + btnToggle.setImageResource(isVisible ? + android.R.drawable.ic_menu_search : + android.R.drawable.ic_menu_close_clear_cancel); + + if (isVisible) { + if (etSearch != null) etSearch.setText(""); + for (Spinner spinner : spinners) { + if (spinner != null) spinner.setSelection(0); + } + } + }); + } } diff --git a/android/app/src/main/java/com/example/petstoremobile/viewmodels/SaleViewModel.java b/android/app/src/main/java/com/example/petstoremobile/viewmodels/SaleViewModel.java index 4bdd337e..a02d3382 100644 --- a/android/app/src/main/java/com/example/petstoremobile/viewmodels/SaleViewModel.java +++ b/android/app/src/main/java/com/example/petstoremobile/viewmodels/SaleViewModel.java @@ -21,8 +21,8 @@ public class SaleViewModel extends ViewModel { this.saleRepository = saleRepository; } - public LiveData>> getAllSales(int page, int size, String query, String paymentMethod, String sortBy) { - return saleRepository.getAllSales(page, size, query, paymentMethod, sortBy); + public LiveData>> getAllSales(int page, int size, String query, String paymentMethod, Long storeId, String sortBy) { + return saleRepository.getAllSales(page, size, query, paymentMethod, storeId, sortBy); } public LiveData> getSaleById(Long id) { diff --git a/android/app/src/main/res/layout/fragment_sale.xml b/android/app/src/main/res/layout/fragment_sale.xml index b5256f3d..ff3a693c 100644 --- a/android/app/src/main/res/layout/fragment_sale.xml +++ b/android/app/src/main/res/layout/fragment_sale.xml @@ -81,7 +81,7 @@ android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" - android:hint="Search by employee or date..." + android:hint="Search by employee or store..." android:inputType="text" android:background="@android:color/transparent" android:textColor="@color/text_dark" @@ -100,7 +100,7 @@ android:gravity="center_vertical"> + +