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 0beeaa7e..61dfbcce 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 @@ -44,7 +44,7 @@ public class AdoptionDetailFragment extends Fragment { private List petList = new ArrayList<>(); private List customerList = new ArrayList<>(); private List storeList = new ArrayList<>(); - private List employeeList = new ArrayList<>(); + private List employeeList = new ArrayList<>(); private final String[] STATUSES = {"Pending", "Completed", "Cancelled"}; @@ -95,6 +95,46 @@ public class AdoptionDetailFragment extends Fragment { */ private void setupSpinners() { SpinnerUtils.setupStringSpinner(requireContext(), binding.spinnerAdoptionStatus, STATUSES); + + // Pet spinner disabled by default until customer is selected + binding.spinnerAdoptionPet.setEnabled(false); + binding.spinnerAdoptionPet.setAlpha(0.5f); + + // Listener to enable pet spinner based on customer selection + binding.spinnerAdoptionCustomer.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView parent, View view, int position, long id) { + if (position > 0) { + binding.spinnerAdoptionPet.setEnabled(true); + binding.spinnerAdoptionPet.setAlpha(1.0f); + } else { + if (!isEditing) { + binding.spinnerAdoptionPet.setSelection(0); + binding.spinnerAdoptionPet.setEnabled(false); + binding.spinnerAdoptionPet.setAlpha(0.5f); + } + } + } + @Override + public void onNothingSelected(AdapterView parent) {} + }); + + // Listener to load employees based on selected store + binding.spinnerAdoptionStore.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + @Override + public void onItemSelected(AdapterView parent, View view, int position, long id) { + if (position > 0 && position <= storeList.size()) { + DropdownDTO selectedStore = storeList.get(position - 1); + loadEmployees(selectedStore.getId()); + } else { + employeeList.clear(); + refreshEmployeeSpinner(); + } + } + + @Override + public void onNothingSelected(AdapterView parent) {} + }); } /** @@ -119,7 +159,6 @@ public class AdoptionDetailFragment extends Fragment { loadPets(); loadCustomers(); loadStores(); - loadEmployees(); } /** @@ -187,12 +226,12 @@ public class AdoptionDetailFragment extends Fragment { } /** - * Loads the list of employees from the API. + * Loads the list of employees for a specific store. */ - private void loadEmployees() { - userViewModel.getUsers("STAFF", 0, 100).observe(getViewLifecycleOwner(), resource -> { - if (resource.status == Resource.Status.SUCCESS && resource.data != null) { - employeeList = resource.data.getContent(); + private void loadEmployees(Long storeId) { + storeViewModel.getStoreEmployees(storeId).observe(getViewLifecycleOwner(), resource -> { + if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) { + employeeList = resource.data; refreshEmployeeSpinner(); } }); @@ -203,8 +242,8 @@ public class AdoptionDetailFragment extends Fragment { */ private void refreshEmployeeSpinner() { SpinnerUtils.populateSpinner(requireContext(), binding.spinnerAdoptionEmployee, employeeList, - UserDTO::getFullName, "-- Select Staff --", - preselectedEmployeeId, UserDTO::getId); + DropdownDTO::getLabel, "-- Select Staff --", + preselectedEmployeeId, DropdownDTO::getId); } /** @@ -221,9 +260,14 @@ public class AdoptionDetailFragment extends Fragment { binding.btnDeleteAdoption.setVisibility(View.VISIBLE); loadAdoptionData(); } else { + isEditing = false; binding.tvAdoptionMode.setText("Add Adoption"); binding.btnDeleteAdoption.setVisibility(View.GONE); binding.tvAdoptionId.setVisibility(View.GONE); + + // Explicitly disable in add mode + binding.spinnerAdoptionPet.setEnabled(false); + binding.spinnerAdoptionPet.setAlpha(0.5f); } } @@ -247,7 +291,12 @@ public class AdoptionDetailFragment extends Fragment { refreshPetSpinner(); refreshCustomerSpinner(); refreshStoreSpinner(); - refreshEmployeeSpinner(); + + // In edit mode, if a customer is already set, ensure pet spinner is enabled + if (preselectedCustomerId != -1) { + binding.spinnerAdoptionPet.setEnabled(true); + binding.spinnerAdoptionPet.setAlpha(1.0f); + } } else if (resource.status == Resource.Status.ERROR) { Toast.makeText(getContext(), "Failed to load adoption: " + resource.message, Toast.LENGTH_SHORT).show(); } diff --git a/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/detailfragments/AppointmentDetailFragment.java b/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/detailfragments/AppointmentDetailFragment.java index 1d25207a..86da3ae7 100644 --- a/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/detailfragments/AppointmentDetailFragment.java +++ b/android/app/src/main/java/com/example/petstoremobile/fragments/listfragments/detailfragments/AppointmentDetailFragment.java @@ -108,6 +108,10 @@ public class AppointmentDetailFragment extends Fragment { SpinnerUtils.setupStringSpinner(requireContext(), binding.spinnerHour, hours); SpinnerUtils.setupStringSpinner(requireContext(), binding.spinnerMinute, new String[]{"00","15","30","45"}); + // Pet spinner disabled by default + binding.spinnerPet.setEnabled(false); + binding.spinnerPet.setAlpha(0.5f); + // Listener to load pets based on selected customer binding.spinnerCustomer.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { @Override @@ -115,9 +119,18 @@ public class AppointmentDetailFragment extends Fragment { if (position > 0 && position <= customerList.size()) { DropdownDTO selectedCustomer = customerList.get(position - 1); loadPets(selectedCustomer.getId()); + if (!isEditing) { + binding.spinnerPet.setEnabled(true); + binding.spinnerPet.setAlpha(1.0f); + } } else { petList.clear(); refreshPetSpinner(); + if (!isEditing) { + binding.spinnerPet.setSelection(0); + binding.spinnerPet.setEnabled(false); + binding.spinnerPet.setAlpha(0.5f); + } } } @@ -280,6 +293,7 @@ public class AppointmentDetailFragment extends Fragment { private void handleArguments() { Bundle a = getArguments(); if (a != null && a.containsKey("appointmentId")) { + //edit mode isEditing = true; appointmentId = a.getLong("appointmentId"); binding.tvApptMode.setText("Edit Appointment"); @@ -287,7 +301,6 @@ public class AppointmentDetailFragment extends Fragment { binding.tvAppointmentId.setVisibility(View.VISIBLE); binding.btnDeleteAppointment.setVisibility(View.VISIBLE); - // Disable and fade fields in edit mode binding.spinnerCustomer.setEnabled(false); binding.spinnerStore.setEnabled(false); binding.spinnerPet.setEnabled(false); @@ -304,18 +317,18 @@ public class AppointmentDetailFragment extends Fragment { loadAppointmentData(); } else { + //add mode binding.tvApptMode.setText("Add Appointment"); binding.btnDeleteAppointment.setVisibility(View.GONE); binding.tvAppointmentId.setVisibility(View.GONE); - // enable fields in add mode binding.spinnerCustomer.setEnabled(true); binding.spinnerStore.setEnabled(true); - binding.spinnerPet.setEnabled(true); + binding.spinnerPet.setEnabled(false); + binding.spinnerPet.setAlpha(0.5f); binding.spinnerService.setEnabled(true); binding.spinnerCustomer.setAlpha(1.0f); binding.spinnerStore.setAlpha(1.0f); - binding.spinnerPet.setAlpha(1.0f); binding.spinnerService.setAlpha(1.0f); binding.tvLabelCustomer.setAlpha(1.0f); diff --git a/backend/src/main/java/com/petshop/backend/controller/DropdownController.java b/backend/src/main/java/com/petshop/backend/controller/DropdownController.java index acf77b52..261a56a3 100644 --- a/backend/src/main/java/com/petshop/backend/controller/DropdownController.java +++ b/backend/src/main/java/com/petshop/backend/controller/DropdownController.java @@ -10,6 +10,7 @@ import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import java.util.Comparator; import java.util.List; import java.util.stream.Collectors; @@ -44,6 +45,7 @@ public class DropdownController { return ResponseEntity.ok( petRepository.findAll().stream() .map(p -> new DropdownOption(p.getPetId(), p.getPetName())) + .sorted(Comparator.comparing(DropdownOption::getLabel, String.CASE_INSENSITIVE_ORDER)) .collect(Collectors.toList()) ); } @@ -64,6 +66,7 @@ public class DropdownController { return ResponseEntity.ok( userRepository.findByRoleAndActiveTrue(User.Role.CUSTOMER).stream() .map(u -> new DropdownOption(u.getId(), u.getFirstName() + " " + u.getLastName())) + .sorted(Comparator.comparing(DropdownOption::getLabel, String.CASE_INSENSITIVE_ORDER)) .collect(Collectors.toList()) ); } @@ -74,6 +77,7 @@ public class DropdownController { return ResponseEntity.ok( userRepository.findByRoleAndActiveTrue(User.Role.CUSTOMER).stream() .map(u -> new DropdownOption(u.getId(), u.getFirstName() + " " + u.getLastName())) + .sorted(Comparator.comparing(DropdownOption::getLabel, String.CASE_INSENSITIVE_ORDER)) .collect(Collectors.toList()) ); } @@ -83,6 +87,7 @@ public class DropdownController { return ResponseEntity.ok( serviceRepository.findAll().stream() .map(s -> new DropdownOption(s.getServiceId(), s.getServiceName())) + .sorted(Comparator.comparing(DropdownOption::getLabel, String.CASE_INSENSITIVE_ORDER)) .collect(Collectors.toList()) ); } @@ -92,6 +97,7 @@ public class DropdownController { return ResponseEntity.ok( productRepository.findAll().stream() .map(p -> new DropdownOption(p.getProdId(), p.getProdName())) + .sorted(Comparator.comparing(DropdownOption::getLabel, String.CASE_INSENSITIVE_ORDER)) .collect(Collectors.toList()) ); } @@ -101,6 +107,7 @@ public class DropdownController { return ResponseEntity.ok( categoryRepository.findAll().stream() .map(c -> new DropdownOption(c.getCategoryId(), c.getCategoryName())) + .sorted(Comparator.comparing(DropdownOption::getLabel, String.CASE_INSENSITIVE_ORDER)) .collect(Collectors.toList()) ); } @@ -111,6 +118,7 @@ public class DropdownController { categoryRepository.findAll().stream() .filter(c -> "product".equalsIgnoreCase(c.getCategoryType())) .map(c -> new DropdownOption(c.getCategoryId(), c.getCategoryName())) + .sorted(Comparator.comparing(DropdownOption::getLabel, String.CASE_INSENSITIVE_ORDER)) .collect(Collectors.toList()) ); } @@ -133,6 +141,7 @@ public class DropdownController { return ResponseEntity.ok( storeRepository.findAll().stream() .map(s -> new DropdownOption(s.getStoreId(), s.getStoreName())) + .sorted(Comparator.comparing(DropdownOption::getLabel, String.CASE_INSENSITIVE_ORDER)) .collect(Collectors.toList()) ); } @@ -149,6 +158,7 @@ public class DropdownController { return ResponseEntity.ok( employees.stream() .map(u -> new DropdownOption(u.getId(), u.getFirstName() + " " + u.getLastName())) + .sorted(Comparator.comparing(DropdownOption::getLabel, String.CASE_INSENSITIVE_ORDER)) .collect(Collectors.toList()) ); } @@ -169,6 +179,7 @@ public class DropdownController { return ResponseEntity.ok( supplierRepository.findAll().stream() .map(s -> new DropdownOption(s.getSupId(), s.getSupCompany())) + .sorted(Comparator.comparing(DropdownOption::getLabel, String.CASE_INSENSITIVE_ORDER)) .collect(Collectors.toList()) ); }