diff --git a/android/app/src/main/java/com/example/petstoremobile/api/UserApi.java b/android/app/src/main/java/com/example/petstoremobile/api/UserApi.java new file mode 100644 index 00000000..53611e66 --- /dev/null +++ b/android/app/src/main/java/com/example/petstoremobile/api/UserApi.java @@ -0,0 +1,13 @@ +package com.example.petstoremobile.api; + +import com.example.petstoremobile.dtos.PageResponse; +import com.example.petstoremobile.dtos.UserDTO; + +import retrofit2.Call; +import retrofit2.http.GET; +import retrofit2.http.Query; + +public interface UserApi { + @GET("api/v1/users") + Call> getUsers(@Query("role") String role, @Query("page") int page, @Query("size") int size); +} diff --git a/android/app/src/main/java/com/example/petstoremobile/di/NetworkModule.java b/android/app/src/main/java/com/example/petstoremobile/di/NetworkModule.java index 0311840d..b5f1ca64 100644 --- a/android/app/src/main/java/com/example/petstoremobile/di/NetworkModule.java +++ b/android/app/src/main/java/com/example/petstoremobile/di/NetworkModule.java @@ -173,4 +173,10 @@ public class NetworkModule { public static CategoryApi provideCategoryApi(Retrofit retrofit) { return retrofit.create(CategoryApi.class); } -} \ No newline at end of file + + @Provides + @Singleton + public static UserApi provideUserApi(Retrofit retrofit) { + return retrofit.create(UserApi.class); + } +} 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 cf9bb837..7757f156 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 @@ -21,6 +21,7 @@ import com.example.petstoremobile.viewmodels.CustomerViewModel; import com.example.petstoremobile.viewmodels.PetViewModel; import com.example.petstoremobile.viewmodels.ServiceViewModel; import com.example.petstoremobile.viewmodels.StoreViewModel; +import com.example.petstoremobile.viewmodels.UserViewModel; import java.util.*; @@ -40,11 +41,13 @@ public class AppointmentDetailFragment extends Fragment { private long preselectedServiceId = -1; private long preselectedCustomerId = -1; private long preselectedStoreId = -1; + private long preselectedStaffId = -1; private List petList = new ArrayList<>(); private List serviceList = new ArrayList<>(); private List customerList = new ArrayList<>(); private List storeList = new ArrayList<>(); + private List staffList = new ArrayList<>(); private final Integer[] HOURS = {9,10,11,12,13,14,15,16,17}; private final Integer[] MINUTES = {0,15,30,45}; @@ -54,6 +57,7 @@ public class AppointmentDetailFragment extends Fragment { private ServiceViewModel serviceViewModel; private StoreViewModel storeViewModel; private CustomerViewModel customerViewModel; + private UserViewModel userViewModel; @Override public void onCreate(Bundle savedInstanceState) { @@ -63,6 +67,7 @@ public class AppointmentDetailFragment extends Fragment { serviceViewModel = new ViewModelProvider(this).get(ServiceViewModel.class); storeViewModel = new ViewModelProvider(this).get(StoreViewModel.class); customerViewModel = new ViewModelProvider(this).get(CustomerViewModel.class); + userViewModel = new ViewModelProvider(this).get(UserViewModel.class); } @Override @@ -128,6 +133,7 @@ public class AppointmentDetailFragment extends Fragment { loadServices(); loadCustomers(); loadStores(); + loadStaff(); } /** @@ -215,6 +221,27 @@ public class AppointmentDetailFragment extends Fragment { preselectedStoreId, StoreDTO::getStoreId); } + /** + * Loads the list of staff from the API. + */ + private void loadStaff() { + userViewModel.getUsers("STAFF", 0, 100).observe(getViewLifecycleOwner(), resource -> { + if (resource.status == Resource.Status.SUCCESS && resource.data != null) { + staffList = resource.data.getContent(); + refreshStaffSpinner(); + } + }); + } + + /** + * Populates the staff selection spinner. + */ + private void refreshStaffSpinner() { + SpinnerUtils.populateSpinner(requireContext(), binding.spinnerStaff, staffList, + UserDTO::getFullName, "-- Select Staff --", + preselectedStaffId, UserDTO::getId); + } + /** * Handles arguments to determine if the fragment is in edit or add mode. */ @@ -247,6 +274,7 @@ public class AppointmentDetailFragment extends Fragment { preselectedServiceId = (a.getServiceId() != null) ? a.getServiceId() : -1; preselectedCustomerId = (a.getCustomerId() != null) ? a.getCustomerId() : -1; preselectedStoreId = (a.getStoreId() != null) ? a.getStoreId() : -1; + preselectedStaffId = (a.getEmployeeId() != null) ? a.getEmployeeId() : -1; binding.etAppointmentDate.setText(a.getAppointmentDate()); @@ -276,6 +304,7 @@ public class AppointmentDetailFragment extends Fragment { refreshServiceSpinner(); refreshCustomerSpinner(); refreshStoreSpinner(); + refreshStaffSpinner(); } else if (resource.status == Resource.Status.ERROR) { Toast.makeText(getContext(), "Failed to load appointment: " + resource.message, Toast.LENGTH_SHORT).show(); } @@ -307,6 +336,11 @@ public class AppointmentDetailFragment extends Fragment { StoreDTO store = storeList.get(binding.spinnerStore.getSelectedItemPosition() - 1); PetDTO pet = petList.get(binding.spinnerPet.getSelectedItemPosition() - 1); ServiceDTO service = serviceList.get(binding.spinnerService.getSelectedItemPosition() - 1); + + Long employeeId = null; + if (binding.spinnerStaff.getSelectedItemPosition() > 0) { + employeeId = staffList.get(binding.spinnerStaff.getSelectedItemPosition() - 1).getId(); + } String time = String.format("%02d:%02d", HOURS[binding.spinnerHour.getSelectedItemPosition()], @@ -346,6 +380,7 @@ public class AppointmentDetailFragment extends Fragment { customer.getCustomerId(), store.getStoreId(), service.getServiceId(), + employeeId, date, time, status, diff --git a/android/app/src/main/java/com/example/petstoremobile/repositories/UserRepository.java b/android/app/src/main/java/com/example/petstoremobile/repositories/UserRepository.java new file mode 100644 index 00000000..0ed9ced9 --- /dev/null +++ b/android/app/src/main/java/com/example/petstoremobile/repositories/UserRepository.java @@ -0,0 +1,26 @@ +package com.example.petstoremobile.repositories; + +import androidx.lifecycle.LiveData; + +import com.example.petstoremobile.api.UserApi; +import com.example.petstoremobile.dtos.PageResponse; +import com.example.petstoremobile.dtos.UserDTO; +import com.example.petstoremobile.utils.Resource; + +import javax.inject.Inject; +import javax.inject.Singleton; + +@Singleton +public class UserRepository extends BaseRepository { + private final UserApi userApi; + + @Inject + public UserRepository(UserApi userApi) { + super("UserRepository"); + this.userApi = userApi; + } + + public LiveData>> getUsers(String role, int page, int size) { + return executeCall(userApi.getUsers(role, page, size)); + } +} diff --git a/android/app/src/main/java/com/example/petstoremobile/viewmodels/UserViewModel.java b/android/app/src/main/java/com/example/petstoremobile/viewmodels/UserViewModel.java new file mode 100644 index 00000000..d839f6c4 --- /dev/null +++ b/android/app/src/main/java/com/example/petstoremobile/viewmodels/UserViewModel.java @@ -0,0 +1,27 @@ +package com.example.petstoremobile.viewmodels; + +import androidx.lifecycle.LiveData; +import androidx.lifecycle.ViewModel; + +import com.example.petstoremobile.dtos.PageResponse; +import com.example.petstoremobile.dtos.UserDTO; +import com.example.petstoremobile.repositories.UserRepository; +import com.example.petstoremobile.utils.Resource; + +import javax.inject.Inject; + +import dagger.hilt.android.lifecycle.HiltViewModel; + +@HiltViewModel +public class UserViewModel extends ViewModel { + private final UserRepository userRepository; + + @Inject + public UserViewModel(UserRepository userRepository) { + this.userRepository = userRepository; + } + + public LiveData>> getUsers(String role, int page, int size) { + return userRepository.getUsers(role, page, size); + } +} diff --git a/android/app/src/main/res/layout/fragment_appointment_detail.xml b/android/app/src/main/res/layout/fragment_appointment_detail.xml index ef1d8b33..1f31bc54 100644 --- a/android/app/src/main/res/layout/fragment_appointment_detail.xml +++ b/android/app/src/main/res/layout/fragment_appointment_detail.xml @@ -124,15 +124,27 @@ android:textSize="12sp" android:layout_marginBottom="4dp"/> - - - + + + + +