Added so adoption status can be missed and fixed adoption bugs for andriod
This commit is contained in:
@@ -1,11 +1,14 @@
|
|||||||
package com.example.petstoremobile.api;
|
package com.example.petstoremobile.api;
|
||||||
|
|
||||||
|
import com.example.petstoremobile.dtos.DropdownDTO;
|
||||||
import com.example.petstoremobile.dtos.PageResponse;
|
import com.example.petstoremobile.dtos.PageResponse;
|
||||||
import com.example.petstoremobile.dtos.ProductDTO;
|
import com.example.petstoremobile.dtos.ProductDTO;
|
||||||
import okhttp3.MultipartBody;
|
import okhttp3.MultipartBody;
|
||||||
import retrofit2.Call;
|
import retrofit2.Call;
|
||||||
import retrofit2.http.*;
|
import retrofit2.http.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public interface ProductApi {
|
public interface ProductApi {
|
||||||
String PRODUCT_IMAGE_PATH = "api/v1/products/%d/image";
|
String PRODUCT_IMAGE_PATH = "api/v1/products/%d/image";
|
||||||
|
|
||||||
@@ -35,4 +38,10 @@ public interface ProductApi {
|
|||||||
|
|
||||||
@DELETE("api/v1/products/{id}/image")
|
@DELETE("api/v1/products/{id}/image")
|
||||||
Call<Void> deleteProductImage(@Path("id") Long id);
|
Call<Void> deleteProductImage(@Path("id") Long id);
|
||||||
|
|
||||||
|
@GET("api/v1/dropdowns/products")
|
||||||
|
Call<List<DropdownDTO>> getProductDropdowns();
|
||||||
|
|
||||||
|
@GET("api/v1/dropdowns/categories")
|
||||||
|
Call<List<DropdownDTO>> getCategoryDropdowns();
|
||||||
}
|
}
|
||||||
@@ -16,7 +16,7 @@ import android.view.ViewGroup;
|
|||||||
import com.example.petstoremobile.R;
|
import com.example.petstoremobile.R;
|
||||||
import com.example.petstoremobile.adapters.ProductAdapter;
|
import com.example.petstoremobile.adapters.ProductAdapter;
|
||||||
import com.example.petstoremobile.databinding.FragmentProductBinding;
|
import com.example.petstoremobile.databinding.FragmentProductBinding;
|
||||||
import com.example.petstoremobile.dtos.CategoryDTO;
|
import com.example.petstoremobile.dtos.DropdownDTO;
|
||||||
import com.example.petstoremobile.dtos.ProductDTO;
|
import com.example.petstoremobile.dtos.ProductDTO;
|
||||||
import com.example.petstoremobile.utils.SpinnerUtils;
|
import com.example.petstoremobile.utils.SpinnerUtils;
|
||||||
import com.example.petstoremobile.utils.UIUtils;
|
import com.example.petstoremobile.utils.UIUtils;
|
||||||
@@ -74,7 +74,7 @@ public class ProductFragment extends Fragment implements ProductAdapter.OnProduc
|
|||||||
|
|
||||||
viewModel.getCategories().observe(getViewLifecycleOwner(), list -> {
|
viewModel.getCategories().observe(getViewLifecycleOwner(), list -> {
|
||||||
SpinnerUtils.populateWhiteSpinner(requireContext(), binding.spinnerCategory, list,
|
SpinnerUtils.populateWhiteSpinner(requireContext(), binding.spinnerCategory, list,
|
||||||
CategoryDTO::getCategoryName, "All Categories", -1L, CategoryDTO::getCategoryId);
|
DropdownDTO::getLabel, "All Categories", -1L, DropdownDTO::getId);
|
||||||
});
|
});
|
||||||
|
|
||||||
viewModel.getIsLoading().observe(getViewLifecycleOwner(), loading -> {
|
viewModel.getIsLoading().observe(getViewLifecycleOwner(), loading -> {
|
||||||
@@ -111,9 +111,9 @@ public class ProductFragment extends Fragment implements ProductAdapter.OnProduc
|
|||||||
if (query.isEmpty()) query = null;
|
if (query.isEmpty()) query = null;
|
||||||
|
|
||||||
Long categoryId = null;
|
Long categoryId = null;
|
||||||
List<CategoryDTO> categories = viewModel.getCategories().getValue();
|
List<DropdownDTO> categories = viewModel.getCategories().getValue();
|
||||||
if (binding.spinnerCategory.getSelectedItemPosition() > 0 && categories != null && !categories.isEmpty()) {
|
if (binding.spinnerCategory.getSelectedItemPosition() > 0 && categories != null && !categories.isEmpty()) {
|
||||||
categoryId = categories.get(binding.spinnerCategory.getSelectedItemPosition() - 1).getCategoryId();
|
categoryId = categories.get(binding.spinnerCategory.getSelectedItemPosition() - 1).getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
viewModel.loadProducts(query, categoryId);
|
viewModel.loadProducts(query, categoryId);
|
||||||
|
|||||||
@@ -32,8 +32,7 @@ public class AdoptionDetailFragment extends Fragment {
|
|||||||
|
|
||||||
private FragmentAdoptionDetailBinding binding;
|
private FragmentAdoptionDetailBinding binding;
|
||||||
private AdoptionDetailViewModel viewModel;
|
private AdoptionDetailViewModel viewModel;
|
||||||
|
private boolean isUpdatingUI = false;
|
||||||
private final String[] STATUSES = {"Pending", "Completed", "Cancelled"};
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
@@ -109,9 +108,7 @@ public class AdoptionDetailFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setupSpinners() {
|
private void setupSpinners() {
|
||||||
SpinnerUtils.setupStringSpinner(requireContext(), binding.spinnerAdoptionStatus, STATUSES);
|
SpinnerUtils.setupStringSpinner(requireContext(), binding.spinnerAdoptionStatus, new String[]{});
|
||||||
|
|
||||||
UIUtils.setViewsEnabled(false, binding.spinnerAdoptionPet);
|
|
||||||
|
|
||||||
binding.spinnerAdoptionCustomer.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
binding.spinnerAdoptionCustomer.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
||||||
@Override
|
@Override
|
||||||
@@ -130,10 +127,22 @@ public class AdoptionDetailFragment extends Fragment {
|
|||||||
@Override
|
@Override
|
||||||
public void onNothingSelected(AdapterView<?> parent) {}
|
public void onNothingSelected(AdapterView<?> parent) {}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
SpinnerUtils.setOnIndexSelectedListener(binding.spinnerAdoptionPet, p -> viewModel.onPetSelected(p));
|
||||||
|
SpinnerUtils.setOnIndexSelectedListener(binding.spinnerAdoptionStatus, p -> notifyDateStatusChange());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupDatePicker() {
|
private void setupDatePicker() {
|
||||||
binding.etAdoptionDate.setOnClickListener(v -> UIUtils.showDatePicker(requireContext(), binding.etAdoptionDate, null));
|
binding.etAdoptionDate.setOnClickListener(v ->
|
||||||
|
UIUtils.showDatePicker(requireContext(), binding.etAdoptionDate, this::notifyDateStatusChange));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void notifyDateStatusChange() {
|
||||||
|
if (isUpdatingUI) return;
|
||||||
|
String date = binding.etAdoptionDate.getText().toString();
|
||||||
|
Object selected = binding.spinnerAdoptionStatus.getSelectedItem();
|
||||||
|
String status = selected != null ? selected.toString() : "";
|
||||||
|
viewModel.onDateChanged(date, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleArguments() {
|
private void handleArguments() {
|
||||||
@@ -157,14 +166,25 @@ public class AdoptionDetailFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void applyViewState(AdoptionDetailViewModel.ViewState state) {
|
private void applyViewState(AdoptionDetailViewModel.ViewState state) {
|
||||||
|
isUpdatingUI = true;
|
||||||
|
|
||||||
binding.tvAdoptionMode.setText(state.modeTitle);
|
binding.tvAdoptionMode.setText(state.modeTitle);
|
||||||
binding.tvAdoptionId.setText(DateTimeUtils.formatId(viewModel.getAdoptionId()));
|
binding.tvAdoptionId.setText(DateTimeUtils.formatId(viewModel.getAdoptionId()));
|
||||||
binding.tvAdoptionId.setVisibility(state.isAdoptionIdVisible ? View.VISIBLE : View.GONE);
|
binding.tvAdoptionId.setVisibility(state.isAdoptionIdVisible ? View.VISIBLE : View.GONE);
|
||||||
binding.btnDeleteAdoption.setVisibility(state.isDeleteVisible ? View.VISIBLE : View.GONE);
|
binding.btnDeleteAdoption.setVisibility(state.isDeleteVisible ? View.VISIBLE : View.GONE);
|
||||||
binding.btnSaveAdoption.setText(state.saveButtonText);
|
binding.btnSaveAdoption.setText(state.saveButtonText);
|
||||||
|
binding.btnSaveAdoption.setVisibility(state.isSaveVisible ? View.VISIBLE : View.GONE);
|
||||||
|
|
||||||
|
UIUtils.setViewsEnabled(state.isCustomerEnabled, binding.spinnerAdoptionCustomer);
|
||||||
UIUtils.setViewsEnabled(state.isPetEnabled, binding.spinnerAdoptionPet);
|
UIUtils.setViewsEnabled(state.isPetEnabled, binding.spinnerAdoptionPet);
|
||||||
|
UIUtils.setViewsEnabled(state.isStoreEnabled, binding.spinnerAdoptionStore);
|
||||||
UIUtils.setViewsEnabled(state.isEmployeeEnabled, binding.spinnerAdoptionEmployee);
|
UIUtils.setViewsEnabled(state.isEmployeeEnabled, binding.spinnerAdoptionEmployee);
|
||||||
|
UIUtils.setViewsEnabled(state.isDateEnabled, binding.etAdoptionDate);
|
||||||
|
UIUtils.setViewsEnabled(state.isFeeEnabled, binding.etAdoptionFee);
|
||||||
|
UIUtils.setViewsEnabled(state.isStatusEnabled, binding.spinnerAdoptionStatus);
|
||||||
|
|
||||||
|
SpinnerUtils.setupStringSpinner(requireContext(), binding.spinnerAdoptionStatus, state.availableStatuses);
|
||||||
|
SpinnerUtils.setSelectionByValue(binding.spinnerAdoptionStatus, state.selectedStatus);
|
||||||
|
|
||||||
if (!state.adoptionDate.isEmpty()) {
|
if (!state.adoptionDate.isEmpty()) {
|
||||||
binding.etAdoptionDate.setText(state.adoptionDate);
|
binding.etAdoptionDate.setText(state.adoptionDate);
|
||||||
@@ -172,9 +192,6 @@ public class AdoptionDetailFragment extends Fragment {
|
|||||||
if (!state.adoptionFee.isEmpty()) {
|
if (!state.adoptionFee.isEmpty()) {
|
||||||
binding.etAdoptionFee.setText(state.adoptionFee);
|
binding.etAdoptionFee.setText(state.adoptionFee);
|
||||||
}
|
}
|
||||||
if (!state.adoptionStatus.isEmpty()) {
|
|
||||||
SpinnerUtils.setSelectionByValue(binding.spinnerAdoptionStatus, state.adoptionStatus);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Re-populate spinners with updated preselected IDs
|
// Re-populate spinners with updated preselected IDs
|
||||||
List<DropdownDTO> pets = viewModel.getPetList().getValue();
|
List<DropdownDTO> pets = viewModel.getPetList().getValue();
|
||||||
@@ -192,6 +209,8 @@ public class AdoptionDetailFragment extends Fragment {
|
|||||||
List<DropdownDTO> employees = viewModel.getEmployeeList().getValue();
|
List<DropdownDTO> employees = viewModel.getEmployeeList().getValue();
|
||||||
if (employees != null) SpinnerUtils.populateSpinner(requireContext(), binding.spinnerAdoptionEmployee,
|
if (employees != null) SpinnerUtils.populateSpinner(requireContext(), binding.spinnerAdoptionEmployee,
|
||||||
employees, DropdownDTO::getLabel, "-- Select Staff --", state.selectedEmployeeId, DropdownDTO::getId);
|
employees, DropdownDTO::getLabel, "-- Select Staff --", state.selectedEmployeeId, DropdownDTO::getId);
|
||||||
|
|
||||||
|
isUpdatingUI = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void saveAdoption() {
|
private void saveAdoption() {
|
||||||
@@ -203,8 +222,7 @@ public class AdoptionDetailFragment extends Fragment {
|
|||||||
BigDecimal fee = BigDecimal.ZERO;
|
BigDecimal fee = BigDecimal.ZERO;
|
||||||
String feeStr = binding.etAdoptionFee.getText().toString().trim();
|
String feeStr = binding.etAdoptionFee.getText().toString().trim();
|
||||||
if (!feeStr.isEmpty()) {
|
if (!feeStr.isEmpty()) {
|
||||||
if (!InputValidator.isPositiveDecimal(binding.etAdoptionFee, "Adoption Fee")) return;
|
try { fee = new BigDecimal(feeStr); } catch (NumberFormatException ignored) {}
|
||||||
fee = new BigDecimal(feeStr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DropdownDTO customer = viewModel.getCustomerList().getValue().get(binding.spinnerAdoptionCustomer.getSelectedItemPosition() - 1);
|
DropdownDTO customer = viewModel.getCustomerList().getValue().get(binding.spinnerAdoptionCustomer.getSelectedItemPosition() - 1);
|
||||||
@@ -217,7 +235,8 @@ public class AdoptionDetailFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String adoptionDate = binding.etAdoptionDate.getText().toString().trim();
|
String adoptionDate = binding.etAdoptionDate.getText().toString().trim();
|
||||||
String status = STATUSES[binding.spinnerAdoptionStatus.getSelectedItemPosition()];
|
Object selectedStatus = binding.spinnerAdoptionStatus.getSelectedItem();
|
||||||
|
String status = selectedStatus != null ? selectedStatus.toString().toUpperCase() : "";
|
||||||
|
|
||||||
AdoptionDTO dto = new AdoptionDTO(
|
AdoptionDTO dto = new AdoptionDTO(
|
||||||
pet.getId(), customer.getId(), employeeId, store.getId(), adoptionDate, status, fee);
|
pet.getId(), customer.getId(), employeeId, store.getId(), adoptionDate, status, fee);
|
||||||
|
|||||||
@@ -177,10 +177,8 @@ public class AppointmentDetailFragment extends Fragment {
|
|||||||
UIUtils.setViewsEnabled(state.isTimeEnabled, binding.spinnerMinute);
|
UIUtils.setViewsEnabled(state.isTimeEnabled, binding.spinnerMinute);
|
||||||
UIUtils.setViewsEnabled(state.isStatusEnabled, binding.spinnerAppointmentStatus);
|
UIUtils.setViewsEnabled(state.isStatusEnabled, binding.spinnerAppointmentStatus);
|
||||||
|
|
||||||
Object selected = binding.spinnerAppointmentStatus.getSelectedItem();
|
|
||||||
String current = selected != null ? selected.toString() : "";
|
|
||||||
SpinnerUtils.setupStringSpinner(requireContext(), binding.spinnerAppointmentStatus, state.availableStatuses);
|
SpinnerUtils.setupStringSpinner(requireContext(), binding.spinnerAppointmentStatus, state.availableStatuses);
|
||||||
SpinnerUtils.setSelectionByValue(binding.spinnerAppointmentStatus, current);
|
SpinnerUtils.setSelectionByValue(binding.spinnerAppointmentStatus, state.selectedStatus);
|
||||||
|
|
||||||
// Re-populate dropdown spinners with current selected IDs from ViewState
|
// Re-populate dropdown spinners with current selected IDs from ViewState
|
||||||
List<DropdownDTO> customers = viewModel.getCustomers().getValue();
|
List<DropdownDTO> customers = viewModel.getCustomers().getValue();
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ public class InventoryDetailFragment extends Fragment {
|
|||||||
if (resource == null) return;
|
if (resource == null) return;
|
||||||
setLoading(resource.status == Resource.Status.LOADING);
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
||||||
viewModel.setProductList(resource.data.getContent());
|
viewModel.setProductList(resource.data);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -105,8 +105,8 @@ public class InventoryDetailFragment extends Fragment {
|
|||||||
|
|
||||||
private void refreshProductSpinner() {
|
private void refreshProductSpinner() {
|
||||||
SpinnerUtils.populateSpinner(requireContext(), binding.spinnerInventoryProduct, viewModel.getProductList().getValue(),
|
SpinnerUtils.populateSpinner(requireContext(), binding.spinnerInventoryProduct, viewModel.getProductList().getValue(),
|
||||||
ProductDTO::getProdName, "-- Select Product --",
|
DropdownDTO::getLabel, "-- Select Product --",
|
||||||
preselectedProductId, ProductDTO::getProdId);
|
preselectedProductId, DropdownDTO::getId);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleArguments() {
|
private void handleArguments() {
|
||||||
@@ -156,9 +156,9 @@ public class InventoryDetailFragment extends Fragment {
|
|||||||
|
|
||||||
int quantity = Integer.parseInt(binding.etQuantity.getText().toString().trim());
|
int quantity = Integer.parseInt(binding.etQuantity.getText().toString().trim());
|
||||||
DropdownDTO store = viewModel.getStoreList().getValue().get(binding.spinnerInventoryStore.getSelectedItemPosition() - 1);
|
DropdownDTO store = viewModel.getStoreList().getValue().get(binding.spinnerInventoryStore.getSelectedItemPosition() - 1);
|
||||||
ProductDTO product = viewModel.getProductList().getValue().get(binding.spinnerInventoryProduct.getSelectedItemPosition() - 1);
|
DropdownDTO product = viewModel.getProductList().getValue().get(binding.spinnerInventoryProduct.getSelectedItemPosition() - 1);
|
||||||
|
|
||||||
InventoryDTO request = new InventoryDTO(product.getProdId(), store.getId(), quantity);
|
InventoryDTO request = new InventoryDTO(product.getId(), store.getId(), quantity);
|
||||||
setButtonsEnabled(false);
|
setButtonsEnabled(false);
|
||||||
|
|
||||||
viewModel.saveInventory(request).observe(getViewLifecycleOwner(), resource -> {
|
viewModel.saveInventory(request).observe(getViewLifecycleOwner(), resource -> {
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ public class ProductDetailFragment extends Fragment {
|
|||||||
if (resource == null) return;
|
if (resource == null) return;
|
||||||
setLoading(resource.status == Resource.Status.LOADING);
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
||||||
viewModel.setCategoryList(resource.data.getContent());
|
viewModel.setCategoryList(resource.data);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -128,8 +128,8 @@ public class ProductDetailFragment extends Fragment {
|
|||||||
|
|
||||||
private void updateCategorySpinner() {
|
private void updateCategorySpinner() {
|
||||||
SpinnerUtils.populateSpinner(requireContext(), binding.spinnerProductCategory, viewModel.getCategoryList().getValue(),
|
SpinnerUtils.populateSpinner(requireContext(), binding.spinnerProductCategory, viewModel.getCategoryList().getValue(),
|
||||||
CategoryDTO::getCategoryName, "-- Select Category --",
|
DropdownDTO::getLabel, "-- Select Category --",
|
||||||
preselectedCategoryId, CategoryDTO::getCategoryId);
|
preselectedCategoryId, DropdownDTO::getId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -248,8 +248,8 @@ public class ProductDetailFragment extends Fragment {
|
|||||||
String desc = binding.etProductDesc.getText().toString().trim();
|
String desc = binding.etProductDesc.getText().toString().trim();
|
||||||
BigDecimal price = new BigDecimal(binding.etProductPrice.getText().toString().trim());
|
BigDecimal price = new BigDecimal(binding.etProductPrice.getText().toString().trim());
|
||||||
|
|
||||||
CategoryDTO category = viewModel.getCategoryList().getValue().get(binding.spinnerProductCategory.getSelectedItemPosition() - 1);
|
DropdownDTO category = viewModel.getCategoryList().getValue().get(binding.spinnerProductCategory.getSelectedItemPosition() - 1);
|
||||||
ProductDTO dto = new ProductDTO(name, category.getCategoryId(), desc, price);
|
ProductDTO dto = new ProductDTO(name, category.getId(), desc, price);
|
||||||
|
|
||||||
viewModel.saveProduct(dto).observe(getViewLifecycleOwner(), resource -> {
|
viewModel.saveProduct(dto).observe(getViewLifecycleOwner(), resource -> {
|
||||||
if (resource == null) return;
|
if (resource == null) return;
|
||||||
|
|||||||
@@ -54,6 +54,13 @@ public class PetRepository extends BaseRepository {
|
|||||||
return executeCall(petApi.getPetDropdowns());
|
return executeCall(petApi.getPetDropdowns());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves available pets for a specific store.
|
||||||
|
*/
|
||||||
|
public LiveData<Resource<PageResponse<PetDTO>>> getAvailablePetsByStore(Long storeId) {
|
||||||
|
return executeCall(petApi.getAllPets(0, 200, null, "available", null, storeId, null, "petName"));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves a specific pet by its ID from the API.
|
* Retrieves a specific pet by its ID from the API.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -3,10 +3,13 @@ package com.example.petstoremobile.repositories;
|
|||||||
import androidx.lifecycle.LiveData;
|
import androidx.lifecycle.LiveData;
|
||||||
|
|
||||||
import com.example.petstoremobile.api.ProductApi;
|
import com.example.petstoremobile.api.ProductApi;
|
||||||
|
import com.example.petstoremobile.dtos.DropdownDTO;
|
||||||
import com.example.petstoremobile.dtos.PageResponse;
|
import com.example.petstoremobile.dtos.PageResponse;
|
||||||
import com.example.petstoremobile.dtos.ProductDTO;
|
import com.example.petstoremobile.dtos.ProductDTO;
|
||||||
import com.example.petstoremobile.utils.Resource;
|
import com.example.petstoremobile.utils.Resource;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
@@ -70,4 +73,18 @@ public class ProductRepository extends BaseRepository {
|
|||||||
public LiveData<Resource<Void>> deleteProductImage(Long id) {
|
public LiveData<Resource<Void>> deleteProductImage(Long id) {
|
||||||
return executeCall(productApi.deleteProductImage(id));
|
return executeCall(productApi.deleteProductImage(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves a list of product dropdowns from the API.
|
||||||
|
*/
|
||||||
|
public LiveData<Resource<List<DropdownDTO>>> getProductDropdowns() {
|
||||||
|
return executeCall(productApi.getProductDropdowns());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves a list of category dropdowns from the API.
|
||||||
|
*/
|
||||||
|
public LiveData<Resource<List<DropdownDTO>>> getCategoryDropdowns() {
|
||||||
|
return executeCall(productApi.getCategoryDropdowns());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,6 +63,31 @@ public class DateTimeUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a given date is strictly before today (today and future return false).
|
||||||
|
* format: date = "YYYY-MM-DD"
|
||||||
|
*/
|
||||||
|
public static boolean isDateBeforeToday(String date) {
|
||||||
|
if (date == null || date.isEmpty()) return false;
|
||||||
|
try {
|
||||||
|
String[] parts = date.split("-");
|
||||||
|
Calendar today = Calendar.getInstance();
|
||||||
|
today.set(Calendar.HOUR_OF_DAY, 0);
|
||||||
|
today.set(Calendar.MINUTE, 0);
|
||||||
|
today.set(Calendar.SECOND, 0);
|
||||||
|
today.set(Calendar.MILLISECOND, 0);
|
||||||
|
|
||||||
|
Calendar selected = Calendar.getInstance();
|
||||||
|
selected.set(Integer.parseInt(parts[0]), Integer.parseInt(parts[1]) - 1,
|
||||||
|
Integer.parseInt(parts[2]), 0, 0, 0);
|
||||||
|
selected.set(Calendar.MILLISECOND, 0);
|
||||||
|
return selected.before(today);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Error parsing date: " + e.getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if a given date and time are in the past.
|
* Checks if a given date and time are in the past.
|
||||||
* format: date = "YYYY-MM-DD", time = "HH:MM"
|
* format: date = "YYYY-MM-DD", time = "HH:MM"
|
||||||
|
|||||||
@@ -10,10 +10,13 @@ import com.example.petstoremobile.repositories.AdoptionRepository;
|
|||||||
import com.example.petstoremobile.repositories.CustomerRepository;
|
import com.example.petstoremobile.repositories.CustomerRepository;
|
||||||
import com.example.petstoremobile.repositories.PetRepository;
|
import com.example.petstoremobile.repositories.PetRepository;
|
||||||
import com.example.petstoremobile.repositories.StoreRepository;
|
import com.example.petstoremobile.repositories.StoreRepository;
|
||||||
|
import com.example.petstoremobile.utils.DateTimeUtils;
|
||||||
import com.example.petstoremobile.utils.Resource;
|
import com.example.petstoremobile.utils.Resource;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
@@ -68,17 +71,30 @@ public class AdoptionDetailViewModel extends ViewModel {
|
|||||||
state.saveButtonText = isEditing ? "Save" : "Add";
|
state.saveButtonText = isEditing ? "Save" : "Add";
|
||||||
state.isAdoptionIdVisible = isEditing;
|
state.isAdoptionIdVisible = isEditing;
|
||||||
state.isDeleteVisible = isEditing;
|
state.isDeleteVisible = isEditing;
|
||||||
state.isPetEnabled = isEditing;
|
state.isFeeEnabled = false; // fee is always read-only
|
||||||
state.isEmployeeEnabled = false;
|
if (!isEditing) {
|
||||||
|
state.isCustomerEnabled = true;
|
||||||
|
state.isStoreEnabled = true;
|
||||||
|
state.isPetEnabled = false; // until customer selected
|
||||||
|
state.isEmployeeEnabled = false; // until store selected
|
||||||
|
state.isDateEnabled = true;
|
||||||
|
state.isStatusEnabled = true;
|
||||||
|
state.availableStatuses = new String[]{"Pending"};
|
||||||
|
state.selectedStatus = "Pending";
|
||||||
|
} else {
|
||||||
|
// edit: date-based logic applied after load
|
||||||
|
state.isCustomerEnabled = false;
|
||||||
|
state.isStoreEnabled = false;
|
||||||
|
state.isPetEnabled = false;
|
||||||
|
state.isEmployeeEnabled = false;
|
||||||
|
state.isDateEnabled = false;
|
||||||
|
state.isStatusEnabled = false;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadInitialFormData(boolean isEditing) {
|
public void loadInitialFormData(boolean isEditing) {
|
||||||
(isEditing ? petRepository.getPetDropdowns() : petRepository.getAdoptionPets()).observeForever(r -> {
|
// Pets are loaded dynamically based on store selection; no pre-load needed.
|
||||||
if (r != null && r.status == Resource.Status.SUCCESS && r.data != null) {
|
|
||||||
petList.setValue(r.data);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
customerRepository.getCustomerDropdowns().observeForever(r -> {
|
customerRepository.getCustomerDropdowns().observeForever(r -> {
|
||||||
if (r != null && r.status == Resource.Status.SUCCESS && r.data != null) {
|
if (r != null && r.status == Resource.Status.SUCCESS && r.data != null) {
|
||||||
customerList.setValue(r.data);
|
customerList.setValue(r.data);
|
||||||
@@ -95,13 +111,7 @@ public class AdoptionDetailViewModel extends ViewModel {
|
|||||||
List<DropdownDTO> list = customerList.getValue();
|
List<DropdownDTO> list = customerList.getValue();
|
||||||
Long customerId = (position > 0 && list != null && position <= list.size())
|
Long customerId = (position > 0 && list != null && position <= list.size())
|
||||||
? list.get(position - 1).getId() : null;
|
? list.get(position - 1).getId() : null;
|
||||||
updateViewState(state -> {
|
updateViewState(state -> state.selectedCustomerId = customerId);
|
||||||
state.selectedCustomerId = customerId;
|
|
||||||
state.isPetEnabled = customerId != null;
|
|
||||||
if (customerId == null && !state.isEditing) {
|
|
||||||
state.selectedPetId = null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onStoreSelected(int position) {
|
public void onStoreSelected(int position) {
|
||||||
@@ -110,19 +120,70 @@ public class AdoptionDetailViewModel extends ViewModel {
|
|||||||
Long storeId = list.get(position - 1).getId();
|
Long storeId = list.get(position - 1).getId();
|
||||||
updateViewState(state -> {
|
updateViewState(state -> {
|
||||||
state.selectedStoreId = storeId;
|
state.selectedStoreId = storeId;
|
||||||
state.isEmployeeEnabled = true;
|
if (!state.isCancelled && !state.isEditing) {
|
||||||
|
state.isEmployeeEnabled = true;
|
||||||
|
state.isPetEnabled = true;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
loadEmployeesForStore(storeId);
|
loadEmployeesForStore(storeId);
|
||||||
|
if (!isEditing()) loadAvailablePetsByStore(storeId);
|
||||||
} else {
|
} else {
|
||||||
employeeList.setValue(new ArrayList<>());
|
employeeList.setValue(new ArrayList<>());
|
||||||
|
petList.setValue(new ArrayList<>());
|
||||||
updateViewState(state -> {
|
updateViewState(state -> {
|
||||||
state.selectedStoreId = null;
|
state.selectedStoreId = null;
|
||||||
state.selectedEmployeeId = null;
|
state.selectedEmployeeId = null;
|
||||||
|
state.selectedPetId = null;
|
||||||
state.isEmployeeEnabled = false;
|
state.isEmployeeEnabled = false;
|
||||||
|
state.isPetEnabled = false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void onPetSelected(int position) {
|
||||||
|
List<DropdownDTO> list = petList.getValue();
|
||||||
|
if (position > 0 && list != null && position <= list.size()) {
|
||||||
|
Long petId = list.get(position - 1).getId();
|
||||||
|
updateViewState(s -> s.selectedPetId = petId);
|
||||||
|
loadPetPrice(petId);
|
||||||
|
} else {
|
||||||
|
updateViewState(s -> {
|
||||||
|
s.selectedPetId = null;
|
||||||
|
s.adoptionFee = "";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadAvailablePetsByStore(Long storeId) {
|
||||||
|
petRepository.getAvailablePetsByStore(storeId).observeForever(r -> {
|
||||||
|
if (r != null && r.status == Resource.Status.SUCCESS && r.data != null) {
|
||||||
|
List<DropdownDTO> dropdowns = new ArrayList<>();
|
||||||
|
for (com.example.petstoremobile.dtos.PetDTO pet : r.data.getContent()) {
|
||||||
|
dropdowns.add(new DropdownDTO(pet.getPetId(), pet.getPetName()));
|
||||||
|
}
|
||||||
|
petList.setValue(dropdowns);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadPetPrice(Long petId) {
|
||||||
|
petRepository.getPetById(petId).observeForever(r -> {
|
||||||
|
if (r != null && r.status == Resource.Status.SUCCESS && r.data != null) {
|
||||||
|
com.example.petstoremobile.dtos.PetDTO pet = r.data;
|
||||||
|
// In edit mode, add the pet to the list so the spinner can display its name
|
||||||
|
if (isEditing()) {
|
||||||
|
List<DropdownDTO> single = new ArrayList<>();
|
||||||
|
single.add(new DropdownDTO(pet.getPetId(), pet.getPetName()));
|
||||||
|
petList.setValue(single);
|
||||||
|
}
|
||||||
|
if (pet.getPetPrice() != null) {
|
||||||
|
String price = String.format(Locale.getDefault(), "%.2f", pet.getPetPrice());
|
||||||
|
updateViewState(s -> s.adoptionFee = price);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private void loadEmployeesForStore(Long storeId) {
|
private void loadEmployeesForStore(Long storeId) {
|
||||||
storeRepository.getStoreEmployees(storeId).observeForever(r -> {
|
storeRepository.getStoreEmployees(storeId).observeForever(r -> {
|
||||||
if (r != null && r.status == Resource.Status.SUCCESS && r.data != null) {
|
if (r != null && r.status == Resource.Status.SUCCESS && r.data != null) {
|
||||||
@@ -131,26 +192,99 @@ public class AdoptionDetailViewModel extends ViewModel {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the date or status changes in the UI. Applies date-based field enabling.
|
||||||
|
*/
|
||||||
|
public void onDateChanged(String date, String currentStatus) {
|
||||||
|
updateViewState(s -> {
|
||||||
|
if (s.isCancelled) return;
|
||||||
|
s.availableStatuses = calculateAvailableStatuses(s.isEditing, date);
|
||||||
|
List<String> available = Arrays.asList(s.availableStatuses);
|
||||||
|
if (!currentStatus.isEmpty() && available.contains(currentStatus)) {
|
||||||
|
s.selectedStatus = currentStatus;
|
||||||
|
} else if (!available.contains(s.selectedStatus) && s.availableStatuses.length > 0) {
|
||||||
|
s.selectedStatus = s.availableStatuses[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!s.isEditing) return; // add mode: field enabling handled separately
|
||||||
|
|
||||||
|
boolean isPast = DateTimeUtils.isDateBeforeToday(date);
|
||||||
|
if (isPast) {
|
||||||
|
setAllEditableFieldsEnabled(s, false);
|
||||||
|
s.isStatusEnabled = true;
|
||||||
|
} else if (!date.isEmpty()) {
|
||||||
|
setAllEditableFieldsEnabled(s, false);
|
||||||
|
s.isEmployeeEnabled = true;
|
||||||
|
s.isDateEnabled = true;
|
||||||
|
s.isStatusEnabled = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private String[] calculateAvailableStatuses(boolean isEditing, String date) {
|
||||||
|
if (!isEditing) return new String[]{"Pending"};
|
||||||
|
if (date == null || date.isEmpty()) return new String[]{};
|
||||||
|
if (DateTimeUtils.isDateBeforeToday(date)) return new String[]{"Completed", "Missed"};
|
||||||
|
return new String[]{"Pending", "Cancelled"};
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Disables all editable fields (fee is always disabled separately). */
|
||||||
|
private void setAllEditableFieldsEnabled(ViewState s, boolean enabled) {
|
||||||
|
s.isCustomerEnabled = enabled;
|
||||||
|
s.isStoreEnabled = enabled;
|
||||||
|
s.isPetEnabled = enabled;
|
||||||
|
s.isEmployeeEnabled = enabled;
|
||||||
|
s.isDateEnabled = enabled;
|
||||||
|
// fee never editable
|
||||||
|
}
|
||||||
|
|
||||||
public LiveData<Resource<AdoptionDTO>> loadAdoption() {
|
public LiveData<Resource<AdoptionDTO>> loadAdoption() {
|
||||||
MutableLiveData<Resource<AdoptionDTO>> result = new MutableLiveData<>();
|
MutableLiveData<Resource<AdoptionDTO>> result = new MutableLiveData<>();
|
||||||
adoptionRepository.getAdoptionById(adoptionId).observeForever(resource -> {
|
adoptionRepository.getAdoptionById(adoptionId).observeForever(resource -> {
|
||||||
if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
||||||
AdoptionDTO a = resource.data;
|
AdoptionDTO a = resource.data;
|
||||||
|
String formattedStatus = DateTimeUtils.formatStatusFromBackend(
|
||||||
|
a.getAdoptionStatus() != null ? a.getAdoptionStatus() : "");
|
||||||
|
String adoptionDate = a.getAdoptionDate() != null ? a.getAdoptionDate() : "";
|
||||||
|
|
||||||
updateViewState(state -> {
|
updateViewState(state -> {
|
||||||
state.selectedPetId = a.getPetId() != null ? a.getPetId() : -1;
|
state.selectedPetId = a.getPetId() != null ? a.getPetId() : -1;
|
||||||
state.selectedCustomerId = a.getCustomerId() != null ? a.getCustomerId() : -1;
|
state.selectedCustomerId = a.getCustomerId() != null ? a.getCustomerId() : -1;
|
||||||
state.selectedStoreId = a.getSourceStoreId() != null ? a.getSourceStoreId() : -1;
|
state.selectedStoreId = a.getSourceStoreId() != null ? a.getSourceStoreId() : -1;
|
||||||
state.selectedEmployeeId = a.getEmployeeId() != null ? a.getEmployeeId() : -1;
|
state.selectedEmployeeId = a.getEmployeeId() != null ? a.getEmployeeId() : -1;
|
||||||
state.adoptionDate = a.getAdoptionDate() != null ? a.getAdoptionDate() : "";
|
state.adoptionDate = adoptionDate;
|
||||||
state.adoptionFee = a.getAdoptionFee() != null ? a.getAdoptionFee().toString() : "";
|
state.adoptionFee = a.getAdoptionFee() != null ? a.getAdoptionFee().toPlainString() : "";
|
||||||
state.adoptionStatus = a.getAdoptionStatus() != null ? a.getAdoptionStatus() : "";
|
state.selectedStatus = formattedStatus;
|
||||||
state.isPetEnabled = state.selectedCustomerId != null && state.selectedCustomerId != -1;
|
state.adoptionStatus = formattedStatus;
|
||||||
state.isEmployeeEnabled = state.selectedStoreId != null && state.selectedStoreId != -1;
|
|
||||||
|
if ("Cancelled".equalsIgnoreCase(formattedStatus)) {
|
||||||
|
state.isCancelled = true;
|
||||||
|
state.isCustomerEnabled = false;
|
||||||
|
state.isStoreEnabled = false;
|
||||||
|
state.isPetEnabled = false;
|
||||||
|
state.isEmployeeEnabled = false;
|
||||||
|
state.isStatusEnabled = false;
|
||||||
|
state.isDateEnabled = false;
|
||||||
|
state.isFeeEnabled = false;
|
||||||
|
state.isSaveVisible = false;
|
||||||
|
state.availableStatuses = new String[]{"Cancelled"};
|
||||||
|
} else {
|
||||||
|
state.availableStatuses = calculateAvailableStatuses(true, adoptionDate);
|
||||||
|
boolean isPast = DateTimeUtils.isDateBeforeToday(adoptionDate);
|
||||||
|
if (isPast) {
|
||||||
|
setAllEditableFieldsEnabled(state, false);
|
||||||
|
state.isStatusEnabled = true;
|
||||||
|
} else if (!adoptionDate.isEmpty()) {
|
||||||
|
setAllEditableFieldsEnabled(state, false);
|
||||||
|
state.isEmployeeEnabled = true;
|
||||||
|
state.isDateEnabled = true;
|
||||||
|
state.isStatusEnabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (a.getSourceStoreId() != null) {
|
if (a.getSourceStoreId() != null) loadEmployeesForStore(a.getSourceStoreId());
|
||||||
loadEmployeesForStore(a.getSourceStoreId());
|
if (a.getPetId() != null) loadPetPrice(a.getPetId());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
result.setValue(resource);
|
result.setValue(resource);
|
||||||
});
|
});
|
||||||
@@ -173,7 +307,6 @@ public class AdoptionDetailViewModel extends ViewModel {
|
|||||||
public LiveData<List<DropdownDTO>> getStoreList() { return storeList; }
|
public LiveData<List<DropdownDTO>> getStoreList() { return storeList; }
|
||||||
public LiveData<List<DropdownDTO>> getEmployeeList() { return employeeList; }
|
public LiveData<List<DropdownDTO>> getEmployeeList() { return employeeList; }
|
||||||
|
|
||||||
// Kept for backward-compatibility with any remaining direct calls
|
|
||||||
public void setEmployeeList(List<DropdownDTO> list) { employeeList.setValue(list); }
|
public void setEmployeeList(List<DropdownDTO> list) { employeeList.setValue(list); }
|
||||||
|
|
||||||
private void updateViewState(Action<ViewState> action) {
|
private void updateViewState(Action<ViewState> action) {
|
||||||
@@ -192,8 +325,17 @@ public class AdoptionDetailViewModel extends ViewModel {
|
|||||||
public boolean isEditing = false;
|
public boolean isEditing = false;
|
||||||
public boolean isAdoptionIdVisible = false;
|
public boolean isAdoptionIdVisible = false;
|
||||||
public boolean isDeleteVisible = false;
|
public boolean isDeleteVisible = false;
|
||||||
|
public boolean isCancelled = false;
|
||||||
public boolean isPetEnabled = false;
|
public boolean isPetEnabled = false;
|
||||||
public boolean isEmployeeEnabled = false;
|
public boolean isEmployeeEnabled = false;
|
||||||
|
public boolean isCustomerEnabled = true;
|
||||||
|
public boolean isStoreEnabled = true;
|
||||||
|
public boolean isStatusEnabled = true;
|
||||||
|
public boolean isDateEnabled = true;
|
||||||
|
public boolean isFeeEnabled = false; // always read-only
|
||||||
|
public boolean isSaveVisible = true;
|
||||||
|
public String[] availableStatuses = new String[]{};
|
||||||
|
public String selectedStatus = "";
|
||||||
public String modeTitle = "Add Adoption";
|
public String modeTitle = "Add Adoption";
|
||||||
public String saveButtonText = "Add";
|
public String saveButtonText = "Add";
|
||||||
public Long selectedPetId = null;
|
public Long selectedPetId = null;
|
||||||
|
|||||||
@@ -237,12 +237,14 @@ public class AppointmentDetailViewModel extends ViewModel {
|
|||||||
currentServiceId = a.getServiceId();
|
currentServiceId = a.getServiceId();
|
||||||
currentStaffId = a.getEmployeeId();
|
currentStaffId = a.getEmployeeId();
|
||||||
|
|
||||||
|
String formattedStatus = DateTimeUtils.formatStatusFromBackend(a.getAppointmentStatus());
|
||||||
updateViewState(s -> {
|
updateViewState(s -> {
|
||||||
s.selectedCustomerId = currentCustomerId;
|
s.selectedCustomerId = currentCustomerId;
|
||||||
s.selectedStoreId = currentStoreId;
|
s.selectedStoreId = currentStoreId;
|
||||||
s.selectedPetId = currentPetId;
|
s.selectedPetId = currentPetId;
|
||||||
s.selectedServiceId = currentServiceId;
|
s.selectedServiceId = currentServiceId;
|
||||||
s.selectedStaffId = currentStaffId;
|
s.selectedStaffId = currentStaffId;
|
||||||
|
s.selectedStatus = formattedStatus;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (currentCustomerId != null) loadPetsForCustomer(currentCustomerId);
|
if (currentCustomerId != null) loadPetsForCustomer(currentCustomerId);
|
||||||
@@ -280,6 +282,13 @@ public class AppointmentDetailViewModel extends ViewModel {
|
|||||||
public void onDateOrTimeChanged(String date, String time, String currentStatus) {
|
public void onDateOrTimeChanged(String date, String time, String currentStatus) {
|
||||||
updateViewState(s -> {
|
updateViewState(s -> {
|
||||||
s.availableStatuses = calculateAvailableStatuses(s.isEditing, date, time, currentStatus);
|
s.availableStatuses = calculateAvailableStatuses(s.isEditing, date, time, currentStatus);
|
||||||
|
// Keep selectedStatus if still valid; prefer explicit currentStatus from UI if valid
|
||||||
|
java.util.List<String> available = java.util.Arrays.asList(s.availableStatuses);
|
||||||
|
if (!currentStatus.isEmpty() && available.contains(currentStatus)) {
|
||||||
|
s.selectedStatus = currentStatus;
|
||||||
|
} else if (!available.contains(s.selectedStatus) && s.availableStatuses.length > 0) {
|
||||||
|
s.selectedStatus = s.availableStatuses[0];
|
||||||
|
}
|
||||||
boolean isPast = DateTimeUtils.isDateTimeInPast(date, time);
|
boolean isPast = DateTimeUtils.isDateTimeInPast(date, time);
|
||||||
|
|
||||||
if (isOriginallyCancel) {
|
if (isOriginallyCancel) {
|
||||||
@@ -349,6 +358,7 @@ public class AppointmentDetailViewModel extends ViewModel {
|
|||||||
s.isPetEnabled = false; // until customer selected
|
s.isPetEnabled = false; // until customer selected
|
||||||
s.isStaffEnabled = false; // until store selected
|
s.isStaffEnabled = false; // until store selected
|
||||||
s.availableStatuses = new String[]{"Booked"};
|
s.availableStatuses = new String[]{"Booked"};
|
||||||
|
s.selectedStatus = "Booked";
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -392,6 +402,7 @@ public class AppointmentDetailViewModel extends ViewModel {
|
|||||||
public boolean isTimeEnabled = true;
|
public boolean isTimeEnabled = true;
|
||||||
public boolean isStatusEnabled = true;
|
public boolean isStatusEnabled = true;
|
||||||
public String[] availableStatuses = new String[]{};
|
public String[] availableStatuses = new String[]{};
|
||||||
|
public String selectedStatus = "";
|
||||||
|
|
||||||
// Selected IDs
|
// Selected IDs
|
||||||
public Long selectedCustomerId = null;
|
public Long selectedCustomerId = null;
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ public class InventoryDetailViewModel extends ViewModel {
|
|||||||
private boolean isEditing = false;
|
private boolean isEditing = false;
|
||||||
|
|
||||||
private final MutableLiveData<List<DropdownDTO>> storeList = new MutableLiveData<>(new ArrayList<>());
|
private final MutableLiveData<List<DropdownDTO>> storeList = new MutableLiveData<>(new ArrayList<>());
|
||||||
private final MutableLiveData<List<ProductDTO>> productList = new MutableLiveData<>(new ArrayList<>());
|
private final MutableLiveData<List<DropdownDTO>> productList = new MutableLiveData<>(new ArrayList<>());
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public InventoryDetailViewModel(InventoryRepository inventoryRepository, StoreRepository storeRepository, ProductRepository productRepository) {
|
public InventoryDetailViewModel(InventoryRepository inventoryRepository, StoreRepository storeRepository, ProductRepository productRepository) {
|
||||||
@@ -55,8 +55,8 @@ public class InventoryDetailViewModel extends ViewModel {
|
|||||||
return storeRepository.getStoreDropdowns();
|
return storeRepository.getStoreDropdowns();
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiveData<Resource<PageResponse<ProductDTO>>> loadProducts() {
|
public LiveData<Resource<List<DropdownDTO>>> loadProducts() {
|
||||||
return productRepository.getAllProducts(null, null, 0, 500, "prodName");
|
return productRepository.getProductDropdowns();
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiveData<Resource<InventoryDTO>> saveInventory(InventoryDTO dto) {
|
public LiveData<Resource<InventoryDTO>> saveInventory(InventoryDTO dto) {
|
||||||
@@ -74,6 +74,6 @@ public class InventoryDetailViewModel extends ViewModel {
|
|||||||
public void setStoreList(List<DropdownDTO> list) { storeList.setValue(list); }
|
public void setStoreList(List<DropdownDTO> list) { storeList.setValue(list); }
|
||||||
public LiveData<List<DropdownDTO>> getStoreList() { return storeList; }
|
public LiveData<List<DropdownDTO>> getStoreList() { return storeList; }
|
||||||
|
|
||||||
public void setProductList(List<ProductDTO> list) { productList.setValue(list); }
|
public void setProductList(List<DropdownDTO> list) { productList.setValue(list); }
|
||||||
public LiveData<List<ProductDTO>> getProductList() { return productList; }
|
public LiveData<List<DropdownDTO>> getProductList() { return productList; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import androidx.lifecycle.MutableLiveData;
|
|||||||
import androidx.lifecycle.ViewModel;
|
import androidx.lifecycle.ViewModel;
|
||||||
|
|
||||||
import com.example.petstoremobile.dtos.CategoryDTO;
|
import com.example.petstoremobile.dtos.CategoryDTO;
|
||||||
|
import com.example.petstoremobile.dtos.DropdownDTO;
|
||||||
import com.example.petstoremobile.dtos.PageResponse;
|
import com.example.petstoremobile.dtos.PageResponse;
|
||||||
import com.example.petstoremobile.dtos.ProductDTO;
|
import com.example.petstoremobile.dtos.ProductDTO;
|
||||||
import com.example.petstoremobile.repositories.CategoryRepository;
|
import com.example.petstoremobile.repositories.CategoryRepository;
|
||||||
@@ -24,7 +25,7 @@ public class ProductDetailViewModel extends ViewModel {
|
|||||||
private final ProductRepository productRepository;
|
private final ProductRepository productRepository;
|
||||||
private final CategoryRepository categoryRepository;
|
private final CategoryRepository categoryRepository;
|
||||||
|
|
||||||
private final MutableLiveData<List<CategoryDTO>> categoryList = new MutableLiveData<>(new ArrayList<>());
|
private final MutableLiveData<List<DropdownDTO>> categoryList = new MutableLiveData<>(new ArrayList<>());
|
||||||
private long prodId = -1;
|
private long prodId = -1;
|
||||||
private boolean isEditing = false;
|
private boolean isEditing = false;
|
||||||
|
|
||||||
@@ -47,8 +48,8 @@ public class ProductDetailViewModel extends ViewModel {
|
|||||||
return isEditing;
|
return isEditing;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiveData<Resource<PageResponse<CategoryDTO>>> loadCategories() {
|
public LiveData<Resource<List<DropdownDTO>>> loadCategories() {
|
||||||
return categoryRepository.getAllCategories(0, 100);
|
return productRepository.getCategoryDropdowns();
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiveData<Resource<ProductDTO>> loadProduct() {
|
public LiveData<Resource<ProductDTO>> loadProduct() {
|
||||||
@@ -75,11 +76,11 @@ public class ProductDetailViewModel extends ViewModel {
|
|||||||
return productRepository.deleteProductImage(prodId);
|
return productRepository.deleteProductImage(prodId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setCategoryList(List<CategoryDTO> list) {
|
public void setCategoryList(List<DropdownDTO> list) {
|
||||||
categoryList.setValue(list);
|
categoryList.setValue(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiveData<List<CategoryDTO>> getCategoryList() {
|
public LiveData<List<DropdownDTO>> getCategoryList() {
|
||||||
return categoryList;
|
return categoryList;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import androidx.lifecycle.LiveData;
|
|||||||
import androidx.lifecycle.MutableLiveData;
|
import androidx.lifecycle.MutableLiveData;
|
||||||
import androidx.lifecycle.ViewModel;
|
import androidx.lifecycle.ViewModel;
|
||||||
|
|
||||||
import com.example.petstoremobile.dtos.CategoryDTO;
|
import com.example.petstoremobile.dtos.DropdownDTO;
|
||||||
import com.example.petstoremobile.dtos.ProductDTO;
|
import com.example.petstoremobile.dtos.ProductDTO;
|
||||||
import com.example.petstoremobile.repositories.CategoryRepository;
|
import com.example.petstoremobile.repositories.CategoryRepository;
|
||||||
import com.example.petstoremobile.repositories.ProductRepository;
|
import com.example.petstoremobile.repositories.ProductRepository;
|
||||||
@@ -23,7 +23,7 @@ public class ProductListViewModel extends ViewModel {
|
|||||||
private final CategoryRepository categoryRepository;
|
private final CategoryRepository categoryRepository;
|
||||||
|
|
||||||
private final MutableLiveData<List<ProductDTO>> products = new MutableLiveData<>(new ArrayList<>());
|
private final MutableLiveData<List<ProductDTO>> products = new MutableLiveData<>(new ArrayList<>());
|
||||||
private final MutableLiveData<List<CategoryDTO>> categories = new MutableLiveData<>(new ArrayList<>());
|
private final MutableLiveData<List<DropdownDTO>> categories = new MutableLiveData<>(new ArrayList<>());
|
||||||
private final MutableLiveData<Boolean> isLoading = new MutableLiveData<>(false);
|
private final MutableLiveData<Boolean> isLoading = new MutableLiveData<>(false);
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@@ -33,7 +33,7 @@ public class ProductListViewModel extends ViewModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public LiveData<List<ProductDTO>> getProducts() { return products; }
|
public LiveData<List<ProductDTO>> getProducts() { return products; }
|
||||||
public LiveData<List<CategoryDTO>> getCategories() { return categories; }
|
public LiveData<List<DropdownDTO>> getCategories() { return categories; }
|
||||||
public LiveData<Boolean> getIsLoading() { return isLoading; }
|
public LiveData<Boolean> getIsLoading() { return isLoading; }
|
||||||
|
|
||||||
public void loadProducts(String query, Long categoryId) {
|
public void loadProducts(String query, Long categoryId) {
|
||||||
@@ -51,9 +51,9 @@ public class ProductListViewModel extends ViewModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void loadCategories() {
|
public void loadCategories() {
|
||||||
categoryRepository.getAllCategories(0, 100).observeForever(resource -> {
|
productRepository.getCategoryDropdowns().observeForever(resource -> {
|
||||||
if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
||||||
categories.setValue(resource.data.getContent());
|
categories.setValue(resource.data);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -84,21 +84,6 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="16dp"/>
|
android:layout_marginBottom="16dp"/>
|
||||||
|
|
||||||
<!-- Pet -->
|
|
||||||
<TextView
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="Pet"
|
|
||||||
android:textColor="@color/text_dark"
|
|
||||||
android:textSize="12sp"
|
|
||||||
android:layout_marginBottom="4dp"/>
|
|
||||||
|
|
||||||
<Spinner
|
|
||||||
android:id="@+id/spinnerAdoptionPet"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginBottom="16dp"/>
|
|
||||||
|
|
||||||
<!-- Store -->
|
<!-- Store -->
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
@@ -129,6 +114,21 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="16dp"/>
|
android:layout_marginBottom="16dp"/>
|
||||||
|
|
||||||
|
<!-- Pet -->
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Pet"
|
||||||
|
android:textColor="@color/text_dark"
|
||||||
|
android:textSize="12sp"
|
||||||
|
android:layout_marginBottom="4dp"/>
|
||||||
|
|
||||||
|
<Spinner
|
||||||
|
android:id="@+id/spinnerAdoptionPet"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="16dp"/>
|
||||||
|
|
||||||
<!-- Adoption Date -->
|
<!-- Adoption Date -->
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ public class AdoptionService {
|
|||||||
private static final String ADOPTION_STATUS_PENDING = "Pending";
|
private static final String ADOPTION_STATUS_PENDING = "Pending";
|
||||||
private static final String ADOPTION_STATUS_COMPLETED = "Completed";
|
private static final String ADOPTION_STATUS_COMPLETED = "Completed";
|
||||||
private static final String ADOPTION_STATUS_CANCELLED = "Cancelled";
|
private static final String ADOPTION_STATUS_CANCELLED = "Cancelled";
|
||||||
|
private static final String ADOPTION_STATUS_MISSED = "Missed";
|
||||||
private static final String PET_STATUS_AVAILABLE = "Available";
|
private static final String PET_STATUS_AVAILABLE = "Available";
|
||||||
private static final String PET_STATUS_ADOPTED = "Adopted";
|
private static final String PET_STATUS_ADOPTED = "Adopted";
|
||||||
|
|
||||||
@@ -218,7 +219,10 @@ public class AdoptionService {
|
|||||||
if (ADOPTION_STATUS_CANCELLED.equalsIgnoreCase(trimmedStatus)) {
|
if (ADOPTION_STATUS_CANCELLED.equalsIgnoreCase(trimmedStatus)) {
|
||||||
return ADOPTION_STATUS_CANCELLED;
|
return ADOPTION_STATUS_CANCELLED;
|
||||||
}
|
}
|
||||||
throw new IllegalArgumentException("Adoption status must be Pending, Completed, or Cancelled");
|
if (ADOPTION_STATUS_MISSED.equalsIgnoreCase(trimmedStatus)) {
|
||||||
|
return ADOPTION_STATUS_MISSED;
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException("Adoption status must be Pending, Completed, Cancelled, or Missed");
|
||||||
}
|
}
|
||||||
|
|
||||||
private void validatePetAvailability(Pet pet, Long adoptionId, Long currentPetId) {
|
private void validatePetAvailability(Pet pet, Long adoptionId, Long currentPetId) {
|
||||||
|
|||||||
Reference in New Issue
Block a user