fix minor bugs and UI inconsistancy
This commit is contained in:
@@ -2,10 +2,12 @@ package com.example.petstoremobile.adapters;
|
|||||||
|
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.view.*;
|
import android.view.*;
|
||||||
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
import com.example.petstoremobile.R;
|
import com.example.petstoremobile.R;
|
||||||
|
import com.example.petstoremobile.databinding.ItemEmployeeBinding;
|
||||||
import com.example.petstoremobile.dtos.EmployeeDTO;
|
import com.example.petstoremobile.dtos.EmployeeDTO;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -24,47 +26,48 @@ public class EmployeeAdapter extends RecyclerView.Adapter<EmployeeAdapter.Employ
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static class EmployeeViewHolder extends RecyclerView.ViewHolder {
|
public static class EmployeeViewHolder extends RecyclerView.ViewHolder {
|
||||||
TextView tvFullName, tvUsername, tvEmail, tvPhone, tvRole, tvStatus;
|
private final ItemEmployeeBinding binding;
|
||||||
|
|
||||||
public EmployeeViewHolder(@NonNull View v) {
|
public EmployeeViewHolder(@NonNull ItemEmployeeBinding binding) {
|
||||||
super(v);
|
super(binding.getRoot());
|
||||||
tvFullName = v.findViewById(R.id.tvEmployeeFullName);
|
this.binding = binding;
|
||||||
tvUsername = v.findViewById(R.id.tvEmployeeUsername);
|
|
||||||
tvEmail = v.findViewById(R.id.tvEmployeeEmail);
|
|
||||||
tvPhone = v.findViewById(R.id.tvEmployeePhone);
|
|
||||||
tvRole = v.findViewById(R.id.tvEmployeeRole);
|
|
||||||
tvStatus = v.findViewById(R.id.tvEmployeeStatus);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public EmployeeViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
public EmployeeViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||||
View v = LayoutInflater.from(parent.getContext())
|
ItemEmployeeBinding binding = ItemEmployeeBinding.inflate(
|
||||||
.inflate(R.layout.item_employee, parent, false);
|
LayoutInflater.from(parent.getContext()), parent, false);
|
||||||
return new EmployeeViewHolder(v);
|
return new EmployeeViewHolder(binding);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(@NonNull EmployeeViewHolder holder, int position) {
|
public void onBindViewHolder(@NonNull EmployeeViewHolder holder, int position) {
|
||||||
EmployeeDTO e = list.get(position);
|
EmployeeDTO e = list.get(position);
|
||||||
|
ItemEmployeeBinding binding = holder.binding;
|
||||||
|
|
||||||
holder.tvFullName.setText(e.getFullName() != null ? e.getFullName() : "");
|
binding.tvEmployeeFullName.setText(e.getFullName() != null ? e.getFullName() : "");
|
||||||
holder.tvUsername.setText("@" + (e.getUsername() != null ? e.getUsername() : ""));
|
binding.tvEmployeeUsername.setText("@" + (e.getUsername() != null ? e.getUsername() : ""));
|
||||||
holder.tvEmail.setText(e.getEmail() != null ? e.getEmail() : "");
|
binding.tvEmployeeEmail.setText(e.getEmail() != null ? e.getEmail() : "");
|
||||||
holder.tvPhone.setText(e.getPhone() != null ? e.getPhone() : "");
|
|
||||||
|
|
||||||
// Role badge
|
// Role badge
|
||||||
String role = e.getRole() != null ? e.getRole() : "";
|
String role = e.getRole() != null ? e.getRole() : "STAFF";
|
||||||
holder.tvRole.setText(role);
|
binding.tvEmployeeRole.setText(role);
|
||||||
holder.tvRole.setBackgroundColor(
|
|
||||||
"ADMIN".equals(role) ? Color.parseColor("#1a759f") : Color.parseColor("#577590"));
|
|
||||||
|
|
||||||
// Status badge
|
if ("ADMIN".equalsIgnoreCase(role)) {
|
||||||
|
binding.tvEmployeeRole.setBackgroundColor(Color.parseColor("#1a759f"));
|
||||||
|
} else {
|
||||||
|
binding.tvEmployeeRole.setBackgroundColor(Color.parseColor("#577590"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Status text and color
|
||||||
boolean active = Boolean.TRUE.equals(e.getActive());
|
boolean active = Boolean.TRUE.equals(e.getActive());
|
||||||
holder.tvStatus.setText(active ? "Active" : "Inactive");
|
binding.tvEmployeeStatus.setText(active ? "Active" : "Inactive");
|
||||||
holder.tvStatus.setBackgroundColor(
|
binding.tvEmployeeStatus.setTextColor(active ? Color.parseColor("#4CAF50") : Color.parseColor("#F44336"));
|
||||||
active ? Color.parseColor("#4CAF50") : Color.parseColor("#F44336"));
|
|
||||||
|
// Placeholder for profile image - matching Pet style
|
||||||
|
binding.ivEmployeeProfile.setImageResource(R.drawable.placeholder);
|
||||||
|
|
||||||
holder.itemView.setOnClickListener(v -> listener.onEmployeeClick(position));
|
holder.itemView.setOnClickListener(v -> listener.onEmployeeClick(position));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
package com.example.petstoremobile.adapters;
|
package com.example.petstoremobile.adapters;
|
||||||
|
|
||||||
import android.graphics.Color;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
import com.example.petstoremobile.R;
|
||||||
import com.example.petstoremobile.databinding.ItemSaleBinding;
|
import com.example.petstoremobile.databinding.ItemSaleBinding;
|
||||||
import com.example.petstoremobile.dtos.SaleDTO;
|
import com.example.petstoremobile.dtos.SaleDTO;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -53,11 +54,10 @@ public class SaleAdapter extends RecyclerView.Adapter<SaleAdapter.SaleViewHolder
|
|||||||
|
|
||||||
if (Boolean.TRUE.equals(s.getIsRefund())) {
|
if (Boolean.TRUE.equals(s.getIsRefund())) {
|
||||||
binding.tvSaleRefundBadge.setVisibility(View.VISIBLE);
|
binding.tvSaleRefundBadge.setVisibility(View.VISIBLE);
|
||||||
binding.tvSaleRefundBadge.setBackgroundColor(Color.parseColor("#F44336"));
|
binding.tvSaleTotal.setTextColor(ContextCompat.getColor(holder.itemView.getContext(), R.color.status_adopted));
|
||||||
binding.tvSaleTotal.setTextColor(Color.parseColor("#F44336"));
|
|
||||||
} else {
|
} else {
|
||||||
binding.tvSaleRefundBadge.setVisibility(View.GONE);
|
binding.tvSaleRefundBadge.setVisibility(View.GONE);
|
||||||
binding.tvSaleTotal.setTextColor(Color.parseColor("#4CAF50"));
|
binding.tvSaleTotal.setTextColor(ContextCompat.getColor(holder.itemView.getContext(), R.color.status_available));
|
||||||
}
|
}
|
||||||
|
|
||||||
holder.itemView.setOnClickListener(v -> listener.onSaleClick(position));
|
holder.itemView.setOnClickListener(v -> listener.onSaleClick(position));
|
||||||
|
|||||||
@@ -15,7 +15,10 @@ public interface SaleApi {
|
|||||||
@GET("api/v1/sales")
|
@GET("api/v1/sales")
|
||||||
Call<PageResponse<SaleDTO>> getAllSales(
|
Call<PageResponse<SaleDTO>> getAllSales(
|
||||||
@Query("page") int page,
|
@Query("page") int page,
|
||||||
@Query("size") int size);
|
@Query("size") int size,
|
||||||
|
@Query("query") String query,
|
||||||
|
@Query("paymentMethod") String paymentMethod,
|
||||||
|
@Query("sortBy") String sortBy);
|
||||||
|
|
||||||
@GET("api/v1/sales/{id}")
|
@GET("api/v1/sales/{id}")
|
||||||
Call<SaleDTO> getSaleById(@Path("id") Long id);
|
Call<SaleDTO> getSaleById(@Path("id") Long id);
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ public class AnalyticsFragment extends Fragment {
|
|||||||
tvAvgTransaction.setText("...");
|
tvAvgTransaction.setText("...");
|
||||||
tvTotalItems.setText("...");
|
tvTotalItems.setText("...");
|
||||||
|
|
||||||
RetrofitClient.getSaleApi(requireContext()).getAllSales(0, 1000)
|
RetrofitClient.getSaleApi(requireContext()).getAllSales(0, 1000, null, null, null)
|
||||||
.enqueue(new Callback<PageResponse<SaleDTO>>() {
|
.enqueue(new Callback<PageResponse<SaleDTO>>() {
|
||||||
public void onResponse(Call<PageResponse<SaleDTO>> c,
|
public void onResponse(Call<PageResponse<SaleDTO>> c,
|
||||||
Response<PageResponse<SaleDTO>> r) {
|
Response<PageResponse<SaleDTO>> r) {
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import android.widget.Toast;
|
|||||||
|
|
||||||
import com.example.petstoremobile.R;
|
import com.example.petstoremobile.R;
|
||||||
import com.example.petstoremobile.adapters.PetAdapter;
|
import com.example.petstoremobile.adapters.PetAdapter;
|
||||||
|
import com.example.petstoremobile.api.auth.TokenManager;
|
||||||
import com.example.petstoremobile.databinding.FragmentPetBinding;
|
import com.example.petstoremobile.databinding.FragmentPetBinding;
|
||||||
import com.example.petstoremobile.dtos.PetDTO;
|
import com.example.petstoremobile.dtos.PetDTO;
|
||||||
import com.example.petstoremobile.dtos.StoreDTO;
|
import com.example.petstoremobile.dtos.StoreDTO;
|
||||||
@@ -48,6 +49,7 @@ public class PetFragment extends Fragment implements PetAdapter.OnPetClickListen
|
|||||||
private BulkDeleteHandler bulkDeleteHandler;
|
private BulkDeleteHandler bulkDeleteHandler;
|
||||||
|
|
||||||
@Inject @Named("baseUrl") String baseUrl;
|
@Inject @Named("baseUrl") String baseUrl;
|
||||||
|
@Inject TokenManager tokenManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the fragment and its associated ViewModels.
|
* Initializes the fragment and its associated ViewModels.
|
||||||
@@ -272,6 +274,7 @@ public class PetFragment extends Fragment implements PetAdapter.OnPetClickListen
|
|||||||
private void setupRecyclerView() {
|
private void setupRecyclerView() {
|
||||||
adapter = new PetAdapter(petList, this);
|
adapter = new PetAdapter(petList, this);
|
||||||
adapter.setBaseUrl(baseUrl);
|
adapter.setBaseUrl(baseUrl);
|
||||||
|
adapter.setToken(tokenManager.getToken());
|
||||||
binding.recyclerViewPets.setLayoutManager(new LinearLayoutManager(getContext()));
|
binding.recyclerViewPets.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||||
binding.recyclerViewPets.setAdapter(adapter);
|
binding.recyclerViewPets.setAdapter(adapter);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,11 +7,14 @@ import androidx.fragment.app.Fragment;
|
|||||||
import androidx.lifecycle.ViewModelProvider;
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
import androidx.navigation.fragment.NavHostFragment;
|
import androidx.navigation.fragment.NavHostFragment;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
import android.text.Editable;
|
import android.text.Editable;
|
||||||
import android.text.TextWatcher;
|
import android.text.TextWatcher;
|
||||||
|
import android.util.Log;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.example.petstoremobile.R;
|
import com.example.petstoremobile.R;
|
||||||
import com.example.petstoremobile.adapters.SaleAdapter;
|
import com.example.petstoremobile.adapters.SaleAdapter;
|
||||||
@@ -19,9 +22,11 @@ import com.example.petstoremobile.databinding.FragmentSaleBinding;
|
|||||||
import com.example.petstoremobile.dtos.SaleDTO;
|
import com.example.petstoremobile.dtos.SaleDTO;
|
||||||
import com.example.petstoremobile.fragments.ListFragment;
|
import com.example.petstoremobile.fragments.ListFragment;
|
||||||
import com.example.petstoremobile.utils.Resource;
|
import com.example.petstoremobile.utils.Resource;
|
||||||
|
import com.example.petstoremobile.utils.SpinnerUtils;
|
||||||
import com.example.petstoremobile.viewmodels.SaleViewModel;
|
import com.example.petstoremobile.viewmodels.SaleViewModel;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import dagger.hilt.android.AndroidEntryPoint;
|
import dagger.hilt.android.AndroidEntryPoint;
|
||||||
@@ -29,12 +34,19 @@ import dagger.hilt.android.AndroidEntryPoint;
|
|||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
public class SaleFragment extends Fragment implements SaleAdapter.OnSaleClickListener {
|
public class SaleFragment extends Fragment implements SaleAdapter.OnSaleClickListener {
|
||||||
|
|
||||||
|
private static final String TAG = "SaleFragment";
|
||||||
|
private static final int PAGE_SIZE = 20;
|
||||||
|
|
||||||
private FragmentSaleBinding binding;
|
private FragmentSaleBinding binding;
|
||||||
private List<SaleDTO> saleList = new ArrayList<>();
|
private final List<SaleDTO> saleList = new ArrayList<>();
|
||||||
private List<SaleDTO> filteredList = new ArrayList<>();
|
|
||||||
private SaleAdapter adapter;
|
private SaleAdapter adapter;
|
||||||
private SaleViewModel saleViewModel;
|
private SaleViewModel saleViewModel;
|
||||||
|
|
||||||
|
// Pagination
|
||||||
|
private int currentPage = 0;
|
||||||
|
private boolean isLastPage = false;
|
||||||
|
private boolean isLoading = false;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
@@ -49,8 +61,10 @@ public class SaleFragment extends Fragment implements SaleAdapter.OnSaleClickLis
|
|||||||
|
|
||||||
setupRecyclerView();
|
setupRecyclerView();
|
||||||
setupSearch();
|
setupSearch();
|
||||||
|
setupPaymentMethodFilter();
|
||||||
setupSwipeRefresh();
|
setupSwipeRefresh();
|
||||||
loadSales();
|
setupFilterToggle();
|
||||||
|
loadSales(true);
|
||||||
|
|
||||||
binding.btnHamburger.setOnClickListener(v -> {
|
binding.btnHamburger.setOnClickListener(v -> {
|
||||||
Fragment parent = getParentFragment();
|
Fragment parent = getParentFragment();
|
||||||
@@ -69,6 +83,28 @@ public class SaleFragment extends Fragment implements SaleAdapter.OnSaleClickLis
|
|||||||
NavHostFragment.findNavController(this).navigate(R.id.nav_refund));
|
NavHostFragment.findNavController(this).navigate(R.id.nav_refund));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
binding.etSearchSale.setText("");
|
||||||
|
binding.spinnerPaymentMethod.setSelection(0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setupPaymentMethodFilter() {
|
||||||
|
List<String> paymentMethods = Arrays.asList("Cash", "Card");
|
||||||
|
SpinnerUtils.populateWhiteSpinner(requireContext(), binding.spinnerPaymentMethod, paymentMethods,
|
||||||
|
s -> s, "All Payments", null, s -> (long) s.hashCode());
|
||||||
|
|
||||||
|
SpinnerUtils.setupFilterSpinner(binding.spinnerPaymentMethod, () -> loadSales(true));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroyView() {
|
public void onDestroyView() {
|
||||||
super.onDestroyView();
|
super.onDestroyView();
|
||||||
@@ -76,9 +112,24 @@ public class SaleFragment extends Fragment implements SaleAdapter.OnSaleClickLis
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setupRecyclerView() {
|
private void setupRecyclerView() {
|
||||||
adapter = new SaleAdapter(filteredList, this);
|
adapter = new SaleAdapter(saleList, this);
|
||||||
binding.recyclerViewSales.setLayoutManager(new LinearLayoutManager(getContext()));
|
binding.recyclerViewSales.setLayoutManager(new LinearLayoutManager(getContext()));
|
||||||
binding.recyclerViewSales.setAdapter(adapter);
|
binding.recyclerViewSales.setAdapter(adapter);
|
||||||
|
|
||||||
|
binding.recyclerViewSales.addOnScrollListener(new RecyclerView.OnScrollListener() {
|
||||||
|
@Override
|
||||||
|
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
|
||||||
|
if (dy <= 0) return;
|
||||||
|
LinearLayoutManager lm = (LinearLayoutManager) binding.recyclerViewSales.getLayoutManager();
|
||||||
|
if (lm == null) return;
|
||||||
|
int visible = lm.getChildCount();
|
||||||
|
int total = lm.getItemCount();
|
||||||
|
int firstVis = lm.findFirstVisibleItemPosition();
|
||||||
|
if (!isLoading && !isLastPage && (visible + firstVis) >= total - 3) {
|
||||||
|
loadSales(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupSearch() {
|
private void setupSearch() {
|
||||||
@@ -87,50 +138,64 @@ public class SaleFragment extends Fragment implements SaleAdapter.OnSaleClickLis
|
|||||||
@Override public void afterTextChanged(Editable s) {}
|
@Override public void afterTextChanged(Editable s) {}
|
||||||
@Override
|
@Override
|
||||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||||
filterSales(s.toString());
|
loadSales(true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void filterSales(String query) {
|
|
||||||
filteredList.clear();
|
|
||||||
if (query.isEmpty()) {
|
|
||||||
filteredList.addAll(saleList);
|
|
||||||
} else {
|
|
||||||
String lower = query.toLowerCase();
|
|
||||||
for (SaleDTO s : saleList) {
|
|
||||||
if ((s.getEmployeeName() != null && s.getEmployeeName().toLowerCase().contains(lower))
|
|
||||||
|| (s.getSaleDate() != null && s.getSaleDate().toLowerCase().contains(lower))
|
|
||||||
|| (s.getPaymentMethod() != null && s.getPaymentMethod().toLowerCase().contains(lower))
|
|
||||||
|| (s.getSaleId() != null && String.valueOf(s.getSaleId()).contains(lower))) {
|
|
||||||
filteredList.add(s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (adapter != null) adapter.notifyDataSetChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setupSwipeRefresh() {
|
private void setupSwipeRefresh() {
|
||||||
binding.swipeRefreshSale.setOnRefreshListener(() -> {
|
binding.swipeRefreshSale.setOnRefreshListener(() -> loadSales(true));
|
||||||
loadSales();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadSales() {
|
private void loadSales(boolean reset) {
|
||||||
saleViewModel.getAllSales(0, 200).observe(getViewLifecycleOwner(), resource -> {
|
if (isLoading) return;
|
||||||
binding.swipeRefreshSale.setRefreshing(false);
|
|
||||||
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
if (reset) {
|
||||||
saleList.clear();
|
currentPage = 0;
|
||||||
saleList.addAll(resource.data.getContent());
|
isLastPage = false;
|
||||||
filterSales(binding.etSearchSale.getText() != null
|
}
|
||||||
? binding.etSearchSale.getText().toString() : "");
|
|
||||||
|
String query = binding.etSearchSale != null ? binding.etSearchSale.getText().toString().trim() : "";
|
||||||
|
if (query.isEmpty()) query = null;
|
||||||
|
|
||||||
|
String paymentMethod = null;
|
||||||
|
if (binding.spinnerPaymentMethod.getSelectedItemPosition() > 0) {
|
||||||
|
paymentMethod = (String) binding.spinnerPaymentMethod.getSelectedItem();
|
||||||
|
}
|
||||||
|
|
||||||
|
saleViewModel.getAllSales(currentPage, PAGE_SIZE, query, paymentMethod, "saleDate,desc").observe(getViewLifecycleOwner(), resource -> {
|
||||||
|
if (resource == null) return;
|
||||||
|
|
||||||
|
switch (resource.status) {
|
||||||
|
case LOADING:
|
||||||
|
isLoading = true;
|
||||||
|
binding.swipeRefreshSale.setRefreshing(true);
|
||||||
|
break;
|
||||||
|
case SUCCESS:
|
||||||
|
isLoading = false;
|
||||||
|
binding.swipeRefreshSale.setRefreshing(false);
|
||||||
|
if (resource.data != null) {
|
||||||
|
if (reset) saleList.clear();
|
||||||
|
saleList.addAll(resource.data.getContent());
|
||||||
|
adapter.notifyDataSetChanged();
|
||||||
|
isLastPage = resource.data.isLast();
|
||||||
|
if (!isLastPage) currentPage++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ERROR:
|
||||||
|
isLoading = false;
|
||||||
|
binding.swipeRefreshSale.setRefreshing(false);
|
||||||
|
Log.e(TAG, "Error loading sales: " + resource.message);
|
||||||
|
Toast.makeText(getContext(), "Failed to load sales: " + resource.message, Toast.LENGTH_SHORT).show();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSaleClick(int position) {
|
public void onSaleClick(int position) {
|
||||||
SaleDTO sale = filteredList.get(position);
|
if (position < 0 || position >= saleList.size()) return;
|
||||||
|
SaleDTO sale = saleList.get(position);
|
||||||
Bundle args = new Bundle();
|
Bundle args = new Bundle();
|
||||||
if (sale.getSaleId() != null) {
|
if (sale.getSaleId() != null) {
|
||||||
args.putLong("saleId", sale.getSaleId());
|
args.putLong("saleId", sale.getSaleId());
|
||||||
|
|||||||
@@ -29,12 +29,15 @@ public class StaffFragment extends Fragment implements EmployeeAdapter.OnEmploye
|
|||||||
private EmployeeAdapter adapter;
|
private EmployeeAdapter adapter;
|
||||||
private SwipeRefreshLayout swipeRefresh;
|
private SwipeRefreshLayout swipeRefresh;
|
||||||
private EditText etSearch;
|
private EditText etSearch;
|
||||||
|
private LinearLayout layoutFilter;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
View view = inflater.inflate(R.layout.fragment_staff, container, false);
|
View view = inflater.inflate(R.layout.fragment_staff, container, false);
|
||||||
|
|
||||||
|
layoutFilter = view.findViewById(R.id.layoutFilterStaff);
|
||||||
|
|
||||||
setupRecyclerView(view);
|
setupRecyclerView(view);
|
||||||
setupSearch(view);
|
setupSearch(view);
|
||||||
setupSwipeRefresh(view);
|
setupSwipeRefresh(view);
|
||||||
@@ -46,6 +49,15 @@ public class StaffFragment extends Fragment implements EmployeeAdapter.OnEmploye
|
|||||||
ImageButton hamburger = view.findViewById(R.id.btnHamburgerStaff);
|
ImageButton hamburger = view.findViewById(R.id.btnHamburgerStaff);
|
||||||
hamburger.setOnClickListener(v -> openDrawer());
|
hamburger.setOnClickListener(v -> openDrawer());
|
||||||
|
|
||||||
|
ImageButton btnToggleFilter = view.findViewById(R.id.btnToggleFilterStaff);
|
||||||
|
btnToggleFilter.setOnClickListener(v -> {
|
||||||
|
if (layoutFilter.getVisibility() == View.VISIBLE) {
|
||||||
|
layoutFilter.setVisibility(View.GONE);
|
||||||
|
} else {
|
||||||
|
layoutFilter.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,8 +124,10 @@ public class StaffFragment extends Fragment implements EmployeeAdapter.OnEmploye
|
|||||||
employeeList.addAll(r.body().getContent());
|
employeeList.addAll(r.body().getContent());
|
||||||
filter(etSearch != null ? etSearch.getText().toString() : "");
|
filter(etSearch != null ? etSearch.getText().toString() : "");
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(getContext(), "Failed to load staff",
|
if (getContext() != null) {
|
||||||
Toast.LENGTH_SHORT).show();
|
Toast.makeText(getContext(), "Failed to load staff",
|
||||||
|
Toast.LENGTH_SHORT).show();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public void onFailure(Call<PageResponse<EmployeeDTO>> c, Throwable t) {
|
public void onFailure(Call<PageResponse<EmployeeDTO>> c, Throwable t) {
|
||||||
|
|||||||
@@ -415,7 +415,7 @@ public class AppointmentDetailFragment extends Fragment {
|
|||||||
} else if (errorMessage.toLowerCase().contains("not available")) {
|
} else if (errorMessage.toLowerCase().contains("not available")) {
|
||||||
showNoAvailabilityDialog();
|
showNoAvailabilityDialog();
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(getContext(), "Operation failed", Toast.LENGTH_SHORT).show();
|
Toast.makeText(getContext(), errorMessage, Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Toast.makeText(getContext(), "Something went wrong", Toast.LENGTH_SHORT).show();
|
Toast.makeText(getContext(), "Something went wrong", Toast.LENGTH_SHORT).show();
|
||||||
|
|||||||
@@ -220,6 +220,13 @@ public class PetDetailFragment extends Fragment {
|
|||||||
binding.tvPetId.setText("ID: " + petId);
|
binding.tvPetId.setText("ID: " + petId);
|
||||||
binding.tvPetId.setVisibility(View.VISIBLE);
|
binding.tvPetId.setVisibility(View.VISIBLE);
|
||||||
binding.btnDeletePet.setVisibility(View.VISIBLE);
|
binding.btnDeletePet.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
|
// Disable species and breed fields in edit mode
|
||||||
|
binding.etPetSpecies.setEnabled(false);
|
||||||
|
binding.etPetBreed.setEnabled(false);
|
||||||
|
binding.etPetSpecies.setAlpha(0.5f);
|
||||||
|
binding.etPetBreed.setAlpha(0.5f);
|
||||||
|
|
||||||
loadPetData();
|
loadPetData();
|
||||||
} else {
|
} else {
|
||||||
// Pet is being added
|
// Pet is being added
|
||||||
@@ -229,6 +236,12 @@ public class PetDetailFragment extends Fragment {
|
|||||||
binding.tvPetId.setVisibility(View.GONE);
|
binding.tvPetId.setVisibility(View.GONE);
|
||||||
binding.btnDeletePet.setVisibility(View.GONE);
|
binding.btnDeletePet.setVisibility(View.GONE);
|
||||||
binding.btnSavePet.setText("Add");
|
binding.btnSavePet.setText("Add");
|
||||||
|
|
||||||
|
// Enable species and breed fields in edit mode
|
||||||
|
binding.etPetSpecies.setEnabled(true);
|
||||||
|
binding.etPetBreed.setEnabled(true);
|
||||||
|
binding.etPetSpecies.setAlpha(1.0f);
|
||||||
|
binding.etPetBreed.setAlpha(1.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -334,16 +347,20 @@ public class PetDetailFragment extends Fragment {
|
|||||||
if ("Available".equalsIgnoreCase(status)) {
|
if ("Available".equalsIgnoreCase(status)) {
|
||||||
binding.spinnerCustomer.setSelection(0);
|
binding.spinnerCustomer.setSelection(0);
|
||||||
binding.spinnerCustomer.setEnabled(false);
|
binding.spinnerCustomer.setEnabled(false);
|
||||||
|
binding.spinnerCustomer.setAlpha(0.5f);
|
||||||
} else {
|
} else {
|
||||||
binding.spinnerCustomer.setEnabled(true);
|
binding.spinnerCustomer.setEnabled(true);
|
||||||
|
binding.spinnerCustomer.setAlpha(1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Disable the store spinner if the status is "Owned"
|
//Disable the store spinner if the status is "Owned"
|
||||||
if ("Owned".equalsIgnoreCase(status)) {
|
if ("Owned".equalsIgnoreCase(status)) {
|
||||||
binding.spinnerStore.setSelection(0);
|
binding.spinnerStore.setSelection(0);
|
||||||
binding.spinnerStore.setEnabled(false);
|
binding.spinnerStore.setEnabled(false);
|
||||||
|
binding.spinnerStore.setAlpha(0.5f);
|
||||||
} else {
|
} else {
|
||||||
binding.spinnerStore.setEnabled(true);
|
binding.spinnerStore.setEnabled(true);
|
||||||
|
binding.spinnerStore.setAlpha(1.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import androidx.lifecycle.ViewModelProvider;
|
|||||||
import androidx.navigation.fragment.NavHostFragment;
|
import androidx.navigation.fragment.NavHostFragment;
|
||||||
|
|
||||||
import com.bumptech.glide.Glide;
|
import com.bumptech.glide.Glide;
|
||||||
|
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||||
import com.example.petstoremobile.R;
|
import com.example.petstoremobile.R;
|
||||||
import com.example.petstoremobile.api.*;
|
import com.example.petstoremobile.api.*;
|
||||||
import com.example.petstoremobile.api.auth.TokenManager;
|
import com.example.petstoremobile.api.auth.TokenManager;
|
||||||
@@ -73,7 +74,11 @@ public class ProductDetailFragment extends Fragment {
|
|||||||
@Override
|
@Override
|
||||||
public void onImagePicked(Uri uri) {
|
public void onImagePicked(Uri uri) {
|
||||||
photoUri = uri;
|
photoUri = uri;
|
||||||
Glide.with(ProductDetailFragment.this).load(uri).into(binding.ivProductImage);
|
Glide.with(ProductDetailFragment.this)
|
||||||
|
.load(uri)
|
||||||
|
.diskCacheStrategy(DiskCacheStrategy.NONE)
|
||||||
|
.skipMemoryCache(true)
|
||||||
|
.into(binding.ivProductImage);
|
||||||
hasImage = true;
|
hasImage = true;
|
||||||
isImageChanged = true;
|
isImageChanged = true;
|
||||||
isImageRemoved = false;
|
isImageRemoved = false;
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ public class RefundFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void loadAllSales() {
|
private void loadAllSales() {
|
||||||
RetrofitClient.getSaleApi(requireContext()).getAllSales(0, 1000)
|
RetrofitClient.getSaleApi(requireContext()).getAllSales(0, 1000, null, null, null)
|
||||||
.enqueue(new Callback<PageResponse<SaleDTO>>() {
|
.enqueue(new Callback<PageResponse<SaleDTO>>() {
|
||||||
public void onResponse(Call<PageResponse<SaleDTO>> c,
|
public void onResponse(Call<PageResponse<SaleDTO>> c,
|
||||||
Response<PageResponse<SaleDTO>> r) {
|
Response<PageResponse<SaleDTO>> r) {
|
||||||
|
|||||||
@@ -131,11 +131,30 @@ public class PetProfileFragment extends Fragment {
|
|||||||
binding.tvPetPrice.setText("$0.00");
|
binding.tvPetPrice.setText("$0.00");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Display owner name if available, otherwise show No Owner
|
String status = pet.getPetStatus();
|
||||||
if (pet.getCustomerName() != null && !pet.getCustomerName().isEmpty()) {
|
|
||||||
binding.tvPetOwner.setText(pet.getCustomerName());
|
// Display owner name only if the pet is Adopted or Owned
|
||||||
|
if ("Adopted".equalsIgnoreCase(status) || "Owned".equalsIgnoreCase(status)) {
|
||||||
|
binding.layoutPetOwner.setVisibility(View.VISIBLE);
|
||||||
|
if (pet.getCustomerName() != null && !pet.getCustomerName().isEmpty()) {
|
||||||
|
binding.tvPetOwner.setText(pet.getCustomerName());
|
||||||
|
} else {
|
||||||
|
binding.tvPetOwner.setText("No Owner");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
binding.tvPetOwner.setText("No Owner");
|
binding.layoutPetOwner.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display store name only if the pet is Adopted or Available
|
||||||
|
if ("Available".equalsIgnoreCase(status) || "Adopted".equalsIgnoreCase(status)) {
|
||||||
|
binding.layoutPetStore.setVisibility(View.VISIBLE);
|
||||||
|
if (pet.getStoreName() != null && !pet.getStoreName().isEmpty()) {
|
||||||
|
binding.tvPetStore.setText(pet.getStoreName());
|
||||||
|
} else {
|
||||||
|
binding.tvPetStore.setText("No Store");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
binding.layoutPetStore.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
} else if (resource.status == Resource.Status.ERROR) {
|
} else if (resource.status == Resource.Status.ERROR) {
|
||||||
Toast.makeText(getContext(), "Failed to load pet data: " + resource.message, Toast.LENGTH_SHORT).show();
|
Toast.makeText(getContext(), "Failed to load pet data: " + resource.message, Toast.LENGTH_SHORT).show();
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ public class SaleRepository extends BaseRepository {
|
|||||||
this.saleApi = saleApi;
|
this.saleApi = saleApi;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiveData<Resource<PageResponse<SaleDTO>>> getAllSales(int page, int size) {
|
public LiveData<Resource<PageResponse<SaleDTO>>> getAllSales(int page, int size, String query, String paymentMethod, String sortBy) {
|
||||||
return executeCall(saleApi.getAllSales(page, size));
|
return executeCall(saleApi.getAllSales(page, size, query, paymentMethod, sortBy));
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiveData<Resource<SaleDTO>> getSaleById(Long id) {
|
public LiveData<Resource<SaleDTO>> getSaleById(Long id) {
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ public class SaleViewModel extends ViewModel {
|
|||||||
this.saleRepository = saleRepository;
|
this.saleRepository = saleRepository;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiveData<Resource<PageResponse<SaleDTO>>> getAllSales(int page, int size) {
|
public LiveData<Resource<PageResponse<SaleDTO>>> getAllSales(int page, int size, String query, String paymentMethod, String sortBy) {
|
||||||
return saleRepository.getAllSales(page, size);
|
return saleRepository.getAllSales(page, size, query, paymentMethod, sortBy);
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiveData<Resource<SaleDTO>> getSaleById(Long id) {
|
public LiveData<Resource<SaleDTO>> getSaleById(Long id) {
|
||||||
|
|||||||
@@ -222,13 +222,15 @@
|
|||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
android:id="@+id/layoutPetOwner"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:background="@color/white"
|
android:background="@color/white"
|
||||||
android:layout_marginTop="16dp"
|
android:layout_marginTop="16dp"
|
||||||
android:padding="16dp">
|
android:padding="16dp"
|
||||||
|
android:visibility="gone">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
@@ -250,6 +252,37 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/layoutPetStore"
|
||||||
|
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"
|
||||||
|
android:visibility="gone">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="STORE"
|
||||||
|
android:textSize="11sp"
|
||||||
|
android:textColor="#888888"
|
||||||
|
android:textAllCaps="true"
|
||||||
|
android:layout_marginBottom="4dp"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvPetStore"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="No Store"
|
||||||
|
android:textSize="20sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:textColor="@color/text_dark"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
|||||||
@@ -29,35 +29,101 @@
|
|||||||
android:contentDescription="Open menu"/>
|
android:contentDescription="Open menu"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
android:text="Sales"
|
android:text="Sales"
|
||||||
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
|
||||||
|
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>
|
||||||
|
|
||||||
<EditText
|
<LinearLayout
|
||||||
android:id="@+id/etSearchSale"
|
android:id="@+id/layoutFilter"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_margin="8dp"
|
android:orientation="vertical"
|
||||||
android:hint="Search by employee or store..."
|
android:paddingStart="12dp"
|
||||||
android:inputType="text"
|
android:paddingEnd="12dp"
|
||||||
android:drawableStart="@android:drawable/ic_menu_search"
|
android:paddingTop="10dp"
|
||||||
android:drawablePadding="8dp"
|
android:paddingBottom="10dp"
|
||||||
android:background="@android:color/white"
|
android:visibility="gone"
|
||||||
android:padding="12dp"
|
android:background="@color/primary_dark"
|
||||||
android:textColor="@color/text_dark"/>
|
android:elevation="4dp">
|
||||||
|
|
||||||
<Button
|
<LinearLayout
|
||||||
android:id="@+id/btnOpenRefund"
|
android:layout_width="match_parent"
|
||||||
android:layout_width="wrap_content"
|
android:layout_height="44dp"
|
||||||
android:layout_height="wrap_content"
|
android:background="@drawable/bg_search_bar"
|
||||||
android:text="Refund"
|
android:gravity="center_vertical"
|
||||||
android:backgroundTint="@color/accent_coral"
|
android:paddingStart="12dp"
|
||||||
android:textColor="@color/white"/>
|
android:paddingEnd="12dp">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="18dp"
|
||||||
|
android:layout_height="18dp"
|
||||||
|
android:src="@android:drawable/ic_menu_search"
|
||||||
|
android:alpha="0.6"/>
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/etSearchSale"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:hint="Search by employee or date..."
|
||||||
|
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"
|
||||||
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
|
<Spinner
|
||||||
|
android:id="@+id/spinnerPaymentMethod"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="44dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:background="@drawable/bg_spinner"
|
||||||
|
android:paddingStart="12dp"
|
||||||
|
android:paddingEnd="8dp"
|
||||||
|
android:layout_marginEnd="4dp"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/btnOpenRefund"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="44dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="Process Refund"
|
||||||
|
android:backgroundTint="@color/accent_coral"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:textSize="12sp"
|
||||||
|
android:insetTop="0dp"
|
||||||
|
android:insetBottom="0dp"
|
||||||
|
android:layout_marginStart="4dp"/>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||||
android:id="@+id/swipeRefreshSale"
|
android:id="@+id/swipeRefreshSale"
|
||||||
@@ -68,7 +134,8 @@
|
|||||||
android:id="@+id/recyclerViewSales"
|
android:id="@+id/recyclerViewSales"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:padding="8dp"/>
|
android:padding="8dp"
|
||||||
|
android:clipToPadding="false"/>
|
||||||
|
|
||||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||||
|
|
||||||
@@ -85,5 +152,4 @@
|
|||||||
app:srcCompat="@android:drawable/ic_input_add"
|
app:srcCompat="@android:drawable/ic_input_add"
|
||||||
app:tint="@color/white"/>
|
app:tint="@color/white"/>
|
||||||
|
|
||||||
|
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
@@ -12,6 +12,7 @@
|
|||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
|
android:id="@+id/headerStaff"
|
||||||
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,22 +35,63 @@
|
|||||||
android:text="Staff Accounts"
|
android:text="Staff Accounts"
|
||||||
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
|
||||||
|
android:id="@+id/btnToggleFilterStaff"
|
||||||
|
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>
|
||||||
|
|
||||||
<EditText
|
<LinearLayout
|
||||||
android:id="@+id/etSearchStaff"
|
android:id="@+id/layoutFilterStaff"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_margin="8dp"
|
android:orientation="vertical"
|
||||||
android:hint="Search by name, username or email..."
|
android:paddingStart="12dp"
|
||||||
android:inputType="text"
|
android:paddingEnd="12dp"
|
||||||
android:drawableStart="@android:drawable/ic_menu_search"
|
android:paddingTop="10dp"
|
||||||
android:drawablePadding="8dp"
|
android:paddingBottom="10dp"
|
||||||
android:background="@android:color/white"
|
android:visibility="gone"
|
||||||
android:padding="12dp"
|
android:background="@color/primary_dark"
|
||||||
android:textColor="@color/text_dark"/>
|
android:elevation="4dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="44dp"
|
||||||
|
android:background="@drawable/bg_search_bar"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:paddingStart="12dp"
|
||||||
|
android:paddingEnd="12dp">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="18dp"
|
||||||
|
android:layout_height="18dp"
|
||||||
|
android:src="@android:drawable/ic_menu_search"
|
||||||
|
android:alpha="0.6"/>
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/etSearchStaff"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:hint="Search staff..."
|
||||||
|
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>
|
||||||
|
|
||||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||||
android:id="@+id/swipeRefreshStaff"
|
android:id="@+id/swipeRefreshStaff"
|
||||||
@@ -78,5 +120,3 @@
|
|||||||
app:tint="@color/white"/>
|
app:tint="@color/white"/>
|
||||||
|
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,99 +1,117 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<androidx.cardview.widget.CardView
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_margin="8dp"
|
android:orientation="vertical"
|
||||||
app:cardCornerRadius="8dp"
|
android:paddingStart="16dp"
|
||||||
app:cardElevation="2dp">
|
android:paddingEnd="16dp"
|
||||||
|
android:paddingTop="16dp"
|
||||||
|
android:paddingBottom="16dp"
|
||||||
|
android:background="@color/white">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical"
|
android:orientation="horizontal"
|
||||||
android:padding="16dp">
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
|
<com.google.android.material.imageview.ShapeableImageView
|
||||||
|
android:id="@+id/ivEmployeeProfile"
|
||||||
|
android:layout_width="60dp"
|
||||||
|
android:layout_height="60dp"
|
||||||
|
android:layout_marginEnd="16dp"
|
||||||
|
android:scaleType="centerCrop"
|
||||||
|
android:src="@drawable/placeholder"
|
||||||
|
app:shapeAppearanceOverlay="@style/CircleImageView"
|
||||||
|
app:strokeWidth="2dp"
|
||||||
|
app:strokeColor="#BDBDBD"
|
||||||
|
android:padding="2dp"
|
||||||
|
android:contentDescription="Employee Profile Image" />
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal">
|
android:layout_weight="1"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="0dp"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="1"
|
android:orientation="horizontal"
|
||||||
android:orientation="vertical">
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvEmployeeFullName"
|
android:id="@+id/tvEmployeeFullName"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textSize="16sp"
|
android:layout_weight="1"
|
||||||
android:textStyle="bold"
|
android:ellipsize="end"
|
||||||
android:textColor="@color/text_dark"/>
|
android:maxLines="1"
|
||||||
|
android:text="Full Name"
|
||||||
<TextView
|
android:textColor="@color/text_dark"
|
||||||
android:id="@+id/tvEmployeeUsername"
|
android:textSize="18sp"
|
||||||
android:layout_width="wrap_content"
|
android:textStyle="bold" />
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:textSize="13sp"
|
|
||||||
android:textColor="@color/text_light"
|
|
||||||
android:layout_marginTop="2dp"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tvEmployeeEmail"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:textSize="12sp"
|
|
||||||
android:textColor="@color/text_light"
|
|
||||||
android:layout_marginTop="2dp"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tvEmployeePhone"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:textSize="12sp"
|
|
||||||
android:textColor="@color/text_light"
|
|
||||||
android:layout_marginTop="2dp"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:orientation="vertical"
|
|
||||||
android:gravity="end"
|
|
||||||
android:layout_gravity="center_vertical">
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvEmployeeRole"
|
android:id="@+id/tvEmployeeRole"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:paddingStart="10dp"
|
android:paddingStart="8dp"
|
||||||
android:paddingEnd="10dp"
|
android:paddingTop="3dp"
|
||||||
android:paddingTop="4dp"
|
android:paddingEnd="8dp"
|
||||||
android:paddingBottom="4dp"
|
android:paddingBottom="3dp"
|
||||||
android:textSize="11sp"
|
android:text="ROLE"
|
||||||
|
android:textAllCaps="true"
|
||||||
android:textColor="@color/white"
|
android:textColor="@color/white"
|
||||||
android:layout_marginBottom="4dp"/>
|
android:textSize="11sp" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvEmployeeUsername"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="2dp"
|
||||||
|
android:text="@username"
|
||||||
|
android:textColor="#888888"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:layout_marginTop="4dp">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvEmployeeEmail"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="email@example.com"
|
||||||
|
android:textColor="#888888"
|
||||||
|
android:textSize="13sp"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:maxLines="1"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvEmployeeStatus"
|
android:id="@+id/tvEmployeeStatus"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:paddingStart="10dp"
|
android:text="Active"
|
||||||
android:paddingEnd="10dp"
|
android:textColor="@color/accent_coral"
|
||||||
android:paddingTop="4dp"
|
android:textSize="13sp"
|
||||||
android:paddingBottom="4dp"
|
android:textStyle="bold" />
|
||||||
android:textSize="11sp"
|
|
||||||
android:textColor="@color/white"/>
|
|
||||||
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</androidx.cardview.widget.CardView>
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:background="#F0F0F0"
|
||||||
|
android:layout_marginTop="12dp"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|||||||
@@ -1,23 +1,64 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<androidx.cardview.widget.CardView
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_margin="8dp"
|
android:orientation="horizontal"
|
||||||
app:cardCornerRadius="8dp"
|
android:background="@color/white"
|
||||||
app:cardElevation="2dp">
|
android:foreground="?attr/selectableItemBackground"
|
||||||
|
android:paddingStart="16dp"
|
||||||
|
android:paddingEnd="16dp"
|
||||||
|
android:paddingTop="16dp"
|
||||||
|
android:paddingBottom="16dp"
|
||||||
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
|
<CheckBox
|
||||||
|
android:id="@+id/cbSelectSale"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginEnd="12dp"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:clickable="false"
|
||||||
|
android:focusable="false"/>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical">
|
||||||
android:padding="16dp">
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal"
|
||||||
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvSaleId"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:ellipsize="end"
|
||||||
|
android:maxLines="1"
|
||||||
|
android:text="Sale #—"
|
||||||
|
android:textColor="@color/text_dark"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvSaleTotal"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="$0.00"
|
||||||
|
android:textColor="#4CAF50"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_marginTop="4dp">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
@@ -25,74 +66,58 @@
|
|||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tvSaleId"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:textSize="16sp"
|
|
||||||
android:textStyle="bold"
|
|
||||||
android:textColor="@color/text_dark"/>
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvSaleEmployee"
|
android:id="@+id/tvSaleEmployee"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textSize="13sp"
|
android:text="By: —"
|
||||||
android:textColor="@color/text_light"
|
android:textColor="#888888"
|
||||||
android:layout_marginTop="2dp"/>
|
android:textSize="14sp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvSaleDate"
|
android:id="@+id/tvSaleDate"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textSize="12sp"
|
android:layout_marginTop="2dp"
|
||||||
android:textColor="@color/text_light"
|
android:text="—"
|
||||||
android:layout_marginTop="2dp"/>
|
android:textColor="#888888"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/tvSalePayment"
|
android:id="@+id/tvSalePayment"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textSize="12sp"
|
android:layout_marginTop="2dp"
|
||||||
android:textColor="@color/text_light"
|
android:text="—"
|
||||||
android:layout_marginTop="2dp"/>
|
android:textColor="#888888"
|
||||||
|
android:textSize="14sp" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<TextView
|
||||||
|
android:id="@+id/tvSaleRefundBadge"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical"
|
android:background="@color/status_adopted"
|
||||||
android:gravity="end"
|
android:paddingStart="8dp"
|
||||||
android:layout_gravity="center_vertical">
|
android:paddingTop="3dp"
|
||||||
|
android:paddingEnd="8dp"
|
||||||
<TextView
|
android:paddingBottom="3dp"
|
||||||
android:id="@+id/tvSaleTotal"
|
android:text="REFUND"
|
||||||
android:layout_width="wrap_content"
|
android:textAllCaps="true"
|
||||||
android:layout_height="wrap_content"
|
android:textColor="@color/white"
|
||||||
android:textSize="18sp"
|
android:textSize="11sp"
|
||||||
android:textStyle="bold"
|
android:visibility="gone"
|
||||||
android:textColor="@color/accent_coral"/>
|
android:layout_gravity="bottom"/>
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/tvSaleRefundBadge"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="REFUND"
|
|
||||||
android:textSize="10sp"
|
|
||||||
android:textColor="@color/white"
|
|
||||||
android:background="@color/accent_coral"
|
|
||||||
android:paddingStart="6dp"
|
|
||||||
android:paddingEnd="6dp"
|
|
||||||
android:paddingTop="2dp"
|
|
||||||
android:paddingBottom="2dp"
|
|
||||||
android:layout_marginTop="4dp"
|
|
||||||
android:visibility="gone"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:background="#F0F0F0"
|
||||||
|
android:layout_marginTop="12dp" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</androidx.cardview.widget.CardView>
|
</LinearLayout>
|
||||||
101
android/app/src/res/layout/item_sale.xml
Normal file
101
android/app/src/res/layout/item_sale.xml
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:background="@color/white"
|
||||||
|
android:paddingStart="16dp"
|
||||||
|
android:paddingEnd="16dp"
|
||||||
|
android:paddingTop="16dp"
|
||||||
|
android:paddingBottom="16dp"
|
||||||
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:gravity="center_vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvSaleId"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="Sale #123"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:textColor="@color/text_dark"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvSaleTotal"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="$0.00"
|
||||||
|
android:textSize="18sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:textColor="@color/accent_coral"/>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_marginTop="4dp">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvSaleEmployee"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="By: Employee"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:textColor="#888888"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvSaleDate"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="2023-01-01"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:textColor="#888888"
|
||||||
|
android:layout_marginTop="2dp"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvSalePayment"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Cash"
|
||||||
|
android:textSize="14sp"
|
||||||
|
android:textColor="#888888"
|
||||||
|
android:layout_marginTop="2dp"/>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvSaleRefundBadge"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="REFUND"
|
||||||
|
android:textSize="12sp"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:textColor="@color/white"
|
||||||
|
android:background="@color/accent_coral"
|
||||||
|
android:paddingStart="8dp"
|
||||||
|
android:paddingEnd="8dp"
|
||||||
|
android:paddingTop="2dp"
|
||||||
|
android:paddingBottom="2dp"
|
||||||
|
android:layout_gravity="bottom"
|
||||||
|
android:visibility="gone"/>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="1dp"
|
||||||
|
android:background="#F0F0F0"
|
||||||
|
android:layout_marginTop="12dp"/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
@@ -25,8 +25,9 @@ public class SaleController {
|
|||||||
@PreAuthorize("hasAnyRole('STAFF', 'ADMIN')")
|
@PreAuthorize("hasAnyRole('STAFF', 'ADMIN')")
|
||||||
public ResponseEntity<Page<SaleResponse>> getAllSales(
|
public ResponseEntity<Page<SaleResponse>> getAllSales(
|
||||||
@RequestParam(required = false) String q,
|
@RequestParam(required = false) String q,
|
||||||
|
@RequestParam(required = false) String paymentMethod,
|
||||||
Pageable pageable) {
|
Pageable pageable) {
|
||||||
return ResponseEntity.ok(saleService.getAllSales(q, pageable));
|
return ResponseEntity.ok(saleService.getAllSales(q, paymentMethod, pageable));
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/{id}")
|
@GetMapping("/{id}")
|
||||||
|
|||||||
@@ -14,10 +14,13 @@ import java.util.List;
|
|||||||
public interface SaleRepository extends JpaRepository<Sale, Long> {
|
public interface SaleRepository extends JpaRepository<Sale, Long> {
|
||||||
|
|
||||||
@Query("SELECT s FROM Sale s WHERE " +
|
@Query("SELECT s FROM Sale s WHERE " +
|
||||||
|
"(:q IS NULL OR (" +
|
||||||
"LOWER(s.employee.firstName) LIKE LOWER(CONCAT('%', :q, '%')) OR " +
|
"LOWER(s.employee.firstName) LIKE LOWER(CONCAT('%', :q, '%')) OR " +
|
||||||
"LOWER(s.employee.lastName) LIKE LOWER(CONCAT('%', :q, '%')) OR " +
|
"LOWER(s.employee.lastName) LIKE LOWER(CONCAT('%', :q, '%')) OR " +
|
||||||
"LOWER(s.store.storeName) LIKE LOWER(CONCAT('%', :q, '%'))")
|
"LOWER(s.store.storeName) LIKE LOWER(CONCAT('%', :q, '%'))" +
|
||||||
Page<Sale> searchSales(@Param("q") String query, Pageable pageable);
|
")) AND " +
|
||||||
|
"(:paymentMethod IS NULL OR LOWER(s.paymentMethod) = LOWER(:paymentMethod))")
|
||||||
|
Page<Sale> searchSales(@Param("q") String query, @Param("paymentMethod") String paymentMethod, Pageable pageable);
|
||||||
|
|
||||||
List<Sale> findByOriginalSaleSaleId(Long originalSaleId);
|
List<Sale> findByOriginalSaleSaleId(Long originalSaleId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,13 +39,8 @@ public class SaleService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Transactional(readOnly = true)
|
@Transactional(readOnly = true)
|
||||||
public Page<SaleResponse> getAllSales(String query, Pageable pageable) {
|
public Page<SaleResponse> getAllSales(String query, String paymentMethod, Pageable pageable) {
|
||||||
Page<Sale> sales;
|
Page<Sale> sales = saleRepository.searchSales(normalizeFilter(query), normalizeFilter(paymentMethod), pageable);
|
||||||
if (query != null && !query.trim().isEmpty()) {
|
|
||||||
sales = saleRepository.searchSales(query, pageable);
|
|
||||||
} else {
|
|
||||||
sales = saleRepository.findAll(pageable);
|
|
||||||
}
|
|
||||||
return sales.map(this::mapToResponse);
|
return sales.map(this::mapToResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -236,6 +231,14 @@ public class SaleService {
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String normalizeFilter(String value) {
|
||||||
|
if (value == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
String trimmed = value.trim();
|
||||||
|
return trimmed.isEmpty() ? null : trimmed;
|
||||||
|
}
|
||||||
|
|
||||||
String normalizePaymentMethod(String paymentMethod) {
|
String normalizePaymentMethod(String paymentMethod) {
|
||||||
if (paymentMethod == null) {
|
if (paymentMethod == null) {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
Reference in New Issue
Block a user