made admin analyics able to select store
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -101,6 +101,9 @@ public class AnalyticsController {
|
||||
@FXML
|
||||
private ComboBox<String> cbTopN;
|
||||
|
||||
@FXML
|
||||
private ComboBox<String> cbStoreFilter;
|
||||
|
||||
@FXML
|
||||
private HBox hbViewToggle;
|
||||
|
||||
@@ -138,6 +141,9 @@ public class AnalyticsController {
|
||||
cbPaymentFilter.setItems(FXCollections.observableArrayList("All"));
|
||||
cbPaymentFilter.getSelectionModel().selectFirst();
|
||||
|
||||
cbStoreFilter.setItems(FXCollections.observableArrayList("All Stores"));
|
||||
cbStoreFilter.getSelectionModel().selectFirst();
|
||||
|
||||
lblFilterSummary.setText("All time");
|
||||
|
||||
ToggleGroup tgViewMode = new ToggleGroup();
|
||||
@@ -151,6 +157,7 @@ public class AnalyticsController {
|
||||
}
|
||||
viewMode = (newVal == tbnMyAnalytics) ? "mine" : "store";
|
||||
updateViewModeStyles();
|
||||
updateStoreFilterVisibility();
|
||||
applyCurrentFilter();
|
||||
});
|
||||
|
||||
@@ -213,6 +220,8 @@ public class AnalyticsController {
|
||||
Platform.runLater(() -> {
|
||||
cachedSales = sales;
|
||||
derivePaymentMethods();
|
||||
deriveStores();
|
||||
updateStoreFilterVisibility();
|
||||
applyCurrentFilter();
|
||||
btnRefresh.setDisable(false);
|
||||
});
|
||||
@@ -250,6 +259,12 @@ public class AnalyticsController {
|
||||
} else {
|
||||
salesForMode = cachedSales;
|
||||
}
|
||||
String storeFilter = currentFilter.storeFilter;
|
||||
if (!storeFilter.equals("All Stores") && !storeFilter.isBlank()) {
|
||||
salesForMode = salesForMode.stream()
|
||||
.filter(s -> storeFilter.equalsIgnoreCase(s.getStoreName() != null ? s.getStoreName() : ""))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
List<SaleResponse> filtered = filterSales(salesForMode, currentFilter);
|
||||
String start = currentFilter.startDate.isEmpty() ? LocalDate.now().minusDays(6).toString() : currentFilter.startDate;
|
||||
String end = currentFilter.endDate.isEmpty() ? LocalDate.now().toString() : currentFilter.endDate;
|
||||
@@ -308,6 +323,31 @@ public class AnalyticsController {
|
||||
}
|
||||
}
|
||||
|
||||
private void deriveStores() {
|
||||
Set<String> stores = new TreeSet<>();
|
||||
for (SaleResponse s : cachedSales) {
|
||||
if (s.getStoreName() != null && !s.getStoreName().isBlank()) {
|
||||
stores.add(s.getStoreName());
|
||||
}
|
||||
}
|
||||
List<String> items = new ArrayList<>();
|
||||
items.add("All Stores");
|
||||
items.addAll(stores);
|
||||
String current = cbStoreFilter.getValue();
|
||||
cbStoreFilter.setItems(FXCollections.observableArrayList(items));
|
||||
if (current != null && items.contains(current)) {
|
||||
cbStoreFilter.setValue(current);
|
||||
} else {
|
||||
cbStoreFilter.getSelectionModel().selectFirst();
|
||||
}
|
||||
}
|
||||
|
||||
private void updateStoreFilterVisibility() {
|
||||
boolean show = UserSession.getInstance().isAdmin() && viewMode.equals("store");
|
||||
cbStoreFilter.setVisible(show);
|
||||
cbStoreFilter.setManaged(show);
|
||||
}
|
||||
|
||||
private void updateFilterSummary() {
|
||||
String start = currentFilter.startDate;
|
||||
String end = currentFilter.endDate;
|
||||
@@ -665,6 +705,7 @@ public class AnalyticsController {
|
||||
dpEndDate.setValue(null);
|
||||
cbPaymentFilter.getSelectionModel().selectFirst();
|
||||
cbTopN.getSelectionModel().selectFirst();
|
||||
cbStoreFilter.getSelectionModel().selectFirst();
|
||||
currentFilter = new FilterState();
|
||||
applyCurrentFilter();
|
||||
}
|
||||
@@ -683,6 +724,8 @@ public class AnalyticsController {
|
||||
currentFilter.paymentMethod = pm != null ? pm : "All";
|
||||
int topNPos = cbTopN.getSelectionModel().getSelectedIndex();
|
||||
currentFilter.topN = (topNPos >= 0 && topNPos < TOP_N_VALUES.length) ? TOP_N_VALUES[topNPos] : 5;
|
||||
String sf = cbStoreFilter.getValue();
|
||||
currentFilter.storeFilter = (sf != null && !sf.isBlank()) ? sf : "All Stores";
|
||||
applyCurrentFilter();
|
||||
}
|
||||
|
||||
@@ -691,5 +734,6 @@ public class AnalyticsController {
|
||||
String endDate = "";
|
||||
String paymentMethod = "All";
|
||||
int topN = 5;
|
||||
String storeFilter = "All Stores";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,6 +102,7 @@
|
||||
</FlowPane>
|
||||
<HBox alignment="CENTER_LEFT" spacing="8.0">
|
||||
<children>
|
||||
<ComboBox fx:id="cbStoreFilter" prefWidth="145.0" promptText="All Stores" visible="false" managed="false" />
|
||||
<ComboBox fx:id="cbPaymentFilter" prefWidth="145.0" promptText="All Payments" />
|
||||
<ComboBox fx:id="cbTopN" prefWidth="110.0" />
|
||||
<Region HBox.hgrow="ALWAYS" />
|
||||
|
||||
Reference in New Issue
Block a user