added more filter options to pets
This commit is contained in:
@@ -23,8 +23,12 @@ import com.example.petstoremobile.adapters.BlackTextArrayAdapter;
|
||||
import com.example.petstoremobile.adapters.PetAdapter;
|
||||
import com.example.petstoremobile.databinding.FragmentPetBinding;
|
||||
import com.example.petstoremobile.dtos.PetDTO;
|
||||
import com.example.petstoremobile.dtos.StoreDTO;
|
||||
import com.example.petstoremobile.fragments.ListFragment;
|
||||
import com.example.petstoremobile.utils.Resource;
|
||||
import com.example.petstoremobile.utils.SpinnerUtils;
|
||||
import com.example.petstoremobile.viewmodels.PetViewModel;
|
||||
import com.example.petstoremobile.viewmodels.StoreViewModel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -38,22 +42,25 @@ import dagger.hilt.android.AndroidEntryPoint;
|
||||
public class PetFragment extends Fragment implements PetAdapter.OnPetClickListener {
|
||||
private FragmentPetBinding binding;
|
||||
private List<PetDTO> petList = new ArrayList<>();
|
||||
private List<StoreDTO> storeList = new ArrayList<>();
|
||||
private PetAdapter adapter;
|
||||
private PetViewModel viewModel;
|
||||
private StoreViewModel storeViewModel;
|
||||
|
||||
@Inject @Named("baseUrl") String baseUrl;
|
||||
|
||||
/**
|
||||
* Initializes the fragment and its associated PetViewModel.
|
||||
* Initializes the fragment and its associated ViewModels.
|
||||
*/
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
viewModel = new ViewModelProvider(this).get(PetViewModel.class);
|
||||
storeViewModel = new ViewModelProvider(this).get(StoreViewModel.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the fragment's UI components, including RecyclerView, search, status filter, and swipe-to-refresh.
|
||||
* Sets up the fragment's UI components, including RecyclerView, filters, and swipe-to-refresh.
|
||||
*/
|
||||
@Override
|
||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
||||
@@ -63,7 +70,10 @@ public class PetFragment extends Fragment implements PetAdapter.OnPetClickListen
|
||||
setupRecyclerView();
|
||||
setupSearch();
|
||||
setupStatusFilter();
|
||||
setupSpeciesFilter();
|
||||
setupStoreFilter();
|
||||
setupSwipeRefresh();
|
||||
setupFilterToggle();
|
||||
|
||||
binding.fabAddPet.setOnClickListener(v -> openPetDetails());
|
||||
|
||||
@@ -87,16 +97,38 @@ public class PetFragment extends Fragment implements PetAdapter.OnPetClickListen
|
||||
}
|
||||
|
||||
/**
|
||||
* Reloads pet data every time the fragment becomes visible.
|
||||
* Reloads data every time the fragment becomes visible.
|
||||
*/
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
loadPetData();
|
||||
loadStoreData();
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the search bar with a for filtering.
|
||||
* Sets up the filter toggle button to show/hide the filter layout.
|
||||
*/
|
||||
private void setupFilterToggle() {
|
||||
binding.btnToggleFilter.setOnClickListener(v -> {
|
||||
if (binding.layoutFilter.getVisibility() == View.GONE) {
|
||||
binding.layoutFilter.setVisibility(View.VISIBLE);
|
||||
binding.btnToggleFilter.setImageResource(android.R.drawable.ic_menu_close_clear_cancel);
|
||||
} else {
|
||||
binding.layoutFilter.setVisibility(View.GONE);
|
||||
binding.btnToggleFilter.setImageResource(android.R.drawable.ic_menu_search);
|
||||
|
||||
// Reset filters when closing
|
||||
binding.etSearchPet.setText("");
|
||||
binding.spinnerStatus.setSelection(0);
|
||||
binding.spinnerSpecies.setSelection(0);
|
||||
binding.spinnerStore.setSelection(0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the search bar.
|
||||
*/
|
||||
private void setupSearch() {
|
||||
binding.etSearchPet.addTextChangedListener(new TextWatcher() {
|
||||
@@ -122,57 +154,100 @@ public class PetFragment extends Fragment implements PetAdapter.OnPetClickListen
|
||||
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
||||
loadPetData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNothingSelected(AdapterView<?> parent) {}
|
||||
@Override public void onNothingSelected(AdapterView<?> parent) {}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the SwipeRefreshLayout to allow manual re-fetching of pet data.
|
||||
* Configures the species filter spinner with species.
|
||||
*/
|
||||
private void setupSpeciesFilter() {
|
||||
String[] species = {"All Species", "Dog", "Cat", "Bird", "Rabbit", "Fish", "Hamster"};
|
||||
BlackTextArrayAdapter<String> adapter = new BlackTextArrayAdapter<>(requireContext(), android.R.layout.simple_spinner_item, species);
|
||||
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
binding.spinnerSpecies.setAdapter(adapter);
|
||||
|
||||
binding.spinnerSpecies.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
||||
@Override
|
||||
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
||||
loadPetData();
|
||||
}
|
||||
@Override public void onNothingSelected(AdapterView<?> parent) {}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the store filter spinner.
|
||||
*/
|
||||
private void setupStoreFilter() {
|
||||
binding.spinnerStore.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
||||
@Override
|
||||
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
||||
loadPetData();
|
||||
}
|
||||
@Override public void onNothingSelected(AdapterView<?> parent) {}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches store data to populate the store filter.
|
||||
*/
|
||||
private void loadStoreData() {
|
||||
storeViewModel.getAllStores(0, 100).observe(getViewLifecycleOwner(), resource -> {
|
||||
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
||||
storeList = resource.data.getContent();
|
||||
SpinnerUtils.populateSpinner(requireContext(), binding.spinnerStore, storeList,
|
||||
StoreDTO::getStoreName, "All Stores", -1L, StoreDTO::getStoreId);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the SwipeRefreshLayout.
|
||||
*/
|
||||
private void setupSwipeRefresh() {
|
||||
binding.swipeRefreshPet.setOnRefreshListener(this::loadPetData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Navigates to the pet profile screen for a specific pet.
|
||||
* Navigates to the pet profile screen.
|
||||
*/
|
||||
private void openPetProfile(int position) {
|
||||
Bundle args = new Bundle();
|
||||
PetDTO pet = petList.get(position);
|
||||
args.putLong("petId", pet.getPetId());
|
||||
|
||||
NavHostFragment.findNavController(this).navigate(R.id.nav_pet_profile, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* Navigates to the pet detail screen. (Only used for adding a new pet on this screen)
|
||||
* Navigates to the pet detail screen.
|
||||
*/
|
||||
private void openPetDetails() {
|
||||
NavHostFragment.findNavController(this).navigate(R.id.nav_pet_detail);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles clicks on individual pet items in the list.
|
||||
*/
|
||||
@Override
|
||||
public void onPetClick(int position) {
|
||||
openPetProfile(position);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches pet data from the server with filters and updates the UI.
|
||||
* Fetches pet data from the server with all active filters.
|
||||
*/
|
||||
private void loadPetData() {
|
||||
String query = binding.etSearchPet.getText().toString().trim();
|
||||
String status = binding.spinnerStatus.getSelectedItem().toString();
|
||||
String status = binding.spinnerStatus.getSelectedItem() != null ? binding.spinnerStatus.getSelectedItem().toString() : "All Statuses";
|
||||
String species = binding.spinnerSpecies.getSelectedItem() != null ? binding.spinnerSpecies.getSelectedItem().toString() : "All Species";
|
||||
|
||||
if (status.equals("All Statuses")) {
|
||||
status = null;
|
||||
Long storeId = null;
|
||||
if (binding.spinnerStore.getSelectedItemPosition() > 0 && !storeList.isEmpty()) {
|
||||
storeId = storeList.get(binding.spinnerStore.getSelectedItemPosition() - 1).getStoreId();
|
||||
}
|
||||
|
||||
viewModel.getAllPets(0, 100, query, status, null, null, "petName").observe(getViewLifecycleOwner(), resource -> {
|
||||
if (status.equals("All Statuses")) status = null;
|
||||
if (species.equals("All Species")) species = null;
|
||||
|
||||
viewModel.getAllPets(0, 100, query, status, species, storeId, "petName").observe(getViewLifecycleOwner(), resource -> {
|
||||
if (resource == null) return;
|
||||
|
||||
switch (resource.status) {
|
||||
@@ -197,7 +272,7 @@ public class PetFragment extends Fragment implements PetAdapter.OnPetClickListen
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the RecyclerView with a layout manager and adapter for displaying pets.
|
||||
* Initializes the RecyclerView.
|
||||
*/
|
||||
private void setupRecyclerView() {
|
||||
adapter = new PetAdapter(petList, this);
|
||||
|
||||
@@ -29,42 +29,76 @@
|
||||
android:contentDescription="Open menu"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:text="Pets"
|
||||
android:textColor="@color/white"
|
||||
android:textSize="20sp"
|
||||
android:textStyle="bold"/>
|
||||
android:textStyle="bold"
|
||||
android:layout_marginStart="8dp"/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/btnToggleFilter"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
android:src="@android:drawable/ic_menu_search"
|
||||
android:background="?attr/selectableItemBackgroundBorderless"
|
||||
app:tint="@color/white"
|
||||
android:contentDescription="Toggle filter"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/layoutFilter"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal"
|
||||
android:orientation="vertical"
|
||||
android:padding="8dp"
|
||||
android:gravity="center_vertical">
|
||||
android:visibility="gone"
|
||||
android:background="@color/white">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/etSearchPet"
|
||||
android:layout_width="0dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:layout_weight="1"
|
||||
android:hint="Search..."
|
||||
android:inputType="text"
|
||||
android:drawableStart="@android:drawable/ic_menu_search"
|
||||
android:drawablePadding="8dp"
|
||||
android:background="@android:color/white"
|
||||
android:background="@android:color/transparent"
|
||||
android:padding="12dp"
|
||||
android:textColor="@color/text_dark"/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/spinnerStatus"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_weight="1"
|
||||
android:background="@android:color/transparent"/>
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/spinnerSpecies"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="48dp"
|
||||
android:layout_weight="1"
|
||||
android:layout_marginStart="4dp"
|
||||
android:background="@android:color/transparent"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/spinnerStatus"
|
||||
android:layout_width="140dp"
|
||||
android:id="@+id/spinnerStore"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="48dp"
|
||||
android:layout_marginStart="8dp"
|
||||
android:background="@android:color/white"
|
||||
android:padding="10dp"/>
|
||||
android:layout_marginTop="4dp"
|
||||
android:background="@android:color/transparent"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
|
||||
Reference in New Issue
Block a user