changed petDetailFragment to support new backend
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
package com.example.petstoremobile.dtos;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
public class CustomerDTO {
|
||||
@SerializedName("id")
|
||||
private Long customerId;
|
||||
private String firstName;
|
||||
private String lastName;
|
||||
@@ -12,18 +15,34 @@ public class CustomerDTO {
|
||||
return customerId;
|
||||
}
|
||||
|
||||
public void setCustomerId(Long customerId) {
|
||||
this.customerId = customerId;
|
||||
}
|
||||
|
||||
public String getFirstName() {
|
||||
return firstName;
|
||||
}
|
||||
|
||||
public void setFirstName(String firstName) {
|
||||
this.firstName = firstName;
|
||||
}
|
||||
|
||||
public String getLastName() {
|
||||
return lastName;
|
||||
}
|
||||
|
||||
public void setLastName(String lastName) {
|
||||
this.lastName = lastName;
|
||||
}
|
||||
|
||||
public String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public String getFullName() {
|
||||
return firstName + " " + lastName;
|
||||
}
|
||||
@@ -32,7 +51,15 @@ public class CustomerDTO {
|
||||
return createdAt;
|
||||
}
|
||||
|
||||
public void setCreatedAt(String createdAt) {
|
||||
this.createdAt = createdAt;
|
||||
}
|
||||
|
||||
public String getUpdatedAt() {
|
||||
return updatedAt;
|
||||
}
|
||||
}
|
||||
|
||||
public void setUpdatedAt(String updatedAt) {
|
||||
this.updatedAt = updatedAt;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,18 +11,27 @@ import androidx.navigation.fragment.NavHostFragment;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.example.petstoremobile.R;
|
||||
import com.example.petstoremobile.databinding.FragmentPetDetailBinding;
|
||||
import com.example.petstoremobile.dtos.CustomerDTO;
|
||||
import com.example.petstoremobile.dtos.PetDTO;
|
||||
import com.example.petstoremobile.dtos.StoreDTO;
|
||||
import com.example.petstoremobile.utils.ActivityLogger;
|
||||
import com.example.petstoremobile.utils.DialogUtils;
|
||||
import com.example.petstoremobile.utils.InputValidator;
|
||||
import com.example.petstoremobile.utils.Resource;
|
||||
import com.example.petstoremobile.utils.SpinnerUtils;
|
||||
import com.example.petstoremobile.viewmodels.CustomerViewModel;
|
||||
import com.example.petstoremobile.viewmodels.PetViewModel;
|
||||
import com.example.petstoremobile.viewmodels.StoreViewModel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import dagger.hilt.android.AndroidEntryPoint;
|
||||
@@ -38,11 +47,19 @@ public class PetDetailFragment extends Fragment {
|
||||
private boolean isEditing = false;
|
||||
|
||||
private PetViewModel viewModel;
|
||||
private CustomerViewModel customerViewModel;
|
||||
private StoreViewModel storeViewModel;
|
||||
private List<CustomerDTO> customerList = new ArrayList<>();
|
||||
private List<StoreDTO> storeList = new ArrayList<>();
|
||||
private Long selectedCustomerId = null;
|
||||
private Long selectedStoreId = null;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
viewModel = new ViewModelProvider(this).get(PetViewModel.class);
|
||||
customerViewModel = new ViewModelProvider(this).get(CustomerViewModel.class);
|
||||
storeViewModel = new ViewModelProvider(this).get(StoreViewModel.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -57,6 +74,8 @@ public class PetDetailFragment extends Fragment {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
setupSpinner();
|
||||
loadCustomers();
|
||||
loadStores();
|
||||
handleArguments();
|
||||
|
||||
//set button click listeners
|
||||
@@ -90,6 +109,36 @@ public class PetDetailFragment extends Fragment {
|
||||
double price = Double.parseDouble(binding.etPetPrice.getText().toString().trim());
|
||||
String status = binding.spinnerPetStatus.getSelectedItem().toString();
|
||||
|
||||
// Get selected customer
|
||||
Long customerId = null;
|
||||
int customerPos = binding.spinnerCustomer.getSelectedItemPosition();
|
||||
if (customerPos > 0) { // 0 means no customer for pet
|
||||
customerId = customerList.get(customerPos - 1).getCustomerId();
|
||||
}
|
||||
|
||||
// Get selected store
|
||||
Long storeId = null;
|
||||
int storePos = binding.spinnerStore.getSelectedItemPosition();
|
||||
if (storePos > 0) {
|
||||
storeId = storeList.get(storePos - 1).getStoreId();
|
||||
}
|
||||
|
||||
// Validation: If status is Available, a store must be selected
|
||||
if ("Available".equalsIgnoreCase(status)) {
|
||||
if (!InputValidator.isSpinnerSelected(binding.spinnerStore, "Store")) return;
|
||||
}
|
||||
|
||||
// Validation: If status is Owned, an owner must be selected
|
||||
if ("Owned".equalsIgnoreCase(status)) {
|
||||
if (!InputValidator.isSpinnerSelected(binding.spinnerCustomer, "Owner")) return;
|
||||
}
|
||||
|
||||
// Validation: If status is Adopted, an owner and store must be selected
|
||||
if ("Adopted".equalsIgnoreCase(status)) {
|
||||
if (!InputValidator.isSpinnerSelected(binding.spinnerCustomer, "Owner")) return;
|
||||
if (!InputValidator.isSpinnerSelected(binding.spinnerStore, "Store")) return;
|
||||
}
|
||||
|
||||
//create a pet object to send to the API
|
||||
PetDTO petDTO = new PetDTO();
|
||||
petDTO.setPetName(name);
|
||||
@@ -98,6 +147,8 @@ public class PetDetailFragment extends Fragment {
|
||||
petDTO.setPetAge(age);
|
||||
petDTO.setPetPrice(price);
|
||||
petDTO.setPetStatus(status);
|
||||
petDTO.setCustomerId(customerId);
|
||||
petDTO.setStoreId(storeId);
|
||||
|
||||
//check if the pet is being edited or added
|
||||
if (isEditing) {
|
||||
@@ -197,17 +248,118 @@ public class PetDetailFragment extends Fragment {
|
||||
binding.etPetPrice.setText(String.format(Locale.getDefault(), "%.2f", p.getPetPrice()));
|
||||
}
|
||||
SpinnerUtils.setSelectionByValue(binding.spinnerPetStatus, p.getPetStatus());
|
||||
|
||||
selectedCustomerId = p.getCustomerId();
|
||||
updateCustomerSpinnerSelection();
|
||||
|
||||
selectedStoreId = p.getStoreId();
|
||||
updateStoreSpinnerSelection();
|
||||
} else if (resource.status == Resource.Status.ERROR) {
|
||||
Toast.makeText(getContext(), "Failed to load pet: " + resource.message, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the list of customers and populates the spinner.
|
||||
*/
|
||||
private void loadCustomers() {
|
||||
customerViewModel.getAllCustomers(0, 1000).observe(getViewLifecycleOwner(), resource -> {
|
||||
if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
||||
customerList = resource.data.getContent();
|
||||
updateCustomerSpinnerSelection();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the list of stores and populates the spinner.
|
||||
*/
|
||||
private void loadStores() {
|
||||
storeViewModel.getAllStores(0, 1000).observe(getViewLifecycleOwner(), resource -> {
|
||||
if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
||||
storeList = resource.data.getContent();
|
||||
updateStoreSpinnerSelection();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the customer spinner with the current list and sets the selection if needed.
|
||||
*/
|
||||
private void updateCustomerSpinnerSelection() {
|
||||
SpinnerUtils.populateSpinner(
|
||||
requireContext(),
|
||||
binding.spinnerCustomer,
|
||||
customerList,
|
||||
CustomerDTO::getFullName,
|
||||
"No Owner",
|
||||
selectedCustomerId,
|
||||
CustomerDTO::getCustomerId
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the store spinner with the current list and sets the selection if needed.
|
||||
*/
|
||||
private void updateStoreSpinnerSelection() {
|
||||
SpinnerUtils.populateSpinner(
|
||||
requireContext(),
|
||||
binding.spinnerStore,
|
||||
storeList,
|
||||
StoreDTO::getStoreName,
|
||||
"None",
|
||||
selectedStoreId,
|
||||
StoreDTO::getStoreId
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the spinner for pet status selection.
|
||||
*/
|
||||
private void setupSpinner() {
|
||||
SpinnerUtils.setupStringSpinner(requireContext(), binding.spinnerPetStatus,
|
||||
new String[]{"Available", "Adopted"});
|
||||
new String[]{"Available", "Adopted", "Owned"});
|
||||
|
||||
binding.spinnerPetStatus.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
||||
@Override
|
||||
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
||||
String status = parent.getItemAtPosition(position).toString();
|
||||
|
||||
// Clear any existing error icons when status changes
|
||||
clearSpinnerError(binding.spinnerCustomer);
|
||||
clearSpinnerError(binding.spinnerStore);
|
||||
|
||||
//Disable the customer spinner if the status is "Available"
|
||||
if ("Available".equalsIgnoreCase(status)) {
|
||||
binding.spinnerCustomer.setSelection(0);
|
||||
binding.spinnerCustomer.setEnabled(false);
|
||||
} else {
|
||||
binding.spinnerCustomer.setEnabled(true);
|
||||
}
|
||||
|
||||
//Disable the store spinner if the status is "Owned"
|
||||
if ("Owned".equalsIgnoreCase(status)) {
|
||||
binding.spinnerStore.setSelection(0);
|
||||
binding.spinnerStore.setEnabled(false);
|
||||
} else {
|
||||
binding.spinnerStore.setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNothingSelected(AdapterView<?> parent) {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears error messages from a Spinner's selected view.
|
||||
*/
|
||||
private void clearSpinnerError(Spinner spinner) {
|
||||
View selectedView = spinner.getSelectedView();
|
||||
if (selectedView instanceof TextView) {
|
||||
((TextView) selectedView).setError(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,6 +130,13 @@ public class PetProfileFragment extends Fragment {
|
||||
} else {
|
||||
binding.tvPetPrice.setText("$0.00");
|
||||
}
|
||||
|
||||
// Display owner name if available, otherwise show No Owner
|
||||
if (pet.getCustomerName() != null && !pet.getCustomerName().isEmpty()) {
|
||||
binding.tvPetOwner.setText(pet.getCustomerName());
|
||||
} else {
|
||||
binding.tvPetOwner.setText("No Owner");
|
||||
}
|
||||
} else if (resource.status == Resource.Status.ERROR) {
|
||||
Toast.makeText(getContext(), "Failed to load pet data: " + resource.message, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package com.example.petstoremobile.utils;
|
||||
|
||||
import android.view.View;
|
||||
import android.widget.EditText;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
|
||||
public class InputValidator {
|
||||
|
||||
@@ -94,4 +97,21 @@ public class InputValidator {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a selection has been made in a Spinner.
|
||||
* Assumes position 0 is a placeholder like "None" or "Select".
|
||||
*/
|
||||
public static boolean isSpinnerSelected(Spinner spinner, String fieldName) {
|
||||
if (spinner.getSelectedItemPosition() <= 0) {
|
||||
View selectedView = spinner.getSelectedView();
|
||||
if (selectedView instanceof TextView) {
|
||||
TextView tv = (TextView) selectedView;
|
||||
tv.setError(fieldName + " is required");
|
||||
spinner.requestFocus();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import com.example.petstoremobile.adapters.BlackTextArrayAdapter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
@@ -36,7 +37,8 @@ public class SpinnerUtils {
|
||||
if (preselectedId != null && preselectedId != -1) {
|
||||
int offset = (defaultText != null) ? 1 : 0;
|
||||
for (int i = 0; i < data.size(); i++) {
|
||||
if (idExtractor.apply(data.get(i)).equals(preselectedId)) {
|
||||
Long currentId = idExtractor.apply(data.get(i));
|
||||
if (Objects.equals(currentId, preselectedId)) {
|
||||
spinner.setSelection(i + offset);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -161,6 +161,34 @@
|
||||
<Spinner
|
||||
android:id="@+id/spinnerPetStatus"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="16dp"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Owner"
|
||||
android:textColor="@color/text_dark"
|
||||
android:textSize="12sp"
|
||||
android:layout_marginBottom="4dp"/>
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/spinnerCustomer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="16dp"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Store"
|
||||
android:textColor="@color/text_dark"
|
||||
android:textSize="12sp"
|
||||
android:layout_marginBottom="4dp"/>
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/spinnerStore"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
@@ -221,6 +221,35 @@
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:gravity="center"
|
||||
android:background="@color/white"
|
||||
android:layout_marginTop="16dp"
|
||||
android:padding="16dp">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="OWNER"
|
||||
android:textSize="11sp"
|
||||
android:textColor="#888888"
|
||||
android:textAllCaps="true"
|
||||
android:layout_marginBottom="4dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tvPetOwner"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="No Owner"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold"
|
||||
android:textColor="@color/text_dark"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</ScrollView>
|
||||
@@ -241,4 +270,4 @@
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
Reference in New Issue
Block a user