made admin analyics able to select store

This commit is contained in:
Alex
2026-04-14 23:17:12 -06:00
parent 1b4a96c923
commit c5a59e8de3
5 changed files with 118 additions and 1 deletions

View File

@@ -57,11 +57,13 @@ public class AnalyticsFragment extends Fragment {
binding.btnMyAnalytics.setOnClickListener(v -> {
viewModel.setViewMode("mine");
updateViewModeButtonStyles("mine");
updateStoreFilterVisibility("mine");
});
binding.btnStoreAnalytics.setOnClickListener(v -> {
viewModel.setViewMode("store");
updateViewModeButtonStyles("store");
updateStoreFilterVisibility("store");
});
}
@@ -72,6 +74,13 @@ public class AnalyticsFragment extends Fragment {
android.content.res.ColorStateList.valueOf(mode.equals("store") ? COLOR_SELECTED : COLOR_UNSELECTED));
}
private void updateStoreFilterVisibility(String mode) {
boolean isAdmin = "ADMIN".equalsIgnoreCase(tokenManager.getRole());
int vis = (isAdmin && mode.equals("store")) ? View.VISIBLE : View.GONE;
binding.tvStoreFilterLabel.setVisibility(vis);
binding.spinnerFilterStore.setVisibility(vis);
}
// Filter Panel
private void setupFilterPanel() {
@@ -126,6 +135,9 @@ public class AnalyticsFragment extends Fragment {
int topNPos = binding.spinnerTopN.getSelectedItemPosition();
filter.topN = (topNPos >= 0 && topNPos < TOP_N_VALUES.length) ? TOP_N_VALUES[topNPos] : 5;
Object store = binding.spinnerFilterStore.getSelectedItem();
viewModel.setStoreFilter(store != null ? store.toString() : "All Stores");
updateFilterSummary();
viewModel.applyFilter(filter);
}
@@ -134,8 +146,8 @@ public class AnalyticsFragment extends Fragment {
binding.etFilterStartDate.setText("");
binding.etFilterEndDate.setText("");
binding.spinnerTopN.setSelection(0);
// Reset payment method to "All"
SpinnerUtils.setSelectionByValue(binding.spinnerFilterPayment, "All");
SpinnerUtils.setSelectionByValue(binding.spinnerFilterStore, "All Stores");
updateFilterSummary();
viewModel.resetFilter();
}
@@ -192,6 +204,16 @@ public class AnalyticsFragment extends Fragment {
methods.toArray(new String[0]));
SpinnerUtils.setSelectionByValue(binding.spinnerFilterPayment, currentSelection);
});
viewModel.getAvailableStores().observe(getViewLifecycleOwner(), stores -> {
if (stores == null || stores.isEmpty()) return;
String currentSelection = binding.spinnerFilterStore.getSelectedItem() != null
? binding.spinnerFilterStore.getSelectedItem().toString() : "All Stores";
SpinnerUtils.setupStringSpinner(requireContext(), binding.spinnerFilterStore,
stores.toArray(new String[0]));
SpinnerUtils.setSelectionByValue(binding.spinnerFilterStore, currentSelection);
updateStoreFilterVisibility(viewModel.getViewMode());
});
}
@Override

View File

@@ -37,10 +37,12 @@ public class AnalyticsViewModel extends ViewModel {
private final MutableLiveData<Boolean> isLoading = new MutableLiveData<>(false);
private final MutableLiveData<String> errorMessage = new MutableLiveData<>();
private final MutableLiveData<List<String>> availablePaymentMethods = new MutableLiveData<>(new ArrayList<>());
private final MutableLiveData<List<String>> availableStores = new MutableLiveData<>(new ArrayList<>());
private List<SaleDTO> cachedSales = new ArrayList<>();
private FilterState currentFilter = new FilterState();
private String viewMode = "store";
private String storeFilter = "All Stores";
@Inject
public AnalyticsViewModel(SaleRepository saleRepository, TokenManager tokenManager) {
@@ -52,6 +54,7 @@ public class AnalyticsViewModel extends ViewModel {
public LiveData<Boolean> getIsLoading() { return isLoading; }
public LiveData<String> getErrorMessage() { return errorMessage; }
public LiveData<List<String>> getAvailablePaymentMethods() { return availablePaymentMethods; }
public LiveData<List<String>> getAvailableStores() { return availableStores; }
public void loadAnalytics() {
isLoading.setValue(true);
@@ -61,6 +64,7 @@ public class AnalyticsViewModel extends ViewModel {
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
cachedSales = resource.data.getContent();
derivePaymentMethods();
deriveStores();
applyCurrentFilter();
isLoading.setValue(false);
} else if (resource.status == Resource.Status.ERROR) {
@@ -78,6 +82,7 @@ public class AnalyticsViewModel extends ViewModel {
public void resetFilter() {
currentFilter = new FilterState();
storeFilter = "All Stores";
applyCurrentFilter();
}
@@ -90,6 +95,15 @@ public class AnalyticsViewModel extends ViewModel {
return viewMode;
}
public void setStoreFilter(String store) {
storeFilter = (store != null && !store.isEmpty()) ? store : "All Stores";
applyCurrentFilter();
}
public String getStoreFilter() {
return storeFilter;
}
private void applyCurrentFilter() {
List<SaleDTO> salesForMode;
if (viewMode.equals("mine")) {
@@ -100,10 +114,29 @@ public class AnalyticsViewModel extends ViewModel {
} else {
salesForMode = cachedSales;
}
if (!storeFilter.equals("All Stores") && !storeFilter.isEmpty()) {
final String sf = storeFilter;
salesForMode = salesForMode.stream()
.filter(s -> sf.equalsIgnoreCase(s.getStoreName() != null ? s.getStoreName() : ""))
.collect(Collectors.toList());
}
List<SaleDTO> filtered = filterSales(salesForMode, currentFilter);
computeAnalytics(filtered, currentFilter);
}
private void deriveStores() {
java.util.Set<String> stores = new java.util.TreeSet<>();
for (SaleDTO s : cachedSales) {
if (s.getStoreName() != null && !s.getStoreName().isEmpty()) {
stores.add(s.getStoreName());
}
}
List<String> result = new ArrayList<>();
result.add("All Stores");
result.addAll(stores);
availableStores.setValue(result);
}
private void derivePaymentMethods() {
java.util.Set<String> methods = new java.util.TreeSet<>();
for (SaleDTO s : cachedSales) {

View File

@@ -136,6 +136,23 @@
android:layout_marginTop="12dp"
android:visibility="gone">
<TextView
android:id="@+id/tvStoreFilterLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Store"
android:textColor="@color/text_light"
android:textSize="11sp"
android:layout_marginBottom="4dp"
android:visibility="gone"/>
<Spinner
android:id="@+id/spinnerFilterStore"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="12dp"
android:visibility="gone"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"