added filtering for Sales and added helper method for setting up filtertoggle andriod

This commit is contained in:
Alex
2026-04-08 01:32:34 -06:00
parent 4fc33fedf4
commit 3e01ad07cd
21 changed files with 151 additions and 155 deletions

View File

@@ -16,13 +16,14 @@ public interface SaleApi {
Call<PageResponse<SaleDTO>> 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<SaleDTO> getSaleById(@Path("id") Long id);
@POST("api/v1/sales")
Call<SaleDTO> createSale(@Body SaleDTO sale);
}
}

View File

@@ -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();
}
});
}

View File

@@ -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<PageResponse<SaleDTO>>() {
public void onResponse(Call<PageResponse<SaleDTO>> c,
Response<PageResponse<SaleDTO>> r) {

View File

@@ -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<CalendarDay> 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();

View File

@@ -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);
}
/**

View File

@@ -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);
}
/**

View File

@@ -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);
}
/**

View File

@@ -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);
}
/**

View File

@@ -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);
}
/**

View File

@@ -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<SaleDTO> saleList = new ArrayList<>();
private final List<StoreDTO> 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<String> 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;
}
});

View File

@@ -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);
}
/**

View File

@@ -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;
}

View File

@@ -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);
}
/**

View File

@@ -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<PageResponse<SaleDTO>>() {
public void onResponse(Call<PageResponse<SaleDTO>> c,
Response<PageResponse<SaleDTO>> r) {

View File

@@ -20,8 +20,8 @@ public class SaleRepository extends BaseRepository {
this.saleApi = saleApi;
}
public LiveData<Resource<PageResponse<SaleDTO>>> getAllSales(int page, int size, String query, String paymentMethod, String sortBy) {
return executeCall(saleApi.getAllSales(page, size, query, paymentMethod, sortBy));
public LiveData<Resource<PageResponse<SaleDTO>>> 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<Resource<SaleDTO>> getSaleById(Long id) {

View File

@@ -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);
}
}
});
}
}

View File

@@ -21,8 +21,8 @@ public class SaleViewModel extends ViewModel {
this.saleRepository = saleRepository;
}
public LiveData<Resource<PageResponse<SaleDTO>>> getAllSales(int page, int size, String query, String paymentMethod, String sortBy) {
return saleRepository.getAllSales(page, size, query, paymentMethod, sortBy);
public LiveData<Resource<PageResponse<SaleDTO>>> getAllSales(int page, int size, String query, String paymentMethod, Long storeId, String sortBy) {
return saleRepository.getAllSales(page, size, query, paymentMethod, storeId, sortBy);
}
public LiveData<Resource<SaleDTO>> getSaleById(Long id) {

View File

@@ -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">
<Spinner
android:id="@+id/spinnerPaymentMethod"
android:id="@+id/spinnerStore"
android:layout_width="0dp"
android:layout_height="44dp"
android:layout_weight="1"
@@ -109,6 +109,17 @@
android:paddingEnd="8dp"
android:layout_marginEnd="4dp"/>
<Spinner
android:id="@+id/spinnerPaymentMethod"
android:layout_width="0dp"
android:layout_height="44dp"
android:layout_weight="1"
android:background="@drawable/bg_spinner"
android:paddingStart="12dp"
android:paddingEnd="8dp"
android:layout_marginEnd="4dp"
android:layout_marginStart="4dp"/>
<Button
android:id="@+id/btnOpenRefund"
android:layout_width="0dp"