added adoption search and filter andriod and backend
This commit is contained in:
@@ -86,7 +86,7 @@ public class AdoptionAdapter extends RecyclerView.Adapter<AdoptionAdapter.Adopti
|
|||||||
case "Pending":
|
case "Pending":
|
||||||
binding.tvAdoptionStatus.setBackgroundColor(Color.parseColor("#FF9800"));
|
binding.tvAdoptionStatus.setBackgroundColor(Color.parseColor("#FF9800"));
|
||||||
break;
|
break;
|
||||||
case "Rejected":
|
case "Cancelled":
|
||||||
binding.tvAdoptionStatus.setBackgroundColor(Color.parseColor("#F44336"));
|
binding.tvAdoptionStatus.setBackgroundColor(Color.parseColor("#F44336"));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -19,7 +19,12 @@ public interface AdoptionApi {
|
|||||||
@GET("api/v1/adoptions")
|
@GET("api/v1/adoptions")
|
||||||
Call<PageResponse<AdoptionDTO>> getAllAdoptions(
|
Call<PageResponse<AdoptionDTO>> getAllAdoptions(
|
||||||
@Query("page") int page,
|
@Query("page") int page,
|
||||||
@Query("size") int size);
|
@Query("size") int size,
|
||||||
|
@Query("q") String query,
|
||||||
|
@Query("status") String status,
|
||||||
|
@Query("storeId") Long storeId,
|
||||||
|
@Query("date") String date,
|
||||||
|
@Query("employeeId") Long employeeId);
|
||||||
|
|
||||||
@GET("api/v1/adoptions/{id}")
|
@GET("api/v1/adoptions/{id}")
|
||||||
Call<AdoptionDTO> getAdoptionById(@Path("id") Long id);
|
Call<AdoptionDTO> getAdoptionById(@Path("id") Long id);
|
||||||
|
|||||||
@@ -2,9 +2,14 @@ package com.example.petstoremobile.fragments.listfragments;
|
|||||||
|
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.text.Editable;
|
||||||
|
import android.text.TextWatcher;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.*;
|
import android.view.LayoutInflater;
|
||||||
import android.widget.*;
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
@@ -16,16 +21,25 @@ import com.example.petstoremobile.R;
|
|||||||
import com.example.petstoremobile.adapters.AdoptionAdapter;
|
import com.example.petstoremobile.adapters.AdoptionAdapter;
|
||||||
import com.example.petstoremobile.databinding.FragmentAdoptionBinding;
|
import com.example.petstoremobile.databinding.FragmentAdoptionBinding;
|
||||||
import com.example.petstoremobile.dtos.AdoptionDTO;
|
import com.example.petstoremobile.dtos.AdoptionDTO;
|
||||||
|
import com.example.petstoremobile.dtos.StoreDTO;
|
||||||
import com.example.petstoremobile.fragments.ListFragment;
|
import com.example.petstoremobile.fragments.ListFragment;
|
||||||
import com.example.petstoremobile.utils.BulkDeleteHandler;
|
import com.example.petstoremobile.utils.BulkDeleteHandler;
|
||||||
|
import com.example.petstoremobile.utils.Resource;
|
||||||
|
import com.example.petstoremobile.utils.SpinnerUtils;
|
||||||
import com.example.petstoremobile.viewmodels.AdoptionViewModel;
|
import com.example.petstoremobile.viewmodels.AdoptionViewModel;
|
||||||
import com.example.petstoremobile.utils.EventDecorator;
|
import com.example.petstoremobile.utils.EventDecorator;
|
||||||
import com.example.petstoremobile.utils.Resource;
|
import com.example.petstoremobile.viewmodels.StoreViewModel;
|
||||||
import com.prolificinteractive.materialcalendarview.CalendarDay;
|
import com.prolificinteractive.materialcalendarview.CalendarDay;
|
||||||
import com.prolificinteractive.materialcalendarview.CalendarMode;
|
import com.prolificinteractive.materialcalendarview.CalendarMode;
|
||||||
|
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
import dagger.hilt.android.AndroidEntryPoint;
|
import dagger.hilt.android.AndroidEntryPoint;
|
||||||
|
|
||||||
@@ -34,21 +48,23 @@ public class AdoptionFragment extends Fragment implements AdoptionAdapter.OnAdop
|
|||||||
|
|
||||||
private FragmentAdoptionBinding binding;
|
private FragmentAdoptionBinding binding;
|
||||||
private List<AdoptionDTO> adoptionList = new ArrayList<>();
|
private List<AdoptionDTO> adoptionList = new ArrayList<>();
|
||||||
private List<AdoptionDTO> filteredList = new ArrayList<>();
|
private List<StoreDTO> storeList = new ArrayList<>();
|
||||||
private AdoptionAdapter adapter;
|
private AdoptionAdapter adapter;
|
||||||
private AdoptionViewModel viewModel;
|
private AdoptionViewModel adoptionViewModel;
|
||||||
|
private StoreViewModel storeViewModel;
|
||||||
private BulkDeleteHandler bulkDeleteHandler;
|
private BulkDeleteHandler bulkDeleteHandler;
|
||||||
private CalendarDay selectedCalendarDay;
|
private CalendarDay selectedCalendarDay;
|
||||||
private boolean isMonthMode = false;
|
private boolean isMonthMode = false;
|
||||||
private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());
|
private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the fragment and its ViewModel.
|
* Initializes the fragment and its ViewModels.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
viewModel = new ViewModelProvider(this).get(AdoptionViewModel.class);
|
adoptionViewModel = new ViewModelProvider(this).get(AdoptionViewModel.class);
|
||||||
|
storeViewModel = new ViewModelProvider(this).get(StoreViewModel.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -61,10 +77,12 @@ public class AdoptionFragment extends Fragment implements AdoptionAdapter.OnAdop
|
|||||||
|
|
||||||
setupRecyclerView();
|
setupRecyclerView();
|
||||||
setupSearch();
|
setupSearch();
|
||||||
|
setupStatusFilter();
|
||||||
|
setupStoreFilter();
|
||||||
setupSwipeRefresh();
|
setupSwipeRefresh();
|
||||||
setupCalendar();
|
setupCalendar();
|
||||||
|
setupFilterToggle();
|
||||||
setupBulkDelete();
|
setupBulkDelete();
|
||||||
loadAdoptions();
|
|
||||||
|
|
||||||
binding.fabAddAdoption.setOnClickListener(v -> openDetail(-1));
|
binding.fabAddAdoption.setOnClickListener(v -> openDetail(-1));
|
||||||
|
|
||||||
@@ -91,7 +109,7 @@ public class AdoptionFragment extends Fragment implements AdoptionAdapter.OnAdop
|
|||||||
binding.btnBulkDelete,
|
binding.btnBulkDelete,
|
||||||
adapter,
|
adapter,
|
||||||
"adoption",
|
"adoption",
|
||||||
viewModel::bulkDeleteAdoptions,
|
adoptionViewModel::bulkDeleteAdoptions,
|
||||||
this::loadAdoptions
|
this::loadAdoptions
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -102,6 +120,13 @@ public class AdoptionFragment extends Fragment implements AdoptionAdapter.OnAdop
|
|||||||
binding = null;
|
binding = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
loadAdoptions();
|
||||||
|
loadStoreData();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Toggles the calendar display between week and month modes.
|
* Toggles the calendar display between week and month modes.
|
||||||
*/
|
*/
|
||||||
@@ -112,6 +137,28 @@ public class AdoptionFragment extends Fragment implements AdoptionAdapter.OnAdop
|
|||||||
.commit();
|
.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets up the filter toggle button to show/hide the filter layout.
|
||||||
|
*/
|
||||||
|
private void setupFilterToggle() {
|
||||||
|
binding.btnToggleFilterAdoption.setOnClickListener(v -> {
|
||||||
|
if (binding.layoutFilterAdoption.getVisibility() == View.GONE) {
|
||||||
|
binding.layoutFilterAdoption.setVisibility(View.VISIBLE);
|
||||||
|
binding.btnToggleFilterAdoption.setImageResource(android.R.drawable.ic_menu_close_clear_cancel);
|
||||||
|
} else {
|
||||||
|
binding.layoutFilterAdoption.setVisibility(View.GONE);
|
||||||
|
binding.btnToggleFilterAdoption.setImageResource(android.R.drawable.ic_menu_search);
|
||||||
|
|
||||||
|
// Reset filters when closing
|
||||||
|
binding.etSearchAdoption.setText("");
|
||||||
|
binding.spinnerStatusAdoption.setSelection(0);
|
||||||
|
binding.spinnerStoreAdoption.setSelection(0);
|
||||||
|
selectedCalendarDay = null;
|
||||||
|
binding.calendarViewAdoption.clearSelection();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets up the date selection listener for the calendar.
|
* Sets up the date selection listener for the calendar.
|
||||||
*/
|
*/
|
||||||
@@ -127,7 +174,7 @@ public class AdoptionFragment extends Fragment implements AdoptionAdapter.OnAdop
|
|||||||
} else {
|
} else {
|
||||||
selectedCalendarDay = null;
|
selectedCalendarDay = null;
|
||||||
}
|
}
|
||||||
filter(binding.etSearchAdoption.getText().toString());
|
loadAdoptions();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,7 +205,7 @@ public class AdoptionFragment extends Fragment implements AdoptionAdapter.OnAdop
|
|||||||
* Initializes the RecyclerView for displaying adoptions.
|
* Initializes the RecyclerView for displaying adoptions.
|
||||||
*/
|
*/
|
||||||
private void setupRecyclerView() {
|
private void setupRecyclerView() {
|
||||||
adapter = new AdoptionAdapter(filteredList, this);
|
adapter = new AdoptionAdapter(adoptionList, this);
|
||||||
binding.recyclerViewAdoptions.setLayoutManager(new LinearLayoutManager(getContext()));
|
binding.recyclerViewAdoptions.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||||
binding.recyclerViewAdoptions.setAdapter(adapter);
|
binding.recyclerViewAdoptions.setAdapter(adapter);
|
||||||
}
|
}
|
||||||
@@ -167,11 +214,39 @@ public class AdoptionFragment extends Fragment implements AdoptionAdapter.OnAdop
|
|||||||
* Sets up the search bar for filtering
|
* Sets up the search bar for filtering
|
||||||
*/
|
*/
|
||||||
private void setupSearch() {
|
private void setupSearch() {
|
||||||
binding.etSearchAdoption.addTextChangedListener(new android.text.TextWatcher() {
|
binding.etSearchAdoption.addTextChangedListener(new TextWatcher() {
|
||||||
public void beforeTextChanged(CharSequence s, int a, int b, int c) {}
|
@Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
|
||||||
public void afterTextChanged(android.text.Editable s) {}
|
@Override public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||||
public void onTextChanged(CharSequence s, int a, int b, int c) {
|
loadAdoptions();
|
||||||
filter(s.toString());
|
}
|
||||||
|
@Override public void afterTextChanged(Editable s) {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures the status filter spinner.
|
||||||
|
*/
|
||||||
|
private void setupStatusFilter() {
|
||||||
|
String[] statuses = {"All Statuses", "Completed", "Pending", "Cancelled"};
|
||||||
|
SpinnerUtils.setupStringFilterSpinner(requireContext(), binding.spinnerStatusAdoption, statuses, this::loadAdoptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures the store filter spinner.
|
||||||
|
*/
|
||||||
|
private void setupStoreFilter() {
|
||||||
|
SpinnerUtils.setupFilterSpinner(binding.spinnerStoreAdoption, this::loadAdoptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.populateWhiteSpinner(requireContext(), binding.spinnerStoreAdoption, storeList,
|
||||||
|
StoreDTO::getStoreName, "All Stores", -1L, StoreDTO::getStoreId);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -184,11 +259,16 @@ public class AdoptionFragment extends Fragment implements AdoptionAdapter.OnAdop
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filters the adoption list based on search query and selected calendar date.
|
* Fetches the adoption list from the server through the ViewModel.
|
||||||
*/
|
*/
|
||||||
private void filter(String query) {
|
private void loadAdoptions() {
|
||||||
filteredList.clear();
|
String query = binding.etSearchAdoption.getText().toString().trim();
|
||||||
String lowerQuery = query.toLowerCase();
|
String status = binding.spinnerStatusAdoption.getSelectedItem() != null ? binding.spinnerStatusAdoption.getSelectedItem().toString() : "All Statuses";
|
||||||
|
|
||||||
|
Long storeId = null;
|
||||||
|
if (binding.spinnerStoreAdoption.getSelectedItemPosition() > 0 && !storeList.isEmpty()) {
|
||||||
|
storeId = storeList.get(binding.spinnerStoreAdoption.getSelectedItemPosition() - 1).getStoreId();
|
||||||
|
}
|
||||||
|
|
||||||
String selectedDateString = null;
|
String selectedDateString = null;
|
||||||
if (selectedCalendarDay != null) {
|
if (selectedCalendarDay != null) {
|
||||||
@@ -196,28 +276,10 @@ public class AdoptionFragment extends Fragment implements AdoptionAdapter.OnAdop
|
|||||||
selectedCalendarDay.getYear(), selectedCalendarDay.getMonth(), selectedCalendarDay.getDay());
|
selectedCalendarDay.getYear(), selectedCalendarDay.getMonth(), selectedCalendarDay.getDay());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (AdoptionDTO a : adoptionList) {
|
if (status.equals("All Statuses")) status = null;
|
||||||
boolean matchesSearch = query.isEmpty() ||
|
else status = status.toUpperCase();
|
||||||
(a.getCustomerName() != null && a.getCustomerName().toLowerCase().contains(lowerQuery)) ||
|
|
||||||
(a.getPetName() != null && a.getPetName().toLowerCase().contains(lowerQuery)) ||
|
|
||||||
(a.getAdoptionStatus() != null && a.getAdoptionStatus().toLowerCase().contains(lowerQuery));
|
|
||||||
|
|
||||||
boolean matchesDate = (selectedDateString == null) ||
|
adoptionViewModel.getAllAdoptions(0, 500, query, status, storeId, selectedDateString, null).observe(getViewLifecycleOwner(), resource -> {
|
||||||
(a.getAdoptionDate() != null && a.getAdoptionDate().startsWith(selectedDateString));
|
|
||||||
|
|
||||||
if (matchesSearch && matchesDate) {
|
|
||||||
filteredList.add(a);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
adapter.notifyDataSetChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetches the adoption list from the server through the ViewModel.
|
|
||||||
*/
|
|
||||||
private void loadAdoptions() {
|
|
||||||
//Load all adoptions from the backend using viewModel
|
|
||||||
viewModel.getAllAdoptions(0, 500).observe(getViewLifecycleOwner(), resource -> {
|
|
||||||
if (resource == null) return;
|
if (resource == null) return;
|
||||||
|
|
||||||
// Check the status to see if the resource is loaded and display the data
|
// Check the status to see if the resource is loaded and display the data
|
||||||
@@ -233,7 +295,7 @@ public class AdoptionFragment extends Fragment implements AdoptionAdapter.OnAdop
|
|||||||
adoptionList.clear();
|
adoptionList.clear();
|
||||||
adoptionList.addAll(resource.data.getContent());
|
adoptionList.addAll(resource.data.getContent());
|
||||||
updateCalendarDecorators();
|
updateCalendarDecorators();
|
||||||
filter(binding.etSearchAdoption != null ? binding.etSearchAdoption.getText().toString() : "");
|
adapter.notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ERROR:
|
case ERROR:
|
||||||
@@ -253,7 +315,7 @@ public class AdoptionFragment extends Fragment implements AdoptionAdapter.OnAdop
|
|||||||
Bundle args = new Bundle();
|
Bundle args = new Bundle();
|
||||||
|
|
||||||
if (position != -1) {
|
if (position != -1) {
|
||||||
AdoptionDTO a = filteredList.get(position);
|
AdoptionDTO a = adoptionList.get(position);
|
||||||
args.putLong("adoptionId", a.getAdoptionId());
|
args.putLong("adoptionId", a.getAdoptionId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,8 +24,8 @@ public class AdoptionRepository extends BaseRepository {
|
|||||||
/**
|
/**
|
||||||
* Retrieves a paginated list of all adoptions from the API.
|
* Retrieves a paginated list of all adoptions from the API.
|
||||||
*/
|
*/
|
||||||
public LiveData<Resource<PageResponse<AdoptionDTO>>> getAllAdoptions(int page, int size) {
|
public LiveData<Resource<PageResponse<AdoptionDTO>>> getAllAdoptions(int page, int size, String query, String status, Long storeId, String date, Long employeeId) {
|
||||||
return executeCall(adoptionApi.getAllAdoptions(page, size));
|
return executeCall(adoptionApi.getAllAdoptions(page, size, query, status, storeId, date, employeeId));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
package com.example.petstoremobile.utils;
|
package com.example.petstoremobile.utils;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.AdapterView;
|
||||||
import android.widget.ArrayAdapter;
|
import android.widget.ArrayAdapter;
|
||||||
import android.widget.Spinner;
|
import android.widget.Spinner;
|
||||||
|
|
||||||
@@ -70,6 +72,30 @@ public class SpinnerUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets up a simple string spinner for filtering with a callback.
|
||||||
|
*/
|
||||||
|
public static void setupStringFilterSpinner(Context context, Spinner spinner, String[] items, Runnable onSelectionChanged) {
|
||||||
|
WhiteTextArrayAdapter<String> adapter = new WhiteTextArrayAdapter<>(context,
|
||||||
|
android.R.layout.simple_spinner_item, items);
|
||||||
|
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||||
|
spinner.setAdapter(adapter);
|
||||||
|
setupFilterSpinner(spinner, onSelectionChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attaches an item selected listener to a spinner that triggers a callback.
|
||||||
|
*/
|
||||||
|
public static void setupFilterSpinner(Spinner spinner, Runnable onSelectionChanged) {
|
||||||
|
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
||||||
|
@Override
|
||||||
|
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
||||||
|
onSelectionChanged.run();
|
||||||
|
}
|
||||||
|
@Override public void onNothingSelected(AdapterView<?> parent) {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the selection of a spinner based on a string value.
|
* Sets the selection of a spinner based on a string value.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -25,10 +25,10 @@ public class AdoptionViewModel extends ViewModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetches a paginated list of all adoptions.
|
* Fetches a paginated list of all adoptions with filters.
|
||||||
*/
|
*/
|
||||||
public LiveData<Resource<PageResponse<AdoptionDTO>>> getAllAdoptions(int page, int size) {
|
public LiveData<Resource<PageResponse<AdoptionDTO>>> getAllAdoptions(int page, int size, String query, String status, Long storeId, String date, Long employeeId) {
|
||||||
return repository.getAllAdoptions(page, size);
|
return repository.getAllAdoptions(page, size, query, status, storeId, date, employeeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
android:id="@+id/header"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="56dp"
|
android:layout_height="56dp"
|
||||||
android:background="@color/primary_dark"
|
android:background="@color/primary_dark"
|
||||||
@@ -34,7 +35,8 @@
|
|||||||
android:text="Adoptions"
|
android:text="Adoptions"
|
||||||
android:textColor="@color/white"
|
android:textColor="@color/white"
|
||||||
android:textSize="20sp"
|
android:textSize="20sp"
|
||||||
android:textStyle="bold"/>
|
android:textStyle="bold"
|
||||||
|
android:layout_marginStart="8dp"/>
|
||||||
|
|
||||||
<ImageButton
|
<ImageButton
|
||||||
android:id="@+id/btnToggleCalendarModeAdoption"
|
android:id="@+id/btnToggleCalendarModeAdoption"
|
||||||
@@ -45,30 +47,90 @@
|
|||||||
app:tint="@color/white"
|
app:tint="@color/white"
|
||||||
android:contentDescription="Toggle Calendar Mode"/>
|
android:contentDescription="Toggle Calendar Mode"/>
|
||||||
|
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/btnToggleFilterAdoption"
|
||||||
|
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>
|
||||||
|
|
||||||
<com.prolificinteractive.materialcalendarview.MaterialCalendarView
|
<LinearLayout
|
||||||
android:id="@+id/calendarViewAdoption"
|
android:id="@+id/layoutFilterAdoption"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:background="@android:color/white"
|
android:orientation="vertical"
|
||||||
app:mcv_showOtherDates="all"
|
android:paddingStart="12dp"
|
||||||
app:mcv_selectionColor="@color/accent_blue"
|
android:paddingEnd="12dp"
|
||||||
app:mcv_calendarMode="week"
|
android:paddingTop="10dp"
|
||||||
app:mcv_tileHeight="40dp" />
|
android:paddingBottom="10dp"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:background="@color/primary_dark"
|
||||||
|
android:elevation="4dp">
|
||||||
|
|
||||||
<EditText
|
<LinearLayout
|
||||||
android:id="@+id/etSearchAdoption"
|
android:layout_width="match_parent"
|
||||||
android:layout_width="match_parent"
|
android:layout_height="44dp"
|
||||||
android:layout_height="wrap_content"
|
android:background="@drawable/bg_search_bar"
|
||||||
android:layout_margin="8dp"
|
android:gravity="center_vertical"
|
||||||
android:hint="Search by customer or pet..."
|
android:paddingStart="12dp"
|
||||||
android:inputType="text"
|
android:paddingEnd="12dp">
|
||||||
android:drawableStart="@android:drawable/ic_menu_search"
|
|
||||||
android:drawablePadding="8dp"
|
<ImageView
|
||||||
android:background="@android:color/white"
|
android:layout_width="18dp"
|
||||||
android:padding="12dp"
|
android:layout_height="18dp"
|
||||||
android:textColor="@color/text_dark"/>
|
android:src="@android:drawable/ic_menu_search"
|
||||||
|
android:alpha="0.6"/>
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/etSearchAdoption"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:hint="Search by customer or pet..."
|
||||||
|
android:inputType="text"
|
||||||
|
android:background="@android:color/transparent"
|
||||||
|
android:textColor="@color/text_dark"
|
||||||
|
android:textColorHint="#99000000"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:paddingStart="8dp"
|
||||||
|
android:paddingEnd="8dp"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_marginTop="8dp">
|
||||||
|
|
||||||
|
<Spinner
|
||||||
|
android:id="@+id/spinnerStatusAdoption"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="44dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="@drawable/bg_spinner"
|
||||||
|
android:paddingStart="12dp"
|
||||||
|
android:paddingEnd="8dp"/>
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="8dp"
|
||||||
|
android:layout_height="0dp"/>
|
||||||
|
|
||||||
|
<Spinner
|
||||||
|
android:id="@+id/spinnerStoreAdoption"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="44dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="@drawable/bg_spinner"
|
||||||
|
android:paddingStart="12dp"
|
||||||
|
android:paddingEnd="8dp"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/layoutBulkDelete"
|
android:id="@+id/layoutBulkDelete"
|
||||||
@@ -101,6 +163,16 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<com.prolificinteractive.materialcalendarview.MaterialCalendarView
|
||||||
|
android:id="@+id/calendarViewAdoption"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@android:color/white"
|
||||||
|
app:mcv_showOtherDates="all"
|
||||||
|
app:mcv_selectionColor="@color/accent_blue"
|
||||||
|
app:mcv_calendarMode="week"
|
||||||
|
app:mcv_tileHeight="40dp" />
|
||||||
|
|
||||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||||
android:id="@+id/swipeRefreshAdoption"
|
android:id="@+id/swipeRefreshAdoption"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ public class AdoptionController {
|
|||||||
@RequestParam(required = false) String q,
|
@RequestParam(required = false) String q,
|
||||||
@RequestParam(required = false) Long customerId,
|
@RequestParam(required = false) Long customerId,
|
||||||
@RequestParam(required = false) String status,
|
@RequestParam(required = false) String status,
|
||||||
|
@RequestParam(required = false) Long storeId,
|
||||||
Pageable pageable) {
|
Pageable pageable) {
|
||||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||||
String role = authentication.getAuthorities().stream()
|
String role = authentication.getAuthorities().stream()
|
||||||
@@ -48,7 +49,7 @@ public class AdoptionController {
|
|||||||
effectiveCustomerId = user.getId();
|
effectiveCustomerId = user.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
return ResponseEntity.ok(adoptionService.getAllAdoptions(q, effectiveCustomerId, status, pageable));
|
return ResponseEntity.ok(adoptionService.getAllAdoptions(q, effectiveCustomerId, status, storeId, pageable));
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/{id}")
|
@GetMapping("/{id}")
|
||||||
|
|||||||
@@ -20,11 +20,13 @@ public interface AdoptionRepository extends JpaRepository<Adoption, Long> {
|
|||||||
"LOWER(a.pet.petName) LIKE LOWER(CONCAT('%', :q, '%'))" +
|
"LOWER(a.pet.petName) LIKE LOWER(CONCAT('%', :q, '%'))" +
|
||||||
")) AND " +
|
")) AND " +
|
||||||
"(:customerId IS NULL OR a.customer.id = :customerId) AND " +
|
"(:customerId IS NULL OR a.customer.id = :customerId) AND " +
|
||||||
"(:status IS NULL OR LOWER(a.adoptionStatus) = LOWER(:status))")
|
"(:status IS NULL OR LOWER(a.adoptionStatus) = LOWER(:status)) AND " +
|
||||||
|
"(:storeId IS NULL OR a.sourceStore.storeId = :storeId)")
|
||||||
Page<Adoption> searchAdoptions(
|
Page<Adoption> searchAdoptions(
|
||||||
@Param("q") String query,
|
@Param("q") String query,
|
||||||
@Param("customerId") Long customerId,
|
@Param("customerId") Long customerId,
|
||||||
@Param("status") String status,
|
@Param("status") String status,
|
||||||
|
@Param("storeId") Long storeId,
|
||||||
Pageable pageable);
|
Pageable pageable);
|
||||||
|
|
||||||
Optional<Adoption> findFirstByPet_IdAndAdoptionStatusOrderByAdoptionDateDesc(Long petId, String adoptionStatus);
|
Optional<Adoption> findFirstByPet_IdAndAdoptionStatusOrderByAdoptionDateDesc(Long petId, String adoptionStatus);
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ public class AdoptionService {
|
|||||||
this.storeRepository = storeRepository;
|
this.storeRepository = storeRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Page<AdoptionResponse> getAllAdoptions(String query, Long customerId, String status, Pageable pageable) {
|
public Page<AdoptionResponse> getAllAdoptions(String query, Long customerId, String status, Long storeId, Pageable pageable) {
|
||||||
String normalizedQuery = normalizeFilter(query);
|
String normalizedQuery = normalizeFilter(query);
|
||||||
String normalizedStatus = normalizeFilter(status);
|
String normalizedStatus = normalizeFilter(status);
|
||||||
|
|
||||||
@@ -46,6 +46,7 @@ public class AdoptionService {
|
|||||||
normalizedQuery,
|
normalizedQuery,
|
||||||
customerId,
|
customerId,
|
||||||
normalizedStatus,
|
normalizedStatus,
|
||||||
|
storeId,
|
||||||
pageable
|
pageable
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user