From 5340ddf98bbbb2639d1180a36c263372176beb57 Mon Sep 17 00:00:00 2001 From: Alex <78383757+Lextical@users.noreply.github.com> Date: Fri, 10 Apr 2026 00:28:01 -0600 Subject: [PATCH] added viewstates to Supplier and Product --- .../AdoptionDetailFragment.java | 208 +++++++----------- .../ProductDetailFragment.java | 4 +- .../SupplierDetailFragment.java | 63 ++++-- .../viewmodels/AdoptionDetailViewModel.java | 163 +++++++++++--- .../viewmodels/ProductDetailViewModel.java | 1 + .../viewmodels/SupplierDetailViewModel.java | 75 ++++++- .../res/layout/fragment_adoption_detail.xml | 29 +-- 7 files changed, 343 insertions(+), 200 deletions(-) diff --git a/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/detailfragments/AdoptionDetailFragment.java b/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/detailfragments/AdoptionDetailFragment.java index 9b0f022b..0e936edf 100644 --- a/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/detailfragments/AdoptionDetailFragment.java +++ b/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/detailfragments/AdoptionDetailFragment.java @@ -33,11 +33,6 @@ public class AdoptionDetailFragment extends Fragment { private FragmentAdoptionDetailBinding binding; private AdoptionDetailViewModel viewModel; - private long preselectedPetId = -1; - private long preselectedCustomerId = -1; - private long preselectedStoreId = -1; - private long preselectedEmployeeId = -1; - private final String[] STATUSES = {"Pending", "Completed", "Cancelled"}; @Override @@ -59,7 +54,7 @@ public class AdoptionDetailFragment extends Fragment { setupSpinners(); setupDatePicker(); observeViewModel(); - loadSpinnersData(); + viewModel.loadInitialFormData(); handleArguments(); binding.btnAdoptionBack.setOnClickListener(v -> navigateBack()); @@ -68,14 +63,39 @@ public class AdoptionDetailFragment extends Fragment { } private void observeViewModel() { - viewModel.getPetList().observe(getViewLifecycleOwner(), list -> refreshPetSpinner()); - viewModel.getCustomerList().observe(getViewLifecycleOwner(), list -> refreshCustomerSpinner()); - viewModel.getStoreList().observe(getViewLifecycleOwner(), list -> refreshStoreSpinner()); - viewModel.getEmployeeList().observe(getViewLifecycleOwner(), list -> refreshEmployeeSpinner()); + viewModel.getViewState().observe(getViewLifecycleOwner(), this::applyViewState); + + viewModel.getPetList().observe(getViewLifecycleOwner(), list -> { + AdoptionDetailViewModel.ViewState state = viewModel.getViewState().getValue(); + Long petId = state != null ? state.selectedPetId : null; + SpinnerUtils.populateSpinner(requireContext(), binding.spinnerAdoptionPet, list, + DropdownDTO::getLabel, "-- Select Pet --", petId, DropdownDTO::getId); + }); + + viewModel.getCustomerList().observe(getViewLifecycleOwner(), list -> { + AdoptionDetailViewModel.ViewState state = viewModel.getViewState().getValue(); + Long customerId = state != null ? state.selectedCustomerId : null; + SpinnerUtils.populateSpinner(requireContext(), binding.spinnerAdoptionCustomer, list, + DropdownDTO::getLabel, "-- Select Customer --", customerId, DropdownDTO::getId); + }); + + viewModel.getStoreList().observe(getViewLifecycleOwner(), list -> { + AdoptionDetailViewModel.ViewState state = viewModel.getViewState().getValue(); + Long storeId = state != null ? state.selectedStoreId : null; + SpinnerUtils.populateSpinner(requireContext(), binding.spinnerAdoptionStore, list, + DropdownDTO::getLabel, "-- Select Store --", storeId, DropdownDTO::getId); + }); + + viewModel.getEmployeeList().observe(getViewLifecycleOwner(), list -> { + AdoptionDetailViewModel.ViewState state = viewModel.getViewState().getValue(); + Long employeeId = state != null ? state.selectedEmployeeId : null; + SpinnerUtils.populateSpinner(requireContext(), binding.spinnerAdoptionEmployee, list, + DropdownDTO::getLabel, "-- Select Staff --", employeeId, DropdownDTO::getId); + }); } private void setLoading(boolean loading) { - if (binding != null && binding.progressBar != null) { + if (binding != null) { binding.progressBar.setVisibility(loading ? View.VISIBLE : View.GONE); } } @@ -94,14 +114,7 @@ public class AdoptionDetailFragment extends Fragment { binding.spinnerAdoptionCustomer.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView parent, View view, int position, long id) { - if (position > 0) { - UIUtils.setViewsEnabled(true, binding.spinnerAdoptionPet); - } else { - if (!viewModel.isEditing()) { - binding.spinnerAdoptionPet.setSelection(0); - UIUtils.setViewsEnabled(false, binding.spinnerAdoptionPet); - } - } + viewModel.onCustomerSelected(position); } @Override public void onNothingSelected(AdapterView parent) {} @@ -110,12 +123,7 @@ public class AdoptionDetailFragment extends Fragment { binding.spinnerAdoptionStore.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView parent, View view, int position, long id) { - if (position > 0 && viewModel.getStoreList().getValue() != null && position <= viewModel.getStoreList().getValue().size()) { - DropdownDTO selectedStore = viewModel.getStoreList().getValue().get(position - 1); - loadEmployees(selectedStore.getId()); - } else { - viewModel.setEmployeeList(new ArrayList<>()); - } + viewModel.onStoreSelected(position); } @Override public void onNothingSelected(AdapterView parent) {} @@ -126,111 +134,64 @@ public class AdoptionDetailFragment extends Fragment { binding.etAdoptionDate.setOnClickListener(v -> UIUtils.showDatePicker(requireContext(), binding.etAdoptionDate, null)); } - private void loadSpinnersData() { - viewModel.loadPets().observe(getViewLifecycleOwner(), resource -> { - if (resource == null) return; - setLoading(resource.status == Resource.Status.LOADING); - if (resource.status == Resource.Status.SUCCESS && resource.data != null) { - viewModel.setPetList(resource.data); - } - }); - viewModel.loadCustomers().observe(getViewLifecycleOwner(), resource -> { - if (resource == null) return; - setLoading(resource.status == Resource.Status.LOADING); - if (resource.status == Resource.Status.SUCCESS && resource.data != null) { - viewModel.setCustomerList(resource.data); - } - }); - viewModel.loadStores().observe(getViewLifecycleOwner(), resource -> { - if (resource == null) return; - setLoading(resource.status == Resource.Status.LOADING); - if (resource.status == Resource.Status.SUCCESS && resource.data != null) { - viewModel.setStoreList(resource.data); - } - }); - } - - private void refreshPetSpinner() { - SpinnerUtils.populateSpinner(requireContext(), binding.spinnerAdoptionPet, viewModel.getPetList().getValue(), - DropdownDTO::getLabel, "-- Select Pet --", - preselectedPetId, DropdownDTO::getId); - } - - private void refreshCustomerSpinner() { - SpinnerUtils.populateSpinner(requireContext(), binding.spinnerAdoptionCustomer, viewModel.getCustomerList().getValue(), - DropdownDTO::getLabel, "-- Select Customer --", - preselectedCustomerId, DropdownDTO::getId); - } - - private void refreshStoreSpinner() { - SpinnerUtils.populateSpinner(requireContext(), binding.spinnerAdoptionStore, viewModel.getStoreList().getValue(), - DropdownDTO::getLabel, "-- Select Store --", - preselectedStoreId, DropdownDTO::getId); - } - - private void loadEmployees(Long storeId) { - viewModel.loadEmployees(storeId).observe(getViewLifecycleOwner(), resource -> { - if (resource == null) return; - setLoading(resource.status == Resource.Status.LOADING); - if (resource.status == Resource.Status.SUCCESS && resource.data != null) { - viewModel.setEmployeeList(resource.data); - } - }); - } - - private void refreshEmployeeSpinner() { - SpinnerUtils.populateSpinner(requireContext(), binding.spinnerAdoptionEmployee, viewModel.getEmployeeList().getValue(), - DropdownDTO::getLabel, "-- Select Staff --", - preselectedEmployeeId, DropdownDTO::getId); - } - private void handleArguments() { Bundle a = getArguments(); if (a != null && a.containsKey("adoptionId")) { - long adoptionId = a.getLong("adoptionId"); - viewModel.setAdoptionId(adoptionId); - binding.tvAdoptionMode.setText("Edit Adoption"); - binding.tvAdoptionId.setText(DateTimeUtils.formatId(adoptionId)); - binding.tvAdoptionId.setVisibility(View.VISIBLE); - binding.btnDeleteAdoption.setVisibility(View.VISIBLE); + viewModel.setAdoptionId(a.getLong("adoptionId")); loadAdoptionData(); - } else { - viewModel.setAdoptionId(-1); - binding.tvAdoptionMode.setText("Add Adoption"); - binding.btnDeleteAdoption.setVisibility(View.GONE); - binding.tvAdoptionId.setVisibility(View.GONE); - UIUtils.setViewsEnabled(false, binding.spinnerAdoptionPet); + return; } + viewModel.setAdoptionId(-1); } private void loadAdoptionData() { viewModel.loadAdoption().observe(getViewLifecycleOwner(), resource -> { if (resource == null) return; setLoading(resource.status == Resource.Status.LOADING); - if (resource.status == Resource.Status.SUCCESS && resource.data != null) { - AdoptionDTO a = resource.data; - preselectedPetId = a.getPetId() != null ? a.getPetId() : -1; - preselectedCustomerId = a.getCustomerId() != null ? a.getCustomerId() : -1; - preselectedStoreId = a.getSourceStoreId() != null ? a.getSourceStoreId() : -1; - preselectedEmployeeId = a.getEmployeeId() != null ? a.getEmployeeId() : -1; - - binding.etAdoptionDate.setText(a.getAdoptionDate()); - binding.etAdoptionFee.setText(a.getAdoptionFee() != null ? a.getAdoptionFee().toString() : ""); - SpinnerUtils.setSelectionByValue(binding.spinnerAdoptionStatus, a.getAdoptionStatus()); - - refreshPetSpinner(); - refreshCustomerSpinner(); - refreshStoreSpinner(); - - if (preselectedCustomerId != -1) { - UIUtils.setViewsEnabled(true, binding.spinnerAdoptionPet); - } - } else if (resource.status == Resource.Status.ERROR) { + if (resource.status == Resource.Status.ERROR) { Toast.makeText(getContext(), "Failed to load adoption: " + resource.message, Toast.LENGTH_SHORT).show(); } }); } + private void applyViewState(AdoptionDetailViewModel.ViewState state) { + binding.tvAdoptionMode.setText(state.modeTitle); + binding.tvAdoptionId.setText(DateTimeUtils.formatId(viewModel.getAdoptionId())); + binding.tvAdoptionId.setVisibility(state.isAdoptionIdVisible ? View.VISIBLE : View.GONE); + binding.btnDeleteAdoption.setVisibility(state.isDeleteVisible ? View.VISIBLE : View.GONE); + binding.btnSaveAdoption.setText(state.saveButtonText); + + UIUtils.setViewsEnabled(state.isPetEnabled, binding.spinnerAdoptionPet); + UIUtils.setViewsEnabled(state.isEmployeeEnabled, binding.spinnerAdoptionEmployee); + + if (!state.adoptionDate.isEmpty()) { + binding.etAdoptionDate.setText(state.adoptionDate); + } + if (!state.adoptionFee.isEmpty()) { + binding.etAdoptionFee.setText(state.adoptionFee); + } + if (!state.adoptionStatus.isEmpty()) { + SpinnerUtils.setSelectionByValue(binding.spinnerAdoptionStatus, state.adoptionStatus); + } + + // Re-populate spinners with updated preselected IDs + List pets = viewModel.getPetList().getValue(); + if (pets != null) SpinnerUtils.populateSpinner(requireContext(), binding.spinnerAdoptionPet, + pets, DropdownDTO::getLabel, "-- Select Pet --", state.selectedPetId, DropdownDTO::getId); + + List customers = viewModel.getCustomerList().getValue(); + if (customers != null) SpinnerUtils.populateSpinner(requireContext(), binding.spinnerAdoptionCustomer, + customers, DropdownDTO::getLabel, "-- Select Customer --", state.selectedCustomerId, DropdownDTO::getId); + + List stores = viewModel.getStoreList().getValue(); + if (stores != null) SpinnerUtils.populateSpinner(requireContext(), binding.spinnerAdoptionStore, + stores, DropdownDTO::getLabel, "-- Select Store --", state.selectedStoreId, DropdownDTO::getId); + + List employees = viewModel.getEmployeeList().getValue(); + if (employees != null) SpinnerUtils.populateSpinner(requireContext(), binding.spinnerAdoptionEmployee, + employees, DropdownDTO::getLabel, "-- Select Staff --", state.selectedEmployeeId, DropdownDTO::getId); + } + private void saveAdoption() { if (!InputValidator.isSpinnerSelected(binding.spinnerAdoptionCustomer, "Customer")) return; if (!InputValidator.isSpinnerSelected(binding.spinnerAdoptionPet, "Pet")) return; @@ -247,24 +208,17 @@ public class AdoptionDetailFragment extends Fragment { DropdownDTO customer = viewModel.getCustomerList().getValue().get(binding.spinnerAdoptionCustomer.getSelectedItemPosition() - 1); DropdownDTO pet = viewModel.getPetList().getValue().get(binding.spinnerAdoptionPet.getSelectedItemPosition() - 1); DropdownDTO store = viewModel.getStoreList().getValue().get(binding.spinnerAdoptionStore.getSelectedItemPosition() - 1); - + Long employeeId = null; - if (binding.spinnerAdoptionEmployee.getSelectedItemPosition() > 0) { + if (binding.spinnerAdoptionEmployee.getSelectedItemPosition() > 0 && viewModel.getEmployeeList().getValue() != null) { employeeId = viewModel.getEmployeeList().getValue().get(binding.spinnerAdoptionEmployee.getSelectedItemPosition() - 1).getId(); } - - String adoptionDate = binding.etAdoptionDate.getText().toString().trim(); - String status = STATUSES[binding.spinnerAdoptionStatus.getSelectedItemPosition()]; + + String adoptionDate = binding.etAdoptionDate.getText().toString().trim(); + String status = STATUSES[binding.spinnerAdoptionStatus.getSelectedItemPosition()]; AdoptionDTO dto = new AdoptionDTO( - pet.getId(), - customer.getId(), - employeeId, - store.getId(), - adoptionDate, - status, - fee - ); + pet.getId(), customer.getId(), employeeId, store.getId(), adoptionDate, status, fee); viewModel.saveAdoption(dto).observe(getViewLifecycleOwner(), resource -> { if (resource == null) return; diff --git a/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/detailfragments/ProductDetailFragment.java b/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/detailfragments/ProductDetailFragment.java index 9f072b51..c580905b 100644 --- a/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/detailfragments/ProductDetailFragment.java +++ b/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/detailfragments/ProductDetailFragment.java @@ -110,7 +110,7 @@ public class ProductDetailFragment extends Fragment { private void observeViewModel() { viewModel.getCategoryList().observe(getViewLifecycleOwner(), list -> updateCategorySpinner()); - + viewModel.loadCategories().observe(getViewLifecycleOwner(), resource -> { if (resource == null) return; setLoading(resource.status == Resource.Status.LOADING); @@ -268,7 +268,7 @@ public class ProductDetailFragment extends Fragment { } private void confirmDelete() { - DialogUtils.showDeleteConfirmDialog(requireContext(), "Product", () -> + DialogUtils.showDeleteConfirmDialog(requireContext(), "Product", () -> viewModel.deleteProduct().observe(getViewLifecycleOwner(), resource -> { if (resource == null) return; setLoading(resource.status == Resource.Status.LOADING); diff --git a/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/detailfragments/SupplierDetailFragment.java b/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/detailfragments/SupplierDetailFragment.java index a7c64079..5eb1f43b 100644 --- a/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/detailfragments/SupplierDetailFragment.java +++ b/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/detailfragments/SupplierDetailFragment.java @@ -11,11 +11,13 @@ import androidx.navigation.fragment.NavHostFragment; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.EditText; import android.widget.Toast; import com.example.petstoremobile.databinding.FragmentSupplierDetailBinding; import com.example.petstoremobile.dtos.SupplierDTO; import com.example.petstoremobile.utils.ActivityLogger; +import com.example.petstoremobile.utils.DateTimeUtils; import com.example.petstoremobile.utils.DialogUtils; import com.example.petstoremobile.utils.InputValidator; import com.example.petstoremobile.utils.Resource; @@ -51,6 +53,7 @@ public class SupplierDetailFragment extends Fragment { super.onViewCreated(view, savedInstanceState); UIUtils.formatPhoneInput(binding.etSupPhone); + observeViewModel(); handleArguments(); binding.btnBack.setOnClickListener(v -> navigateBack()); @@ -58,8 +61,12 @@ public class SupplierDetailFragment extends Fragment { binding.btnDeleteSupplier.setOnClickListener(v -> deleteSupplier()); } + private void observeViewModel() { + viewModel.getViewState().observe(getViewLifecycleOwner(), this::applyViewState); + } + private void setLoading(boolean loading) { - if (binding != null && binding.progressBar != null) { + if (binding != null) { binding.progressBar.setVisibility(loading ? View.VISIBLE : View.GONE); } } @@ -129,36 +136,50 @@ public class SupplierDetailFragment extends Fragment { private void handleArguments() { if (getArguments() != null && getArguments().containsKey("supId")) { - long supId = getArguments().getLong("supId"); - viewModel.setSupId(supId); - binding.tvMode.setText("Edit Supplier"); - binding.tvSupId.setText("ID: " + supId); - binding.tvSupId.setVisibility(View.VISIBLE); - binding.btnDeleteSupplier.setVisibility(View.VISIBLE); + viewModel.setSupId(getArguments().getLong("supId")); loadSupplierData(); - } else { - viewModel.setSupId(-1); - binding.tvMode.setText("Add Supplier"); - binding.tvSupId.setVisibility(View.GONE); - binding.btnDeleteSupplier.setVisibility(View.GONE); - binding.btnSaveSupplier.setText("Add"); + return; } + + viewModel.setSupId(-1); } private void loadSupplierData() { viewModel.loadSupplier().observe(getViewLifecycleOwner(), resource -> { if (resource == null) return; setLoading(resource.status == Resource.Status.LOADING); - if (resource.status == Resource.Status.SUCCESS && resource.data != null) { - SupplierDTO s = resource.data; - binding.etSupCompany.setText(s.getSupCompany()); - binding.etSupContactFirstName.setText(s.getSupContactFirstName()); - binding.etSupContactLastName.setText(s.getSupContactLastName()); - binding.etSupEmail.setText(s.getSupEmail()); - binding.etSupPhone.setText(s.getSupPhone()); - } else if (resource.status == Resource.Status.ERROR) { + if (resource.status == Resource.Status.ERROR) { Toast.makeText(getContext(), "Failed to load supplier: " + resource.message, Toast.LENGTH_SHORT).show(); } }); } + + private void applyViewState(SupplierDetailViewModel.ViewState state) { + binding.tvMode.setText(state.modeTitle); + binding.tvSupId.setText(DateTimeUtils.formatId(viewModel.getSupId())); + binding.tvSupId.setVisibility(state.isSupIdVisible ? View.VISIBLE : View.GONE); + binding.btnDeleteSupplier.setVisibility(state.isDeleteVisible ? View.VISIBLE : View.GONE); + binding.btnSaveSupplier.setText(state.saveButtonText); + + UIUtils.setViewsEnabled(state.isFieldsEnabled, + binding.etSupCompany, + binding.etSupContactFirstName, + binding.etSupContactLastName, + binding.etSupEmail, + binding.etSupPhone); + + updateIfDifferent(binding.etSupCompany, state.supCompany); + updateIfDifferent(binding.etSupContactFirstName, state.supFirstName); + updateIfDifferent(binding.etSupContactLastName, state.supLastName); + updateIfDifferent(binding.etSupEmail, state.supEmail); + updateIfDifferent(binding.etSupPhone, state.supPhone); + } + + private void updateIfDifferent(EditText field, String value) { + String current = field.getText() != null ? field.getText().toString() : ""; + String next = value != null ? value : ""; + if (!current.equals(next)) { + field.setText(next); + } + } } diff --git a/android/app/src/main/java/com/example/petstoremobile/viewmodels/AdoptionDetailViewModel.java b/android/app/src/main/java/com/example/petstoremobile/viewmodels/AdoptionDetailViewModel.java index f6e24cd6..6a8ae492 100644 --- a/android/app/src/main/java/com/example/petstoremobile/viewmodels/AdoptionDetailViewModel.java +++ b/android/app/src/main/java/com/example/petstoremobile/viewmodels/AdoptionDetailViewModel.java @@ -27,12 +27,12 @@ public class AdoptionDetailViewModel extends ViewModel { private final StoreRepository storeRepository; private long adoptionId = -1; - private boolean isEditing = false; private final MutableLiveData> petList = new MutableLiveData<>(new ArrayList<>()); private final MutableLiveData> customerList = new MutableLiveData<>(new ArrayList<>()); private final MutableLiveData> storeList = new MutableLiveData<>(new ArrayList<>()); private final MutableLiveData> employeeList = new MutableLiveData<>(new ArrayList<>()); + private final MutableLiveData viewState = new MutableLiveData<>(new ViewState()); @Inject public AdoptionDetailViewModel(AdoptionRepository adoptionRepository, PetRepository petRepository, @@ -45,7 +45,7 @@ public class AdoptionDetailViewModel extends ViewModel { public void setAdoptionId(long id) { this.adoptionId = id; - this.isEditing = id != -1; + initMode(id != -1); } public long getAdoptionId() { @@ -53,50 +53,155 @@ public class AdoptionDetailViewModel extends ViewModel { } public boolean isEditing() { - return isEditing; + ViewState current = viewState.getValue(); + return current != null && current.isEditing; + } + + public LiveData getViewState() { + return viewState; + } + + public void initMode(boolean isEditing) { + updateViewState(state -> { + state.isEditing = isEditing; + state.modeTitle = isEditing ? "Edit Adoption" : "Add Adoption"; + state.saveButtonText = isEditing ? "Save" : "Add"; + state.isAdoptionIdVisible = isEditing; + state.isDeleteVisible = isEditing; + state.isPetEnabled = isEditing; + state.isEmployeeEnabled = isEditing; + }); + } + + public void loadInitialFormData() { + petRepository.getAdoptionPets().observeForever(r -> { + if (r != null && r.status == Resource.Status.SUCCESS && r.data != null) { + petList.setValue(r.data); + } + }); + customerRepository.getCustomerDropdowns().observeForever(r -> { + if (r != null && r.status == Resource.Status.SUCCESS && r.data != null) { + customerList.setValue(r.data); + } + }); + storeRepository.getStoreDropdowns().observeForever(r -> { + if (r != null && r.status == Resource.Status.SUCCESS && r.data != null) { + storeList.setValue(r.data); + } + }); + } + + public void onCustomerSelected(int position) { + List list = customerList.getValue(); + Long customerId = (position > 0 && list != null && position <= list.size()) + ? list.get(position - 1).getId() : null; + updateViewState(state -> { + state.selectedCustomerId = customerId; + state.isPetEnabled = customerId != null; + if (customerId == null && !state.isEditing) { + state.selectedPetId = null; + } + }); + } + + public void onStoreSelected(int position) { + List list = storeList.getValue(); + if (position > 0 && list != null && position <= list.size()) { + Long storeId = list.get(position - 1).getId(); + updateViewState(state -> { + state.selectedStoreId = storeId; + state.isEmployeeEnabled = true; + }); + loadEmployeesForStore(storeId); + } else { + employeeList.setValue(new ArrayList<>()); + updateViewState(state -> { + state.selectedStoreId = null; + state.selectedEmployeeId = null; + state.isEmployeeEnabled = false; + }); + } + } + + private void loadEmployeesForStore(Long storeId) { + storeRepository.getStoreEmployees(storeId).observeForever(r -> { + if (r != null && r.status == Resource.Status.SUCCESS && r.data != null) { + employeeList.setValue(r.data); + } + }); } public LiveData> loadAdoption() { - return adoptionRepository.getAdoptionById(adoptionId); - } + MutableLiveData> result = new MutableLiveData<>(); + adoptionRepository.getAdoptionById(adoptionId).observeForever(resource -> { + if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) { + AdoptionDTO a = resource.data; + updateViewState(state -> { + state.selectedPetId = a.getPetId() != null ? a.getPetId() : -1; + state.selectedCustomerId = a.getCustomerId() != null ? a.getCustomerId() : -1; + state.selectedStoreId = a.getSourceStoreId() != null ? a.getSourceStoreId() : -1; + state.selectedEmployeeId = a.getEmployeeId() != null ? a.getEmployeeId() : -1; + state.adoptionDate = a.getAdoptionDate() != null ? a.getAdoptionDate() : ""; + state.adoptionFee = a.getAdoptionFee() != null ? a.getAdoptionFee().toString() : ""; + state.adoptionStatus = a.getAdoptionStatus() != null ? a.getAdoptionStatus() : ""; + state.isPetEnabled = state.selectedCustomerId != null && state.selectedCustomerId != -1; + state.isEmployeeEnabled = state.selectedStoreId != null && state.selectedStoreId != -1; + }); - public LiveData>> loadPets() { - return petRepository.getAdoptionPets(); - } - - public LiveData>> loadCustomers() { - return customerRepository.getCustomerDropdowns(); - } - - public LiveData>> loadStores() { - return storeRepository.getStoreDropdowns(); - } - - public LiveData>> loadEmployees(Long storeId) { - return storeRepository.getStoreEmployees(storeId); + if (a.getSourceStoreId() != null) { + loadEmployeesForStore(a.getSourceStoreId()); + } + } + result.setValue(resource); + }); + return result; } public LiveData> saveAdoption(AdoptionDTO dto) { - if (isEditing) { + if (isEditing()) { return adoptionRepository.updateAdoption(adoptionId, dto); - } else { - return adoptionRepository.createAdoption(dto); } + return adoptionRepository.createAdoption(dto); } public LiveData> deleteAdoption() { return adoptionRepository.deleteAdoption(adoptionId); } - public void setPetList(List list) { petList.setValue(list); } public LiveData> getPetList() { return petList; } - - public void setCustomerList(List list) { customerList.setValue(list); } public LiveData> getCustomerList() { return customerList; } - - public void setStoreList(List list) { storeList.setValue(list); } public LiveData> getStoreList() { return storeList; } - - public void setEmployeeList(List list) { employeeList.setValue(list); } public LiveData> getEmployeeList() { return employeeList; } + + // Kept for backward-compatibility with any remaining direct calls + public void setEmployeeList(List list) { employeeList.setValue(list); } + + private void updateViewState(Action action) { + ViewState current = viewState.getValue(); + if (current != null) { + action.run(current); + viewState.setValue(current); + } + } + + private interface Action { + void run(T target); + } + + public static class ViewState { + public boolean isEditing = false; + public boolean isAdoptionIdVisible = false; + public boolean isDeleteVisible = false; + public boolean isPetEnabled = false; + public boolean isEmployeeEnabled = false; + public String modeTitle = "Add Adoption"; + public String saveButtonText = "Add"; + public Long selectedPetId = null; + public Long selectedCustomerId = null; + public Long selectedStoreId = null; + public Long selectedEmployeeId = null; + public String adoptionDate = ""; + public String adoptionFee = ""; + public String adoptionStatus = ""; + } } diff --git a/android/app/src/main/java/com/example/petstoremobile/viewmodels/ProductDetailViewModel.java b/android/app/src/main/java/com/example/petstoremobile/viewmodels/ProductDetailViewModel.java index 9ec0628a..54ff65b5 100644 --- a/android/app/src/main/java/com/example/petstoremobile/viewmodels/ProductDetailViewModel.java +++ b/android/app/src/main/java/com/example/petstoremobile/viewmodels/ProductDetailViewModel.java @@ -83,3 +83,4 @@ public class ProductDetailViewModel extends ViewModel { return categoryList; } } + diff --git a/android/app/src/main/java/com/example/petstoremobile/viewmodels/SupplierDetailViewModel.java b/android/app/src/main/java/com/example/petstoremobile/viewmodels/SupplierDetailViewModel.java index 591beb52..88078102 100644 --- a/android/app/src/main/java/com/example/petstoremobile/viewmodels/SupplierDetailViewModel.java +++ b/android/app/src/main/java/com/example/petstoremobile/viewmodels/SupplierDetailViewModel.java @@ -1,6 +1,7 @@ package com.example.petstoremobile.viewmodels; import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.ViewModel; import com.example.petstoremobile.dtos.SupplierDTO; @@ -14,8 +15,9 @@ import dagger.hilt.android.lifecycle.HiltViewModel; @HiltViewModel public class SupplierDetailViewModel extends ViewModel { private final SupplierRepository repository; + private final MutableLiveData viewState = new MutableLiveData<>(new ViewState()); + private long supId = -1; - private boolean isEditing = false; @Inject public SupplierDetailViewModel(SupplierRepository repository) { @@ -24,7 +26,7 @@ public class SupplierDetailViewModel extends ViewModel { public void setSupId(long id) { this.supId = id; - this.isEditing = id != -1; + initMode(id != -1); } public long getSupId() { @@ -32,23 +34,82 @@ public class SupplierDetailViewModel extends ViewModel { } public boolean isEditing() { - return isEditing; + ViewState current = viewState.getValue(); + return current != null && current.isEditing; + } + + public LiveData getViewState() { + return viewState; + } + + public void initMode(boolean isEditing) { + updateViewState(state -> { + state.isEditing = isEditing; + state.modeTitle = isEditing ? "Edit Supplier" : "Add Supplier"; + state.saveButtonText = isEditing ? "Save" : "Add"; + state.isSupIdVisible = isEditing; + state.isDeleteVisible = isEditing; + state.isFieldsEnabled = true; + }); } public LiveData> loadSupplier() { - return repository.getSupplierById(supId); + MutableLiveData> result = new MutableLiveData<>(); + repository.getSupplierById(supId).observeForever(resource -> { + if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) { + SupplierDTO s = resource.data; + updateViewState(state -> { + state.supCompany = safeText(s.getSupCompany()); + state.supFirstName = safeText(s.getSupContactFirstName()); + state.supLastName = safeText(s.getSupContactLastName()); + state.supEmail = safeText(s.getSupEmail()); + state.supPhone = safeText(s.getSupPhone()); + }); + } + result.setValue(resource); + }); + return result; } public LiveData> saveSupplier(SupplierDTO dto) { - if (isEditing) { + if (isEditing()) { dto.setSupId(supId); return repository.updateSupplier(supId, dto); - } else { - return repository.createSupplier(dto); } + return repository.createSupplier(dto); } public LiveData> deleteSupplier() { return repository.deleteSupplier(supId); } + + private String safeText(String value) { + return value == null ? "" : value.trim(); + } + + private void updateViewState(Action action) { + ViewState current = viewState.getValue(); + if (current != null) { + action.run(current); + viewState.setValue(current); + } + } + + private interface Action { + void run(T target); + } + + public static class ViewState { + public boolean isEditing = false; + public boolean isDeleteVisible = false; + public boolean isSupIdVisible = false; + public boolean isFieldsEnabled = true; + public String modeTitle = "Add Supplier"; + public String saveButtonText = "Add"; + public String supCompany = ""; + public String supFirstName = ""; + public String supLastName = ""; + public String supEmail = ""; + public String supPhone = ""; + } } diff --git a/android/app/src/main/res/layout/fragment_adoption_detail.xml b/android/app/src/main/res/layout/fragment_adoption_detail.xml index 0608f96f..a5170113 100644 --- a/android/app/src/main/res/layout/fragment_adoption_detail.xml +++ b/android/app/src/main/res/layout/fragment_adoption_detail.xml @@ -99,6 +99,21 @@ android:layout_height="wrap_content" android:layout_marginBottom="16dp"/> + + + + + - - - -