cleaning code
This commit is contained in:
@@ -214,9 +214,11 @@ public class ChatFragment extends Fragment implements ChatAdapter.OnChatClickLis
|
|||||||
Toast.makeText(requireContext(), "Downloading " + message.getAttachmentName() + "...", Toast.LENGTH_SHORT).show();
|
Toast.makeText(requireContext(), "Downloading " + message.getAttachmentName() + "...", Toast.LENGTH_SHORT).show();
|
||||||
|
|
||||||
viewModel.downloadAttachment(message.getId()).observe(getViewLifecycleOwner(), resource -> {
|
viewModel.downloadAttachment(message.getId()).observe(getViewLifecycleOwner(), resource -> {
|
||||||
if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
if (resource == null) return;
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
|
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
||||||
saveFileToDownloads(resource.data, message.getAttachmentName(), message.getAttachmentMimeType());
|
saveFileToDownloads(resource.data, message.getAttachmentName(), message.getAttachmentMimeType());
|
||||||
} else if (resource != null && resource.status == Resource.Status.ERROR) {
|
} else if (resource.status == Resource.Status.ERROR) {
|
||||||
Toast.makeText(requireContext(), "Download failed: " + resource.message, Toast.LENGTH_SHORT).show();
|
Toast.makeText(requireContext(), "Download failed: " + resource.message, Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -285,9 +287,13 @@ public class ChatFragment extends Fragment implements ChatAdapter.OnChatClickLis
|
|||||||
scrollToBottom();
|
scrollToBottom();
|
||||||
});
|
});
|
||||||
|
|
||||||
viewModel.getIsLoading().observe(getViewLifecycleOwner(), loading -> {
|
viewModel.getIsLoading().observe(getViewLifecycleOwner(), this::setLoading);
|
||||||
// Can show a progress bar if needed
|
}
|
||||||
});
|
|
||||||
|
private void setLoading(boolean loading) {
|
||||||
|
if (binding != null && binding.progressBar != null) {
|
||||||
|
binding.progressBar.setVisibility(loading ? View.VISIBLE : View.GONE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateTitleAndStateIfActive(List<Chat> list) {
|
private void updateTitleAndStateIfActive(List<Chat> list) {
|
||||||
@@ -324,15 +330,12 @@ public class ChatFragment extends Fragment implements ChatAdapter.OnChatClickLis
|
|||||||
activeConversationId = getActivity().getIntent().getLongExtra("conversation_id", -1);
|
activeConversationId = getActivity().getIntent().getLongExtra("conversation_id", -1);
|
||||||
getActivity().getIntent().removeExtra("conversation_id");
|
getActivity().getIntent().removeExtra("conversation_id");
|
||||||
} else {
|
} else {
|
||||||
// Restore last active conversation if any
|
|
||||||
activeConversationId = viewModel.getLastActiveConversationId();
|
activeConversationId = viewModel.getLastActiveConversationId();
|
||||||
}
|
}
|
||||||
|
|
||||||
viewModel.loadCustomers();
|
viewModel.loadCustomers();
|
||||||
|
|
||||||
//
|
|
||||||
if (activeConversationId != null) {
|
if (activeConversationId != null) {
|
||||||
// Re-subscribe and load history if there is an active conversation ID
|
|
||||||
if (stompChatManager != null) stompChatManager.subscribeToConversation(activeConversationId);
|
if (stompChatManager != null) stompChatManager.subscribeToConversation(activeConversationId);
|
||||||
viewModel.loadMessageHistory(activeConversationId);
|
viewModel.loadMessageHistory(activeConversationId);
|
||||||
} else {
|
} else {
|
||||||
@@ -360,7 +363,9 @@ public class ChatFragment extends Fragment implements ChatAdapter.OnChatClickLis
|
|||||||
|
|
||||||
binding.etMessage.setText("");
|
binding.etMessage.setText("");
|
||||||
viewModel.sendMessage(activeConversationId, text).observe(getViewLifecycleOwner(), resource -> {
|
viewModel.sendMessage(activeConversationId, text).observe(getViewLifecycleOwner(), resource -> {
|
||||||
if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
if (resource == null) return;
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
|
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
||||||
viewModel.addMessageLocally(resource.data);
|
viewModel.addMessageLocally(resource.data);
|
||||||
viewModel.loadConversations();
|
viewModel.loadConversations();
|
||||||
}
|
}
|
||||||
@@ -416,10 +421,12 @@ public class ChatFragment extends Fragment implements ChatAdapter.OnChatClickLis
|
|||||||
removeAttachment();
|
removeAttachment();
|
||||||
|
|
||||||
viewModel.sendMessageWithAttachment(activeConversationId, contentPart, filePart).observe(getViewLifecycleOwner(), resource -> {
|
viewModel.sendMessageWithAttachment(activeConversationId, contentPart, filePart).observe(getViewLifecycleOwner(), resource -> {
|
||||||
if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
if (resource == null) return;
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
|
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
||||||
viewModel.addMessageLocally(resource.data);
|
viewModel.addMessageLocally(resource.data);
|
||||||
viewModel.loadConversations();
|
viewModel.loadConversations();
|
||||||
} else if (resource != null && resource.status == Resource.Status.ERROR) {
|
} else if (resource.status == Resource.Status.ERROR) {
|
||||||
Toast.makeText(requireContext(), "Failed to send attachment: " + resource.message, Toast.LENGTH_SHORT).show();
|
Toast.makeText(requireContext(), "Failed to send attachment: " + resource.message, Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -172,6 +172,12 @@ public class ProfileFragment extends Fragment {
|
|||||||
return binding.getRoot();
|
return binding.getRoot();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setLoading(boolean loading) {
|
||||||
|
if (binding != null && binding.progressBar != null) {
|
||||||
|
binding.progressBar.setVisibility(loading ? View.VISIBLE : View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroyView() {
|
public void onDestroyView() {
|
||||||
super.onDestroyView();
|
super.onDestroyView();
|
||||||
@@ -184,6 +190,7 @@ public class ProfileFragment extends Fragment {
|
|||||||
private void loadProfileData() {
|
private void loadProfileData() {
|
||||||
viewModel.getMe().observe(getViewLifecycleOwner(), resource -> {
|
viewModel.getMe().observe(getViewLifecycleOwner(), resource -> {
|
||||||
if (resource == null) return;
|
if (resource == null) return;
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
||||||
currentUser = resource.data;
|
currentUser = resource.data;
|
||||||
|
|
||||||
@@ -229,6 +236,7 @@ public class ProfileFragment extends Fragment {
|
|||||||
//Call the backend to upload the avatar
|
//Call the backend to upload the avatar
|
||||||
viewModel.uploadAvatar(body).observe(getViewLifecycleOwner(), resource -> {
|
viewModel.uploadAvatar(body).observe(getViewLifecycleOwner(), resource -> {
|
||||||
if (resource == null) return;
|
if (resource == null) return;
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
if (resource.status == Resource.Status.SUCCESS) {
|
if (resource.status == Resource.Status.SUCCESS) {
|
||||||
Toast.makeText(getContext(), "Avatar updated successfully", Toast.LENGTH_SHORT).show();
|
Toast.makeText(getContext(), "Avatar updated successfully", Toast.LENGTH_SHORT).show();
|
||||||
loadProfileData();
|
loadProfileData();
|
||||||
@@ -247,6 +255,7 @@ public class ProfileFragment extends Fragment {
|
|||||||
private void deleteAvatar() {
|
private void deleteAvatar() {
|
||||||
viewModel.deleteAvatar().observe(getViewLifecycleOwner(), resource -> {
|
viewModel.deleteAvatar().observe(getViewLifecycleOwner(), resource -> {
|
||||||
if (resource == null) return;
|
if (resource == null) return;
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
if (resource.status == Resource.Status.SUCCESS) {
|
if (resource.status == Resource.Status.SUCCESS) {
|
||||||
hasImage = false;
|
hasImage = false;
|
||||||
binding.imgProfile.setImageResource(R.drawable.placeholder);
|
binding.imgProfile.setImageResource(R.drawable.placeholder);
|
||||||
@@ -266,6 +275,7 @@ public class ProfileFragment extends Fragment {
|
|||||||
|
|
||||||
viewModel.updateMe(updates).observe(getViewLifecycleOwner(), resource -> {
|
viewModel.updateMe(updates).observe(getViewLifecycleOwner(), resource -> {
|
||||||
if (resource == null) return;
|
if (resource == null) return;
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
||||||
currentUser = resource.data;
|
currentUser = resource.data;
|
||||||
Toast.makeText(getContext(), "Profile updated successfully", Toast.LENGTH_SHORT).show();
|
Toast.makeText(getContext(), "Profile updated successfully", Toast.LENGTH_SHORT).show();
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ public class AnalyticsFragment extends Fragment {
|
|||||||
viewModel.getAnalyticsData().observe(getViewLifecycleOwner(), this::computeAndDisplay);
|
viewModel.getAnalyticsData().observe(getViewLifecycleOwner(), this::computeAndDisplay);
|
||||||
|
|
||||||
viewModel.getIsLoading().observe(getViewLifecycleOwner(), loading -> {
|
viewModel.getIsLoading().observe(getViewLifecycleOwner(), loading -> {
|
||||||
|
binding.progressBar.setVisibility(loading ? View.VISIBLE : View.GONE);
|
||||||
if (loading) {
|
if (loading) {
|
||||||
binding.tvTotalRevenue.setText("Loading...");
|
binding.tvTotalRevenue.setText("Loading...");
|
||||||
binding.tvTotalTransactions.setText("...");
|
binding.tvTotalTransactions.setText("...");
|
||||||
@@ -117,8 +118,6 @@ public class AnalyticsFragment extends Fragment {
|
|||||||
if (data.employeePerformance != null && !data.employeePerformance.isEmpty()) {
|
if (data.employeePerformance != null && !data.employeePerformance.isEmpty()) {
|
||||||
BigDecimal maxEmp = data.employeePerformance.get(data.employeePerformance.size() - 1).getValue();
|
BigDecimal maxEmp = data.employeePerformance.get(data.employeePerformance.size() - 1).getValue();
|
||||||
if (maxEmp.compareTo(BigDecimal.ZERO) == 0) maxEmp = BigDecimal.ONE;
|
if (maxEmp.compareTo(BigDecimal.ZERO) == 0) maxEmp = BigDecimal.ONE;
|
||||||
// Sorting is ascending from VM for some reason? Let's check VM... it says b.getValue().compareTo(a.getValue()) which is DESC.
|
|
||||||
// Wait, computeAnalytics sorts them... let's assume DESC as per VM code.
|
|
||||||
maxEmp = data.employeePerformance.get(0).getValue();
|
maxEmp = data.employeePerformance.get(0).getValue();
|
||||||
if (maxEmp.compareTo(BigDecimal.ZERO) == 0) maxEmp = BigDecimal.ONE;
|
if (maxEmp.compareTo(BigDecimal.ZERO) == 0) maxEmp = BigDecimal.ONE;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package com.example.petstoremobile.fragments.listfragments.detailfragments;
|
package com.example.petstoremobile.fragments.listfragments.detailfragments;
|
||||||
|
|
||||||
import android.app.DatePickerDialog;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.*;
|
import android.view.*;
|
||||||
import android.widget.*;
|
import android.widget.*;
|
||||||
@@ -12,7 +11,9 @@ import androidx.navigation.fragment.NavHostFragment;
|
|||||||
|
|
||||||
import com.example.petstoremobile.databinding.FragmentAdoptionDetailBinding;
|
import com.example.petstoremobile.databinding.FragmentAdoptionDetailBinding;
|
||||||
import com.example.petstoremobile.dtos.*;
|
import com.example.petstoremobile.dtos.*;
|
||||||
|
import com.example.petstoremobile.utils.DateTimeUtils;
|
||||||
import com.example.petstoremobile.utils.DialogUtils;
|
import com.example.petstoremobile.utils.DialogUtils;
|
||||||
|
import com.example.petstoremobile.utils.InputValidator;
|
||||||
import com.example.petstoremobile.utils.Resource;
|
import com.example.petstoremobile.utils.Resource;
|
||||||
import com.example.petstoremobile.utils.SpinnerUtils;
|
import com.example.petstoremobile.utils.SpinnerUtils;
|
||||||
import com.example.petstoremobile.utils.UIUtils;
|
import com.example.petstoremobile.utils.UIUtils;
|
||||||
@@ -73,6 +74,12 @@ public class AdoptionDetailFragment extends Fragment {
|
|||||||
viewModel.getEmployeeList().observe(getViewLifecycleOwner(), list -> refreshEmployeeSpinner());
|
viewModel.getEmployeeList().observe(getViewLifecycleOwner(), list -> refreshEmployeeSpinner());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setLoading(boolean loading) {
|
||||||
|
if (binding != null && binding.progressBar != null) {
|
||||||
|
binding.progressBar.setVisibility(loading ? View.VISIBLE : View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroyView() {
|
public void onDestroyView() {
|
||||||
super.onDestroyView();
|
super.onDestroyView();
|
||||||
@@ -116,29 +123,27 @@ public class AdoptionDetailFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setupDatePicker() {
|
private void setupDatePicker() {
|
||||||
binding.etAdoptionDate.setOnClickListener(v -> {
|
binding.etAdoptionDate.setOnClickListener(v -> UIUtils.showDatePicker(requireContext(), binding.etAdoptionDate, null));
|
||||||
Calendar c = Calendar.getInstance();
|
|
||||||
new DatePickerDialog(requireContext(),
|
|
||||||
(dp, y, m, d) -> binding.etAdoptionDate.setText(
|
|
||||||
String.format("%04d-%02d-%02d", y, m + 1, d)),
|
|
||||||
c.get(Calendar.YEAR),
|
|
||||||
c.get(Calendar.MONTH),
|
|
||||||
c.get(Calendar.DAY_OF_MONTH)).show();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadSpinnersData() {
|
private void loadSpinnersData() {
|
||||||
viewModel.loadPets().observe(getViewLifecycleOwner(), resource -> {
|
viewModel.loadPets().observe(getViewLifecycleOwner(), resource -> {
|
||||||
|
if (resource == null) return;
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
||||||
viewModel.setPetList(resource.data);
|
viewModel.setPetList(resource.data);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
viewModel.loadCustomers().observe(getViewLifecycleOwner(), resource -> {
|
viewModel.loadCustomers().observe(getViewLifecycleOwner(), resource -> {
|
||||||
|
if (resource == null) return;
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
||||||
viewModel.setCustomerList(resource.data);
|
viewModel.setCustomerList(resource.data);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
viewModel.loadStores().observe(getViewLifecycleOwner(), resource -> {
|
viewModel.loadStores().observe(getViewLifecycleOwner(), resource -> {
|
||||||
|
if (resource == null) return;
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
||||||
viewModel.setStoreList(resource.data);
|
viewModel.setStoreList(resource.data);
|
||||||
}
|
}
|
||||||
@@ -165,7 +170,9 @@ public class AdoptionDetailFragment extends Fragment {
|
|||||||
|
|
||||||
private void loadEmployees(Long storeId) {
|
private void loadEmployees(Long storeId) {
|
||||||
viewModel.loadEmployees(storeId).observe(getViewLifecycleOwner(), resource -> {
|
viewModel.loadEmployees(storeId).observe(getViewLifecycleOwner(), resource -> {
|
||||||
if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
if (resource == null) return;
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
|
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
||||||
viewModel.setEmployeeList(resource.data);
|
viewModel.setEmployeeList(resource.data);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -183,7 +190,7 @@ public class AdoptionDetailFragment extends Fragment {
|
|||||||
long adoptionId = a.getLong("adoptionId");
|
long adoptionId = a.getLong("adoptionId");
|
||||||
viewModel.setAdoptionId(adoptionId);
|
viewModel.setAdoptionId(adoptionId);
|
||||||
binding.tvAdoptionMode.setText("Edit Adoption");
|
binding.tvAdoptionMode.setText("Edit Adoption");
|
||||||
binding.tvAdoptionId.setText("ID: " + adoptionId);
|
binding.tvAdoptionId.setText(DateTimeUtils.formatId(adoptionId));
|
||||||
binding.tvAdoptionId.setVisibility(View.VISIBLE);
|
binding.tvAdoptionId.setVisibility(View.VISIBLE);
|
||||||
binding.btnDeleteAdoption.setVisibility(View.VISIBLE);
|
binding.btnDeleteAdoption.setVisibility(View.VISIBLE);
|
||||||
loadAdoptionData();
|
loadAdoptionData();
|
||||||
@@ -199,6 +206,7 @@ public class AdoptionDetailFragment extends Fragment {
|
|||||||
private void loadAdoptionData() {
|
private void loadAdoptionData() {
|
||||||
viewModel.loadAdoption().observe(getViewLifecycleOwner(), resource -> {
|
viewModel.loadAdoption().observe(getViewLifecycleOwner(), resource -> {
|
||||||
if (resource == null) return;
|
if (resource == null) return;
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
||||||
AdoptionDTO a = resource.data;
|
AdoptionDTO a = resource.data;
|
||||||
preselectedPetId = a.getPetId() != null ? a.getPetId() : -1;
|
preselectedPetId = a.getPetId() != null ? a.getPetId() : -1;
|
||||||
@@ -224,29 +232,16 @@ public class AdoptionDetailFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void saveAdoption() {
|
private void saveAdoption() {
|
||||||
if (binding.spinnerAdoptionCustomer.getSelectedItemPosition() == 0) {
|
if (!InputValidator.isSpinnerSelected(binding.spinnerAdoptionCustomer, "Customer")) return;
|
||||||
Toast.makeText(getContext(), "Select a customer", Toast.LENGTH_SHORT).show(); return;
|
if (!InputValidator.isSpinnerSelected(binding.spinnerAdoptionPet, "Pet")) return;
|
||||||
}
|
if (!InputValidator.isSpinnerSelected(binding.spinnerAdoptionStore, "Store")) return;
|
||||||
if (binding.spinnerAdoptionPet.getSelectedItemPosition() == 0) {
|
if (!InputValidator.isNotEmpty(binding.etAdoptionDate, "Adoption Date")) return;
|
||||||
Toast.makeText(getContext(), "Select a pet", Toast.LENGTH_SHORT).show(); return;
|
|
||||||
}
|
|
||||||
if (binding.spinnerAdoptionStore.getSelectedItemPosition() == 0) {
|
|
||||||
Toast.makeText(getContext(), "Select a store", Toast.LENGTH_SHORT).show(); return;
|
|
||||||
}
|
|
||||||
String date = binding.etAdoptionDate.getText().toString().trim();
|
|
||||||
if (date.isEmpty()) {
|
|
||||||
Toast.makeText(getContext(), "Select a date", Toast.LENGTH_SHORT).show(); return;
|
|
||||||
}
|
|
||||||
|
|
||||||
BigDecimal fee = BigDecimal.ZERO;
|
BigDecimal fee = BigDecimal.ZERO;
|
||||||
String feeStr = binding.etAdoptionFee.getText().toString().trim();
|
String feeStr = binding.etAdoptionFee.getText().toString().trim();
|
||||||
if (!feeStr.isEmpty()) {
|
if (!feeStr.isEmpty()) {
|
||||||
try {
|
if (!InputValidator.isPositiveDecimal(binding.etAdoptionFee, "Adoption Fee")) return;
|
||||||
fee = new BigDecimal(feeStr);
|
fee = new BigDecimal(feeStr);
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
Toast.makeText(getContext(), "Invalid fee format", Toast.LENGTH_SHORT).show();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DropdownDTO customer = viewModel.getCustomerList().getValue().get(binding.spinnerAdoptionCustomer.getSelectedItemPosition() - 1);
|
DropdownDTO customer = viewModel.getCustomerList().getValue().get(binding.spinnerAdoptionCustomer.getSelectedItemPosition() - 1);
|
||||||
@@ -258,6 +253,7 @@ public class AdoptionDetailFragment extends Fragment {
|
|||||||
employeeId = viewModel.getEmployeeList().getValue().get(binding.spinnerAdoptionEmployee.getSelectedItemPosition() - 1).getId();
|
employeeId = viewModel.getEmployeeList().getValue().get(binding.spinnerAdoptionEmployee.getSelectedItemPosition() - 1).getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String adoptionDate = binding.etAdoptionDate.getText().toString().trim();
|
||||||
String status = STATUSES[binding.spinnerAdoptionStatus.getSelectedItemPosition()];
|
String status = STATUSES[binding.spinnerAdoptionStatus.getSelectedItemPosition()];
|
||||||
|
|
||||||
AdoptionDTO dto = new AdoptionDTO(
|
AdoptionDTO dto = new AdoptionDTO(
|
||||||
@@ -265,12 +261,14 @@ public class AdoptionDetailFragment extends Fragment {
|
|||||||
customer.getId(),
|
customer.getId(),
|
||||||
employeeId,
|
employeeId,
|
||||||
store.getId(),
|
store.getId(),
|
||||||
date,
|
adoptionDate,
|
||||||
status,
|
status,
|
||||||
fee
|
fee
|
||||||
);
|
);
|
||||||
|
|
||||||
viewModel.saveAdoption(dto).observe(getViewLifecycleOwner(), resource -> {
|
viewModel.saveAdoption(dto).observe(getViewLifecycleOwner(), resource -> {
|
||||||
|
if (resource == null) return;
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
if (resource.status == Resource.Status.SUCCESS) {
|
if (resource.status == Resource.Status.SUCCESS) {
|
||||||
Toast.makeText(getContext(), viewModel.isEditing() ? "Updated" : "Saved", Toast.LENGTH_SHORT).show();
|
Toast.makeText(getContext(), viewModel.isEditing() ? "Updated" : "Saved", Toast.LENGTH_SHORT).show();
|
||||||
navigateBack();
|
navigateBack();
|
||||||
@@ -281,8 +279,10 @@ public class AdoptionDetailFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void confirmDelete() {
|
private void confirmDelete() {
|
||||||
DialogUtils.showDeleteConfirmDialog(requireContext(), "Adoption", () ->
|
DialogUtils.showDeleteConfirmDialog(requireContext(), "Adoption Record", () ->
|
||||||
viewModel.deleteAdoption().observe(getViewLifecycleOwner(), resource -> {
|
viewModel.deleteAdoption().observe(getViewLifecycleOwner(), resource -> {
|
||||||
|
if (resource == null) return;
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
if (resource.status == Resource.Status.SUCCESS) {
|
if (resource.status == Resource.Status.SUCCESS) {
|
||||||
Toast.makeText(getContext(), "Deleted", Toast.LENGTH_SHORT).show();
|
Toast.makeText(getContext(), "Deleted", Toast.LENGTH_SHORT).show();
|
||||||
navigateBack();
|
navigateBack();
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import com.example.petstoremobile.dtos.DropdownDTO;
|
|||||||
import com.example.petstoremobile.dtos.ServiceDTO;
|
import com.example.petstoremobile.dtos.ServiceDTO;
|
||||||
import com.example.petstoremobile.utils.DateTimeUtils;
|
import com.example.petstoremobile.utils.DateTimeUtils;
|
||||||
import com.example.petstoremobile.utils.DialogUtils;
|
import com.example.petstoremobile.utils.DialogUtils;
|
||||||
|
import com.example.petstoremobile.utils.InputValidator;
|
||||||
import com.example.petstoremobile.utils.Resource;
|
import com.example.petstoremobile.utils.Resource;
|
||||||
import com.example.petstoremobile.utils.SpinnerUtils;
|
import com.example.petstoremobile.utils.SpinnerUtils;
|
||||||
import com.example.petstoremobile.utils.UIUtils;
|
import com.example.petstoremobile.utils.UIUtils;
|
||||||
@@ -140,6 +141,12 @@ public class AppointmentDetailFragment extends Fragment {
|
|||||||
SpinnerUtils.populateSpinner(requireContext(), binding.spinnerStaff, list, DropdownDTO::getLabel, "-- Select Staff --", preselectedStaffId, DropdownDTO::getId));
|
SpinnerUtils.populateSpinner(requireContext(), binding.spinnerStaff, list, DropdownDTO::getLabel, "-- Select Staff --", preselectedStaffId, DropdownDTO::getId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setLoading(boolean loading) {
|
||||||
|
if (binding != null && binding.progressBar != null) {
|
||||||
|
binding.progressBar.setVisibility(loading ? View.VISIBLE : View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void applyViewState(AppointmentDetailViewModel.ViewState state) {
|
private void applyViewState(AppointmentDetailViewModel.ViewState state) {
|
||||||
isUpdatingUI = true;
|
isUpdatingUI = true;
|
||||||
|
|
||||||
@@ -189,7 +196,9 @@ public class AppointmentDetailFragment extends Fragment {
|
|||||||
|
|
||||||
private void loadAppointmentData() {
|
private void loadAppointmentData() {
|
||||||
viewModel.loadAppointment().observe(getViewLifecycleOwner(), resource -> {
|
viewModel.loadAppointment().observe(getViewLifecycleOwner(), resource -> {
|
||||||
if (resource == null || resource.status != Resource.Status.SUCCESS || resource.data == null) return;
|
if (resource == null) return;
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
|
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
||||||
AppointmentDTO a = resource.data;
|
AppointmentDTO a = resource.data;
|
||||||
preselectedPetId = a.getPetId() != null ? a.getPetId() : -1;
|
preselectedPetId = a.getPetId() != null ? a.getPetId() : -1;
|
||||||
preselectedServiceId = a.getServiceId() != null ? a.getServiceId() : -1;
|
preselectedServiceId = a.getServiceId() != null ? a.getServiceId() : -1;
|
||||||
@@ -205,6 +214,7 @@ public class AppointmentDetailFragment extends Fragment {
|
|||||||
SpinnerUtils.setSelectionByValue(binding.spinnerAppointmentStatus, DateTimeUtils.formatStatusFromBackend(status));
|
SpinnerUtils.setSelectionByValue(binding.spinnerAppointmentStatus, DateTimeUtils.formatStatusFromBackend(status));
|
||||||
}
|
}
|
||||||
notifyDateTimeStatusChange();
|
notifyDateTimeStatusChange();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,6 +231,8 @@ public class AppointmentDetailFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
viewModel.saveAppointment(date, time, status).observe(getViewLifecycleOwner(), resource -> {
|
viewModel.saveAppointment(date, time, status).observe(getViewLifecycleOwner(), resource -> {
|
||||||
|
if (resource == null) return;
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
if (resource.status == Resource.Status.SUCCESS) {
|
if (resource.status == Resource.Status.SUCCESS) {
|
||||||
AppointmentDetailViewModel.ViewState state = viewModel.getViewState().getValue();
|
AppointmentDetailViewModel.ViewState state = viewModel.getViewState().getValue();
|
||||||
String message = (state != null && state.isEditing) ? "Updated" : "Saved";
|
String message = (state != null && state.isEditing) ? "Updated" : "Saved";
|
||||||
@@ -233,11 +245,11 @@ public class AppointmentDetailFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean validateRequiredFields() {
|
private boolean validateRequiredFields() {
|
||||||
if (binding.spinnerCustomer.getSelectedItemPosition() == 0) return UIUtils.showToast(getContext(), "Select a customer");
|
if (!InputValidator.isSpinnerSelected(binding.spinnerCustomer, "Customer")) return false;
|
||||||
if (binding.spinnerStore.getSelectedItemPosition() == 0) return UIUtils.showToast(getContext(), "Select a store");
|
if (!InputValidator.isSpinnerSelected(binding.spinnerStore, "Store")) return false;
|
||||||
if (binding.spinnerPet.getSelectedItemPosition() == 0) return UIUtils.showToast(getContext(), "Select a pet");
|
if (!InputValidator.isSpinnerSelected(binding.spinnerPet, "Pet")) return false;
|
||||||
if (binding.spinnerService.getSelectedItemPosition() == 0) return UIUtils.showToast(getContext(), "Select a service");
|
if (!InputValidator.isSpinnerSelected(binding.spinnerService, "Service")) return false;
|
||||||
if (binding.etAppointmentDate.getText().toString().trim().isEmpty()) return UIUtils.showToast(getContext(), "Select a date");
|
if (!InputValidator.isNotEmpty(binding.etAppointmentDate, "Appointment Date")) return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,6 +273,8 @@ public class AppointmentDetailFragment extends Fragment {
|
|||||||
private void confirmDelete() {
|
private void confirmDelete() {
|
||||||
DialogUtils.showDeleteConfirmDialog(requireContext(), "Appointment", () ->
|
DialogUtils.showDeleteConfirmDialog(requireContext(), "Appointment", () ->
|
||||||
viewModel.deleteAppointment().observe(getViewLifecycleOwner(), resource -> {
|
viewModel.deleteAppointment().observe(getViewLifecycleOwner(), resource -> {
|
||||||
|
if (resource == null) return;
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
if (resource.status == Resource.Status.SUCCESS) navigateBack();
|
if (resource.status == Resource.Status.SUCCESS) navigateBack();
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import android.widget.Toast;
|
|||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.appcompat.app.AlertDialog;
|
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.lifecycle.ViewModelProvider;
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
import androidx.navigation.fragment.NavHostFragment;
|
import androidx.navigation.fragment.NavHostFragment;
|
||||||
@@ -17,9 +16,11 @@ import com.example.petstoremobile.databinding.FragmentInventoryDetailBinding;
|
|||||||
import com.example.petstoremobile.dtos.DropdownDTO;
|
import com.example.petstoremobile.dtos.DropdownDTO;
|
||||||
import com.example.petstoremobile.dtos.InventoryDTO;
|
import com.example.petstoremobile.dtos.InventoryDTO;
|
||||||
import com.example.petstoremobile.dtos.ProductDTO;
|
import com.example.petstoremobile.dtos.ProductDTO;
|
||||||
|
import com.example.petstoremobile.utils.DialogUtils;
|
||||||
import com.example.petstoremobile.utils.InputValidator;
|
import com.example.petstoremobile.utils.InputValidator;
|
||||||
import com.example.petstoremobile.utils.Resource;
|
import com.example.petstoremobile.utils.Resource;
|
||||||
import com.example.petstoremobile.utils.SpinnerUtils;
|
import com.example.petstoremobile.utils.SpinnerUtils;
|
||||||
|
import com.example.petstoremobile.utils.UIUtils;
|
||||||
import com.example.petstoremobile.viewmodels.InventoryDetailViewModel;
|
import com.example.petstoremobile.viewmodels.InventoryDetailViewModel;
|
||||||
|
|
||||||
import dagger.hilt.android.AndroidEntryPoint;
|
import dagger.hilt.android.AndroidEntryPoint;
|
||||||
@@ -67,6 +68,12 @@ public class InventoryDetailFragment extends Fragment {
|
|||||||
viewModel.getProductList().observe(getViewLifecycleOwner(), list -> refreshProductSpinner());
|
viewModel.getProductList().observe(getViewLifecycleOwner(), list -> refreshProductSpinner());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setLoading(boolean loading) {
|
||||||
|
if (binding != null && binding.progressBar != null) {
|
||||||
|
binding.progressBar.setVisibility(loading ? View.VISIBLE : View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroyView() {
|
public void onDestroyView() {
|
||||||
super.onDestroyView();
|
super.onDestroyView();
|
||||||
@@ -75,11 +82,15 @@ public class InventoryDetailFragment extends Fragment {
|
|||||||
|
|
||||||
private void loadSpinnersData() {
|
private void loadSpinnersData() {
|
||||||
viewModel.loadStores().observe(getViewLifecycleOwner(), resource -> {
|
viewModel.loadStores().observe(getViewLifecycleOwner(), resource -> {
|
||||||
|
if (resource == null) return;
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
||||||
viewModel.setStoreList(resource.data);
|
viewModel.setStoreList(resource.data);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
viewModel.loadProducts().observe(getViewLifecycleOwner(), resource -> {
|
viewModel.loadProducts().observe(getViewLifecycleOwner(), resource -> {
|
||||||
|
if (resource == null) return;
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
||||||
viewModel.setProductList(resource.data.getContent());
|
viewModel.setProductList(resource.data.getContent());
|
||||||
}
|
}
|
||||||
@@ -123,6 +134,7 @@ public class InventoryDetailFragment extends Fragment {
|
|||||||
private void loadInventoryData() {
|
private void loadInventoryData() {
|
||||||
viewModel.loadInventory().observe(getViewLifecycleOwner(), resource -> {
|
viewModel.loadInventory().observe(getViewLifecycleOwner(), resource -> {
|
||||||
if (resource == null) return;
|
if (resource == null) return;
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
||||||
InventoryDTO inv = resource.data;
|
InventoryDTO inv = resource.data;
|
||||||
binding.etQuantity.setText(String.valueOf(inv.getQuantity()));
|
binding.etQuantity.setText(String.valueOf(inv.getQuantity()));
|
||||||
@@ -138,19 +150,9 @@ public class InventoryDetailFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void saveInventory() {
|
private void saveInventory() {
|
||||||
if (binding.spinnerInventoryStore.getSelectedItemPosition() == 0) {
|
if (!InputValidator.isSpinnerSelected(binding.spinnerInventoryStore, "Store")) return;
|
||||||
Toast.makeText(getContext(), "Please select a store", Toast.LENGTH_SHORT).show();
|
if (!InputValidator.isSpinnerSelected(binding.spinnerInventoryProduct, "Product")) return;
|
||||||
return;
|
if (!InputValidator.isPositiveInteger(binding.etQuantity, "Quantity")) return;
|
||||||
}
|
|
||||||
if (binding.spinnerInventoryProduct.getSelectedItemPosition() == 0) {
|
|
||||||
Toast.makeText(getContext(), "Please select a product", Toast.LENGTH_SHORT).show();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!InputValidator.isNotEmpty(binding.etQuantity, "Quantity") ||
|
|
||||||
!InputValidator.isPositiveInteger(binding.etQuantity, "Quantity")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int quantity = Integer.parseInt(binding.etQuantity.getText().toString().trim());
|
int quantity = Integer.parseInt(binding.etQuantity.getText().toString().trim());
|
||||||
DropdownDTO store = viewModel.getStoreList().getValue().get(binding.spinnerInventoryStore.getSelectedItemPosition() - 1);
|
DropdownDTO store = viewModel.getStoreList().getValue().get(binding.spinnerInventoryStore.getSelectedItemPosition() - 1);
|
||||||
@@ -160,6 +162,9 @@ public class InventoryDetailFragment extends Fragment {
|
|||||||
setButtonsEnabled(false);
|
setButtonsEnabled(false);
|
||||||
|
|
||||||
viewModel.saveInventory(request).observe(getViewLifecycleOwner(), resource -> {
|
viewModel.saveInventory(request).observe(getViewLifecycleOwner(), resource -> {
|
||||||
|
if (resource == null) return;
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
|
if (resource.status != Resource.Status.LOADING) {
|
||||||
setButtonsEnabled(true);
|
setButtonsEnabled(true);
|
||||||
if (resource.status == Resource.Status.SUCCESS) {
|
if (resource.status == Resource.Status.SUCCESS) {
|
||||||
Toast.makeText(getContext(), viewModel.isEditing() ? "Inventory updated" : "Inventory created", Toast.LENGTH_SHORT).show();
|
Toast.makeText(getContext(), viewModel.isEditing() ? "Inventory updated" : "Inventory created", Toast.LENGTH_SHORT).show();
|
||||||
@@ -167,21 +172,20 @@ public class InventoryDetailFragment extends Fragment {
|
|||||||
} else if (resource.status == Resource.Status.ERROR) {
|
} else if (resource.status == Resource.Status.ERROR) {
|
||||||
Toast.makeText(getContext(), "Error: " + resource.message, Toast.LENGTH_SHORT).show();
|
Toast.makeText(getContext(), "Error: " + resource.message, Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void confirmDelete() {
|
private void confirmDelete() {
|
||||||
new AlertDialog.Builder(requireContext())
|
DialogUtils.showDeleteConfirmDialog(requireContext(), "Inventory Item", this::deleteInventory);
|
||||||
.setTitle("Delete inventory item?")
|
|
||||||
.setMessage("This cannot be undone.")
|
|
||||||
.setPositiveButton("Delete", (d, w) -> deleteInventory())
|
|
||||||
.setNegativeButton("Cancel", null)
|
|
||||||
.show();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void deleteInventory() {
|
private void deleteInventory() {
|
||||||
setButtonsEnabled(false);
|
setButtonsEnabled(false);
|
||||||
viewModel.deleteInventory().observe(getViewLifecycleOwner(), resource -> {
|
viewModel.deleteInventory().observe(getViewLifecycleOwner(), resource -> {
|
||||||
|
if (resource == null) return;
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
|
if (resource.status != Resource.Status.LOADING) {
|
||||||
setButtonsEnabled(true);
|
setButtonsEnabled(true);
|
||||||
if (resource.status == Resource.Status.SUCCESS) {
|
if (resource.status == Resource.Status.SUCCESS) {
|
||||||
Toast.makeText(getContext(), "Inventory deleted", Toast.LENGTH_SHORT).show();
|
Toast.makeText(getContext(), "Inventory deleted", Toast.LENGTH_SHORT).show();
|
||||||
@@ -189,6 +193,7 @@ public class InventoryDetailFragment extends Fragment {
|
|||||||
} else if (resource.status == Resource.Status.ERROR) {
|
} else if (resource.status == Resource.Status.ERROR) {
|
||||||
Toast.makeText(getContext(), "Delete failed: " + resource.message, Toast.LENGTH_SHORT).show();
|
Toast.makeText(getContext(), "Delete failed: " + resource.message, Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,8 +202,6 @@ public class InventoryDetailFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setButtonsEnabled(boolean enabled) {
|
private void setButtonsEnabled(boolean enabled) {
|
||||||
binding.btnSaveInventory.setEnabled(enabled);
|
UIUtils.setViewsEnabled(enabled, binding.btnSaveInventory, binding.btnDeleteInventory, binding.btnInventoryBack);
|
||||||
binding.btnDeleteInventory.setEnabled(enabled);
|
|
||||||
binding.btnInventoryBack.setEnabled(enabled);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import com.example.petstoremobile.databinding.FragmentPetDetailBinding;
|
|||||||
import com.example.petstoremobile.dtos.DropdownDTO;
|
import com.example.petstoremobile.dtos.DropdownDTO;
|
||||||
import com.example.petstoremobile.dtos.PetDTO;
|
import com.example.petstoremobile.dtos.PetDTO;
|
||||||
import com.example.petstoremobile.utils.ActivityLogger;
|
import com.example.petstoremobile.utils.ActivityLogger;
|
||||||
|
import com.example.petstoremobile.utils.DateTimeUtils;
|
||||||
import com.example.petstoremobile.utils.DialogUtils;
|
import com.example.petstoremobile.utils.DialogUtils;
|
||||||
import com.example.petstoremobile.utils.InputValidator;
|
import com.example.petstoremobile.utils.InputValidator;
|
||||||
import com.example.petstoremobile.utils.Resource;
|
import com.example.petstoremobile.utils.Resource;
|
||||||
@@ -65,7 +66,6 @@ public class PetDetailFragment extends Fragment {
|
|||||||
observeViewModel();
|
observeViewModel();
|
||||||
handleArguments();
|
handleArguments();
|
||||||
|
|
||||||
//set button click listeners
|
|
||||||
binding.btnBack.setOnClickListener(v -> navigateBack());
|
binding.btnBack.setOnClickListener(v -> navigateBack());
|
||||||
binding.btnSavePet.setOnClickListener(v -> savePet());
|
binding.btnSavePet.setOnClickListener(v -> savePet());
|
||||||
binding.btnDeletePet.setOnClickListener(v -> deletePet());
|
binding.btnDeletePet.setOnClickListener(v -> deletePet());
|
||||||
@@ -76,36 +76,41 @@ public class PetDetailFragment extends Fragment {
|
|||||||
viewModel.getStoreList().observe(getViewLifecycleOwner(), list -> updateStoreSpinnerSelection());
|
viewModel.getStoreList().observe(getViewLifecycleOwner(), list -> updateStoreSpinnerSelection());
|
||||||
|
|
||||||
viewModel.loadCustomers().observe(getViewLifecycleOwner(), resource -> {
|
viewModel.loadCustomers().observe(getViewLifecycleOwner(), resource -> {
|
||||||
if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
if (resource == null) return;
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
|
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
||||||
viewModel.setCustomerList(resource.data);
|
viewModel.setCustomerList(resource.data);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
viewModel.loadStores().observe(getViewLifecycleOwner(), resource -> {
|
viewModel.loadStores().observe(getViewLifecycleOwner(), resource -> {
|
||||||
if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
if (resource == null) return;
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
|
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
||||||
viewModel.setStoreList(resource.data);
|
viewModel.setStoreList(resource.data);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setLoading(boolean loading) {
|
||||||
|
if (binding != null && binding.progressBar != null) {
|
||||||
|
binding.progressBar.setVisibility(loading ? View.VISIBLE : View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroyView() {
|
public void onDestroyView() {
|
||||||
super.onDestroyView();
|
super.onDestroyView();
|
||||||
binding = null;
|
binding = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles the saving of pet data (adding/updating).
|
|
||||||
*/
|
|
||||||
private void savePet() {
|
private void savePet() {
|
||||||
// Validates all fields using InputValidator
|
|
||||||
if (!InputValidator.isNotEmpty(binding.etPetName, "Pet Name")) return;
|
if (!InputValidator.isNotEmpty(binding.etPetName, "Pet Name")) return;
|
||||||
if (!InputValidator.isNotEmpty(binding.etPetSpecies, "Species")) return;
|
if (!InputValidator.isNotEmpty(binding.etPetSpecies, "Species")) return;
|
||||||
if (!InputValidator.isNotEmpty(binding.etPetBreed, "Breed")) return;
|
if (!InputValidator.isNotEmpty(binding.etPetBreed, "Breed")) return;
|
||||||
if (!InputValidator.isPositiveInteger(binding.etPetAge, "Age")) return;
|
if (!InputValidator.isPositiveInteger(binding.etPetAge, "Age")) return;
|
||||||
if (!InputValidator.isPositiveDecimal(binding.etPetPrice, "Price")) return;
|
if (!InputValidator.isPositiveDecimal(binding.etPetPrice, "Price")) return;
|
||||||
|
|
||||||
//get all the values from the fields
|
|
||||||
String name = binding.etPetName.getText().toString().trim();
|
String name = binding.etPetName.getText().toString().trim();
|
||||||
String species = binding.etPetSpecies.getText().toString().trim();
|
String species = binding.etPetSpecies.getText().toString().trim();
|
||||||
String breed = binding.etPetBreed.getText().toString().trim();
|
String breed = binding.etPetBreed.getText().toString().trim();
|
||||||
@@ -113,37 +118,27 @@ public class PetDetailFragment extends Fragment {
|
|||||||
double price = Double.parseDouble(binding.etPetPrice.getText().toString().trim());
|
double price = Double.parseDouble(binding.etPetPrice.getText().toString().trim());
|
||||||
String status = binding.spinnerPetStatus.getSelectedItem().toString();
|
String status = binding.spinnerPetStatus.getSelectedItem().toString();
|
||||||
|
|
||||||
// Get selected customer
|
|
||||||
Long customerId = null;
|
Long customerId = null;
|
||||||
int customerPos = binding.spinnerCustomer.getSelectedItemPosition();
|
if (binding.spinnerCustomer.getSelectedItemPosition() > 0) {
|
||||||
if (customerPos > 0) { // 0 means no customer for pet
|
customerId = viewModel.getCustomerList().getValue().get(binding.spinnerCustomer.getSelectedItemPosition() - 1).getId();
|
||||||
customerId = viewModel.getCustomerList().getValue().get(customerPos - 1).getId();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get selected store
|
|
||||||
Long storeId = null;
|
Long storeId = null;
|
||||||
int storePos = binding.spinnerStore.getSelectedItemPosition();
|
if (binding.spinnerStore.getSelectedItemPosition() > 0) {
|
||||||
if (storePos > 0) {
|
storeId = viewModel.getStoreList().getValue().get(binding.spinnerStore.getSelectedItemPosition() - 1).getId();
|
||||||
storeId = viewModel.getStoreList().getValue().get(storePos - 1).getId();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validation: If status is Available, a store must be selected
|
|
||||||
if ("Available".equalsIgnoreCase(status)) {
|
if ("Available".equalsIgnoreCase(status)) {
|
||||||
if (!InputValidator.isSpinnerSelected(binding.spinnerStore, "Store")) return;
|
if (!InputValidator.isSpinnerSelected(binding.spinnerStore, "Store")) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validation: If status is Owned, an owner must be selected
|
|
||||||
if ("Owned".equalsIgnoreCase(status)) {
|
if ("Owned".equalsIgnoreCase(status)) {
|
||||||
if (!InputValidator.isSpinnerSelected(binding.spinnerCustomer, "Owner")) return;
|
if (!InputValidator.isSpinnerSelected(binding.spinnerCustomer, "Owner")) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validation: If status is Adopted, an owner and store must be selected
|
|
||||||
if ("Adopted".equalsIgnoreCase(status)) {
|
if ("Adopted".equalsIgnoreCase(status)) {
|
||||||
if (!InputValidator.isSpinnerSelected(binding.spinnerCustomer, "Owner")) return;
|
if (!InputValidator.isSpinnerSelected(binding.spinnerCustomer, "Owner")) return;
|
||||||
if (!InputValidator.isSpinnerSelected(binding.spinnerStore, "Store")) return;
|
if (!InputValidator.isSpinnerSelected(binding.spinnerStore, "Store")) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//create a pet object to send to the API
|
|
||||||
PetDTO petDTO = new PetDTO();
|
PetDTO petDTO = new PetDTO();
|
||||||
petDTO.setPetName(name);
|
petDTO.setPetName(name);
|
||||||
petDTO.setPetSpecies(species);
|
petDTO.setPetSpecies(species);
|
||||||
@@ -155,6 +150,8 @@ public class PetDetailFragment extends Fragment {
|
|||||||
petDTO.setStoreId(storeId);
|
petDTO.setStoreId(storeId);
|
||||||
|
|
||||||
viewModel.savePet(petDTO).observe(getViewLifecycleOwner(), resource -> {
|
viewModel.savePet(petDTO).observe(getViewLifecycleOwner(), resource -> {
|
||||||
|
if (resource == null) return;
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
if (resource.status == Resource.Status.SUCCESS) {
|
if (resource.status == Resource.Status.SUCCESS) {
|
||||||
if (viewModel.isEditing()) {
|
if (viewModel.isEditing()) {
|
||||||
ActivityLogger.logChange(requireContext(), "Pet", "UPDATED", (int) viewModel.getPetId());
|
ActivityLogger.logChange(requireContext(), "Pet", "UPDATED", (int) viewModel.getPetId());
|
||||||
@@ -170,12 +167,11 @@ public class PetDetailFragment extends Fragment {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Displays a confirmation dialog and handles the deletion of a pet.
|
|
||||||
*/
|
|
||||||
private void deletePet() {
|
private void deletePet() {
|
||||||
DialogUtils.showDeleteConfirmDialog(requireContext(), "Pet", () ->
|
DialogUtils.showDeleteConfirmDialog(requireContext(), "Pet", () -> {
|
||||||
viewModel.deletePet().observe(getViewLifecycleOwner(), resource -> {
|
viewModel.deletePet().observe(getViewLifecycleOwner(), resource -> {
|
||||||
|
if (resource == null) return;
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
if (resource.status == Resource.Status.SUCCESS) {
|
if (resource.status == Resource.Status.SUCCESS) {
|
||||||
ActivityLogger.logChange(requireContext(), "Pet", "DELETED", (int) viewModel.getPetId());
|
ActivityLogger.logChange(requireContext(), "Pet", "DELETED", (int) viewModel.getPetId());
|
||||||
Toast.makeText(getContext(), "Pet deleted successfully!", Toast.LENGTH_SHORT).show();
|
Toast.makeText(getContext(), "Pet deleted successfully!", Toast.LENGTH_SHORT).show();
|
||||||
@@ -183,32 +179,24 @@ public class PetDetailFragment extends Fragment {
|
|||||||
} else if (resource.status == Resource.Status.ERROR) {
|
} else if (resource.status == Resource.Status.ERROR) {
|
||||||
Toast.makeText(getContext(), "Delete failed: " + resource.message, Toast.LENGTH_SHORT).show();
|
Toast.makeText(getContext(), "Delete failed: " + resource.message, Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
}));
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Navigates back to the pet list screen.
|
|
||||||
*/
|
|
||||||
private void navigateToPetList() {
|
private void navigateToPetList() {
|
||||||
NavHostFragment.findNavController(this).popBackStack(R.id.nav_pet, false);
|
NavHostFragment.findNavController(this).popBackStack(R.id.nav_pet, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Navigates back to the previous screen.
|
|
||||||
*/
|
|
||||||
private void navigateBack() {
|
private void navigateBack() {
|
||||||
NavHostFragment.findNavController(this).popBackStack();
|
NavHostFragment.findNavController(this).popBackStack();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles arguments passed to the fragment to determine if it's in edit or add mode.
|
|
||||||
*/
|
|
||||||
private void handleArguments() {
|
private void handleArguments() {
|
||||||
if (getArguments() != null && getArguments().containsKey("petId")) {
|
if (getArguments() != null && getArguments().containsKey("petId")) {
|
||||||
long petId = getArguments().getLong("petId");
|
long petId = getArguments().getLong("petId");
|
||||||
viewModel.setPetId(petId);
|
viewModel.setPetId(petId);
|
||||||
binding.tvMode.setText("Edit Pet");
|
binding.tvMode.setText("Edit Pet");
|
||||||
binding.tvPetId.setText("ID: " + petId);
|
binding.tvPetId.setText(DateTimeUtils.formatId(petId));
|
||||||
binding.tvPetId.setVisibility(View.VISIBLE);
|
binding.tvPetId.setVisibility(View.VISIBLE);
|
||||||
binding.btnDeletePet.setVisibility(View.VISIBLE);
|
binding.btnDeletePet.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
@@ -225,12 +213,10 @@ public class PetDetailFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetches specific pet details from the backend using the ID.
|
|
||||||
*/
|
|
||||||
private void loadPetData() {
|
private void loadPetData() {
|
||||||
viewModel.loadPet().observe(getViewLifecycleOwner(), resource -> {
|
viewModel.loadPet().observe(getViewLifecycleOwner(), resource -> {
|
||||||
if (resource == null) return;
|
if (resource == null) return;
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
||||||
PetDTO p = resource.data;
|
PetDTO p = resource.data;
|
||||||
binding.etPetName.setText(p.getPetName());
|
binding.etPetName.setText(p.getPetName());
|
||||||
@@ -253,9 +239,6 @@ public class PetDetailFragment extends Fragment {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the customer spinner with the current list and sets the selection if needed.
|
|
||||||
*/
|
|
||||||
private void updateCustomerSpinnerSelection() {
|
private void updateCustomerSpinnerSelection() {
|
||||||
SpinnerUtils.populateSpinner(
|
SpinnerUtils.populateSpinner(
|
||||||
requireContext(),
|
requireContext(),
|
||||||
@@ -268,9 +251,6 @@ public class PetDetailFragment extends Fragment {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the store spinner with the current list and sets the selection if needed.
|
|
||||||
*/
|
|
||||||
private void updateStoreSpinnerSelection() {
|
private void updateStoreSpinnerSelection() {
|
||||||
SpinnerUtils.populateSpinner(
|
SpinnerUtils.populateSpinner(
|
||||||
requireContext(),
|
requireContext(),
|
||||||
@@ -283,9 +263,6 @@ public class PetDetailFragment extends Fragment {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Initializes the spinner for pet status selection.
|
|
||||||
*/
|
|
||||||
private void setupSpinner() {
|
private void setupSpinner() {
|
||||||
SpinnerUtils.setupStringSpinner(requireContext(), binding.spinnerPetStatus,
|
SpinnerUtils.setupStringSpinner(requireContext(), binding.spinnerPetStatus,
|
||||||
new String[]{"Available", "Adopted", "Owned"});
|
new String[]{"Available", "Adopted", "Owned"});
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import com.example.petstoremobile.api.auth.TokenManager;
|
|||||||
import com.example.petstoremobile.databinding.FragmentProductDetailBinding;
|
import com.example.petstoremobile.databinding.FragmentProductDetailBinding;
|
||||||
import com.example.petstoremobile.dtos.*;
|
import com.example.petstoremobile.dtos.*;
|
||||||
import com.example.petstoremobile.viewmodels.ProductDetailViewModel;
|
import com.example.petstoremobile.viewmodels.ProductDetailViewModel;
|
||||||
|
import com.example.petstoremobile.utils.DateTimeUtils;
|
||||||
import com.example.petstoremobile.utils.DialogUtils;
|
import com.example.petstoremobile.utils.DialogUtils;
|
||||||
import com.example.petstoremobile.utils.FileUtils;
|
import com.example.petstoremobile.utils.FileUtils;
|
||||||
import com.example.petstoremobile.utils.GlideUtils;
|
import com.example.petstoremobile.utils.GlideUtils;
|
||||||
@@ -111,12 +112,20 @@ public class ProductDetailFragment extends Fragment {
|
|||||||
viewModel.getCategoryList().observe(getViewLifecycleOwner(), list -> updateCategorySpinner());
|
viewModel.getCategoryList().observe(getViewLifecycleOwner(), list -> updateCategorySpinner());
|
||||||
|
|
||||||
viewModel.loadCategories().observe(getViewLifecycleOwner(), resource -> {
|
viewModel.loadCategories().observe(getViewLifecycleOwner(), resource -> {
|
||||||
if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
if (resource == null) return;
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
|
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
||||||
viewModel.setCategoryList(resource.data.getContent());
|
viewModel.setCategoryList(resource.data.getContent());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setLoading(boolean loading) {
|
||||||
|
if (binding != null && binding.progressBar != null) {
|
||||||
|
binding.progressBar.setVisibility(loading ? View.VISIBLE : View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void updateCategorySpinner() {
|
private void updateCategorySpinner() {
|
||||||
SpinnerUtils.populateSpinner(requireContext(), binding.spinnerProductCategory, viewModel.getCategoryList().getValue(),
|
SpinnerUtils.populateSpinner(requireContext(), binding.spinnerProductCategory, viewModel.getCategoryList().getValue(),
|
||||||
CategoryDTO::getCategoryName, "-- Select Category --",
|
CategoryDTO::getCategoryName, "-- Select Category --",
|
||||||
@@ -135,7 +144,7 @@ public class ProductDetailFragment extends Fragment {
|
|||||||
long prodId = a.getLong("prodId");
|
long prodId = a.getLong("prodId");
|
||||||
viewModel.setProdId(prodId);
|
viewModel.setProdId(prodId);
|
||||||
binding.tvProductMode.setText("Edit Product");
|
binding.tvProductMode.setText("Edit Product");
|
||||||
binding.tvProductId.setText("ID: " + prodId);
|
binding.tvProductId.setText(DateTimeUtils.formatId(prodId));
|
||||||
binding.tvProductId.setVisibility(View.VISIBLE);
|
binding.tvProductId.setVisibility(View.VISIBLE);
|
||||||
binding.btnDeleteProduct.setVisibility(View.VISIBLE);
|
binding.btnDeleteProduct.setVisibility(View.VISIBLE);
|
||||||
loadProductData();
|
loadProductData();
|
||||||
@@ -152,6 +161,7 @@ public class ProductDetailFragment extends Fragment {
|
|||||||
private void loadProductData() {
|
private void loadProductData() {
|
||||||
viewModel.loadProduct().observe(getViewLifecycleOwner(), resource -> {
|
viewModel.loadProduct().observe(getViewLifecycleOwner(), resource -> {
|
||||||
if (resource == null) return;
|
if (resource == null) return;
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
||||||
ProductDTO p = resource.data;
|
ProductDTO p = resource.data;
|
||||||
binding.etProductName.setText(p.getProdName());
|
binding.etProductName.setText(p.getProdName());
|
||||||
@@ -185,7 +195,9 @@ public class ProductDetailFragment extends Fragment {
|
|||||||
private void performPendingImageActions(String successMsg) {
|
private void performPendingImageActions(String successMsg) {
|
||||||
if (isImageRemoved) {
|
if (isImageRemoved) {
|
||||||
viewModel.deleteProductImage().observe(getViewLifecycleOwner(), resource -> {
|
viewModel.deleteProductImage().observe(getViewLifecycleOwner(), resource -> {
|
||||||
if (resource != null && resource.status != Resource.Status.LOADING) {
|
if (resource == null) return;
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
|
if (resource.status != Resource.Status.LOADING) {
|
||||||
if (resource.status == Resource.Status.SUCCESS) {
|
if (resource.status == Resource.Status.SUCCESS) {
|
||||||
Toast.makeText(getContext(), successMsg, Toast.LENGTH_SHORT).show();
|
Toast.makeText(getContext(), successMsg, Toast.LENGTH_SHORT).show();
|
||||||
} else {
|
} else {
|
||||||
@@ -214,7 +226,9 @@ public class ProductDetailFragment extends Fragment {
|
|||||||
MultipartBody.Part body = MultipartBody.Part.createFormData("image", file.getName(), requestFile);
|
MultipartBody.Part body = MultipartBody.Part.createFormData("image", file.getName(), requestFile);
|
||||||
|
|
||||||
viewModel.uploadProductImage(body).observe(getViewLifecycleOwner(), resource -> {
|
viewModel.uploadProductImage(body).observe(getViewLifecycleOwner(), resource -> {
|
||||||
if (resource != null && resource.status != Resource.Status.LOADING) {
|
if (resource == null) return;
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
|
if (resource.status != Resource.Status.LOADING) {
|
||||||
if (resource.status == Resource.Status.SUCCESS) {
|
if (resource.status == Resource.Status.SUCCESS) {
|
||||||
Toast.makeText(getContext(), successMsg, Toast.LENGTH_SHORT).show();
|
Toast.makeText(getContext(), successMsg, Toast.LENGTH_SHORT).show();
|
||||||
} else {
|
} else {
|
||||||
@@ -227,15 +241,8 @@ public class ProductDetailFragment extends Fragment {
|
|||||||
|
|
||||||
private void saveProduct() {
|
private void saveProduct() {
|
||||||
if (!InputValidator.isNotEmpty(binding.etProductName, "Product Name")) return;
|
if (!InputValidator.isNotEmpty(binding.etProductName, "Product Name")) return;
|
||||||
|
if (!InputValidator.isSpinnerSelected(binding.spinnerProductCategory, "Category")) return;
|
||||||
if (binding.spinnerProductCategory.getSelectedItemPosition() == 0) {
|
if (!InputValidator.isPositiveDecimal(binding.etProductPrice, "Price")) return;
|
||||||
Toast.makeText(getContext(), "Select a category", Toast.LENGTH_SHORT).show(); return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!InputValidator.isNotEmpty(binding.etProductPrice, "Price") ||
|
|
||||||
!InputValidator.isPositiveDecimal(binding.etProductPrice, "Price")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
String name = binding.etProductName.getText().toString().trim();
|
String name = binding.etProductName.getText().toString().trim();
|
||||||
String desc = binding.etProductDesc.getText().toString().trim();
|
String desc = binding.etProductDesc.getText().toString().trim();
|
||||||
@@ -245,7 +252,9 @@ public class ProductDetailFragment extends Fragment {
|
|||||||
ProductDTO dto = new ProductDTO(name, category.getCategoryId(), desc, price);
|
ProductDTO dto = new ProductDTO(name, category.getCategoryId(), desc, price);
|
||||||
|
|
||||||
viewModel.saveProduct(dto).observe(getViewLifecycleOwner(), resource -> {
|
viewModel.saveProduct(dto).observe(getViewLifecycleOwner(), resource -> {
|
||||||
if (resource != null && resource.status != Resource.Status.LOADING) {
|
if (resource == null) return;
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
|
if (resource.status != Resource.Status.LOADING) {
|
||||||
if (resource.status == Resource.Status.SUCCESS) {
|
if (resource.status == Resource.Status.SUCCESS) {
|
||||||
if (resource.data != null) {
|
if (resource.data != null) {
|
||||||
viewModel.setProdId(resource.data.getProdId());
|
viewModel.setProdId(resource.data.getProdId());
|
||||||
@@ -261,9 +270,11 @@ public class ProductDetailFragment extends Fragment {
|
|||||||
private void confirmDelete() {
|
private void confirmDelete() {
|
||||||
DialogUtils.showDeleteConfirmDialog(requireContext(), "Product", () ->
|
DialogUtils.showDeleteConfirmDialog(requireContext(), "Product", () ->
|
||||||
viewModel.deleteProduct().observe(getViewLifecycleOwner(), resource -> {
|
viewModel.deleteProduct().observe(getViewLifecycleOwner(), resource -> {
|
||||||
if (resource != null && resource.status == Resource.Status.SUCCESS) {
|
if (resource == null) return;
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
|
if (resource.status == Resource.Status.SUCCESS) {
|
||||||
navigateBack();
|
navigateBack();
|
||||||
} else if (resource != null && resource.status == Resource.Status.ERROR) {
|
} else if (resource.status == Resource.Status.ERROR) {
|
||||||
Toast.makeText(getContext(), "Delete failed: " + resource.message, Toast.LENGTH_SHORT).show();
|
Toast.makeText(getContext(), "Delete failed: " + resource.message, Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import com.example.petstoremobile.utils.DialogUtils;
|
|||||||
import com.example.petstoremobile.utils.InputValidator;
|
import com.example.petstoremobile.utils.InputValidator;
|
||||||
import com.example.petstoremobile.utils.Resource;
|
import com.example.petstoremobile.utils.Resource;
|
||||||
import com.example.petstoremobile.utils.SpinnerUtils;
|
import com.example.petstoremobile.utils.SpinnerUtils;
|
||||||
|
import com.example.petstoremobile.utils.UIUtils;
|
||||||
import com.example.petstoremobile.viewmodels.ProductSupplierDetailViewModel;
|
import com.example.petstoremobile.viewmodels.ProductSupplierDetailViewModel;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
@@ -64,6 +65,12 @@ public class ProductSupplierDetailFragment extends Fragment {
|
|||||||
viewModel.getSupplierList().observe(getViewLifecycleOwner(), list -> refreshSupplierSpinner());
|
viewModel.getSupplierList().observe(getViewLifecycleOwner(), list -> refreshSupplierSpinner());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setLoading(boolean loading) {
|
||||||
|
if (binding != null && binding.progressBar != null) {
|
||||||
|
binding.progressBar.setVisibility(loading ? View.VISIBLE : View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroyView() {
|
public void onDestroyView() {
|
||||||
super.onDestroyView();
|
super.onDestroyView();
|
||||||
@@ -72,11 +79,15 @@ public class ProductSupplierDetailFragment extends Fragment {
|
|||||||
|
|
||||||
private void loadSpinnersData() {
|
private void loadSpinnersData() {
|
||||||
viewModel.loadProducts().observe(getViewLifecycleOwner(), resource -> {
|
viewModel.loadProducts().observe(getViewLifecycleOwner(), resource -> {
|
||||||
|
if (resource == null) return;
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
||||||
viewModel.setProductList(resource.data.getContent());
|
viewModel.setProductList(resource.data.getContent());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
viewModel.loadSuppliers().observe(getViewLifecycleOwner(), resource -> {
|
viewModel.loadSuppliers().observe(getViewLifecycleOwner(), resource -> {
|
||||||
|
if (resource == null) return;
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
||||||
viewModel.setSupplierList(resource.data.getContent());
|
viewModel.setSupplierList(resource.data.getContent());
|
||||||
}
|
}
|
||||||
@@ -113,17 +124,9 @@ public class ProductSupplierDetailFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void save() {
|
private void save() {
|
||||||
if (binding.spinnerPSProduct.getSelectedItemPosition() == 0) {
|
if (!InputValidator.isSpinnerSelected(binding.spinnerPSProduct, "Product")) return;
|
||||||
Toast.makeText(getContext(), "Select a product", Toast.LENGTH_SHORT).show(); return;
|
if (!InputValidator.isSpinnerSelected(binding.spinnerPSSupplier, "Supplier")) return;
|
||||||
}
|
if (!InputValidator.isPositiveDecimal(binding.etPSCost, "Cost")) return;
|
||||||
if (binding.spinnerPSSupplier.getSelectedItemPosition() == 0) {
|
|
||||||
Toast.makeText(getContext(), "Select a supplier", Toast.LENGTH_SHORT).show(); return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!InputValidator.isNotEmpty(binding.etPSCost, "Cost") ||
|
|
||||||
!InputValidator.isPositiveDecimal(binding.etPSCost, "Cost")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ProductDTO product = viewModel.getProductList().getValue().get(binding.spinnerPSProduct.getSelectedItemPosition() - 1);
|
ProductDTO product = viewModel.getProductList().getValue().get(binding.spinnerPSProduct.getSelectedItemPosition() - 1);
|
||||||
SupplierDTO supplier = viewModel.getSupplierList().getValue().get(binding.spinnerPSSupplier.getSelectedItemPosition() - 1);
|
SupplierDTO supplier = viewModel.getSupplierList().getValue().get(binding.spinnerPSSupplier.getSelectedItemPosition() - 1);
|
||||||
@@ -132,6 +135,8 @@ public class ProductSupplierDetailFragment extends Fragment {
|
|||||||
ProductSupplierDTO dto = new ProductSupplierDTO(product.getProdId(), supplier.getSupId(), cost);
|
ProductSupplierDTO dto = new ProductSupplierDTO(product.getProdId(), supplier.getSupId(), cost);
|
||||||
|
|
||||||
viewModel.saveProductSupplier(dto).observe(getViewLifecycleOwner(), resource -> {
|
viewModel.saveProductSupplier(dto).observe(getViewLifecycleOwner(), resource -> {
|
||||||
|
if (resource == null) return;
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
if (resource.status == Resource.Status.SUCCESS) {
|
if (resource.status == Resource.Status.SUCCESS) {
|
||||||
Toast.makeText(getContext(), viewModel.isEditing() ? "Updated" : "Saved", Toast.LENGTH_SHORT).show();
|
Toast.makeText(getContext(), viewModel.isEditing() ? "Updated" : "Saved", Toast.LENGTH_SHORT).show();
|
||||||
navigateBack();
|
navigateBack();
|
||||||
@@ -142,8 +147,10 @@ public class ProductSupplierDetailFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void confirmDelete() {
|
private void confirmDelete() {
|
||||||
DialogUtils.showDeleteConfirmDialog(requireContext(), "Product Supplier", () ->
|
DialogUtils.showDeleteConfirmDialog(requireContext(), "Product Supplier Relationship", () ->
|
||||||
viewModel.deleteProductSupplier().observe(getViewLifecycleOwner(), resource -> {
|
viewModel.deleteProductSupplier().observe(getViewLifecycleOwner(), resource -> {
|
||||||
|
if (resource == null) return;
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
if (resource.status == Resource.Status.SUCCESS) {
|
if (resource.status == Resource.Status.SUCCESS) {
|
||||||
Toast.makeText(getContext(), "Deleted", Toast.LENGTH_SHORT).show();
|
Toast.makeText(getContext(), "Deleted", Toast.LENGTH_SHORT).show();
|
||||||
navigateBack();
|
navigateBack();
|
||||||
|
|||||||
@@ -66,9 +66,16 @@ public class PurchaseOrderDetailFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setLoading(boolean loading) {
|
||||||
|
if (binding != null && binding.progressBar != null) {
|
||||||
|
binding.progressBar.setVisibility(loading ? View.VISIBLE : View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void loadPurchaseOrderData() {
|
private void loadPurchaseOrderData() {
|
||||||
viewModel.loadPurchaseOrder(purchaseOrderId).observe(getViewLifecycleOwner(), resource -> {
|
viewModel.loadPurchaseOrder(purchaseOrderId).observe(getViewLifecycleOwner(), resource -> {
|
||||||
if (resource == null) return;
|
if (resource == null) return;
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
||||||
PurchaseOrderDTO po = resource.data;
|
PurchaseOrderDTO po = resource.data;
|
||||||
binding.tvPODetailId.setText("PO #" + po.getPurchaseOrderId());
|
binding.tvPODetailId.setText("PO #" + po.getPurchaseOrderId());
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package com.example.petstoremobile.fragments.listfragments.detailfragments;
|
package com.example.petstoremobile.fragments.listfragments.detailfragments;
|
||||||
|
|
||||||
import android.app.AlertDialog;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.*;
|
import android.view.*;
|
||||||
@@ -13,7 +12,9 @@ import com.example.petstoremobile.R;
|
|||||||
import com.example.petstoremobile.databinding.FragmentRefundBinding;
|
import com.example.petstoremobile.databinding.FragmentRefundBinding;
|
||||||
import com.example.petstoremobile.dtos.SaleDTO;
|
import com.example.petstoremobile.dtos.SaleDTO;
|
||||||
import com.example.petstoremobile.viewmodels.RefundViewModel;
|
import com.example.petstoremobile.viewmodels.RefundViewModel;
|
||||||
|
import com.example.petstoremobile.utils.DialogUtils;
|
||||||
import com.example.petstoremobile.utils.Resource;
|
import com.example.petstoremobile.utils.Resource;
|
||||||
|
import com.example.petstoremobile.utils.SpinnerUtils;
|
||||||
import dagger.hilt.android.AndroidEntryPoint;
|
import dagger.hilt.android.AndroidEntryPoint;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.math.RoundingMode;
|
import java.math.RoundingMode;
|
||||||
@@ -50,8 +51,7 @@ public class RefundFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setupSpinner() {
|
private void setupSpinner() {
|
||||||
binding.spinnerRefundPayment.setAdapter(new ArrayAdapter<>(requireContext(),
|
SpinnerUtils.setupStringSpinner(requireContext(), binding.spinnerRefundPayment, PAYMENT_METHODS);
|
||||||
android.R.layout.simple_spinner_item, PAYMENT_METHODS));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void observeViewModel() {
|
private void observeViewModel() {
|
||||||
@@ -63,9 +63,17 @@ public class RefundFragment extends Fragment {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setLoading(boolean loading) {
|
||||||
|
if (binding != null && binding.progressBar != null) {
|
||||||
|
binding.progressBar.setVisibility(loading ? View.VISIBLE : View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void loadAllSales() {
|
private void loadAllSales() {
|
||||||
viewModel.loadAllSales().observe(getViewLifecycleOwner(), resource -> {
|
viewModel.loadAllSales().observe(getViewLifecycleOwner(), resource -> {
|
||||||
if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
if (resource == null) return;
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
|
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
||||||
viewModel.setAllSales(resource.data.getContent());
|
viewModel.setAllSales(resource.data.getContent());
|
||||||
Bundle args = getArguments();
|
Bundle args = getArguments();
|
||||||
if (args != null && args.containsKey("saleId")) {
|
if (args != null && args.containsKey("saleId")) {
|
||||||
@@ -122,11 +130,7 @@ public class RefundFragment extends Fragment {
|
|||||||
+ " | Payment: " + currentSale.getPaymentMethod());
|
+ " | Payment: " + currentSale.getPaymentMethod());
|
||||||
|
|
||||||
if (currentSale.getPaymentMethod() != null) {
|
if (currentSale.getPaymentMethod() != null) {
|
||||||
for (int i = 0; i < PAYMENT_METHODS.length; i++) {
|
SpinnerUtils.setSelectionByValue(binding.spinnerRefundPayment, currentSale.getPaymentMethod());
|
||||||
if (PAYMENT_METHODS[i].equalsIgnoreCase(currentSale.getPaymentMethod())) {
|
|
||||||
binding.spinnerRefundPayment.setSelection(i); break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (viewModel.getAvailableItems().getValue() == null || viewModel.getAvailableItems().getValue().isEmpty()) {
|
if (viewModel.getAvailableItems().getValue() == null || viewModel.getAvailableItems().getValue().isEmpty()) {
|
||||||
@@ -263,17 +267,17 @@ public class RefundFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void showQuantityDialog(RefundViewModel.RefundItem item, int available) {
|
private void showQuantityDialog(RefundViewModel.RefundItem item, int available) {
|
||||||
AlertDialog.Builder builder = new AlertDialog.Builder(requireContext());
|
|
||||||
builder.setTitle("Refund Quantity");
|
|
||||||
builder.setMessage("Product: " + item.productName + "\nAvailable: " + available);
|
|
||||||
|
|
||||||
EditText input = new EditText(getContext());
|
EditText input = new EditText(getContext());
|
||||||
input.setInputType(android.text.InputType.TYPE_CLASS_NUMBER);
|
input.setInputType(android.text.InputType.TYPE_CLASS_NUMBER);
|
||||||
input.setText(String.valueOf(available));
|
input.setText(String.valueOf(available));
|
||||||
input.setSelectAllOnFocus(true);
|
input.setSelectAllOnFocus(true);
|
||||||
builder.setView(input);
|
input.setPadding(40, 40, 40, 40);
|
||||||
|
|
||||||
builder.setPositiveButton("Add to Refund", (d, w) -> {
|
new androidx.appcompat.app.AlertDialog.Builder(requireContext())
|
||||||
|
.setTitle("Refund Quantity")
|
||||||
|
.setMessage("Product: " + item.productName + "\nAvailable: " + available)
|
||||||
|
.setView(input)
|
||||||
|
.setPositiveButton("Add to Refund", (d, w) -> {
|
||||||
String val = input.getText().toString().trim();
|
String val = input.getText().toString().trim();
|
||||||
if (val.isEmpty()) return;
|
if (val.isEmpty()) return;
|
||||||
int qty;
|
int qty;
|
||||||
@@ -290,12 +294,10 @@ public class RefundFragment extends Fragment {
|
|||||||
Toast.makeText(getContext(), "Cannot exceed " + available, Toast.LENGTH_SHORT).show();
|
Toast.makeText(getContext(), "Cannot exceed " + available, Toast.LENGTH_SHORT).show();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
viewModel.addToCart(item, qty);
|
viewModel.addToCart(item, qty);
|
||||||
});
|
})
|
||||||
|
.setNegativeButton("Cancel", null)
|
||||||
builder.setNegativeButton("Cancel", null);
|
.show();
|
||||||
builder.show();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateRefundTotal() {
|
private void updateRefundTotal() {
|
||||||
@@ -322,18 +324,16 @@ public class RefundFragment extends Fragment {
|
|||||||
for (RefundViewModel.RefundItem item : viewModel.getRefundCart().getValue()) total = total.add(item.getTotal());
|
for (RefundViewModel.RefundItem item : viewModel.getRefundCart().getValue()) total = total.add(item.getTotal());
|
||||||
final BigDecimal finalTotal = total;
|
final BigDecimal finalTotal = total;
|
||||||
|
|
||||||
new AlertDialog.Builder(requireContext())
|
DialogUtils.showConfirmDialog(requireContext(), "Confirm Refund",
|
||||||
.setTitle("Confirm Refund")
|
"Process refund for Sale #" + viewModel.getCurrentSale().getSaleId()
|
||||||
.setMessage("Process refund for Sale #" + viewModel.getCurrentSale().getSaleId()
|
+ "?\nRefund amount: $" + finalTotal.setScale(2, RoundingMode.HALF_UP),
|
||||||
+ "?\nRefund amount: $" + finalTotal.setScale(2, RoundingMode.HALF_UP))
|
() -> submitRefund(payment));
|
||||||
.setPositiveButton("Yes", (d, w) -> submitRefund(payment))
|
|
||||||
.setNegativeButton("No", null)
|
|
||||||
.show();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void submitRefund(String payment) {
|
private void submitRefund(String payment) {
|
||||||
viewModel.submitRefund(payment).observe(getViewLifecycleOwner(), resource -> {
|
viewModel.submitRefund(payment).observe(getViewLifecycleOwner(), resource -> {
|
||||||
if (resource != null) {
|
if (resource != null) {
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
if (resource.status == Resource.Status.SUCCESS) {
|
if (resource.status == Resource.Status.SUCCESS) {
|
||||||
Toast.makeText(getContext(), "Refund processed successfully!", Toast.LENGTH_LONG).show();
|
Toast.makeText(getContext(), "Refund processed successfully!", Toast.LENGTH_LONG).show();
|
||||||
navigateBack();
|
navigateBack();
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import com.example.petstoremobile.dtos.*;
|
|||||||
import com.example.petstoremobile.viewmodels.SaleDetailViewModel;
|
import com.example.petstoremobile.viewmodels.SaleDetailViewModel;
|
||||||
import com.example.petstoremobile.utils.SpinnerUtils;
|
import com.example.petstoremobile.utils.SpinnerUtils;
|
||||||
import com.example.petstoremobile.utils.DialogUtils;
|
import com.example.petstoremobile.utils.DialogUtils;
|
||||||
|
import com.example.petstoremobile.utils.InputValidator;
|
||||||
import com.example.petstoremobile.utils.Resource;
|
import com.example.petstoremobile.utils.Resource;
|
||||||
import com.example.petstoremobile.utils.UIUtils;
|
import com.example.petstoremobile.utils.UIUtils;
|
||||||
import dagger.hilt.android.AndroidEntryPoint;
|
import dagger.hilt.android.AndroidEntryPoint;
|
||||||
@@ -107,21 +108,35 @@ public class SaleDetailFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setLoading(boolean loading) {
|
||||||
|
if (binding != null && binding.progressBar != null) {
|
||||||
|
binding.progressBar.setVisibility(loading ? View.VISIBLE : View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void loadData() {
|
private void loadData() {
|
||||||
viewModel.loadStores().observe(getViewLifecycleOwner(), resource -> {
|
viewModel.loadStores().observe(getViewLifecycleOwner(), resource -> {
|
||||||
|
if (resource == null) return;
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
if (resource.status == Resource.Status.SUCCESS && resource.data != null) viewModel.setStoreList(resource.data);
|
if (resource.status == Resource.Status.SUCCESS && resource.data != null) viewModel.setStoreList(resource.data);
|
||||||
});
|
});
|
||||||
viewModel.loadCustomers().observe(getViewLifecycleOwner(), resource -> {
|
viewModel.loadCustomers().observe(getViewLifecycleOwner(), resource -> {
|
||||||
|
if (resource == null) return;
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
if (resource.status == Resource.Status.SUCCESS && resource.data != null) viewModel.setCustomerList(resource.data);
|
if (resource.status == Resource.Status.SUCCESS && resource.data != null) viewModel.setCustomerList(resource.data);
|
||||||
});
|
});
|
||||||
viewModel.loadProducts().observe(getViewLifecycleOwner(), resource -> {
|
viewModel.loadProducts().observe(getViewLifecycleOwner(), resource -> {
|
||||||
|
if (resource == null) return;
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
if (resource.status == Resource.Status.SUCCESS && resource.data != null) viewModel.setProductList(resource.data.getContent());
|
if (resource.status == Resource.Status.SUCCESS && resource.data != null) viewModel.setProductList(resource.data.getContent());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadSaleDetails() {
|
private void loadSaleDetails() {
|
||||||
viewModel.loadSaleDetails().observe(getViewLifecycleOwner(), resource -> {
|
viewModel.loadSaleDetails().observe(getViewLifecycleOwner(), resource -> {
|
||||||
if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
if (resource == null) return;
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
|
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
||||||
SaleDTO sale = resource.data;
|
SaleDTO sale = resource.data;
|
||||||
binding.tvSaleDetailTotal.setText("Total: $" + sale.getTotalAmount());
|
binding.tvSaleDetailTotal.setText("Total: $" + sale.getTotalAmount());
|
||||||
binding.tvSaleSubtotal.setText("$" + (sale.getSubtotalAmount() != null ? sale.getSubtotalAmount() : sale.getTotalAmount()));
|
binding.tvSaleSubtotal.setText("$" + (sale.getSubtotalAmount() != null ? sale.getSubtotalAmount() : sale.getTotalAmount()));
|
||||||
@@ -157,22 +172,10 @@ public class SaleDetailFragment extends Fragment {
|
|||||||
|
|
||||||
private void setupAddItem() {
|
private void setupAddItem() {
|
||||||
binding.btnAddItem.setOnClickListener(v -> {
|
binding.btnAddItem.setOnClickListener(v -> {
|
||||||
if (binding.spinnerSaleProduct.getSelectedItemPosition() == 0) {
|
if (!InputValidator.isSpinnerSelected(binding.spinnerSaleProduct, "Product")) return;
|
||||||
Toast.makeText(getContext(), "Select a product", Toast.LENGTH_SHORT).show();
|
if (!InputValidator.isPositiveInteger(binding.etSaleQuantity, "Quantity")) return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
String qtyStr = binding.etSaleQuantity.getText().toString().trim();
|
|
||||||
if (qtyStr.isEmpty()) {
|
|
||||||
binding.etSaleQuantity.setError("Enter quantity");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
int qty;
|
|
||||||
try { qty = Integer.parseInt(qtyStr); }
|
|
||||||
catch (Exception e) {
|
|
||||||
binding.etSaleQuantity.setError("Invalid quantity");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
int qty = Integer.parseInt(binding.etSaleQuantity.getText().toString().trim());
|
||||||
ProductDTO product = viewModel.getProductList().getValue().get(binding.spinnerSaleProduct.getSelectedItemPosition() - 1);
|
ProductDTO product = viewModel.getProductList().getValue().get(binding.spinnerSaleProduct.getSelectedItemPosition() - 1);
|
||||||
|
|
||||||
for (SaleDTO.SaleItemDTO existing : viewModel.getCartItems().getValue()) {
|
for (SaleDTO.SaleItemDTO existing : viewModel.getCartItems().getValue()) {
|
||||||
@@ -238,10 +241,8 @@ public class SaleDetailFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void saveSale() {
|
private void saveSale() {
|
||||||
if (binding.spinnerSaleStore.getSelectedItemPosition() == 0) {
|
if (!InputValidator.isSpinnerSelected(binding.spinnerSaleStore, "Store")) return;
|
||||||
Toast.makeText(getContext(), "Select a store", Toast.LENGTH_SHORT).show();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (viewModel.getCartItems().getValue() == null || viewModel.getCartItems().getValue().isEmpty()) {
|
if (viewModel.getCartItems().getValue() == null || viewModel.getCartItems().getValue().isEmpty()) {
|
||||||
Toast.makeText(getContext(), "Add at least one item", Toast.LENGTH_SHORT).show();
|
Toast.makeText(getContext(), "Add at least one item", Toast.LENGTH_SHORT).show();
|
||||||
return;
|
return;
|
||||||
@@ -259,6 +260,7 @@ public class SaleDetailFragment extends Fragment {
|
|||||||
|
|
||||||
viewModel.createSale(dto).observe(getViewLifecycleOwner(), resource -> {
|
viewModel.createSale(dto).observe(getViewLifecycleOwner(), resource -> {
|
||||||
if (resource != null) {
|
if (resource != null) {
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
if (resource.status == Resource.Status.SUCCESS) {
|
if (resource.status == Resource.Status.SUCCESS) {
|
||||||
Toast.makeText(getContext(), "Sale saved!", Toast.LENGTH_SHORT).show();
|
Toast.makeText(getContext(), "Sale saved!", Toast.LENGTH_SHORT).show();
|
||||||
navigateBack();
|
navigateBack();
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import com.example.petstoremobile.R;
|
|||||||
import com.example.petstoremobile.databinding.FragmentServiceDetailBinding;
|
import com.example.petstoremobile.databinding.FragmentServiceDetailBinding;
|
||||||
import com.example.petstoremobile.dtos.ServiceDTO;
|
import com.example.petstoremobile.dtos.ServiceDTO;
|
||||||
import com.example.petstoremobile.utils.ActivityLogger;
|
import com.example.petstoremobile.utils.ActivityLogger;
|
||||||
|
import com.example.petstoremobile.utils.DateTimeUtils;
|
||||||
import com.example.petstoremobile.utils.DialogUtils;
|
import com.example.petstoremobile.utils.DialogUtils;
|
||||||
import com.example.petstoremobile.utils.InputValidator;
|
import com.example.petstoremobile.utils.InputValidator;
|
||||||
import com.example.petstoremobile.utils.Resource;
|
import com.example.petstoremobile.utils.Resource;
|
||||||
@@ -57,6 +58,12 @@ public class ServiceDetailFragment extends Fragment {
|
|||||||
binding.btnDeleteService.setOnClickListener(v -> deleteService());
|
binding.btnDeleteService.setOnClickListener(v -> deleteService());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setLoading(boolean loading) {
|
||||||
|
if (binding != null && binding.progressBar != null) {
|
||||||
|
binding.progressBar.setVisibility(loading ? View.VISIBLE : View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroyView() {
|
public void onDestroyView() {
|
||||||
super.onDestroyView();
|
super.onDestroyView();
|
||||||
@@ -81,6 +88,8 @@ public class ServiceDetailFragment extends Fragment {
|
|||||||
serviceDTO.setServicePrice(price);
|
serviceDTO.setServicePrice(price);
|
||||||
|
|
||||||
viewModel.saveService(serviceDTO).observe(getViewLifecycleOwner(), resource -> {
|
viewModel.saveService(serviceDTO).observe(getViewLifecycleOwner(), resource -> {
|
||||||
|
if (resource == null) return;
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
if (resource.status == Resource.Status.SUCCESS) {
|
if (resource.status == Resource.Status.SUCCESS) {
|
||||||
if (viewModel.isEditing()) {
|
if (viewModel.isEditing()) {
|
||||||
ActivityLogger.logChange(requireContext(), "Service", "UPDATED", (int) viewModel.getServiceId());
|
ActivityLogger.logChange(requireContext(), "Service", "UPDATED", (int) viewModel.getServiceId());
|
||||||
@@ -99,6 +108,8 @@ public class ServiceDetailFragment extends Fragment {
|
|||||||
private void deleteService() {
|
private void deleteService() {
|
||||||
DialogUtils.showDeleteConfirmDialog(requireContext(), "Service", () ->
|
DialogUtils.showDeleteConfirmDialog(requireContext(), "Service", () ->
|
||||||
viewModel.deleteService().observe(getViewLifecycleOwner(), resource -> {
|
viewModel.deleteService().observe(getViewLifecycleOwner(), resource -> {
|
||||||
|
if (resource == null) return;
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
if (resource.status == Resource.Status.SUCCESS) {
|
if (resource.status == Resource.Status.SUCCESS) {
|
||||||
ActivityLogger.logChange(requireContext(), "Service", "DELETED", (int) viewModel.getServiceId());
|
ActivityLogger.logChange(requireContext(), "Service", "DELETED", (int) viewModel.getServiceId());
|
||||||
Toast.makeText(getContext(), "Service deleted successfully!", Toast.LENGTH_SHORT).show();
|
Toast.makeText(getContext(), "Service deleted successfully!", Toast.LENGTH_SHORT).show();
|
||||||
@@ -118,7 +129,7 @@ public class ServiceDetailFragment extends Fragment {
|
|||||||
long serviceId = getArguments().getLong("serviceId");
|
long serviceId = getArguments().getLong("serviceId");
|
||||||
viewModel.setServiceId(serviceId);
|
viewModel.setServiceId(serviceId);
|
||||||
binding.tvMode.setText("Edit Service");
|
binding.tvMode.setText("Edit Service");
|
||||||
binding.tvServiceId.setText("ID: " + serviceId);
|
binding.tvServiceId.setText(DateTimeUtils.formatId(serviceId));
|
||||||
binding.btnDeleteService.setVisibility(View.VISIBLE);
|
binding.btnDeleteService.setVisibility(View.VISIBLE);
|
||||||
loadServiceData();
|
loadServiceData();
|
||||||
} else {
|
} else {
|
||||||
@@ -133,6 +144,7 @@ public class ServiceDetailFragment extends Fragment {
|
|||||||
private void loadServiceData() {
|
private void loadServiceData() {
|
||||||
viewModel.loadService().observe(getViewLifecycleOwner(), resource -> {
|
viewModel.loadService().observe(getViewLifecycleOwner(), resource -> {
|
||||||
if (resource == null) return;
|
if (resource == null) return;
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
||||||
ServiceDTO s = resource.data;
|
ServiceDTO s = resource.data;
|
||||||
binding.etServiceName.setText(s.getServiceName());
|
binding.etServiceName.setText(s.getServiceName());
|
||||||
|
|||||||
@@ -4,13 +4,16 @@ import android.os.Bundle;
|
|||||||
import android.view.*;
|
import android.view.*;
|
||||||
import android.widget.*;
|
import android.widget.*;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.appcompat.app.AlertDialog;
|
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.lifecycle.ViewModelProvider;
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
import androidx.navigation.fragment.NavHostFragment;
|
import androidx.navigation.fragment.NavHostFragment;
|
||||||
import com.example.petstoremobile.R;
|
import com.example.petstoremobile.R;
|
||||||
import com.example.petstoremobile.databinding.FragmentStaffDetailBinding;
|
import com.example.petstoremobile.databinding.FragmentStaffDetailBinding;
|
||||||
import com.example.petstoremobile.dtos.EmployeeDTO;
|
import com.example.petstoremobile.dtos.EmployeeDTO;
|
||||||
|
import com.example.petstoremobile.utils.DialogUtils;
|
||||||
|
import com.example.petstoremobile.utils.InputValidator;
|
||||||
|
import com.example.petstoremobile.utils.SpinnerUtils;
|
||||||
|
import com.example.petstoremobile.utils.UIUtils;
|
||||||
import com.example.petstoremobile.viewmodels.StaffDetailViewModel;
|
import com.example.petstoremobile.viewmodels.StaffDetailViewModel;
|
||||||
import com.example.petstoremobile.utils.Resource;
|
import com.example.petstoremobile.utils.Resource;
|
||||||
import dagger.hilt.android.AndroidEntryPoint;
|
import dagger.hilt.android.AndroidEntryPoint;
|
||||||
@@ -36,14 +39,15 @@ public class StaffDetailFragment extends Fragment {
|
|||||||
binding.btnStaffBack.setOnClickListener(v -> navigateBack());
|
binding.btnStaffBack.setOnClickListener(v -> navigateBack());
|
||||||
binding.btnSaveStaff.setOnClickListener(v -> save());
|
binding.btnSaveStaff.setOnClickListener(v -> save());
|
||||||
binding.btnDeleteStaff.setOnClickListener(v -> confirmDelete());
|
binding.btnDeleteStaff.setOnClickListener(v -> confirmDelete());
|
||||||
|
|
||||||
|
UIUtils.formatPhoneInput(binding.etStaffPhone);
|
||||||
|
|
||||||
return binding.getRoot();
|
return binding.getRoot();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupSpinners() {
|
private void setupSpinners() {
|
||||||
binding.spinnerStaffRole.setAdapter(new ArrayAdapter<>(requireContext(),
|
SpinnerUtils.setupStringSpinner(requireContext(), binding.spinnerStaffRole, ROLES);
|
||||||
android.R.layout.simple_spinner_item, ROLES));
|
SpinnerUtils.setupStringSpinner(requireContext(), binding.spinnerStaffStatus, STATUSES);
|
||||||
binding.spinnerStaffStatus.setAdapter(new ArrayAdapter<>(requireContext(),
|
|
||||||
android.R.layout.simple_spinner_item, STATUSES));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleArguments() {
|
private void handleArguments() {
|
||||||
@@ -62,16 +66,8 @@ public class StaffDetailFragment extends Fragment {
|
|||||||
binding.etStaffPhone.setText(a.getString("phone", ""));
|
binding.etStaffPhone.setText(a.getString("phone", ""));
|
||||||
binding.btnDeleteStaff.setVisibility(View.VISIBLE);
|
binding.btnDeleteStaff.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
String role = a.getString("role", "STAFF");
|
SpinnerUtils.setSelectionByValue(binding.spinnerStaffRole, a.getString("role", "STAFF"));
|
||||||
for (int i = 0; i < ROLES.length; i++) {
|
binding.spinnerStaffStatus.setSelection(a.getBoolean("active", true) ? 0 : 1);
|
||||||
if (ROLES[i].equals(role)) {
|
|
||||||
binding.spinnerStaffRole.setSelection(i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean active = a.getBoolean("active", true);
|
|
||||||
binding.spinnerStaffStatus.setSelection(active ? 0 : 1);
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
viewModel.setEmployeeId(-1, false);
|
viewModel.setEmployeeId(-1, false);
|
||||||
@@ -81,29 +77,39 @@ public class StaffDetailFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setLoading(boolean loading) {
|
||||||
|
if (binding != null && binding.progressBar != null) {
|
||||||
|
binding.progressBar.setVisibility(loading ? View.VISIBLE : View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void save() {
|
private void save() {
|
||||||
String username = binding.etStaffUsername.getText() != null ? binding.etStaffUsername.getText().toString().trim() : "";
|
if (!InputValidator.isNotEmpty(binding.etStaffUsername, "Username")) return;
|
||||||
String password = binding.etStaffPassword.getText() != null ? binding.etStaffPassword.getText().toString().trim() : "";
|
|
||||||
String firstName = binding.etStaffFirstName.getText() != null ? binding.etStaffFirstName.getText().toString().trim() : "";
|
if (!viewModel.isEditing()) {
|
||||||
String lastName = binding.etStaffLastName.getText() != null ? binding.etStaffLastName.getText().toString().trim() : "";
|
if (!InputValidator.isNotEmpty(binding.etStaffPassword, "Password")) return;
|
||||||
String email = binding.etStaffEmail.getText() != null ? binding.etStaffEmail.getText().toString().trim() : "";
|
String pass = binding.etStaffPassword.getText().toString();
|
||||||
String phone = binding.etStaffPhone.getText() != null ? binding.etStaffPhone.getText().toString().trim() : "";
|
if (pass.length() < 6) {
|
||||||
|
binding.etStaffPassword.setError("At least 6 characters");
|
||||||
|
binding.etStaffPassword.requestFocus();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!InputValidator.isNotEmpty(binding.etStaffFirstName, "First Name")) return;
|
||||||
|
if (!InputValidator.isNotEmpty(binding.etStaffLastName, "Last Name")) return;
|
||||||
|
if (!InputValidator.isValidEmail(binding.etStaffEmail)) return;
|
||||||
|
if (!InputValidator.isValidPhone(binding.etStaffPhone)) return;
|
||||||
|
|
||||||
|
String username = binding.etStaffUsername.getText().toString().trim();
|
||||||
|
String password = binding.etStaffPassword.getText().toString().trim();
|
||||||
|
String firstName = binding.etStaffFirstName.getText().toString().trim();
|
||||||
|
String lastName = binding.etStaffLastName.getText().toString().trim();
|
||||||
|
String email = binding.etStaffEmail.getText().toString().trim();
|
||||||
|
String phone = binding.etStaffPhone.getText().toString().trim();
|
||||||
String role = ROLES[binding.spinnerStaffRole.getSelectedItemPosition()];
|
String role = ROLES[binding.spinnerStaffRole.getSelectedItemPosition()];
|
||||||
boolean active = binding.spinnerStaffStatus.getSelectedItemPosition() == 0;
|
boolean active = binding.spinnerStaffStatus.getSelectedItemPosition() == 0;
|
||||||
|
|
||||||
if (username.isEmpty()) { binding.etStaffUsername.setError("Required"); return; }
|
|
||||||
if (!viewModel.isEditing() && password.isEmpty()) {
|
|
||||||
binding.etStaffPassword.setError("Required for new account"); return;
|
|
||||||
}
|
|
||||||
if (!viewModel.isEditing() && password.length() < 6) {
|
|
||||||
binding.etStaffPassword.setError("At least 6 characters"); return;
|
|
||||||
}
|
|
||||||
if (firstName.isEmpty()) { binding.etStaffFirstName.setError("Required"); return; }
|
|
||||||
if (lastName.isEmpty()) { binding.etStaffLastName.setError("Required"); return; }
|
|
||||||
if (email.isEmpty()) { binding.etStaffEmail.setError("Required"); return; }
|
|
||||||
if (phone.isEmpty()) { binding.etStaffPhone.setError("Required"); return; }
|
|
||||||
|
|
||||||
EmployeeDTO dto = new EmployeeDTO(
|
EmployeeDTO dto = new EmployeeDTO(
|
||||||
username,
|
username,
|
||||||
password.isEmpty() ? null : password,
|
password.isEmpty() ? null : password,
|
||||||
@@ -117,6 +123,7 @@ public class StaffDetailFragment extends Fragment {
|
|||||||
|
|
||||||
viewModel.saveEmployee(dto).observe(getViewLifecycleOwner(), resource -> {
|
viewModel.saveEmployee(dto).observe(getViewLifecycleOwner(), resource -> {
|
||||||
if (resource != null) {
|
if (resource != null) {
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
if (resource.status == Resource.Status.SUCCESS) {
|
if (resource.status == Resource.Status.SUCCESS) {
|
||||||
Toast.makeText(getContext(), viewModel.isEditing() ? "Updated successfully" : "Staff account created", Toast.LENGTH_SHORT).show();
|
Toast.makeText(getContext(), viewModel.isEditing() ? "Updated successfully" : "Staff account created", Toast.LENGTH_SHORT).show();
|
||||||
navigateBack();
|
navigateBack();
|
||||||
@@ -128,12 +135,10 @@ public class StaffDetailFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void confirmDelete() {
|
private void confirmDelete() {
|
||||||
new AlertDialog.Builder(requireContext())
|
DialogUtils.showDeleteConfirmDialog(requireContext(), "Staff Account", () ->
|
||||||
.setTitle("Delete Staff Account?")
|
|
||||||
.setMessage("This will permanently delete this staff account.")
|
|
||||||
.setPositiveButton("Yes", (d, w) ->
|
|
||||||
viewModel.deleteEmployee().observe(getViewLifecycleOwner(), resource -> {
|
viewModel.deleteEmployee().observe(getViewLifecycleOwner(), resource -> {
|
||||||
if (resource != null) {
|
if (resource != null) {
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
if (resource.status == Resource.Status.SUCCESS) {
|
if (resource.status == Resource.Status.SUCCESS) {
|
||||||
navigateBack();
|
navigateBack();
|
||||||
} else if (resource.status == Resource.Status.ERROR) {
|
} else if (resource.status == Resource.Status.ERROR) {
|
||||||
@@ -141,8 +146,7 @@ public class StaffDetailFragment extends Fragment {
|
|||||||
Toast.LENGTH_SHORT).show();
|
Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}))
|
}));
|
||||||
.setNegativeButton("No", null).show();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void navigateBack() {
|
private void navigateBack() {
|
||||||
|
|||||||
@@ -58,6 +58,12 @@ public class SupplierDetailFragment extends Fragment {
|
|||||||
binding.btnDeleteSupplier.setOnClickListener(v -> deleteSupplier());
|
binding.btnDeleteSupplier.setOnClickListener(v -> deleteSupplier());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setLoading(boolean loading) {
|
||||||
|
if (binding != null && binding.progressBar != null) {
|
||||||
|
binding.progressBar.setVisibility(loading ? View.VISIBLE : View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroyView() {
|
public void onDestroyView() {
|
||||||
super.onDestroyView();
|
super.onDestroyView();
|
||||||
@@ -85,6 +91,8 @@ public class SupplierDetailFragment extends Fragment {
|
|||||||
supplierDTO.setSupPhone(phone);
|
supplierDTO.setSupPhone(phone);
|
||||||
|
|
||||||
viewModel.saveSupplier(supplierDTO).observe(getViewLifecycleOwner(), resource -> {
|
viewModel.saveSupplier(supplierDTO).observe(getViewLifecycleOwner(), resource -> {
|
||||||
|
if (resource == null) return;
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
if (resource.status == Resource.Status.SUCCESS) {
|
if (resource.status == Resource.Status.SUCCESS) {
|
||||||
if (viewModel.isEditing()) {
|
if (viewModel.isEditing()) {
|
||||||
ActivityLogger.logChange(requireContext(), "Supplier", "UPDATED", (int) viewModel.getSupId());
|
ActivityLogger.logChange(requireContext(), "Supplier", "UPDATED", (int) viewModel.getSupId());
|
||||||
@@ -103,6 +111,8 @@ public class SupplierDetailFragment extends Fragment {
|
|||||||
private void deleteSupplier() {
|
private void deleteSupplier() {
|
||||||
DialogUtils.showDeleteConfirmDialog(requireContext(), "Supplier", () ->
|
DialogUtils.showDeleteConfirmDialog(requireContext(), "Supplier", () ->
|
||||||
viewModel.deleteSupplier().observe(getViewLifecycleOwner(), resource -> {
|
viewModel.deleteSupplier().observe(getViewLifecycleOwner(), resource -> {
|
||||||
|
if (resource == null) return;
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
if (resource.status == Resource.Status.SUCCESS) {
|
if (resource.status == Resource.Status.SUCCESS) {
|
||||||
ActivityLogger.logChange(requireContext(), "Supplier", "DELETED", (int) viewModel.getSupId());
|
ActivityLogger.logChange(requireContext(), "Supplier", "DELETED", (int) viewModel.getSupId());
|
||||||
Toast.makeText(getContext(), "Supplier deleted successfully!", Toast.LENGTH_SHORT).show();
|
Toast.makeText(getContext(), "Supplier deleted successfully!", Toast.LENGTH_SHORT).show();
|
||||||
@@ -138,6 +148,7 @@ public class SupplierDetailFragment extends Fragment {
|
|||||||
private void loadSupplierData() {
|
private void loadSupplierData() {
|
||||||
viewModel.loadSupplier().observe(getViewLifecycleOwner(), resource -> {
|
viewModel.loadSupplier().observe(getViewLifecycleOwner(), resource -> {
|
||||||
if (resource == null) return;
|
if (resource == null) return;
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
||||||
SupplierDTO s = resource.data;
|
SupplierDTO s = resource.data;
|
||||||
binding.etSupCompany.setText(s.getSupCompany());
|
binding.etSupCompany.setText(s.getSupCompany());
|
||||||
|
|||||||
@@ -95,6 +95,12 @@ public class PetProfileFragment extends Fragment {
|
|||||||
return binding.getRoot();
|
return binding.getRoot();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setLoading(boolean loading) {
|
||||||
|
if (binding != null && binding.progressBar != null) {
|
||||||
|
binding.progressBar.setVisibility(loading ? View.VISIBLE : View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroyView() {
|
public void onDestroyView() {
|
||||||
super.onDestroyView();
|
super.onDestroyView();
|
||||||
@@ -104,6 +110,7 @@ public class PetProfileFragment extends Fragment {
|
|||||||
private void loadPetData() {
|
private void loadPetData() {
|
||||||
viewModel.getPetById(petId).observe(getViewLifecycleOwner(), resource -> {
|
viewModel.getPetById(petId).observe(getViewLifecycleOwner(), resource -> {
|
||||||
if (resource == null) return;
|
if (resource == null) return;
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
||||||
PetDTO pet = resource.data;
|
PetDTO pet = resource.data;
|
||||||
binding.tvPetName.setText(pet.getPetName());
|
binding.tvPetName.setText(pet.getPetName());
|
||||||
@@ -172,14 +179,14 @@ public class PetProfileFragment extends Fragment {
|
|||||||
MultipartBody.Part body = MultipartBody.Part.createFormData("image", file.getName(), requestFile);
|
MultipartBody.Part body = MultipartBody.Part.createFormData("image", file.getName(), requestFile);
|
||||||
|
|
||||||
viewModel.uploadPetImage(petId, body).observe(getViewLifecycleOwner(), resource -> {
|
viewModel.uploadPetImage(petId, body).observe(getViewLifecycleOwner(), resource -> {
|
||||||
if (resource != null && resource.status != Resource.Status.LOADING) {
|
if (resource == null) return;
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
if (resource.status == Resource.Status.SUCCESS) {
|
if (resource.status == Resource.Status.SUCCESS) {
|
||||||
Toast.makeText(getContext(), "Pet photo updated successfully", Toast.LENGTH_SHORT).show();
|
Toast.makeText(getContext(), "Pet photo updated successfully", Toast.LENGTH_SHORT).show();
|
||||||
loadPetImage((int) petId);
|
loadPetImage((int) petId);
|
||||||
} else {
|
} else if (resource.status == Resource.Status.ERROR) {
|
||||||
Toast.makeText(getContext(), "Upload failed: " + resource.message, Toast.LENGTH_SHORT).show();
|
Toast.makeText(getContext(), "Upload failed: " + resource.message, Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
});
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Log.e("UPLOAD_PET_IMAGE", "Error: " + e.getMessage());
|
Log.e("UPLOAD_PET_IMAGE", "Error: " + e.getMessage());
|
||||||
@@ -188,15 +195,15 @@ public class PetProfileFragment extends Fragment {
|
|||||||
|
|
||||||
private void deletePetImage() {
|
private void deletePetImage() {
|
||||||
viewModel.deletePetImage(petId).observe(getViewLifecycleOwner(), resource -> {
|
viewModel.deletePetImage(petId).observe(getViewLifecycleOwner(), resource -> {
|
||||||
if (resource != null && resource.status != Resource.Status.LOADING) {
|
if (resource == null) return;
|
||||||
|
setLoading(resource.status == Resource.Status.LOADING);
|
||||||
if (resource.status == Resource.Status.SUCCESS) {
|
if (resource.status == Resource.Status.SUCCESS) {
|
||||||
Toast.makeText(getContext(), "Pet photo removed", Toast.LENGTH_SHORT).show();
|
Toast.makeText(getContext(), "Pet photo removed", Toast.LENGTH_SHORT).show();
|
||||||
hasImage = false;
|
hasImage = false;
|
||||||
binding.imgPet.setImageResource(R.drawable.placeholder);
|
binding.imgPet.setImageResource(R.drawable.placeholder);
|
||||||
} else {
|
} else if (resource.status == Resource.Status.ERROR) {
|
||||||
Toast.makeText(getContext(), "Delete failed: " + resource.message, Toast.LENGTH_SHORT).show();
|
Toast.makeText(getContext(), "Delete failed: " + resource.message, Toast.LENGTH_SHORT).show();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,12 +61,15 @@ public class ChatListViewModel extends ViewModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void loadCustomers() {
|
public void loadCustomers() {
|
||||||
|
isLoading.setValue(true);
|
||||||
customerRepository.getAllCustomers(0, 100).observeForever(resource -> {
|
customerRepository.getAllCustomers(0, 100).observeForever(resource -> {
|
||||||
if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
||||||
for (CustomerDTO c : resource.data.getContent()) {
|
for (CustomerDTO c : resource.data.getContent()) {
|
||||||
customerNames.put(c.getCustomerId(), c.getFullName());
|
customerNames.put(c.getCustomerId(), c.getFullName());
|
||||||
}
|
}
|
||||||
loadConversations();
|
loadConversations();
|
||||||
|
} else if (resource != null && resource.status == Resource.Status.ERROR) {
|
||||||
|
isLoading.setValue(false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -96,6 +99,7 @@ public class ChatListViewModel extends ViewModel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void loadMessageHistory(Long conversationId) {
|
public void loadMessageHistory(Long conversationId) {
|
||||||
|
isLoading.setValue(true);
|
||||||
chatRepository.getMessages(conversationId).observeForever(resource -> {
|
chatRepository.getMessages(conversationId).observeForever(resource -> {
|
||||||
if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
if (resource != null && resource.status == Resource.Status.SUCCESS && resource.data != null) {
|
||||||
List<Message> messages = new ArrayList<>();
|
List<Message> messages = new ArrayList<>();
|
||||||
@@ -103,6 +107,9 @@ public class ChatListViewModel extends ViewModel {
|
|||||||
messages.add(dtoToModel(dto));
|
messages.add(dtoToModel(dto));
|
||||||
}
|
}
|
||||||
messageList.setValue(messages);
|
messageList.setValue(messages);
|
||||||
|
isLoading.setValue(false);
|
||||||
|
} else if (resource != null && resource.status == Resource.Status.ERROR) {
|
||||||
|
isLoading.setValue(false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ public class PetDetailViewModel extends ViewModel {
|
|||||||
private final MutableLiveData<PetDTO> petState = new MutableLiveData<>();
|
private final MutableLiveData<PetDTO> petState = new MutableLiveData<>();
|
||||||
private final MutableLiveData<List<DropdownDTO>> customerList = new MutableLiveData<>(new ArrayList<>());
|
private final MutableLiveData<List<DropdownDTO>> customerList = new MutableLiveData<>(new ArrayList<>());
|
||||||
private final MutableLiveData<List<DropdownDTO>> storeList = new MutableLiveData<>(new ArrayList<>());
|
private final MutableLiveData<List<DropdownDTO>> storeList = new MutableLiveData<>(new ArrayList<>());
|
||||||
|
private final MutableLiveData<Boolean> isLoading = new MutableLiveData<>(false);
|
||||||
|
|
||||||
private long petId = -1;
|
private long petId = -1;
|
||||||
private boolean isEditing = false;
|
private boolean isEditing = false;
|
||||||
@@ -91,4 +92,12 @@ public class PetDetailViewModel extends ViewModel {
|
|||||||
public LiveData<List<DropdownDTO>> getStoreList() {
|
public LiveData<List<DropdownDTO>> getStoreList() {
|
||||||
return storeList;
|
return storeList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public LiveData<Boolean> getIsLoading() {
|
||||||
|
return isLoading;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLoading(boolean loading) {
|
||||||
|
isLoading.setValue(loading);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ public class SaleDetailViewModel extends ViewModel {
|
|||||||
private final MutableLiveData<List<DropdownDTO>> customerList = new MutableLiveData<>(new ArrayList<>());
|
private final MutableLiveData<List<DropdownDTO>> customerList = new MutableLiveData<>(new ArrayList<>());
|
||||||
private final MutableLiveData<List<ProductDTO>> productList = new MutableLiveData<>(new ArrayList<>());
|
private final MutableLiveData<List<ProductDTO>> productList = new MutableLiveData<>(new ArrayList<>());
|
||||||
private final MutableLiveData<List<SaleDTO.SaleItemDTO>> cartItems = new MutableLiveData<>(new ArrayList<>());
|
private final MutableLiveData<List<SaleDTO.SaleItemDTO>> cartItems = new MutableLiveData<>(new ArrayList<>());
|
||||||
|
private final MutableLiveData<Boolean> isLoading = new MutableLiveData<>(false);
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public SaleDetailViewModel(SaleRepository saleRepository, StoreRepository storeRepository,
|
public SaleDetailViewModel(SaleRepository saleRepository, StoreRepository storeRepository,
|
||||||
@@ -106,4 +107,12 @@ public class SaleDetailViewModel extends ViewModel {
|
|||||||
}
|
}
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public LiveData<Boolean> getIsLoading() {
|
||||||
|
return isLoading;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLoading(boolean loading) {
|
||||||
|
isLoading.setValue(loading);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
@@ -211,4 +215,14 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/progressBar"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:indeterminateTint="@color/accent_coral"/>
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
@@ -1,5 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
@@ -315,4 +319,14 @@
|
|||||||
|
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/progressBar"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:indeterminateTint="@color/accent_coral"/>
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
@@ -1,5 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
@@ -265,4 +269,14 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/progressBar"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:indeterminateTint="@color/accent_coral"/>
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
@@ -6,11 +6,15 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<RelativeLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:background="@color/background_grey">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical">
|
||||||
android:background="@color/background_grey">
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@@ -126,6 +130,16 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/progressBar"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_centerInParent="true"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:indeterminateTint="@color/accent_coral"/>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
||||||
<androidx.core.widget.NestedScrollView
|
<androidx.core.widget.NestedScrollView
|
||||||
android:id="@+id/chatListDrawer"
|
android:id="@+id/chatListDrawer"
|
||||||
android:layout_width="260dp"
|
android:layout_width="260dp"
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
@@ -152,4 +156,14 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/progressBar"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:indeterminateTint="@color/accent_coral"/>
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
@@ -1,5 +1,10 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<FrameLayout 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_height="match_parent">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
@@ -226,4 +231,14 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/progressBar"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:indeterminateTint="@color/accent_coral"/>
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
@@ -1,5 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
@@ -303,4 +307,14 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/progressBar"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:indeterminateTint="@color/accent_coral"/>
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
@@ -1,5 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
@@ -192,4 +196,14 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/progressBar"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:indeterminateTint="@color/accent_coral"/>
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
@@ -1,5 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
@@ -135,4 +139,14 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/progressBar"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:indeterminateTint="@color/accent_coral"/>
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
@@ -1,5 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<ScrollView
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:background="@color/background_grey">
|
android:background="@color/background_grey">
|
||||||
@@ -197,4 +201,14 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/progressBar"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:indeterminateTint="@color/accent_coral"/>
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
@@ -1,5 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
@@ -137,4 +141,14 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/progressBar"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:indeterminateTint="@color/accent_coral"/>
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
@@ -1,5 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
@@ -219,4 +223,14 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/progressBar"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:indeterminateTint="@color/accent_coral"/>
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
@@ -1,5 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
@@ -330,4 +334,14 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/progressBar"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:indeterminateTint="@color/accent_coral"/>
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
@@ -1,5 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
@@ -168,4 +172,14 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/progressBar"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:indeterminateTint="@color/accent_coral"/>
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
@@ -1,5 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
@@ -230,4 +234,14 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/progressBar"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:indeterminateTint="@color/accent_coral"/>
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
@@ -1,5 +1,9 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
@@ -179,4 +183,14 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/progressBar"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:visibility="gone"
|
||||||
|
android:indeterminateTint="@color/accent_coral"/>
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
Reference in New Issue
Block a user