Refactored more of the project to MVVM and created helper class RetrofitUtil to reduce redundent code

This commit is contained in:
Alex
2026-04-05 21:27:32 -06:00
parent 693829ce42
commit 38a0242264
28 changed files with 855 additions and 1669 deletions

View File

@@ -80,6 +80,7 @@ public class HomeActivity extends AppCompatActivity {
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent); // Set the new intent so fragments can access updated extras
handleIntent(intent);
}
@@ -88,13 +89,9 @@ public class HomeActivity extends AppCompatActivity {
*/
private void handleIntent(Intent intent) {
if (intent != null && "chat".equals(intent.getStringExtra("navigate_to"))) {
Bundle args = new Bundle();
if (intent.hasExtra("conversation_id")) {
args.putLong("conversation_id", intent.getLongExtra("conversation_id", -1));
}
// Use NavController to navigate
if (navController != null) {
navController.navigate(R.id.nav_chat, args);
if (bottomNav != null) {
// Navigate by selecting the bottom nav item.
bottomNav.setSelectedItemId(R.id.nav_chat);
}
}
}

View File

@@ -34,6 +34,7 @@ import com.example.petstoremobile.dtos.SendMessageRequest;
import com.example.petstoremobile.models.Chat;
import com.example.petstoremobile.models.Message;
import com.example.petstoremobile.services.ChatNotificationService;
import com.example.petstoremobile.utils.RetrofitUtils;
import com.example.petstoremobile.websocket.StompChatManager;
import java.util.*;
@@ -202,6 +203,10 @@ public class ChatFragment extends Fragment implements ChatAdapter.OnChatClickLis
if (getArguments() != null && getArguments().containsKey("conversation_id")) {
activeConversationId = getArguments().getLong("conversation_id");
} else if (getActivity() != null && getActivity().getIntent().hasExtra("conversation_id")) {
activeConversationId = getActivity().getIntent().getLongExtra("conversation_id", -1);
getActivity().getIntent().removeExtra("conversation_id");
getActivity().getIntent().removeExtra("navigate_to");
}
loadCustomers();
@@ -211,74 +216,51 @@ public class ChatFragment extends Fragment implements ChatAdapter.OnChatClickLis
* Fetches a list of customers from the API to display customer names for the chat list.
*/
private void loadCustomers() {
customerApi.getAllCustomers(0, 100).enqueue(new Callback<PageResponse<CustomerDTO>>() {
@Override
public void onResponse(@NonNull Call<PageResponse<CustomerDTO>> call,
@NonNull Response<PageResponse<CustomerDTO>> response) {
if (response.isSuccessful() && response.body() != null) {
for (CustomerDTO c : response.body().getContent()) {
customerNames.put(c.getCustomerId(), c.getFullName());
}
}
loadConversations();
customerApi.getAllCustomers(0, 100).enqueue(RetrofitUtils.createSilentCallback(TAG, result -> {
for (CustomerDTO c : result.getContent()) {
customerNames.put(c.getCustomerId(), c.getFullName());
}
@Override
public void onFailure(@NonNull Call<PageResponse<CustomerDTO>> call,
@NonNull Throwable t) {
loadConversations();
}
});
loadConversations();
}));
}
/**
* Retrieves all conversations for the current user and populates the chat drawer.
*/
private void loadConversations() {
chatApi.getAllConversations().enqueue(new Callback<List<ConversationDTO>>() {
@Override
public void onResponse(@NonNull Call<List<ConversationDTO>> call,
@NonNull Response<List<ConversationDTO>> response) {
if (response.isSuccessful() && response.body() != null) {
chatList.clear();
List<Chat> loaded = response.body().stream()
.map(dto -> {
String name = customerNames.getOrDefault(
dto.getCustomerId(), "Customer #" + dto.getCustomerId());
return new Chat(String.valueOf(dto.getId()),
name, dto.getLastMessage(),
dto.getCustomerId(), dto.getStaffId());
})
.collect(Collectors.toList());
chatList.addAll(loaded);
chatAdapter.notifyDataSetChanged();
if (activeConversationId != null) {
setConversationActive(true);
// Update title to customer name of active conversation
for (Chat chat : chatList) {
if (chat.getChatId().equals(String.valueOf(activeConversationId))) {
tvChatTitle.setText(chat.getCustomerName());
break;
}
}
if (stompChatManager != null) {
stompChatManager.subscribeToConversation(activeConversationId);
}
loadMessageHistory(activeConversationId);
} else {
messageList.clear();
messageAdapter.notifyDataSetChanged();
setConversationActive(false);
chatApi.getAllConversations().enqueue(RetrofitUtils.createSilentCallback(TAG, result -> {
chatList.clear();
List<Chat> loaded = result.stream()
.map(dto -> {
String name = customerNames.getOrDefault(
dto.getCustomerId(), "Customer #" + dto.getCustomerId());
return new Chat(String.valueOf(dto.getId()),
name, dto.getLastMessage(),
dto.getCustomerId(), dto.getStaffId());
})
.collect(Collectors.toList());
chatList.addAll(loaded);
chatAdapter.notifyDataSetChanged();
if (activeConversationId != null) {
setConversationActive(true);
// Update title to customer name of active conversation
for (Chat chat : chatList) {
if (chat.getChatId().equals(String.valueOf(activeConversationId))) {
tvChatTitle.setText(chat.getCustomerName());
break;
}
}
if (stompChatManager != null) {
stompChatManager.subscribeToConversation(activeConversationId);
}
loadMessageHistory(activeConversationId);
} else {
messageList.clear();
messageAdapter.notifyDataSetChanged();
setConversationActive(false);
}
@Override
public void onFailure(@NonNull Call<List<ConversationDTO>> call,
@NonNull Throwable t) {
Log.e(TAG, "Error loading conversations", t);
}
});
}));
}
/**
@@ -302,25 +284,14 @@ public class ChatFragment extends Fragment implements ChatAdapter.OnChatClickLis
* Fetches the full message history for a specific conversation from the API.
*/
private void loadMessageHistory(Long conversationId) {
messageApi.getMessages(conversationId).enqueue(new Callback<List<MessageDTO>>() {
@Override
public void onResponse(@NonNull Call<List<MessageDTO>> call,
@NonNull Response<List<MessageDTO>> response) {
if (response.isSuccessful() && response.body() != null) {
messageList.clear();
for (MessageDTO dto : response.body()) {
messageList.add(dtoToModel(dto));
}
messageAdapter.notifyDataSetChanged();
scrollToBottom();
}
messageApi.getMessages(conversationId).enqueue(RetrofitUtils.createSilentCallback(TAG, result -> {
messageList.clear();
for (MessageDTO dto : result) {
messageList.add(dtoToModel(dto));
}
@Override
public void onFailure(@NonNull Call<List<MessageDTO>> call,
@NonNull Throwable t) {
Log.e(TAG, "Error loading messages", t);
}
});
messageAdapter.notifyDataSetChanged();
scrollToBottom();
}));
}
/**
@@ -339,23 +310,12 @@ public class ChatFragment extends Fragment implements ChatAdapter.OnChatClickLis
//calls api to send the message
messageApi.sendMessage(activeConversationId, new SendMessageRequest(text))
.enqueue(new Callback<MessageDTO>() {
@Override
public void onResponse(@NonNull Call<MessageDTO> call,
@NonNull Response<MessageDTO> response) {
if (response.isSuccessful() && response.body() != null) {
messageList.add(dtoToModel(response.body()));
messageAdapter.notifyItemInserted(messageList.size() - 1);
scrollToBottom();
loadConversations();
}
}
@Override
public void onFailure(@NonNull Call<MessageDTO> call,
@NonNull Throwable t) {
Log.e(TAG, "Send failed", t);
}
});
.enqueue(RetrofitUtils.createSilentCallback(TAG, result -> {
messageList.add(dtoToModel(result));
messageAdapter.notifyItemInserted(messageList.size() - 1);
scrollToBottom();
loadConversations();
}));
}
/**

View File

@@ -27,6 +27,7 @@ import com.example.petstoremobile.utils.FileUtils;
import com.example.petstoremobile.utils.GlideUtils;
import com.example.petstoremobile.utils.ImagePickerHelper;
import com.example.petstoremobile.utils.InputValidator;
import com.example.petstoremobile.utils.RetrofitUtils;
import com.example.petstoremobile.utils.UIUtils;
import java.io.File;
@@ -189,47 +190,31 @@ public class ProfileFragment extends Fragment {
* Fetches current user profile data from the API and then updates the UI.
*/
private void loadProfileData() {
authApi.getMe().enqueue(new Callback<UserDTO>() {
@Override
public void onResponse(Call<UserDTO> call, Response<UserDTO> response) {
//if the response is successful and the body is not null then set the user to the view
if (response.isSuccessful() && response.body() != null) {
currentUser = response.body();
authApi.getMe().enqueue(RetrofitUtils.createCallback(requireContext(), "PROFILE", null, result -> {
currentUser = result;
//set the user data to the view
tvProfileName.setText(currentUser.getFullName());
tvProfileEmail.setText(currentUser.getEmail());
tvProfilePhone.setText(currentUser.getPhone());
tvProfileRole.setText(currentUser.getRole());
//set the user data to the view
tvProfileName.setText(currentUser.getFullName());
tvProfileEmail.setText(currentUser.getEmail());
tvProfilePhone.setText(currentUser.getPhone());
tvProfileRole.setText(currentUser.getRole());
// get the avatar endpoint to load profile image and the token for authorization
String avatarUrl = baseUrl + AuthApi.AVATAR_FILE_PATH;
String token = tokenManager.getToken();
// get the avatar endpoint to load profile image and the token for authorization
String avatarUrl = baseUrl + AuthApi.AVATAR_FILE_PATH;
String token = tokenManager.getToken();
GlideUtils.loadImageWithToken(requireContext(), imgProfile, avatarUrl, token, R.drawable.placeholder, new GlideUtils.ImageLoadListener() {
@Override
public void onResourceReady() {
hasImage = true;
}
@Override
public void onLoadFailed() {
hasImage = false;
}
});
GlideUtils.loadImageWithToken(requireContext(), imgProfile, avatarUrl, token, R.drawable.placeholder, new GlideUtils.ImageLoadListener() {
@Override
public void onResourceReady() {
hasImage = true;
}
else {
Log.e("onResponse: ", response.message());
ErrorUtils.showErrorMessage(getContext(), response, "Failed to load profile");
}
}
@Override
public void onFailure(Call<UserDTO> call, Throwable t) {
Log.e("PROFILE", "onFailure: " + t.getMessage());
Toast.makeText(getContext(), "Network error: could not load profile", Toast.LENGTH_SHORT).show();
}
});
@Override
public void onLoadFailed() {
hasImage = false;
}
});
}));
}
/**
@@ -245,25 +230,11 @@ public class ProfileFragment extends Fragment {
MultipartBody.Part body = MultipartBody.Part.createFormData("avatar", file.getName(), requestFile);
//Call the backend to upload the avatar
authApi.uploadAvatar(body).enqueue(new Callback<UserDTO>() {
@Override
public void onResponse(Call<UserDTO> call, Response<UserDTO> response) {
if (response.isSuccessful() && response.body() != null) {
currentUser = response.body();
Toast.makeText(requireContext(), "Avatar updated successfully", Toast.LENGTH_SHORT).show();
// Reload image after successful upload
loadProfileData();
} else {
ErrorUtils.showErrorMessage(getContext(), response, "Failed to upload avatar");
}
}
@Override
public void onFailure(Call<UserDTO> call, Throwable t) {
Log.e("UPLOAD_AVATAR", "Failure: " + t.getMessage());
Toast.makeText(requireContext(), "Network error", Toast.LENGTH_SHORT).show();
}
});
authApi.uploadAvatar(body).enqueue(RetrofitUtils.createCallback(requireContext(), "UPLOAD_AVATAR", "Avatar updated successfully", result -> {
currentUser = result;
// Reload image after successful upload
loadProfileData();
}));
} catch (Exception e) {
Log.e("UPLOAD_AVATAR", "Error: " + e.getMessage());
}
@@ -273,24 +244,10 @@ public class ProfileFragment extends Fragment {
* Sends a request to the API to delete the current user's avatar image.
*/
private void deleteAvatar() {
authApi.deleteAvatar().enqueue(new Callback<Void>() {
@Override
public void onResponse(Call<Void> call, Response<Void> response) {
if (response.isSuccessful()) {
Toast.makeText(requireContext(), "Avatar removed successfully", Toast.LENGTH_SHORT).show();
hasImage = false;
imgProfile.setImageResource(R.drawable.placeholder);
} else {
ErrorUtils.showErrorMessage(getContext(), response, "Failed to remove avatar");
}
}
@Override
public void onFailure(Call<Void> call, Throwable t) {
Log.e("DELETE_AVATAR", "Failure: " + t.getMessage());
Toast.makeText(requireContext(), "Network error", Toast.LENGTH_SHORT).show();
}
});
authApi.deleteAvatar().enqueue(RetrofitUtils.createCallback(requireContext(), "DELETE_AVATAR", "Avatar removed successfully", result -> {
hasImage = false;
imgProfile.setImageResource(R.drawable.placeholder);
}));
}
/**
@@ -300,25 +257,11 @@ public class ProfileFragment extends Fragment {
Map<String, String> updates = new HashMap<>();
updates.put(fieldName, value);
authApi.updateMe(updates).enqueue(new Callback<UserDTO>() {
@Override
public void onResponse(Call<UserDTO> call, Response<UserDTO> response) {
if (response.isSuccessful() && response.body() != null) {
currentUser = response.body();
// Update the view with the new data from backend
tvProfileEmail.setText(currentUser.getEmail());
tvProfilePhone.setText(currentUser.getPhone());
Toast.makeText(requireContext(), "Profile updated successfully", Toast.LENGTH_SHORT).show();
} else {
ErrorUtils.showErrorMessage(getContext(), response, "Failed to update profile");
}
}
@Override
public void onFailure(Call<UserDTO> call, Throwable t) {
Log.e("UPDATE_PROFILE", "Failure: " + t.getMessage());
Toast.makeText(requireContext(), "Network error", Toast.LENGTH_SHORT).show();
}
});
authApi.updateMe(updates).enqueue(RetrofitUtils.createCallback(requireContext(), "UPDATE_PROFILE", "Profile updated successfully", result -> {
currentUser = result;
// Update the view with the new data from backend
tvProfileEmail.setText(currentUser.getEmail());
tvProfilePhone.setText(currentUser.getPhone());
}));
}
}

View File

@@ -7,21 +7,21 @@ import android.view.*;
import android.widget.*;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.fragment.NavHostFragment;
import com.example.petstoremobile.R;
import com.example.petstoremobile.api.*;
import com.example.petstoremobile.dtos.*;
import com.example.petstoremobile.utils.DialogUtils;
import com.example.petstoremobile.utils.ErrorUtils;
import com.example.petstoremobile.utils.Resource;
import com.example.petstoremobile.utils.SpinnerUtils;
import com.example.petstoremobile.viewmodels.AdoptionViewModel;
import com.example.petstoremobile.viewmodels.CustomerViewModel;
import com.example.petstoremobile.viewmodels.PetViewModel;
import java.util.*;
import javax.inject.Inject;
import dagger.hilt.android.AndroidEntryPoint;
import retrofit2.*;
/**
* Fragment for displaying and editing adoption request details.
@@ -44,9 +44,17 @@ public class AdoptionDetailFragment extends Fragment {
private final String[] STATUSES = {"Pending", "Approved", "Rejected"};
@Inject AdoptionApi adoptionApi;
@Inject PetApi petApi;
@Inject CustomerApi customerApi;
private AdoptionViewModel adoptionViewModel;
private PetViewModel petViewModel;
private CustomerViewModel customerViewModel;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
adoptionViewModel = new ViewModelProvider(this).get(AdoptionViewModel.class);
petViewModel = new ViewModelProvider(this).get(PetViewModel.class);
customerViewModel = new ViewModelProvider(this).get(CustomerViewModel.class);
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
@@ -113,43 +121,29 @@ public class AdoptionDetailFragment extends Fragment {
* Loads the list of pets from the API.
*/
private void loadPets() {
petApi.getAllPets(0, 200)
.enqueue(new Callback<PageResponse<PetDTO>>() {
public void onResponse(Call<PageResponse<PetDTO>> c,
Response<PageResponse<PetDTO>> r) {
if (r.isSuccessful() && r.body() != null) {
petList = r.body().getContent();
SpinnerUtils.populateSpinner(requireContext(), spinnerPet, petList,
PetDTO::getPetName, "-- Select Pet --",
preselectedPetId, PetDTO::getPetId);
}
}
public void onFailure(Call<PageResponse<PetDTO>> c, Throwable t) {
Log.e("ADOPTION", "Pet load failed: " + t.getMessage());
}
});
petViewModel.getAllPets(0, 200).observe(getViewLifecycleOwner(), resource -> {
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
petList = resource.data.getContent();
SpinnerUtils.populateSpinner(requireContext(), spinnerPet, petList,
PetDTO::getPetName, "-- Select Pet --",
preselectedPetId, PetDTO::getPetId);
}
});
}
/**
* Loads the list of customers from the API.
*/
private void loadCustomers() {
customerApi.getAllCustomers(0, 200)
.enqueue(new Callback<PageResponse<CustomerDTO>>() {
public void onResponse(Call<PageResponse<CustomerDTO>> c,
Response<PageResponse<CustomerDTO>> r) {
if (r.isSuccessful() && r.body() != null) {
customerList = r.body().getContent();
SpinnerUtils.populateSpinner(requireContext(), spinnerCustomer, customerList,
item -> item.getFirstName() + " " + item.getLastName(),
"-- Select Customer --",
preselectedCustomerId, CustomerDTO::getCustomerId);
}
}
public void onFailure(Call<PageResponse<CustomerDTO>> c, Throwable t) {
Log.e("ADOPTION", "Customer load failed: " + t.getMessage());
}
});
customerViewModel.getAllCustomers(0, 200).observe(getViewLifecycleOwner(), resource -> {
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
customerList = resource.data.getContent();
SpinnerUtils.populateSpinner(requireContext(), spinnerCustomer, customerList,
item -> item.getFirstName() + " " + item.getLastName(),
"-- Select Customer --",
preselectedCustomerId, CustomerDTO::getCustomerId);
}
});
}
/**
@@ -204,51 +198,40 @@ public class AdoptionDetailFragment extends Fragment {
status
);
Log.d("ADOPTION_SAVE", "petId=" + pet.getPetId()
+ " customerId=" + customer.getCustomerId()
+ " date=" + date + " status=" + status);
if (isEditing) {
adoptionApi.updateAdoption(adoptionId, dto).enqueue(simpleCallback("Updated"));
} else {
adoptionApi.createAdoption(dto).enqueue(simpleCallback("Saved"));
}
}
/**
* callback for adoption save/update operations.
*/
private Callback<AdoptionDTO> simpleCallback(String msg) {
return new Callback<>() {
public void onResponse(Call<AdoptionDTO> c, Response<AdoptionDTO> r) {
Log.d("ADOPTION_SAVE", "Response: " + r.code());
if (r.isSuccessful()) {
Toast.makeText(getContext(), msg, Toast.LENGTH_SHORT).show();
adoptionViewModel.updateAdoption(adoptionId, dto).observe(getViewLifecycleOwner(), resource -> {
if (resource.status == Resource.Status.SUCCESS) {
Toast.makeText(getContext(), "Updated", Toast.LENGTH_SHORT).show();
navigateBack();
} else {
ErrorUtils.showErrorMessage(getContext(), r, "Error " + r.code());
} else if (resource.status == Resource.Status.ERROR) {
Toast.makeText(getContext(), "Error: " + resource.message, Toast.LENGTH_SHORT).show();
}
}
public void onFailure(Call<AdoptionDTO> c, Throwable t) {
Log.e("ADOPTION_SAVE", "Failure: " + t.getMessage());
Toast.makeText(getContext(), "Network error", Toast.LENGTH_SHORT).show();
}
};
});
} else {
adoptionViewModel.createAdoption(dto).observe(getViewLifecycleOwner(), resource -> {
if (resource.status == Resource.Status.SUCCESS) {
Toast.makeText(getContext(), "Saved", Toast.LENGTH_SHORT).show();
navigateBack();
} else if (resource.status == Resource.Status.ERROR) {
Toast.makeText(getContext(), "Error: " + resource.message, Toast.LENGTH_SHORT).show();
}
});
}
}
/**
* Shows a confirmation dialog before deleting an adoption request.
*/
private void confirmDelete() {
DialogUtils.showDeleteConfirmDialog(requireContext(), "Adoption", () ->
adoptionApi.deleteAdoption(adoptionId)
.enqueue(new Callback<Void>() {
public void onResponse(Call<Void> c, Response<Void> r) { navigateBack(); }
public void onFailure(Call<Void> c, Throwable t) {
Toast.makeText(getContext(), "Delete failed",
Toast.LENGTH_SHORT).show();
}
}));
DialogUtils.showDeleteConfirmDialog(requireContext(), "Adoption", () ->
adoptionViewModel.deleteAdoption(adoptionId).observe(getViewLifecycleOwner(), resource -> {
if (resource.status == Resource.Status.SUCCESS) {
Toast.makeText(getContext(), "Deleted", Toast.LENGTH_SHORT).show();
navigateBack();
} else if (resource.status == Resource.Status.ERROR) {
Toast.makeText(getContext(), "Delete failed: " + resource.message, Toast.LENGTH_SHORT).show();
}
}));
}
/**

View File

@@ -7,21 +7,23 @@ import android.view.*;
import android.widget.*;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.fragment.NavHostFragment;
import com.example.petstoremobile.R;
import com.example.petstoremobile.api.*;
import com.example.petstoremobile.dtos.*;
import com.example.petstoremobile.utils.DialogUtils;
import com.example.petstoremobile.utils.ErrorUtils;
import com.example.petstoremobile.utils.Resource;
import com.example.petstoremobile.utils.SpinnerUtils;
import com.example.petstoremobile.viewmodels.AppointmentViewModel;
import com.example.petstoremobile.viewmodels.CustomerViewModel;
import com.example.petstoremobile.viewmodels.PetViewModel;
import com.example.petstoremobile.viewmodels.ServiceViewModel;
import com.example.petstoremobile.viewmodels.StoreViewModel;
import java.util.*;
import javax.inject.Inject;
import dagger.hilt.android.AndroidEntryPoint;
import retrofit2.*;
/**
* Fragment for displaying and editing appointment details.
@@ -46,17 +48,26 @@ public class AppointmentDetailFragment extends Fragment {
private List<ServiceDTO> serviceList = new ArrayList<>();
private List<CustomerDTO> customerList = new ArrayList<>();
private List<StoreDTO> storeList = new ArrayList<>();
private List<AppointmentDTO> allAppointments = new ArrayList<>();
private final Integer[] HOURS = {9,10,11,12,13,14,15,16,17};
private final Integer[] MINUTES = {0,15,30,45};
private final String[] STATUSES = {"Booked","Completed","Cancelled"};
@Inject AppointmentApi appointmentApi;
@Inject PetApi petApi;
@Inject ServiceApi serviceApi;
@Inject CustomerApi customerApi;
@Inject StoreApi storeApi;
private AppointmentViewModel appointmentViewModel;
private PetViewModel petViewModel;
private ServiceViewModel serviceViewModel;
private StoreViewModel storeViewModel;
private CustomerViewModel customerViewModel;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
appointmentViewModel = new ViewModelProvider(this).get(AppointmentViewModel.class);
petViewModel = new ViewModelProvider(this).get(PetViewModel.class);
serviceViewModel = new ViewModelProvider(this).get(ServiceViewModel.class);
storeViewModel = new ViewModelProvider(this).get(StoreViewModel.class);
customerViewModel = new ViewModelProvider(this).get(CustomerViewModel.class);
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
@@ -129,102 +140,63 @@ public class AppointmentDetailFragment extends Fragment {
loadServices();
loadCustomers();
loadStores();
loadAllAppointments();
}
/**
* Loads the list of pets from the API.
* Loads the list of pets from the ViewModel.
*/
private void loadPets() {
petApi.getAllPets(0, 200)
.enqueue(new Callback<PageResponse<PetDTO>>() {
public void onResponse(Call<PageResponse<PetDTO>> c, Response<PageResponse<PetDTO>> r) {
if (r.isSuccessful() && r.body() != null) {
petList = r.body().getContent();
SpinnerUtils.populateSpinner(requireContext(), spinnerPet, petList,
PetDTO::getPetName, "-- Select Pet --",
preselectedPetId, PetDTO::getPetId);
}
}
public void onFailure(Call<PageResponse<PetDTO>> c, Throwable t) {
Log.e("APPT", "Pet load failed: " + t.getMessage());
}
});
petViewModel.getAllPets(0, 200).observe(getViewLifecycleOwner(), resource -> {
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
petList = resource.data.getContent();
SpinnerUtils.populateSpinner(requireContext(), spinnerPet, petList,
PetDTO::getPetName, "-- Select Pet --",
preselectedPetId, PetDTO::getPetId);
}
});
}
/**
* Loads the list of services from the API.
*/
private void loadServices() {
serviceApi.getAllServices(0, 200)
.enqueue(new Callback<PageResponse<ServiceDTO>>() {
public void onResponse(Call<PageResponse<ServiceDTO>> c, Response<PageResponse<ServiceDTO>> r) {
if (r.isSuccessful() && r.body() != null) {
serviceList = r.body().getContent();
SpinnerUtils.populateSpinner(requireContext(), spinnerService, serviceList,
ServiceDTO::getServiceName, "-- Select Service --",
preselectedServiceId, ServiceDTO::getServiceId);
}
}
public void onFailure(Call<PageResponse<ServiceDTO>> c, Throwable t) {
Log.e("APPT", "Service load failed: " + t.getMessage());
}
});
serviceViewModel.getAllServices(0, 200).observe(getViewLifecycleOwner(), resource -> {
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
serviceList = resource.data.getContent();
SpinnerUtils.populateSpinner(requireContext(), spinnerService, serviceList,
ServiceDTO::getServiceName, "-- Select Service --",
preselectedServiceId, ServiceDTO::getServiceId);
}
});
}
/**
* Loads the list of customers from the API.
*/
private void loadCustomers() {
customerApi.getAllCustomers(0, 200)
.enqueue(new Callback<PageResponse<CustomerDTO>>() {
public void onResponse(Call<PageResponse<CustomerDTO>> c, Response<PageResponse<CustomerDTO>> r) {
if (r.isSuccessful() && r.body() != null) {
customerList = r.body().getContent();
SpinnerUtils.populateSpinner(requireContext(), spinnerCustomer, customerList,
item -> item.getFirstName() + " " + item.getLastName(),
"-- Select Customer --",
preselectedCustomerId, CustomerDTO::getCustomerId);
}
}
public void onFailure(Call<PageResponse<CustomerDTO>> c, Throwable t) {
Log.e("APPT", "Customer load failed: " + t.getMessage());
}
});
customerViewModel.getAllCustomers(0, 200).observe(getViewLifecycleOwner(), resource -> {
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
customerList = resource.data.getContent();
SpinnerUtils.populateSpinner(requireContext(), spinnerCustomer, customerList,
item -> item.getFirstName() + " " + item.getLastName(),
"-- Select Customer --",
preselectedCustomerId, CustomerDTO::getCustomerId);
}
});
}
/**
* Loads the list of stores from the API.
*/
private void loadStores() {
storeApi.getAllStores(0, 50)
.enqueue(new Callback<PageResponse<StoreDTO>>() {
public void onResponse(Call<PageResponse<StoreDTO>> c, Response<PageResponse<StoreDTO>> r) {
if (r.isSuccessful() && r.body() != null) {
storeList = r.body().getContent();
SpinnerUtils.populateSpinner(requireContext(), spinnerStore, storeList,
StoreDTO::getStoreName, "-- Select Store --",
preselectedStoreId, StoreDTO::getStoreId);
}
}
public void onFailure(Call<PageResponse<StoreDTO>> c, Throwable t) {
Log.e("APPT", "Store load failed: " + t.getMessage());
}
});
}
/**
* Loads all appointments from the API.
*/
private void loadAllAppointments() {
appointmentApi.getAllAppointments(0, 500)
.enqueue(new Callback<PageResponse<AppointmentDTO>>() {
public void onResponse(Call<PageResponse<AppointmentDTO>> c, Response<PageResponse<AppointmentDTO>> r) {
if (r.isSuccessful() && r.body() != null)
allAppointments = r.body().getContent();
}
public void onFailure(Call<PageResponse<AppointmentDTO>> c, Throwable t) {}
});
storeViewModel.getAllStores(0, 50).observe(getViewLifecycleOwner(), resource -> {
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
storeList = resource.data.getContent();
SpinnerUtils.populateSpinner(requireContext(), spinnerStore, storeList,
StoreDTO::getStoreName, "-- Select Store --",
preselectedStoreId, StoreDTO::getStoreId);
}
});
}
/**
@@ -337,57 +309,36 @@ public class AppointmentDetailFragment extends Fragment {
Collections.singletonList(pet.getPetId())
);
Log.d("APPT_SAVE", "customerId=" + customer.getCustomerId()
+ " storeId=" + store.getStoreId()
+ " serviceId=" + service.getServiceId()
+ " petId=" + pet.getPetId()
+ " date=" + date + " time=" + time);
androidx.lifecycle.Observer<Resource<AppointmentDTO>> observer = resource -> {
if (resource.status == Resource.Status.SUCCESS) {
Toast.makeText(getContext(), isEditing ? "Updated" : "Saved", Toast.LENGTH_SHORT).show();
navigateBack();
} else if (resource.status == Resource.Status.ERROR) {
handleSaveError(resource.message);
}
};
if (isEditing) {
appointmentApi.updateAppointment(appointmentId, dto).enqueue(simpleCallback("Updated"));
appointmentViewModel.updateAppointment(appointmentId, dto).observe(getViewLifecycleOwner(), observer);
} else {
appointmentApi.createAppointment(dto).enqueue(simpleCallback("Saved"));
appointmentViewModel.createAppointment(dto).observe(getViewLifecycleOwner(), observer);
}
}
/**
* callback for appointment save/update operations.
*/
private Callback<AppointmentDTO> simpleCallback(String msg) {
return new Callback<>() {
public void onResponse(Call<AppointmentDTO> c, Response<AppointmentDTO> r) {
Log.d("APPT_SAVE", "Response: " + r.code());
if (r.isSuccessful()) {
Toast.makeText(getContext(), msg, Toast.LENGTH_SHORT).show();
navigateBack();
} else {
try {
String errorBody = r.errorBody().string();
Log.e("APPT_SAVE", "Error: " + errorBody);
// Show proper dialog based on error type
if (errorBody.toLowerCase().contains("future")) {
DialogUtils.showInfoDialog(requireContext(), "Invalid Date/Time",
"Booked appointments must be scheduled in the future. " +
"Please select a future date and time.");
} else if (errorBody.toLowerCase().contains("not available") ||
errorBody.toLowerCase().contains("time is not available")) {
showNoAvailabilityDialog();
} else {
ErrorUtils.showErrorMessage(getContext(), r, "Something went wrong. Please try again.");
}
} catch (Exception e) {
Log.e("APPT_SAVE", "Failed to read error body");
DialogUtils.showInfoDialog(requireContext(), "Error", "Something went wrong. Please try again.");
}
}
private void handleSaveError(String errorMessage) {
if (errorMessage != null) {
Log.e("APPT_SAVE", "Error: " + errorMessage);
if (errorMessage.toLowerCase().contains("future")) {
DialogUtils.showInfoDialog(requireContext(), "Invalid Date/Time",
"Booked appointments must be scheduled in the future.");
} else if (errorMessage.toLowerCase().contains("not available")) {
showNoAvailabilityDialog();
} else {
Toast.makeText(getContext(), "Operation failed", Toast.LENGTH_SHORT).show();
}
public void onFailure(Call<AppointmentDTO> c, Throwable t) {
Log.e("APPT_SAVE", "Failure: " + t.getMessage());
Toast.makeText(getContext(), "Network error", Toast.LENGTH_SHORT).show();
}
};
} else {
Toast.makeText(getContext(), "Something went wrong", Toast.LENGTH_SHORT).show();
}
}
/**
@@ -396,7 +347,7 @@ public class AppointmentDetailFragment extends Fragment {
private void showNoAvailabilityDialog() {
new androidx.appcompat.app.AlertDialog.Builder(requireContext())
.setTitle("No Availability")
.setMessage("This time slot is already booked for the selected service and store. Please choose a different time or date.")
.setMessage("This time slot is already booked. Please choose a different time or date.")
.setPositiveButton("Change Time", (d, w) -> d.dismiss())
.setNegativeButton("Cancel Booking", (d, w) -> navigateBack())
.setCancelable(false)
@@ -407,14 +358,15 @@ public class AppointmentDetailFragment extends Fragment {
* Shows a confirmation dialog and handles the deletion of an appointment.
*/
private void confirmDelete() {
DialogUtils.showDeleteConfirmDialog(requireContext(), "Appointment", () ->
appointmentApi.deleteAppointment(appointmentId)
.enqueue(new Callback<Void>() {
public void onResponse(Call<Void> c, Response<Void> r) { navigateBack(); }
public void onFailure(Call<Void> c, Throwable t) {
Toast.makeText(getContext(), "Delete failed", Toast.LENGTH_SHORT).show();
}
}));
DialogUtils.showDeleteConfirmDialog(requireContext(), "Appointment", () ->
appointmentViewModel.deleteAppointment(appointmentId).observe(getViewLifecycleOwner(), resource -> {
if (resource.status == Resource.Status.SUCCESS) {
Toast.makeText(getContext(), "Deleted", Toast.LENGTH_SHORT).show();
navigateBack();
} else if (resource.status == Resource.Status.ERROR) {
Toast.makeText(getContext(), "Delete failed", Toast.LENGTH_SHORT).show();
}
}));
}
/**

View File

@@ -14,30 +14,26 @@ import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.fragment.NavHostFragment;
import com.example.petstoremobile.R;
import com.example.petstoremobile.adapters.BlackTextArrayAdapter;
import com.example.petstoremobile.api.InventoryApi;
import com.example.petstoremobile.api.ProductApi;
import com.example.petstoremobile.dtos.InventoryDTO;
import com.example.petstoremobile.dtos.InventoryRequest;
import com.example.petstoremobile.dtos.PageResponse;
import com.example.petstoremobile.dtos.ProductDTO;
import com.example.petstoremobile.utils.ErrorUtils;
import com.example.petstoremobile.utils.InputValidator;
import com.example.petstoremobile.utils.Resource;
import com.example.petstoremobile.viewmodels.InventoryViewModel;
import com.example.petstoremobile.viewmodels.ProductViewModel;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
import dagger.hilt.android.AndroidEntryPoint;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
/**
* Fragment for displaying and editing inventory item details.
@@ -50,8 +46,8 @@ public class InventoryDetailFragment extends Fragment {
private android.widget.EditText etQuantity;
private Button btnSave, btnDelete, btnBack;
@Inject InventoryApi inventoryApi;
@Inject ProductApi productApi;
private InventoryViewModel inventoryViewModel;
private ProductViewModel productViewModel;
private boolean isEditing = false;
private long inventoryId = -1;
@@ -68,7 +64,14 @@ public class InventoryDetailFragment extends Fragment {
private ArrayAdapter<String> dropdownAdapter;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
inventoryViewModel = new ViewModelProvider(this).get(InventoryViewModel.class);
productViewModel = new ViewModelProvider(this).get(ProductViewModel.class);
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_inventory_detail, container, false);
@@ -150,30 +153,21 @@ public class InventoryDetailFragment extends Fragment {
* Searches for products matching the query from the backend.
*/
private void searchProducts(String query) {
productApi.getAllProducts(query, 0, 20).enqueue(new Callback<PageResponse<ProductDTO>>() {
@Override
public void onResponse(Call<PageResponse<ProductDTO>> call,
Response<PageResponse<ProductDTO>> response) {
if (response.isSuccessful() && response.body() != null) {
productSuggestions.clear();
productSuggestions.addAll(response.body().getContent());
productViewModel.getAllProducts(query, 0, 20).observe(getViewLifecycleOwner(), resource -> {
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
productSuggestions.clear();
productSuggestions.addAll(resource.data.getContent());
// Build display strings: "Product Name (ID: X)"
List<String> names = new ArrayList<>();
for (ProductDTO p : productSuggestions) {
names.add(p.getProdName() + " (ID: " + p.getProdId() + ")");
}
dropdownAdapter.clear();
dropdownAdapter.addAll(names);
dropdownAdapter.notifyDataSetChanged();
etProductSearch.showDropDown();
// Build display strings: "Product Name (ID: X)"
List<String> names = new ArrayList<>();
for (ProductDTO p : productSuggestions) {
names.add(p.getProdName() + " (ID: " + p.getProdId() + ")");
}
}
@Override
public void onFailure(Call<PageResponse<ProductDTO>> call, Throwable t) {
Toast.makeText(getContext(), "Failed to load products", Toast.LENGTH_SHORT).show();
dropdownAdapter.clear();
dropdownAdapter.addAll(names);
dropdownAdapter.notifyDataSetChanged();
etProductSearch.showDropDown();
}
});
}
@@ -242,41 +236,23 @@ public class InventoryDetailFragment extends Fragment {
setButtonsEnabled(false);
if (isEditing) {
inventoryApi.updateInventory(inventoryId, request).enqueue(new Callback<InventoryDTO>() {
@Override
public void onResponse(Call<InventoryDTO> call, Response<InventoryDTO> response) {
setButtonsEnabled(true);
if (response.isSuccessful()) {
Toast.makeText(getContext(), "Inventory updated", Toast.LENGTH_SHORT).show();
navigateBack();
} else {
ErrorUtils.showErrorMessage(getContext(), response, "Update failed");
}
}
@Override
public void onFailure(Call<InventoryDTO> call, Throwable t) {
setButtonsEnabled(true);
Toast.makeText(getContext(), "Network error", Toast.LENGTH_SHORT).show();
inventoryViewModel.updateInventory(inventoryId, request).observe(getViewLifecycleOwner(), resource -> {
setButtonsEnabled(true);
if (resource.status == Resource.Status.SUCCESS) {
Toast.makeText(getContext(), "Inventory updated", Toast.LENGTH_SHORT).show();
navigateBack();
} else if (resource.status == Resource.Status.ERROR) {
Toast.makeText(getContext(), "Error: " + resource.message, Toast.LENGTH_SHORT).show();
}
});
} else {
inventoryApi.createInventory(request).enqueue(new Callback<InventoryDTO>() {
@Override
public void onResponse(Call<InventoryDTO> call, Response<InventoryDTO> response) {
setButtonsEnabled(true);
if (response.isSuccessful()) {
Toast.makeText(getContext(), "Inventory created", Toast.LENGTH_SHORT).show();
navigateBack();
} else {
ErrorUtils.showErrorMessage(getContext(), response, "Create failed");
}
}
@Override
public void onFailure(Call<InventoryDTO> call, Throwable t) {
setButtonsEnabled(true);
Toast.makeText(getContext(), "Network error", Toast.LENGTH_SHORT).show();
inventoryViewModel.createInventory(request).observe(getViewLifecycleOwner(), resource -> {
setButtonsEnabled(true);
if (resource.status == Resource.Status.SUCCESS) {
Toast.makeText(getContext(), "Inventory created", Toast.LENGTH_SHORT).show();
navigateBack();
} else if (resource.status == Resource.Status.ERROR) {
Toast.makeText(getContext(), "Error: " + resource.message, Toast.LENGTH_SHORT).show();
}
});
}
@@ -299,22 +275,13 @@ public class InventoryDetailFragment extends Fragment {
*/
private void deleteInventory() {
setButtonsEnabled(false);
inventoryApi.deleteInventory(inventoryId).enqueue(new Callback<Void>() {
@Override
public void onResponse(Call<Void> call, Response<Void> response) {
setButtonsEnabled(true);
if (response.isSuccessful()) {
Toast.makeText(getContext(), "Inventory deleted", Toast.LENGTH_SHORT).show();
navigateBack();
} else {
ErrorUtils.showErrorMessage(getContext(), response, "Delete failed");
}
}
@Override
public void onFailure(Call<Void> call, Throwable t) {
setButtonsEnabled(true);
Toast.makeText(getContext(), "Network error", Toast.LENGTH_SHORT).show();
inventoryViewModel.deleteInventory(inventoryId).observe(getViewLifecycleOwner(), resource -> {
setButtonsEnabled(true);
if (resource.status == Resource.Status.SUCCESS) {
Toast.makeText(getContext(), "Inventory deleted", Toast.LENGTH_SHORT).show();
navigateBack();
} else if (resource.status == Resource.Status.ERROR) {
Toast.makeText(getContext(), "Delete failed: " + resource.message, Toast.LENGTH_SHORT).show();
}
});
}

View File

@@ -4,9 +4,9 @@ import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.fragment.NavHostFragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -17,20 +17,15 @@ import android.widget.TextView;
import android.widget.Toast;
import com.example.petstoremobile.R;
import com.example.petstoremobile.api.PetApi;
import com.example.petstoremobile.dtos.PetDTO;
import com.example.petstoremobile.utils.ActivityLogger;
import com.example.petstoremobile.utils.DialogUtils;
import com.example.petstoremobile.utils.ErrorUtils;
import com.example.petstoremobile.utils.InputValidator;
import com.example.petstoremobile.utils.Resource;
import com.example.petstoremobile.utils.SpinnerUtils;
import javax.inject.Inject;
import com.example.petstoremobile.viewmodels.PetViewModel;
import dagger.hilt.android.AndroidEntryPoint;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
/**
* Fragment for displaying and editing pet details.
@@ -45,7 +40,13 @@ public class PetDetailFragment extends Fragment {
private int petId;
private boolean isEditing = false;
@Inject PetApi petApi;
private PetViewModel viewModel;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
viewModel = new ViewModelProvider(this).get(PetViewModel.class);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
@@ -97,44 +98,24 @@ public class PetDetailFragment extends Fragment {
if (isEditing) {
// Update existing pet
petDTO.setPetId((long) petId);
petApi.updatePet((long) petId, petDTO).enqueue(new Callback<PetDTO>() {
@Override
public void onResponse(Call<PetDTO> call, Response<PetDTO> response) {
if (response.isSuccessful()) {
ActivityLogger.logChange(requireContext(), "Pet", "UPDATED", petId);
Toast.makeText(getContext(), "Pet updated successfully!", Toast.LENGTH_SHORT).show();
navigateBack();
} else {
ErrorUtils.showErrorMessage(getContext(), response, "Failed to update pet");
}
}
@Override
public void onFailure(Call<PetDTO> call, Throwable t) {
ActivityLogger.logException(requireContext(), "PetDetailFragment.updatePet", new Exception(t));
Log.e("PetDetailFragment", "Error updating pet", t);
Toast.makeText(getContext(), "Network error: " + t.getMessage(), Toast.LENGTH_SHORT).show();
viewModel.updatePet((long) petId, petDTO).observe(getViewLifecycleOwner(), resource -> {
if (resource.status == Resource.Status.SUCCESS) {
ActivityLogger.logChange(requireContext(), "Pet", "UPDATED", petId);
Toast.makeText(getContext(), "Pet updated successfully!", Toast.LENGTH_SHORT).show();
navigateBack();
} else if (resource.status == Resource.Status.ERROR) {
Toast.makeText(getContext(), "Error: " + resource.message, Toast.LENGTH_SHORT).show();
}
});
} else {
// Add new pet
petApi.createPet(petDTO).enqueue(new Callback<PetDTO>() {
@Override
public void onResponse(Call<PetDTO> call, Response<PetDTO> response) {
if (response.isSuccessful()) {
ActivityLogger.log(requireContext(), "Added new Pet: " + name);
Toast.makeText(getContext(), "Pet added successfully!", Toast.LENGTH_SHORT).show();
navigateBack();
} else {
ErrorUtils.showErrorMessage(getContext(), response, "Failed to add pet");
}
}
@Override
public void onFailure(Call<PetDTO> call, Throwable t) {
ActivityLogger.logException(requireContext(), "PetDetailFragment.createPet", new Exception(t));
Log.e("PetDetailFragment", "Error adding pet", t);
Toast.makeText(getContext(), "Network error: " + t.getMessage(), Toast.LENGTH_SHORT).show();
viewModel.createPet(petDTO).observe(getViewLifecycleOwner(), resource -> {
if (resource.status == Resource.Status.SUCCESS) {
ActivityLogger.log(requireContext(), "Added new Pet: " + name);
Toast.makeText(getContext(), "Pet added successfully!", Toast.LENGTH_SHORT).show();
navigateBack();
} else if (resource.status == Resource.Status.ERROR) {
Toast.makeText(getContext(), "Error: " + resource.message, Toast.LENGTH_SHORT).show();
}
});
}
@@ -145,23 +126,13 @@ public class PetDetailFragment extends Fragment {
*/
private void deletePet() {
DialogUtils.showDeleteConfirmDialog(requireContext(), "Pet", () ->
petApi.deletePet((long) petId).enqueue(new Callback<Void>() {
@Override
public void onResponse(Call<Void> call, Response<Void> response) {
if (response.isSuccessful()) {
ActivityLogger.logChange(requireContext(), "Pet", "DELETED", petId);
Toast.makeText(getContext(), "Pet deleted successfully!", Toast.LENGTH_SHORT).show();
navigateBack();
} else {
ErrorUtils.showErrorMessage(getContext(), response, "Failed to delete pet");
}
}
@Override
public void onFailure(Call<Void> call, Throwable t) {
ActivityLogger.logException(requireContext(), "PetDetailFragment.deletePet", new Exception(t));
Log.e("PetDetailFragment", "Error deleting pet", t);
Toast.makeText(getContext(), "Network error: " + t.getMessage(), Toast.LENGTH_SHORT).show();
viewModel.deletePet((long) petId).observe(getViewLifecycleOwner(), resource -> {
if (resource.status == Resource.Status.SUCCESS) {
ActivityLogger.logChange(requireContext(), "Pet", "DELETED", petId);
Toast.makeText(getContext(), "Pet deleted successfully!", Toast.LENGTH_SHORT).show();
navigateBack();
} else if (resource.status == Resource.Status.ERROR) {
Toast.makeText(getContext(), "Delete failed: " + resource.message, Toast.LENGTH_SHORT).show();
}
}));
}
@@ -189,9 +160,7 @@ public class PetDetailFragment extends Fragment {
etPetBreed.setText(getArguments().getString("petBreed"));
etPetAge.setText(String.valueOf(getArguments().getInt("petAge")));
etPetPrice.setText(String.valueOf(getArguments().getDouble("petPrice")));
SpinnerUtils.setSelectionByValue(spinnerPetStatus, getArguments().getString("petStatus"));
btnDeletePet.setVisibility(View.VISIBLE);
} else {
// Pet is being added
@@ -228,5 +197,4 @@ public class PetDetailFragment extends Fragment {
SpinnerUtils.setupStringSpinner(requireContext(), spinnerPetStatus,
new String[]{"Available", "Adopted"});
}
}

View File

@@ -1,31 +1,30 @@
package com.example.petstoremobile.fragments.listfragments.detailfragments;
import android.os.Bundle;
import android.util.Log;
import android.view.*;
import android.widget.*;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.fragment.NavHostFragment;
import com.example.petstoremobile.R;
import com.example.petstoremobile.api.*;
import com.example.petstoremobile.dtos.*;
import com.example.petstoremobile.utils.DialogUtils;
import com.example.petstoremobile.utils.ErrorUtils;
import com.example.petstoremobile.utils.InputValidator;
import com.example.petstoremobile.utils.Resource;
import com.example.petstoremobile.utils.SpinnerUtils;
import com.example.petstoremobile.viewmodels.ProductSupplierViewModel;
import com.example.petstoremobile.viewmodels.ProductViewModel;
import com.example.petstoremobile.viewmodels.SupplierViewModel;
import java.math.BigDecimal;
import java.util.*;
import javax.inject.Inject;
import dagger.hilt.android.AndroidEntryPoint;
import retrofit2.*;
/**
* Fragment for displaying and editing the relationship between products and suppliers,
* Fragment for displaying and editing the relationship between products and suppliers.
*/
@AndroidEntryPoint
public class ProductSupplierDetailFragment extends Fragment {
@@ -44,9 +43,17 @@ public class ProductSupplierDetailFragment extends Fragment {
private List<ProductDTO> productList = new ArrayList<>();
private List<SupplierDTO> supplierList = new ArrayList<>();
@Inject ProductSupplierApi productSupplierApi;
@Inject ProductApi productApi;
@Inject SupplierApi supplierApi;
private ProductSupplierViewModel psViewModel;
private ProductViewModel productViewModel;
private SupplierViewModel supplierViewModel;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
psViewModel = new ViewModelProvider(this).get(ProductSupplierViewModel.class);
productViewModel = new ViewModelProvider(this).get(ProductViewModel.class);
supplierViewModel = new ViewModelProvider(this).get(SupplierViewModel.class);
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
@@ -87,42 +94,28 @@ public class ProductSupplierDetailFragment extends Fragment {
* Loads the list of products from the API.
*/
private void loadProducts() {
productApi.getAllProducts(null, 0, 200)
.enqueue(new Callback<PageResponse<ProductDTO>>() {
public void onResponse(Call<PageResponse<ProductDTO>> c,
Response<PageResponse<ProductDTO>> r) {
if (r.isSuccessful() && r.body() != null) {
productList = r.body().getContent();
SpinnerUtils.populateSpinner(requireContext(), spinnerProduct, productList,
ProductDTO::getProdName, "-- Select Product --",
preselectedProductId, ProductDTO::getProdId);
}
}
public void onFailure(Call<PageResponse<ProductDTO>> c, Throwable t) {
Log.e("PSDetail", "Product load failed: " + t.getMessage());
}
});
productViewModel.getAllProducts(null, 0, 200).observe(getViewLifecycleOwner(), resource -> {
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
productList = resource.data.getContent();
SpinnerUtils.populateSpinner(requireContext(), spinnerProduct, productList,
ProductDTO::getProdName, "-- Select Product --",
preselectedProductId, ProductDTO::getProdId);
}
});
}
/**
* Loads the list of suppliers from the API.
*/
private void loadSuppliers() {
supplierApi.getAllSuppliers(0, 200)
.enqueue(new Callback<PageResponse<SupplierDTO>>() {
public void onResponse(Call<PageResponse<SupplierDTO>> c,
Response<PageResponse<SupplierDTO>> r) {
if (r.isSuccessful() && r.body() != null) {
supplierList = r.body().getContent();
SpinnerUtils.populateSpinner(requireContext(), spinnerSupplier, supplierList,
SupplierDTO::getSupCompany, "-- Select Supplier --",
preselectedSupplierId, SupplierDTO::getSupId);
}
}
public void onFailure(Call<PageResponse<SupplierDTO>> c, Throwable t) {
Log.e("PSDetail", "Supplier load failed: " + t.getMessage());
}
});
supplierViewModel.getAllSuppliers(0, 200).observe(getViewLifecycleOwner(), resource -> {
if (resource.status == Resource.Status.SUCCESS && resource.data != null) {
supplierList = resource.data.getContent();
SpinnerUtils.populateSpinner(requireContext(), spinnerSupplier, supplierList,
SupplierDTO::getSupCompany, "-- Select Supplier --",
preselectedSupplierId, SupplierDTO::getSupId);
}
});
}
/**
@@ -169,48 +162,39 @@ public class ProductSupplierDetailFragment extends Fragment {
product.getProdId(), supplier.getSupId(), cost);
if (isEditing) {
productSupplierApi.updateProductSupplier(editProductId, editSupplierId, dto)
.enqueue(simpleCallback("Updated"));
} else {
productSupplierApi.createProductSupplier(dto).enqueue(simpleCallback("Saved"));
}
}
/**
* callback for product-supplier save/update operations.
*/
private Callback<ProductSupplierDTO> simpleCallback(String msg) {
return new Callback<>() {
public void onResponse(Call<ProductSupplierDTO> c, Response<ProductSupplierDTO> r) {
if (r.isSuccessful()) {
Toast.makeText(getContext(), msg, Toast.LENGTH_SHORT).show();
psViewModel.updateProductSupplier(editProductId, editSupplierId, dto).observe(getViewLifecycleOwner(), resource -> {
if (resource.status == Resource.Status.SUCCESS) {
Toast.makeText(getContext(), "Updated", Toast.LENGTH_SHORT).show();
navigateBack();
} else {
ErrorUtils.showErrorMessage(getContext(), r, "Error " + r.code());
} else if (resource.status == Resource.Status.ERROR) {
Toast.makeText(getContext(), "Error: " + resource.message, Toast.LENGTH_SHORT).show();
}
}
public void onFailure(Call<ProductSupplierDTO> c, Throwable t) {
Log.e("PS_SAVE", "Failure: " + t.getMessage());
Toast.makeText(getContext(), "Network error", Toast.LENGTH_SHORT).show();
}
};
});
} else {
psViewModel.createProductSupplier(dto).observe(getViewLifecycleOwner(), resource -> {
if (resource.status == Resource.Status.SUCCESS) {
Toast.makeText(getContext(), "Saved", Toast.LENGTH_SHORT).show();
navigateBack();
} else if (resource.status == Resource.Status.ERROR) {
Toast.makeText(getContext(), "Error: " + resource.message, Toast.LENGTH_SHORT).show();
}
});
}
}
/**
* Shows a confirmation dialog before deleting a product-supplier relationship.
*/
private void confirmDelete() {
DialogUtils.showDeleteConfirmDialog(requireContext(), "Product Supplier", () ->
productSupplierApi.deleteProductSupplier(editProductId, editSupplierId)
.enqueue(new Callback<Void>() {
public void onResponse(Call<Void> c, Response<Void> r) {
navigateBack();
}
public void onFailure(Call<Void> c, Throwable t) {
Toast.makeText(getContext(), "Delete failed",
Toast.LENGTH_SHORT).show();
}
}));
DialogUtils.showDeleteConfirmDialog(requireContext(), "Product Supplier", () ->
psViewModel.deleteProductSupplier(editProductId, editSupplierId).observe(getViewLifecycleOwner(), resource -> {
if (resource.status == Resource.Status.SUCCESS) {
Toast.makeText(getContext(), "Deleted", Toast.LENGTH_SHORT).show();
navigateBack();
} else if (resource.status == Resource.Status.ERROR) {
Toast.makeText(getContext(), "Delete failed: " + resource.message, Toast.LENGTH_SHORT).show();
}
}));
}
/**

View File

@@ -2,10 +2,11 @@ package com.example.petstoremobile.fragments.listfragments.detailfragments;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.fragment.NavHostFragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -15,19 +16,14 @@ import android.widget.TextView;
import android.widget.Toast;
import com.example.petstoremobile.R;
import com.example.petstoremobile.api.ServiceApi;
import com.example.petstoremobile.dtos.ServiceDTO;
import com.example.petstoremobile.utils.ActivityLogger;
import com.example.petstoremobile.utils.DialogUtils;
import com.example.petstoremobile.utils.ErrorUtils;
import com.example.petstoremobile.utils.InputValidator;
import javax.inject.Inject;
import com.example.petstoremobile.utils.Resource;
import com.example.petstoremobile.viewmodels.ServiceViewModel;
import dagger.hilt.android.AndroidEntryPoint;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
/**
* Fragment for displaying and editing service details.
@@ -41,10 +37,16 @@ public class ServiceDetailFragment extends Fragment {
private int serviceId;
private boolean isEditing = false;
@Inject ServiceApi serviceApi;
private ServiceViewModel viewModel;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
viewModel = new ViewModelProvider(this).get(ServiceViewModel.class);
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_service_detail, container, false);
@@ -87,44 +89,23 @@ public class ServiceDetailFragment extends Fragment {
if (isEditing) {
// Update existing service
serviceDTO.setServiceId((long) serviceId);
serviceApi.updateService((long) serviceId, serviceDTO).enqueue(new Callback<ServiceDTO>() {
@Override
public void onResponse(Call<ServiceDTO> call, Response<ServiceDTO> response) {
if (response.isSuccessful()) {
ActivityLogger.logChange(requireContext(), "Service", "UPDATED", serviceId);
Toast.makeText(getContext(), "Service updated successfully!", Toast.LENGTH_SHORT).show();
navigateBack();
} else {
ErrorUtils.showErrorMessage(getContext(), response, "Failed to update service");
}
}
@Override
public void onFailure(Call<ServiceDTO> call, Throwable t) {
ActivityLogger.logException(requireContext(), "ServiceDetailFragment.updateService", new Exception(t));
Log.e("ServiceDetailFragment", "Error updating service", t);
Toast.makeText(getContext(), "Network error: " + t.getMessage(), Toast.LENGTH_SHORT).show();
viewModel.updateService((long) serviceId, serviceDTO).observe(getViewLifecycleOwner(), resource -> {
if (resource.status == Resource.Status.SUCCESS) {
ActivityLogger.logChange(requireContext(), "Service", "UPDATED", serviceId);
Toast.makeText(getContext(), "Service updated successfully!", Toast.LENGTH_SHORT).show();
navigateBack();
} else if (resource.status == Resource.Status.ERROR) {
Toast.makeText(getContext(), "Error: " + resource.message, Toast.LENGTH_SHORT).show();
}
});
} else {
// Add new service
serviceApi.createService(serviceDTO).enqueue(new Callback<ServiceDTO>() {
@Override
public void onResponse(Call<ServiceDTO> call, Response<ServiceDTO> response) {
if (response.isSuccessful()) {
ActivityLogger.log(requireContext(), "Added new Service: " + name);
Toast.makeText(getContext(), "Service added successfully!", Toast.LENGTH_SHORT).show();
navigateBack();
} else {
ErrorUtils.showErrorMessage(getContext(), response, "Failed to add service");
}
}
@Override
public void onFailure(Call<ServiceDTO> call, Throwable t) {
ActivityLogger.logException(requireContext(), "ServiceDetailFragment.createService", new Exception(t));
Log.e("ServiceDetailFragment", "Error adding service", t);
Toast.makeText(getContext(), "Network error: " + t.getMessage(), Toast.LENGTH_SHORT).show();
viewModel.createService(serviceDTO).observe(getViewLifecycleOwner(), resource -> {
if (resource.status == Resource.Status.SUCCESS) {
ActivityLogger.log(requireContext(), "Added new Service: " + name);
Toast.makeText(getContext(), "Service added successfully!", Toast.LENGTH_SHORT).show();
navigateBack();
} else if (resource.status == Resource.Status.ERROR) {
Toast.makeText(getContext(), "Error: " + resource.message, Toast.LENGTH_SHORT).show();
}
});
}
@@ -135,23 +116,13 @@ public class ServiceDetailFragment extends Fragment {
*/
private void deleteService() {
DialogUtils.showDeleteConfirmDialog(requireContext(), "Service", () ->
serviceApi.deleteService((long) serviceId).enqueue(new Callback<Void>() {
@Override
public void onResponse(Call<Void> call, Response<Void> response) {
if (response.isSuccessful()) {
ActivityLogger.logChange(requireContext(), "Service", "DELETED", serviceId);
Toast.makeText(getContext(), "Service deleted successfully!", Toast.LENGTH_SHORT).show();
navigateBack();
} else {
ErrorUtils.showErrorMessage(getContext(), response, "Failed to delete service");
}
}
@Override
public void onFailure(Call<Void> call, Throwable t) {
ActivityLogger.logException(requireContext(), "ServiceDetailFragment.deleteService", new Exception(t));
Log.e("ServiceDetailFragment", "Error deleting service", t);
Toast.makeText(getContext(), "Network error: " + t.getMessage(), Toast.LENGTH_SHORT).show();
viewModel.deleteService((long) serviceId).observe(getViewLifecycleOwner(), resource -> {
if (resource.status == Resource.Status.SUCCESS) {
ActivityLogger.logChange(requireContext(), "Service", "DELETED", serviceId);
Toast.makeText(getContext(), "Service deleted successfully!", Toast.LENGTH_SHORT).show();
navigateBack();
} else if (resource.status == Resource.Status.ERROR) {
Toast.makeText(getContext(), "Delete failed: " + resource.message, Toast.LENGTH_SHORT).show();
}
}));
}

View File

@@ -2,10 +2,11 @@ package com.example.petstoremobile.fragments.listfragments.detailfragments;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.navigation.fragment.NavHostFragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -15,20 +16,15 @@ import android.widget.TextView;
import android.widget.Toast;
import com.example.petstoremobile.R;
import com.example.petstoremobile.api.SupplierApi;
import com.example.petstoremobile.dtos.SupplierDTO;
import com.example.petstoremobile.utils.ActivityLogger;
import com.example.petstoremobile.utils.DialogUtils;
import com.example.petstoremobile.utils.ErrorUtils;
import com.example.petstoremobile.utils.InputValidator;
import com.example.petstoremobile.utils.Resource;
import com.example.petstoremobile.utils.UIUtils;
import javax.inject.Inject;
import com.example.petstoremobile.viewmodels.SupplierViewModel;
import dagger.hilt.android.AndroidEntryPoint;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
/**
* Fragment for displaying and editing supplier details.
@@ -42,10 +38,16 @@ public class SupplierDetailFragment extends Fragment {
private int supId;
private boolean isEditing = false;
@Inject SupplierApi supplierApi;
private SupplierViewModel viewModel;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
viewModel = new ViewModelProvider(this).get(SupplierViewModel.class);
}
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_supplier_detail, container, false);
@@ -91,44 +93,24 @@ public class SupplierDetailFragment extends Fragment {
if (isEditing) {
// Update existing supplier
supplierDTO.setSupId((long) supId);
supplierApi.updateSupplier((long) supId, supplierDTO).enqueue(new Callback<SupplierDTO>() {
@Override
public void onResponse(Call<SupplierDTO> call, Response<SupplierDTO> response) {
if (response.isSuccessful()) {
ActivityLogger.logChange(requireContext(), "Supplier", "UPDATED", supId);
Toast.makeText(getContext(), "Supplier updated successfully!", Toast.LENGTH_SHORT).show();
navigateBack();
} else {
ErrorUtils.showErrorMessage(getContext(), response, "Failed to update supplier");
}
}
@Override
public void onFailure(Call<SupplierDTO> call, Throwable t) {
ActivityLogger.logException(requireContext(), "SupplierDetailFragment.updateSupplier", new Exception(t));
Log.e("SupplierDetailFragment", "Error updating supplier", t);
Toast.makeText(getContext(), "Network error: " + t.getMessage(), Toast.LENGTH_SHORT).show();
viewModel.updateSupplier((long) supId, supplierDTO).observe(getViewLifecycleOwner(), resource -> {
if (resource.status == Resource.Status.SUCCESS) {
ActivityLogger.logChange(requireContext(), "Supplier", "UPDATED", supId);
Toast.makeText(getContext(), "Supplier updated successfully!", Toast.LENGTH_SHORT).show();
navigateBack();
} else if (resource.status == Resource.Status.ERROR) {
Toast.makeText(getContext(), "Error: " + resource.message, Toast.LENGTH_SHORT).show();
}
});
} else {
// Add new supplier
supplierApi.createSupplier(supplierDTO).enqueue(new Callback<SupplierDTO>() {
@Override
public void onResponse(Call<SupplierDTO> call, Response<SupplierDTO> response) {
if (response.isSuccessful()) {
ActivityLogger.log(requireContext(), "Added new Supplier: " + company);
Toast.makeText(getContext(), "Supplier added successfully!", Toast.LENGTH_SHORT).show();
navigateBack();
} else {
ErrorUtils.showErrorMessage(getContext(), response, "Failed to add supplier");
}
}
@Override
public void onFailure(Call<SupplierDTO> call, Throwable t) {
ActivityLogger.logException(requireContext(), "SupplierDetailFragment.createSupplier", new Exception(t));
Log.e("SupplierDetailFragment", "Error adding supplier", t);
Toast.makeText(getContext(), "Network error: " + t.getMessage(), Toast.LENGTH_SHORT).show();
viewModel.createSupplier(supplierDTO).observe(getViewLifecycleOwner(), resource -> {
if (resource.status == Resource.Status.SUCCESS) {
ActivityLogger.log(requireContext(), "Added new Supplier: " + company);
Toast.makeText(getContext(), "Supplier added successfully!", Toast.LENGTH_SHORT).show();
navigateBack();
} else if (resource.status == Resource.Status.ERROR) {
Toast.makeText(getContext(), "Error: " + resource.message, Toast.LENGTH_SHORT).show();
}
});
}
@@ -138,24 +120,14 @@ public class SupplierDetailFragment extends Fragment {
* Displays a confirmation dialog and handles the deletion of a supplier.
*/
private void deleteSupplier() {
DialogUtils.showDeleteConfirmDialog(requireContext(), "Supplier", () ->
supplierApi.deleteSupplier((long) supId).enqueue(new Callback<Void>() {
@Override
public void onResponse(Call<Void> call, Response<Void> response) {
if (response.isSuccessful()) {
ActivityLogger.logChange(requireContext(), "Supplier", "DELETED", supId);
Toast.makeText(getContext(), "Supplier deleted successfully!", Toast.LENGTH_SHORT).show();
navigateBack();
} else {
ErrorUtils.showErrorMessage(getContext(), response, "Failed to delete supplier");
}
}
@Override
public void onFailure(Call<Void> call, Throwable t) {
ActivityLogger.logException(requireContext(), "SupplierDetailFragment.deleteSupplier", new Exception(t));
Log.e("SupplierDetailFragment", "Error deleting supplier", t);
Toast.makeText(getContext(), "Network error: " + t.getMessage(), Toast.LENGTH_SHORT).show();
DialogUtils.showDeleteConfirmDialog(requireContext(), "Supplier", () ->
viewModel.deleteSupplier((long) supId).observe(getViewLifecycleOwner(), resource -> {
if (resource.status == Resource.Status.SUCCESS) {
ActivityLogger.logChange(requireContext(), "Supplier", "DELETED", supId);
Toast.makeText(getContext(), "Supplier deleted successfully!", Toast.LENGTH_SHORT).show();
navigateBack();
} else if (resource.status == Resource.Status.ERROR) {
Toast.makeText(getContext(), "Delete failed: " + resource.message, Toast.LENGTH_SHORT).show();
}
}));
}

View File

@@ -13,7 +13,6 @@ import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import com.example.petstoremobile.R;
import com.example.petstoremobile.api.PetApi;
@@ -21,6 +20,7 @@ import com.example.petstoremobile.api.auth.TokenManager;
import com.example.petstoremobile.utils.FileUtils;
import com.example.petstoremobile.utils.GlideUtils;
import com.example.petstoremobile.utils.ImagePickerHelper;
import com.example.petstoremobile.utils.RetrofitUtils;
import java.io.File;
import java.util.Locale;
@@ -32,9 +32,6 @@ import dagger.hilt.android.AndroidEntryPoint;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.RequestBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
@AndroidEntryPoint
public class PetProfileFragment extends Fragment {
@@ -157,24 +154,12 @@ public class PetProfileFragment extends Fragment {
MultipartBody.Part body = MultipartBody.Part.createFormData("image", file.getName(), requestFile);
// Call the backend to upload the image
petApi.uploadPetImage((long) petId, body).enqueue(new Callback<Void>() {
@Override
public void onResponse(Call<Void> call, Response<Void> response) {
if (response.isSuccessful()) {
Toast.makeText(requireContext(), "Pet photo updated successfully", Toast.LENGTH_SHORT).show();
// Reload image after successful upload
loadPetImage(petId);
} else {
Toast.makeText(requireContext(), "Failed to upload pet photo", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onFailure(Call<Void> call, Throwable t) {
Log.e("UPLOAD_PET_IMAGE", "Failure: " + t.getMessage());
Toast.makeText(requireContext(), "Network error", Toast.LENGTH_SHORT).show();
}
});
petApi.uploadPetImage((long) petId, body).enqueue(RetrofitUtils.createCallback(
requireContext(),
"UPLOAD_PET_IMAGE",
"Pet photo updated successfully",
result -> loadPetImage(petId)
));
} catch (Exception e) {
Log.e("UPLOAD_PET_IMAGE", "Error: " + e.getMessage());
}
@@ -184,23 +169,14 @@ public class PetProfileFragment extends Fragment {
* Sends a request to the API to remove the current pet photo.
*/
private void deletePetImage() {
petApi.deletePetImage((long) petId).enqueue(new Callback<Void>() {
@Override
public void onResponse(Call<Void> call, Response<Void> response) {
if (response.isSuccessful()) {
Toast.makeText(requireContext(), "Pet photo removed", Toast.LENGTH_SHORT).show();
petApi.deletePetImage((long) petId).enqueue(RetrofitUtils.createCallback(
requireContext(),
"DELETE_PET_IMAGE",
"Pet photo removed",
result -> {
hasImage = false;
imgPet.setImageResource(R.drawable.placeholder);
} else {
Toast.makeText(requireContext(), "Failed to remove pet photo", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onFailure(Call<Void> call, Throwable t) {
Log.e("DELETE_PET_IMAGE", "Failure: " + t.getMessage());
Toast.makeText(requireContext(), "Network error", Toast.LENGTH_SHORT).show();
}
});
));
}
}

View File

@@ -7,16 +7,14 @@ import com.example.petstoremobile.api.AdoptionApi;
import com.example.petstoremobile.dtos.AdoptionDTO;
import com.example.petstoremobile.dtos.PageResponse;
import com.example.petstoremobile.utils.Resource;
import com.example.petstoremobile.utils.RetrofitUtils;
import javax.inject.Inject;
import javax.inject.Singleton;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
@Singleton
public class AdoptionRepository {
private static final String TAG = "AdoptionRepository";
private final AdoptionApi adoptionApi;
@Inject
@@ -31,21 +29,8 @@ public class AdoptionRepository {
MutableLiveData<Resource<PageResponse<AdoptionDTO>>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
adoptionApi.getAllAdoptions(page, size).enqueue(new Callback<PageResponse<AdoptionDTO>>() {
@Override
public void onResponse(Call<PageResponse<AdoptionDTO>> call, Response<PageResponse<AdoptionDTO>> response) {
if (response.isSuccessful() && response.body() != null) {
data.setValue(Resource.success(response.body()));
} else {
data.setValue(Resource.error("Error: " + response.message(), null));
}
}
@Override
public void onFailure(Call<PageResponse<AdoptionDTO>> call, Throwable t) {
data.setValue(Resource.error(t.getMessage(), null));
}
});
adoptionApi.getAllAdoptions(page, size).enqueue(RetrofitUtils.createSilentCallback(TAG,
result -> data.setValue(Resource.success(result))));
return data;
}
@@ -57,21 +42,8 @@ public class AdoptionRepository {
MutableLiveData<Resource<AdoptionDTO>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
adoptionApi.getAdoptionById(id).enqueue(new Callback<AdoptionDTO>() {
@Override
public void onResponse(Call<AdoptionDTO> call, Response<AdoptionDTO> response) {
if (response.isSuccessful() && response.body() != null) {
data.setValue(Resource.success(response.body()));
} else {
data.setValue(Resource.error("Error: " + response.message(), null));
}
}
@Override
public void onFailure(Call<AdoptionDTO> call, Throwable t) {
data.setValue(Resource.error(t.getMessage(), null));
}
});
adoptionApi.getAdoptionById(id).enqueue(RetrofitUtils.createSilentCallback(TAG,
result -> data.setValue(Resource.success(result))));
return data;
}
@@ -83,21 +55,8 @@ public class AdoptionRepository {
MutableLiveData<Resource<AdoptionDTO>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
adoptionApi.createAdoption(adoption).enqueue(new Callback<AdoptionDTO>() {
@Override
public void onResponse(Call<AdoptionDTO> call, Response<AdoptionDTO> response) {
if (response.isSuccessful() && response.body() != null) {
data.setValue(Resource.success(response.body()));
} else {
data.setValue(Resource.error("Error: " + response.message(), null));
}
}
@Override
public void onFailure(Call<AdoptionDTO> call, Throwable t) {
data.setValue(Resource.error(t.getMessage(), null));
}
});
adoptionApi.createAdoption(adoption).enqueue(RetrofitUtils.createSilentCallback(TAG,
result -> data.setValue(Resource.success(result))));
return data;
}
@@ -109,21 +68,8 @@ public class AdoptionRepository {
MutableLiveData<Resource<AdoptionDTO>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
adoptionApi.updateAdoption(id, adoption).enqueue(new Callback<AdoptionDTO>() {
@Override
public void onResponse(Call<AdoptionDTO> call, Response<AdoptionDTO> response) {
if (response.isSuccessful() && response.body() != null) {
data.setValue(Resource.success(response.body()));
} else {
data.setValue(Resource.error("Error: " + response.message(), null));
}
}
@Override
public void onFailure(Call<AdoptionDTO> call, Throwable t) {
data.setValue(Resource.error(t.getMessage(), null));
}
});
adoptionApi.updateAdoption(id, adoption).enqueue(RetrofitUtils.createSilentCallback(TAG,
result -> data.setValue(Resource.success(result))));
return data;
}
@@ -135,21 +81,8 @@ public class AdoptionRepository {
MutableLiveData<Resource<Void>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
adoptionApi.deleteAdoption(id).enqueue(new Callback<Void>() {
@Override
public void onResponse(Call<Void> call, Response<Void> response) {
if (response.isSuccessful()) {
data.setValue(Resource.success(null));
} else {
data.setValue(Resource.error("Error: " + response.message(), null));
}
}
@Override
public void onFailure(Call<Void> call, Throwable t) {
data.setValue(Resource.error(t.getMessage(), null));
}
});
adoptionApi.deleteAdoption(id).enqueue(RetrofitUtils.createSilentCallback(TAG,
result -> data.setValue(Resource.success(null))));
return data;
}

View File

@@ -7,16 +7,14 @@ import com.example.petstoremobile.api.AppointmentApi;
import com.example.petstoremobile.dtos.AppointmentDTO;
import com.example.petstoremobile.dtos.PageResponse;
import com.example.petstoremobile.utils.Resource;
import com.example.petstoremobile.utils.RetrofitUtils;
import javax.inject.Inject;
import javax.inject.Singleton;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
@Singleton
public class AppointmentRepository {
private static final String TAG = "AppointmentRepository";
private final AppointmentApi appointmentApi;
@Inject
@@ -31,21 +29,8 @@ public class AppointmentRepository {
MutableLiveData<Resource<PageResponse<AppointmentDTO>>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
appointmentApi.getAllAppointments(page, size).enqueue(new Callback<PageResponse<AppointmentDTO>>() {
@Override
public void onResponse(Call<PageResponse<AppointmentDTO>> call, Response<PageResponse<AppointmentDTO>> response) {
if (response.isSuccessful() && response.body() != null) {
data.setValue(Resource.success(response.body()));
} else {
data.setValue(Resource.error("Error: " + response.message(), null));
}
}
@Override
public void onFailure(Call<PageResponse<AppointmentDTO>> call, Throwable t) {
data.setValue(Resource.error(t.getMessage(), null));
}
});
appointmentApi.getAllAppointments(page, size).enqueue(RetrofitUtils.createSilentCallback(TAG,
result -> data.setValue(Resource.success(result))));
return data;
}
@@ -57,21 +42,8 @@ public class AppointmentRepository {
MutableLiveData<Resource<AppointmentDTO>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
appointmentApi.getAppointmentById(id).enqueue(new Callback<AppointmentDTO>() {
@Override
public void onResponse(Call<AppointmentDTO> call, Response<AppointmentDTO> response) {
if (response.isSuccessful() && response.body() != null) {
data.setValue(Resource.success(response.body()));
} else {
data.setValue(Resource.error("Error: " + response.message(), null));
}
}
@Override
public void onFailure(Call<AppointmentDTO> call, Throwable t) {
data.setValue(Resource.error(t.getMessage(), null));
}
});
appointmentApi.getAppointmentById(id).enqueue(RetrofitUtils.createSilentCallback(TAG,
result -> data.setValue(Resource.success(result))));
return data;
}
@@ -83,21 +55,8 @@ public class AppointmentRepository {
MutableLiveData<Resource<AppointmentDTO>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
appointmentApi.createAppointment(appointment).enqueue(new Callback<AppointmentDTO>() {
@Override
public void onResponse(Call<AppointmentDTO> call, Response<AppointmentDTO> response) {
if (response.isSuccessful() && response.body() != null) {
data.setValue(Resource.success(response.body()));
} else {
data.setValue(Resource.error("Error: " + response.message(), null));
}
}
@Override
public void onFailure(Call<AppointmentDTO> call, Throwable t) {
data.setValue(Resource.error(t.getMessage(), null));
}
});
appointmentApi.createAppointment(appointment).enqueue(RetrofitUtils.createSilentCallback(TAG,
result -> data.setValue(Resource.success(result))));
return data;
}
@@ -109,21 +68,8 @@ public class AppointmentRepository {
MutableLiveData<Resource<AppointmentDTO>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
appointmentApi.updateAppointment(id, appointment).enqueue(new Callback<AppointmentDTO>() {
@Override
public void onResponse(Call<AppointmentDTO> call, Response<AppointmentDTO> response) {
if (response.isSuccessful() && response.body() != null) {
data.setValue(Resource.success(response.body()));
} else {
data.setValue(Resource.error("Error: " + response.message(), null));
}
}
@Override
public void onFailure(Call<AppointmentDTO> call, Throwable t) {
data.setValue(Resource.error(t.getMessage(), null));
}
});
appointmentApi.updateAppointment(id, appointment).enqueue(RetrofitUtils.createSilentCallback(TAG,
result -> data.setValue(Resource.success(result))));
return data;
}
@@ -135,21 +81,8 @@ public class AppointmentRepository {
MutableLiveData<Resource<Void>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
appointmentApi.deleteAppointment(id).enqueue(new Callback<Void>() {
@Override
public void onResponse(Call<Void> call, Response<Void> response) {
if (response.isSuccessful()) {
data.setValue(Resource.success(null));
} else {
data.setValue(Resource.error("Error: " + response.message(), null));
}
}
@Override
public void onFailure(Call<Void> call, Throwable t) {
data.setValue(Resource.error(t.getMessage(), null));
}
});
appointmentApi.deleteAppointment(id).enqueue(RetrofitUtils.createSilentCallback(TAG,
result -> data.setValue(Resource.success(null))));
return data;
}

View File

@@ -1,5 +1,7 @@
package com.example.petstoremobile.repositories;
import android.util.Log;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
@@ -8,6 +10,7 @@ import com.example.petstoremobile.api.auth.TokenManager;
import com.example.petstoremobile.dtos.AuthDTO;
import com.example.petstoremobile.dtos.UserDTO;
import com.example.petstoremobile.utils.Resource;
import com.example.petstoremobile.utils.RetrofitUtils;
import java.util.Map;
@@ -15,12 +18,10 @@ import javax.inject.Inject;
import javax.inject.Singleton;
import okhttp3.MultipartBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
@Singleton
public class AuthRepository {
private static final String TAG = "AuthRepository";
private final AuthApi authApi;
private final TokenManager tokenManager;
@@ -37,26 +38,14 @@ public class AuthRepository {
MutableLiveData<Resource<AuthDTO.LoginResponse>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
authApi.login(loginRequest).enqueue(new Callback<AuthDTO.LoginResponse>() {
@Override
public void onResponse(Call<AuthDTO.LoginResponse> call, Response<AuthDTO.LoginResponse> response) {
if (response.isSuccessful() && response.body() != null) {
tokenManager.saveLoginData(
response.body().getToken(),
response.body().getUsername(),
response.body().getRole()
);
data.setValue(Resource.success(response.body()));
} else {
data.setValue(Resource.error("Login failed: " + response.message(), null));
}
authApi.login(loginRequest).enqueue(RetrofitUtils.createSilentCallback(TAG, result -> {
if (result != null && result.getToken() != null) {
tokenManager.saveLoginData(result.getToken(), result.getUsername(), result.getRole());
data.setValue(Resource.success(result));
} else {
data.setValue(Resource.error("Login failed", null));
}
@Override
public void onFailure(Call<AuthDTO.LoginResponse> call, Throwable t) {
data.setValue(Resource.error(t.getMessage(), null));
}
});
}));
return data;
}
@@ -68,21 +57,8 @@ public class AuthRepository {
MutableLiveData<Resource<UserDTO>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
authApi.getMe().enqueue(new Callback<UserDTO>() {
@Override
public void onResponse(Call<UserDTO> call, Response<UserDTO> response) {
if (response.isSuccessful() && response.body() != null) {
data.setValue(Resource.success(response.body()));
} else {
data.setValue(Resource.error("Error: " + response.message(), null));
}
}
@Override
public void onFailure(Call<UserDTO> call, Throwable t) {
data.setValue(Resource.error(t.getMessage(), null));
}
});
authApi.getMe().enqueue(RetrofitUtils.createSilentCallback(TAG,
result -> data.setValue(Resource.success(result))));
return data;
}
@@ -94,21 +70,8 @@ public class AuthRepository {
MutableLiveData<Resource<UserDTO>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
authApi.updateMe(updates).enqueue(new Callback<UserDTO>() {
@Override
public void onResponse(Call<UserDTO> call, Response<UserDTO> response) {
if (response.isSuccessful() && response.body() != null) {
data.setValue(Resource.success(response.body()));
} else {
data.setValue(Resource.error("Error: " + response.message(), null));
}
}
@Override
public void onFailure(Call<UserDTO> call, Throwable t) {
data.setValue(Resource.error(t.getMessage(), null));
}
});
authApi.updateMe(updates).enqueue(RetrofitUtils.createSilentCallback(TAG,
result -> data.setValue(Resource.success(result))));
return data;
}
@@ -120,21 +83,8 @@ public class AuthRepository {
MutableLiveData<Resource<UserDTO>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
authApi.uploadAvatar(avatar).enqueue(new Callback<UserDTO>() {
@Override
public void onResponse(Call<UserDTO> call, Response<UserDTO> response) {
if (response.isSuccessful() && response.body() != null) {
data.setValue(Resource.success(response.body()));
} else {
data.setValue(Resource.error("Error: " + response.message(), null));
}
}
@Override
public void onFailure(Call<UserDTO> call, Throwable t) {
data.setValue(Resource.error(t.getMessage(), null));
}
});
authApi.uploadAvatar(avatar).enqueue(RetrofitUtils.createSilentCallback(TAG,
result -> data.setValue(Resource.success(result))));
return data;
}
@@ -146,21 +96,8 @@ public class AuthRepository {
MutableLiveData<Resource<Void>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
authApi.deleteAvatar().enqueue(new Callback<Void>() {
@Override
public void onResponse(Call<Void> call, Response<Void> response) {
if (response.isSuccessful()) {
data.setValue(Resource.success(null));
} else {
data.setValue(Resource.error("Error: " + response.message(), null));
}
}
@Override
public void onFailure(Call<Void> call, Throwable t) {
data.setValue(Resource.error(t.getMessage(), null));
}
});
authApi.deleteAvatar().enqueue(RetrofitUtils.createSilentCallback(TAG,
result -> data.setValue(Resource.success(null))));
return data;
}
@@ -171,4 +108,8 @@ public class AuthRepository {
public void logout() {
tokenManager.clearLoginData();
}
public boolean isLoggedIn() {
return tokenManager.getToken() != null;
}
}

View File

@@ -7,16 +7,14 @@ import com.example.petstoremobile.api.CategoryApi;
import com.example.petstoremobile.dtos.CategoryDTO;
import com.example.petstoremobile.dtos.PageResponse;
import com.example.petstoremobile.utils.Resource;
import com.example.petstoremobile.utils.RetrofitUtils;
import javax.inject.Inject;
import javax.inject.Singleton;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
@Singleton
public class CategoryRepository {
private static final String TAG = "CategoryRepository";
private final CategoryApi categoryApi;
@Inject
@@ -31,21 +29,8 @@ public class CategoryRepository {
MutableLiveData<Resource<PageResponse<CategoryDTO>>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
categoryApi.getAllCategories(page, size).enqueue(new Callback<PageResponse<CategoryDTO>>() {
@Override
public void onResponse(Call<PageResponse<CategoryDTO>> call, Response<PageResponse<CategoryDTO>> response) {
if (response.isSuccessful() && response.body() != null) {
data.setValue(Resource.success(response.body()));
} else {
data.setValue(Resource.error("Error: " + response.message(), null));
}
}
@Override
public void onFailure(Call<PageResponse<CategoryDTO>> call, Throwable t) {
data.setValue(Resource.error(t.getMessage(), null));
}
});
categoryApi.getAllCategories(page, size).enqueue(RetrofitUtils.createSilentCallback(TAG,
result -> data.setValue(Resource.success(result))));
return data;
}

View File

@@ -0,0 +1,50 @@
package com.example.petstoremobile.repositories;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import com.example.petstoremobile.api.CustomerApi;
import com.example.petstoremobile.dtos.CustomerDTO;
import com.example.petstoremobile.dtos.PageResponse;
import com.example.petstoremobile.utils.Resource;
import com.example.petstoremobile.utils.RetrofitUtils;
import javax.inject.Inject;
import javax.inject.Singleton;
@Singleton
public class CustomerRepository {
private static final String TAG = "CustomerRepository";
private final CustomerApi customerApi;
@Inject
public CustomerRepository(CustomerApi customerApi) {
this.customerApi = customerApi;
}
/**
* Retrieves a paginated list of all customers from the API.
*/
public LiveData<Resource<PageResponse<CustomerDTO>>> getAllCustomers(int page, int size) {
MutableLiveData<Resource<PageResponse<CustomerDTO>>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
customerApi.getAllCustomers(page, size).enqueue(RetrofitUtils.createSilentCallback(TAG,
result -> data.setValue(Resource.success(result))));
return data;
}
/**
* Retrieves a specific customer by their ID.
*/
public LiveData<Resource<CustomerDTO>> getCustomerById(Long id) {
MutableLiveData<Resource<CustomerDTO>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
customerApi.getCustomerById(id).enqueue(RetrofitUtils.createSilentCallback(TAG,
result -> data.setValue(Resource.success(result))));
return data;
}
}

View File

@@ -9,16 +9,16 @@ import com.example.petstoremobile.dtos.InventoryDTO;
import com.example.petstoremobile.dtos.InventoryRequest;
import com.example.petstoremobile.dtos.PageResponse;
import com.example.petstoremobile.utils.Resource;
import com.example.petstoremobile.utils.RetrofitUtils;
import java.util.List;
import javax.inject.Inject;
import javax.inject.Singleton;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
@Singleton
public class InventoryRepository {
private static final String TAG = "InventoryRepository";
private final InventoryApi inventoryApi;
@Inject
@@ -33,21 +33,8 @@ public class InventoryRepository {
MutableLiveData<Resource<PageResponse<InventoryDTO>>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
inventoryApi.getAllInventory(query, page, size, sort).enqueue(new Callback<PageResponse<InventoryDTO>>() {
@Override
public void onResponse(Call<PageResponse<InventoryDTO>> call, Response<PageResponse<InventoryDTO>> response) {
if (response.isSuccessful() && response.body() != null) {
data.setValue(Resource.success(response.body()));
} else {
data.setValue(Resource.error("Error: " + response.message(), null));
}
}
@Override
public void onFailure(Call<PageResponse<InventoryDTO>> call, Throwable t) {
data.setValue(Resource.error(t.getMessage(), null));
}
});
inventoryApi.getAllInventory(query, page, size, sort).enqueue(RetrofitUtils.createSilentCallback(TAG,
result -> data.setValue(Resource.success(result))));
return data;
}
@@ -59,21 +46,8 @@ public class InventoryRepository {
MutableLiveData<Resource<InventoryDTO>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
inventoryApi.getInventoryById(id).enqueue(new Callback<InventoryDTO>() {
@Override
public void onResponse(Call<InventoryDTO> call, Response<InventoryDTO> response) {
if (response.isSuccessful() && response.body() != null) {
data.setValue(Resource.success(response.body()));
} else {
data.setValue(Resource.error("Error: " + response.message(), null));
}
}
@Override
public void onFailure(Call<InventoryDTO> call, Throwable t) {
data.setValue(Resource.error(t.getMessage(), null));
}
});
inventoryApi.getInventoryById(id).enqueue(RetrofitUtils.createSilentCallback(TAG,
result -> data.setValue(Resource.success(result))));
return data;
}
@@ -85,47 +59,18 @@ public class InventoryRepository {
MutableLiveData<Resource<InventoryDTO>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
inventoryApi.createInventory(request).enqueue(new Callback<InventoryDTO>() {
@Override
public void onResponse(Call<InventoryDTO> call, Response<InventoryDTO> response) {
if (response.isSuccessful() && response.body() != null) {
data.setValue(Resource.success(response.body()));
} else {
data.setValue(Resource.error("Error: " + response.message(), null));
}
}
@Override
public void onFailure(Call<InventoryDTO> call, Throwable t) {
data.setValue(Resource.error(t.getMessage(), null));
}
});
inventoryApi.createInventory(request).enqueue(RetrofitUtils.createSilentCallback(TAG,
result -> data.setValue(Resource.success(result))));
return data;
}
/**
* Sends a request to the API to update an existing inventory record.
*/
public LiveData<Resource<InventoryDTO>> updateInventory(Long id, InventoryRequest request) {
MutableLiveData<Resource<InventoryDTO>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
inventoryApi.updateInventory(id, request).enqueue(new Callback<InventoryDTO>() {
@Override
public void onResponse(Call<InventoryDTO> call, Response<InventoryDTO> response) {
if (response.isSuccessful() && response.body() != null) {
data.setValue(Resource.success(response.body()));
} else {
data.setValue(Resource.error("Error: " + response.message(), null));
}
}
@Override
public void onFailure(Call<InventoryDTO> call, Throwable t) {
data.setValue(Resource.error(t.getMessage(), null));
}
});
inventoryApi.updateInventory(id, request).enqueue(RetrofitUtils.createSilentCallback(TAG,
result -> data.setValue(Resource.success(result))));
return data;
}
@@ -137,47 +82,18 @@ public class InventoryRepository {
MutableLiveData<Resource<Void>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
inventoryApi.deleteInventory(id).enqueue(new Callback<Void>() {
@Override
public void onResponse(Call<Void> call, Response<Void> response) {
if (response.isSuccessful()) {
data.setValue(Resource.success(null));
} else {
data.setValue(Resource.error("Error: " + response.message(), null));
}
}
@Override
public void onFailure(Call<Void> call, Throwable t) {
data.setValue(Resource.error(t.getMessage(), null));
}
});
inventoryApi.deleteInventory(id).enqueue(RetrofitUtils.createSilentCallback(TAG,
result -> data.setValue(Resource.success(null))));
return data;
}
/**
* Sends a request to the API to delete multiple inventory records at once.
*/
public LiveData<Resource<Void>> bulkDeleteInventory(BulkDeleteRequest request) {
MutableLiveData<Resource<Void>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
inventoryApi.bulkDeleteInventory(request).enqueue(new Callback<Void>() {
@Override
public void onResponse(Call<Void> call, Response<Void> response) {
if (response.isSuccessful()) {
data.setValue(Resource.success(null));
} else {
data.setValue(Resource.error("Error: " + response.message(), null));
}
}
@Override
public void onFailure(Call<Void> call, Throwable t) {
data.setValue(Resource.error(t.getMessage(), null));
}
});
inventoryApi.bulkDeleteInventory(request).enqueue(RetrofitUtils.createSilentCallback(TAG,
result -> data.setValue(Resource.success(null))));
return data;
}

View File

@@ -1,22 +1,22 @@
package com.example.petstoremobile.repositories;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import com.example.petstoremobile.api.PetApi;
import com.example.petstoremobile.dtos.PageResponse;
import com.example.petstoremobile.dtos.PetDTO;
import com.example.petstoremobile.utils.Resource;
import com.example.petstoremobile.utils.RetrofitUtils;
import javax.inject.Inject;
import javax.inject.Singleton;
import okhttp3.MultipartBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
@Singleton
public class PetRepository {
private static final String TAG = "PetRepository";
private final PetApi petApi;
@Inject
@@ -31,21 +31,8 @@ public class PetRepository {
MutableLiveData<Resource<PageResponse<PetDTO>>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
petApi.getAllPets(page, size).enqueue(new Callback<PageResponse<PetDTO>>() {
@Override
public void onResponse(Call<PageResponse<PetDTO>> call, Response<PageResponse<PetDTO>> response) {
if (response.isSuccessful() && response.body() != null) {
data.setValue(Resource.success(response.body()));
} else {
data.setValue(Resource.error("Error: " + response.message(), null));
}
}
@Override
public void onFailure(Call<PageResponse<PetDTO>> call, Throwable t) {
data.setValue(Resource.error(t.getMessage(), null));
}
});
petApi.getAllPets(page, size).enqueue(RetrofitUtils.createSilentCallback(TAG,
result -> data.setValue(Resource.success(result))));
return data;
}
@@ -57,21 +44,8 @@ public class PetRepository {
MutableLiveData<Resource<PetDTO>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
petApi.getPetById(id).enqueue(new Callback<PetDTO>() {
@Override
public void onResponse(Call<PetDTO> call, Response<PetDTO> response) {
if (response.isSuccessful() && response.body() != null) {
data.setValue(Resource.success(response.body()));
} else {
data.setValue(Resource.error("Error: " + response.message(), null));
}
}
@Override
public void onFailure(Call<PetDTO> call, Throwable t) {
data.setValue(Resource.error(t.getMessage(), null));
}
});
petApi.getPetById(id).enqueue(RetrofitUtils.createSilentCallback(TAG,
result -> data.setValue(Resource.success(result))));
return data;
}
@@ -83,21 +57,8 @@ public class PetRepository {
MutableLiveData<Resource<PetDTO>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
petApi.createPet(pet).enqueue(new Callback<PetDTO>() {
@Override
public void onResponse(Call<PetDTO> call, Response<PetDTO> response) {
if (response.isSuccessful() && response.body() != null) {
data.setValue(Resource.success(response.body()));
} else {
data.setValue(Resource.error("Error: " + response.message(), null));
}
}
@Override
public void onFailure(Call<PetDTO> call, Throwable t) {
data.setValue(Resource.error(t.getMessage(), null));
}
});
petApi.createPet(pet).enqueue(RetrofitUtils.createSilentCallback(TAG,
result -> data.setValue(Resource.success(result))));
return data;
}
@@ -109,21 +70,8 @@ public class PetRepository {
MutableLiveData<Resource<PetDTO>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
petApi.updatePet(id, pet).enqueue(new Callback<PetDTO>() {
@Override
public void onResponse(Call<PetDTO> call, Response<PetDTO> response) {
if (response.isSuccessful() && response.body() != null) {
data.setValue(Resource.success(response.body()));
} else {
data.setValue(Resource.error("Error: " + response.message(), null));
}
}
@Override
public void onFailure(Call<PetDTO> call, Throwable t) {
data.setValue(Resource.error(t.getMessage(), null));
}
});
petApi.updatePet(id, pet).enqueue(RetrofitUtils.createSilentCallback(TAG,
result -> data.setValue(Resource.success(result))));
return data;
}
@@ -135,21 +83,8 @@ public class PetRepository {
MutableLiveData<Resource<Void>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
petApi.deletePet(id).enqueue(new Callback<Void>() {
@Override
public void onResponse(Call<Void> call, Response<Void> response) {
if (response.isSuccessful()) {
data.setValue(Resource.success(null));
} else {
data.setValue(Resource.error("Error: " + response.message(), null));
}
}
@Override
public void onFailure(Call<Void> call, Throwable t) {
data.setValue(Resource.error(t.getMessage(), null));
}
});
petApi.deletePet(id).enqueue(RetrofitUtils.createSilentCallback(TAG,
result -> data.setValue(Resource.success(null))));
return data;
}
@@ -161,21 +96,8 @@ public class PetRepository {
MutableLiveData<Resource<Void>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
petApi.uploadPetImage(id, image).enqueue(new Callback<Void>() {
@Override
public void onResponse(Call<Void> call, Response<Void> response) {
if (response.isSuccessful()) {
data.setValue(Resource.success(null));
} else {
data.setValue(Resource.error("Error: " + response.message(), null));
}
}
@Override
public void onFailure(Call<Void> call, Throwable t) {
data.setValue(Resource.error(t.getMessage(), null));
}
});
petApi.uploadPetImage(id, image).enqueue(RetrofitUtils.createSilentCallback(TAG,
result -> data.setValue(Resource.success(null))));
return data;
}
@@ -187,21 +109,8 @@ public class PetRepository {
MutableLiveData<Resource<Void>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
petApi.deletePetImage(id).enqueue(new Callback<Void>() {
@Override
public void onResponse(Call<Void> call, Response<Void> response) {
if (response.isSuccessful()) {
data.setValue(Resource.success(null));
} else {
data.setValue(Resource.error("Error: " + response.message(), null));
}
}
@Override
public void onFailure(Call<Void> call, Throwable t) {
data.setValue(Resource.error(t.getMessage(), null));
}
});
petApi.deletePetImage(id).enqueue(RetrofitUtils.createSilentCallback(TAG,
result -> data.setValue(Resource.success(null))));
return data;
}

View File

@@ -7,17 +7,16 @@ import com.example.petstoremobile.api.ProductApi;
import com.example.petstoremobile.dtos.PageResponse;
import com.example.petstoremobile.dtos.ProductDTO;
import com.example.petstoremobile.utils.Resource;
import com.example.petstoremobile.utils.RetrofitUtils;
import javax.inject.Inject;
import javax.inject.Singleton;
import okhttp3.MultipartBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
@Singleton
public class ProductRepository {
private static final String TAG = "ProductRepository";
private final ProductApi productApi;
@Inject
@@ -32,21 +31,8 @@ public class ProductRepository {
MutableLiveData<Resource<PageResponse<ProductDTO>>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
productApi.getAllProducts(query, page, size).enqueue(new Callback<PageResponse<ProductDTO>>() {
@Override
public void onResponse(Call<PageResponse<ProductDTO>> call, Response<PageResponse<ProductDTO>> response) {
if (response.isSuccessful() && response.body() != null) {
data.setValue(Resource.success(response.body()));
} else {
data.setValue(Resource.error("Error: " + response.message(), null));
}
}
@Override
public void onFailure(Call<PageResponse<ProductDTO>> call, Throwable t) {
data.setValue(Resource.error(t.getMessage(), null));
}
});
productApi.getAllProducts(query, page, size).enqueue(RetrofitUtils.createSilentCallback(TAG,
result -> data.setValue(Resource.success(result))));
return data;
}
@@ -58,21 +44,8 @@ public class ProductRepository {
MutableLiveData<Resource<ProductDTO>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
productApi.getProductById(id).enqueue(new Callback<ProductDTO>() {
@Override
public void onResponse(Call<ProductDTO> call, Response<ProductDTO> response) {
if (response.isSuccessful() && response.body() != null) {
data.setValue(Resource.success(response.body()));
} else {
data.setValue(Resource.error("Error: " + response.message(), null));
}
}
@Override
public void onFailure(Call<ProductDTO> call, Throwable t) {
data.setValue(Resource.error(t.getMessage(), null));
}
});
productApi.getProductById(id).enqueue(RetrofitUtils.createSilentCallback(TAG,
result -> data.setValue(Resource.success(result))));
return data;
}
@@ -84,21 +57,8 @@ public class ProductRepository {
MutableLiveData<Resource<ProductDTO>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
productApi.createProduct(product).enqueue(new Callback<ProductDTO>() {
@Override
public void onResponse(Call<ProductDTO> call, Response<ProductDTO> response) {
if (response.isSuccessful() && response.body() != null) {
data.setValue(Resource.success(response.body()));
} else {
data.setValue(Resource.error("Error: " + response.message(), null));
}
}
@Override
public void onFailure(Call<ProductDTO> call, Throwable t) {
data.setValue(Resource.error(t.getMessage(), null));
}
});
productApi.createProduct(product).enqueue(RetrofitUtils.createSilentCallback(TAG,
result -> data.setValue(Resource.success(result))));
return data;
}
@@ -110,21 +70,8 @@ public class ProductRepository {
MutableLiveData<Resource<ProductDTO>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
productApi.updateProduct(id, product).enqueue(new Callback<ProductDTO>() {
@Override
public void onResponse(Call<ProductDTO> call, Response<ProductDTO> response) {
if (response.isSuccessful() && response.body() != null) {
data.setValue(Resource.success(response.body()));
} else {
data.setValue(Resource.error("Error: " + response.message(), null));
}
}
@Override
public void onFailure(Call<ProductDTO> call, Throwable t) {
data.setValue(Resource.error(t.getMessage(), null));
}
});
productApi.updateProduct(id, product).enqueue(RetrofitUtils.createSilentCallback(TAG,
result -> data.setValue(Resource.success(result))));
return data;
}
@@ -136,21 +83,8 @@ public class ProductRepository {
MutableLiveData<Resource<Void>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
productApi.deleteProduct(id).enqueue(new Callback<Void>() {
@Override
public void onResponse(Call<Void> call, Response<Void> response) {
if (response.isSuccessful()) {
data.setValue(Resource.success(null));
} else {
data.setValue(Resource.error("Error: " + response.message(), null));
}
}
@Override
public void onFailure(Call<Void> call, Throwable t) {
data.setValue(Resource.error(t.getMessage(), null));
}
});
productApi.deleteProduct(id).enqueue(RetrofitUtils.createSilentCallback(TAG,
result -> data.setValue(Resource.success(null))));
return data;
}
@@ -162,21 +96,8 @@ public class ProductRepository {
MutableLiveData<Resource<Void>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
productApi.uploadProductImage(id, image).enqueue(new Callback<Void>() {
@Override
public void onResponse(Call<Void> call, Response<Void> response) {
if (response.isSuccessful()) {
data.setValue(Resource.success(null));
} else {
data.setValue(Resource.error("Error: " + response.message(), null));
}
}
@Override
public void onFailure(Call<Void> call, Throwable t) {
data.setValue(Resource.error(t.getMessage(), null));
}
});
productApi.uploadProductImage(id, image).enqueue(RetrofitUtils.createSilentCallback(TAG,
result -> data.setValue(Resource.success(null))));
return data;
}
@@ -188,21 +109,8 @@ public class ProductRepository {
MutableLiveData<Resource<Void>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
productApi.deleteProductImage(id).enqueue(new Callback<Void>() {
@Override
public void onResponse(Call<Void> call, Response<Void> response) {
if (response.isSuccessful()) {
data.setValue(Resource.success(null));
} else {
data.setValue(Resource.error("Error: " + response.message(), null));
}
}
@Override
public void onFailure(Call<Void> call, Throwable t) {
data.setValue(Resource.error(t.getMessage(), null));
}
});
productApi.deleteProductImage(id).enqueue(RetrofitUtils.createSilentCallback(TAG,
result -> data.setValue(Resource.success(null))));
return data;
}

View File

@@ -7,16 +7,14 @@ import com.example.petstoremobile.api.ProductSupplierApi;
import com.example.petstoremobile.dtos.PageResponse;
import com.example.petstoremobile.dtos.ProductSupplierDTO;
import com.example.petstoremobile.utils.Resource;
import com.example.petstoremobile.utils.RetrofitUtils;
import javax.inject.Inject;
import javax.inject.Singleton;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
@Singleton
public class ProductSupplierRepository {
private static final String TAG = "ProductSupplierRepository";
private final ProductSupplierApi api;
@Inject
@@ -31,21 +29,8 @@ public class ProductSupplierRepository {
MutableLiveData<Resource<PageResponse<ProductSupplierDTO>>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
api.getAllProductSuppliers(page, size).enqueue(new Callback<PageResponse<ProductSupplierDTO>>() {
@Override
public void onResponse(Call<PageResponse<ProductSupplierDTO>> call, Response<PageResponse<ProductSupplierDTO>> response) {
if (response.isSuccessful() && response.body() != null) {
data.setValue(Resource.success(response.body()));
} else {
data.setValue(Resource.error("Error: " + response.message(), null));
}
}
@Override
public void onFailure(Call<PageResponse<ProductSupplierDTO>> call, Throwable t) {
data.setValue(Resource.error(t.getMessage(), null));
}
});
api.getAllProductSuppliers(page, size).enqueue(RetrofitUtils.createSilentCallback(TAG,
result -> data.setValue(Resource.success(result))));
return data;
}
@@ -57,21 +42,8 @@ public class ProductSupplierRepository {
MutableLiveData<Resource<ProductSupplierDTO>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
api.createProductSupplier(dto).enqueue(new Callback<ProductSupplierDTO>() {
@Override
public void onResponse(Call<ProductSupplierDTO> call, Response<ProductSupplierDTO> response) {
if (response.isSuccessful() && response.body() != null) {
data.setValue(Resource.success(response.body()));
} else {
data.setValue(Resource.error("Error: " + response.message(), null));
}
}
@Override
public void onFailure(Call<ProductSupplierDTO> call, Throwable t) {
data.setValue(Resource.error(t.getMessage(), null));
}
});
api.createProductSupplier(dto).enqueue(RetrofitUtils.createSilentCallback(TAG,
result -> data.setValue(Resource.success(result))));
return data;
}
@@ -83,21 +55,8 @@ public class ProductSupplierRepository {
MutableLiveData<Resource<ProductSupplierDTO>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
api.updateProductSupplier(productId, supplierId, dto).enqueue(new Callback<ProductSupplierDTO>() {
@Override
public void onResponse(Call<ProductSupplierDTO> call, Response<ProductSupplierDTO> response) {
if (response.isSuccessful() && response.body() != null) {
data.setValue(Resource.success(response.body()));
} else {
data.setValue(Resource.error("Error: " + response.message(), null));
}
}
@Override
public void onFailure(Call<ProductSupplierDTO> call, Throwable t) {
data.setValue(Resource.error(t.getMessage(), null));
}
});
api.updateProductSupplier(productId, supplierId, dto).enqueue(RetrofitUtils.createSilentCallback(TAG,
result -> data.setValue(Resource.success(result))));
return data;
}
@@ -109,21 +68,8 @@ public class ProductSupplierRepository {
MutableLiveData<Resource<Void>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
api.deleteProductSupplier(productId, supplierId).enqueue(new Callback<Void>() {
@Override
public void onResponse(Call<Void> call, Response<Void> response) {
if (response.isSuccessful()) {
data.setValue(Resource.success(null));
} else {
data.setValue(Resource.error("Error: " + response.message(), null));
}
}
@Override
public void onFailure(Call<Void> call, Throwable t) {
data.setValue(Resource.error(t.getMessage(), null));
}
});
api.deleteProductSupplier(productId, supplierId).enqueue(RetrofitUtils.createSilentCallback(TAG,
result -> data.setValue(Resource.success(null))));
return data;
}

View File

@@ -7,6 +7,7 @@ import com.example.petstoremobile.api.PurchaseOrderApi;
import com.example.petstoremobile.dtos.PageResponse;
import com.example.petstoremobile.dtos.PurchaseOrderDTO;
import com.example.petstoremobile.utils.Resource;
import com.example.petstoremobile.utils.RetrofitUtils;
import javax.inject.Inject;
import javax.inject.Singleton;
@@ -17,6 +18,7 @@ import retrofit2.Response;
@Singleton
public class PurchaseOrderRepository {
private static final String TAG = "PurchaseOrderRepo";
private final PurchaseOrderApi api;
@Inject
@@ -31,21 +33,9 @@ public class PurchaseOrderRepository {
MutableLiveData<Resource<PageResponse<PurchaseOrderDTO>>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
api.getAllPurchaseOrders(page, size).enqueue(new Callback<PageResponse<PurchaseOrderDTO>>() {
@Override
public void onResponse(Call<PageResponse<PurchaseOrderDTO>> call, Response<PageResponse<PurchaseOrderDTO>> response) {
if (response.isSuccessful() && response.body() != null) {
data.setValue(Resource.success(response.body()));
} else {
data.setValue(Resource.error("Error: " + response.message(), null));
}
}
@Override
public void onFailure(Call<PageResponse<PurchaseOrderDTO>> call, Throwable t) {
data.setValue(Resource.error(t.getMessage(), null));
}
});
api.getAllPurchaseOrders(page, size).enqueue(RetrofitUtils.createSilentCallback(TAG, result -> {
data.setValue(Resource.success(result));
}));
return data;
}
@@ -57,21 +47,9 @@ public class PurchaseOrderRepository {
MutableLiveData<Resource<PurchaseOrderDTO>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
api.getPurchaseOrderById(id).enqueue(new Callback<PurchaseOrderDTO>() {
@Override
public void onResponse(Call<PurchaseOrderDTO> call, Response<PurchaseOrderDTO> response) {
if (response.isSuccessful() && response.body() != null) {
data.setValue(Resource.success(response.body()));
} else {
data.setValue(Resource.error("Error: " + response.message(), null));
}
}
@Override
public void onFailure(Call<PurchaseOrderDTO> call, Throwable t) {
data.setValue(Resource.error(t.getMessage(), null));
}
});
api.getPurchaseOrderById(id).enqueue(RetrofitUtils.createSilentCallback(TAG, result -> {
data.setValue(Resource.success(result));
}));
return data;
}

View File

@@ -7,16 +7,14 @@ import com.example.petstoremobile.api.ServiceApi;
import com.example.petstoremobile.dtos.PageResponse;
import com.example.petstoremobile.dtos.ServiceDTO;
import com.example.petstoremobile.utils.Resource;
import com.example.petstoremobile.utils.RetrofitUtils;
import javax.inject.Inject;
import javax.inject.Singleton;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
@Singleton
public class ServiceRepository {
private static final String TAG = "ServiceRepository";
private final ServiceApi serviceApi;
@Inject
@@ -31,21 +29,8 @@ public class ServiceRepository {
MutableLiveData<Resource<PageResponse<ServiceDTO>>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
serviceApi.getAllServices(page, size).enqueue(new Callback<PageResponse<ServiceDTO>>() {
@Override
public void onResponse(Call<PageResponse<ServiceDTO>> call, Response<PageResponse<ServiceDTO>> response) {
if (response.isSuccessful() && response.body() != null) {
data.setValue(Resource.success(response.body()));
} else {
data.setValue(Resource.error("Error: " + response.message(), null));
}
}
@Override
public void onFailure(Call<PageResponse<ServiceDTO>> call, Throwable t) {
data.setValue(Resource.error(t.getMessage(), null));
}
});
serviceApi.getAllServices(page, size).enqueue(RetrofitUtils.createSilentCallback(TAG,
result -> data.setValue(Resource.success(result))));
return data;
}
@@ -57,21 +42,8 @@ public class ServiceRepository {
MutableLiveData<Resource<ServiceDTO>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
serviceApi.getServiceById(id).enqueue(new Callback<ServiceDTO>() {
@Override
public void onResponse(Call<ServiceDTO> call, Response<ServiceDTO> response) {
if (response.isSuccessful() && response.body() != null) {
data.setValue(Resource.success(response.body()));
} else {
data.setValue(Resource.error("Error: " + response.message(), null));
}
}
@Override
public void onFailure(Call<ServiceDTO> call, Throwable t) {
data.setValue(Resource.error(t.getMessage(), null));
}
});
serviceApi.getServiceById(id).enqueue(RetrofitUtils.createSilentCallback(TAG,
result -> data.setValue(Resource.success(result))));
return data;
}
@@ -83,21 +55,8 @@ public class ServiceRepository {
MutableLiveData<Resource<ServiceDTO>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
serviceApi.createService(service).enqueue(new Callback<ServiceDTO>() {
@Override
public void onResponse(Call<ServiceDTO> call, Response<ServiceDTO> response) {
if (response.isSuccessful() && response.body() != null) {
data.setValue(Resource.success(response.body()));
} else {
data.setValue(Resource.error("Error: " + response.message(), null));
}
}
@Override
public void onFailure(Call<ServiceDTO> call, Throwable t) {
data.setValue(Resource.error(t.getMessage(), null));
}
});
serviceApi.createService(service).enqueue(RetrofitUtils.createSilentCallback(TAG,
result -> data.setValue(Resource.success(result))));
return data;
}
@@ -109,21 +68,8 @@ public class ServiceRepository {
MutableLiveData<Resource<ServiceDTO>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
serviceApi.updateService(id, service).enqueue(new Callback<ServiceDTO>() {
@Override
public void onResponse(Call<ServiceDTO> call, Response<ServiceDTO> response) {
if (response.isSuccessful() && response.body() != null) {
data.setValue(Resource.success(response.body()));
} else {
data.setValue(Resource.error("Error: " + response.message(), null));
}
}
@Override
public void onFailure(Call<ServiceDTO> call, Throwable t) {
data.setValue(Resource.error(t.getMessage(), null));
}
});
serviceApi.updateService(id, service).enqueue(RetrofitUtils.createSilentCallback(TAG,
result -> data.setValue(Resource.success(result))));
return data;
}
@@ -135,21 +81,8 @@ public class ServiceRepository {
MutableLiveData<Resource<Void>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
serviceApi.deleteService(id).enqueue(new Callback<Void>() {
@Override
public void onResponse(Call<Void> call, Response<Void> response) {
if (response.isSuccessful()) {
data.setValue(Resource.success(null));
} else {
data.setValue(Resource.error("Error: " + response.message(), null));
}
}
@Override
public void onFailure(Call<Void> call, Throwable t) {
data.setValue(Resource.error(t.getMessage(), null));
}
});
serviceApi.deleteService(id).enqueue(RetrofitUtils.createSilentCallback(TAG,
result -> data.setValue(Resource.success(null))));
return data;
}

View File

@@ -0,0 +1,37 @@
package com.example.petstoremobile.repositories;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import com.example.petstoremobile.api.StoreApi;
import com.example.petstoremobile.dtos.PageResponse;
import com.example.petstoremobile.dtos.StoreDTO;
import com.example.petstoremobile.utils.Resource;
import com.example.petstoremobile.utils.RetrofitUtils;
import javax.inject.Inject;
import javax.inject.Singleton;
@Singleton
public class StoreRepository {
private static final String TAG = "StoreRepository";
private final StoreApi storeApi;
@Inject
public StoreRepository(StoreApi storeApi) {
this.storeApi = storeApi;
}
/**
* Retrieves a paginated list of all stores from the API.
*/
public LiveData<Resource<PageResponse<StoreDTO>>> getAllStores(int page, int size) {
MutableLiveData<Resource<PageResponse<StoreDTO>>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
storeApi.getAllStores(page, size).enqueue(RetrofitUtils.createSilentCallback(TAG,
result -> data.setValue(Resource.success(result))));
return data;
}
}

View File

@@ -7,16 +7,14 @@ import com.example.petstoremobile.api.SupplierApi;
import com.example.petstoremobile.dtos.PageResponse;
import com.example.petstoremobile.dtos.SupplierDTO;
import com.example.petstoremobile.utils.Resource;
import com.example.petstoremobile.utils.RetrofitUtils;
import javax.inject.Inject;
import javax.inject.Singleton;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
@Singleton
public class SupplierRepository {
private static final String TAG = "SupplierRepository";
private final SupplierApi supplierApi;
@Inject
@@ -31,21 +29,8 @@ public class SupplierRepository {
MutableLiveData<Resource<PageResponse<SupplierDTO>>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
supplierApi.getAllSuppliers(page, size).enqueue(new Callback<PageResponse<SupplierDTO>>() {
@Override
public void onResponse(Call<PageResponse<SupplierDTO>> call, Response<PageResponse<SupplierDTO>> response) {
if (response.isSuccessful() && response.body() != null) {
data.setValue(Resource.success(response.body()));
} else {
data.setValue(Resource.error("Error: " + response.message(), null));
}
}
@Override
public void onFailure(Call<PageResponse<SupplierDTO>> call, Throwable t) {
data.setValue(Resource.error(t.getMessage(), null));
}
});
supplierApi.getAllSuppliers(page, size).enqueue(RetrofitUtils.createSilentCallback(TAG,
result -> data.setValue(Resource.success(result))));
return data;
}
@@ -57,21 +42,8 @@ public class SupplierRepository {
MutableLiveData<Resource<SupplierDTO>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
supplierApi.getSupplierById(id).enqueue(new Callback<SupplierDTO>() {
@Override
public void onResponse(Call<SupplierDTO> call, Response<SupplierDTO> response) {
if (response.isSuccessful() && response.body() != null) {
data.setValue(Resource.success(response.body()));
} else {
data.setValue(Resource.error("Error: " + response.message(), null));
}
}
@Override
public void onFailure(Call<SupplierDTO> call, Throwable t) {
data.setValue(Resource.error(t.getMessage(), null));
}
});
supplierApi.getSupplierById(id).enqueue(RetrofitUtils.createSilentCallback(TAG,
result -> data.setValue(Resource.success(result))));
return data;
}
@@ -83,21 +55,8 @@ public class SupplierRepository {
MutableLiveData<Resource<SupplierDTO>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
supplierApi.createSupplier(supplier).enqueue(new Callback<SupplierDTO>() {
@Override
public void onResponse(Call<SupplierDTO> call, Response<SupplierDTO> response) {
if (response.isSuccessful() && response.body() != null) {
data.setValue(Resource.success(response.body()));
} else {
data.setValue(Resource.error("Error: " + response.message(), null));
}
}
@Override
public void onFailure(Call<SupplierDTO> call, Throwable t) {
data.setValue(Resource.error(t.getMessage(), null));
}
});
supplierApi.createSupplier(supplier).enqueue(RetrofitUtils.createSilentCallback(TAG,
result -> data.setValue(Resource.success(result))));
return data;
}
@@ -106,26 +65,15 @@ public class SupplierRepository {
* Sends a request to the API to update an existing supplier record by ID.
*/
public LiveData<Resource<SupplierDTO>> updateSupplier(Long id, SupplierDTO supplier) {
MutableLiveData<Resource<SupplierDTO>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
MutableLiveData<Resource<Resource<SupplierDTO>>> data = new MutableLiveData<>();
// Note: The original return type was LiveData<Resource<SupplierDTO>>, fixing here
MutableLiveData<Resource<SupplierDTO>> resultData = new MutableLiveData<>();
resultData.setValue(Resource.loading(null));
supplierApi.updateSupplier(id, supplier).enqueue(new Callback<SupplierDTO>() {
@Override
public void onResponse(Call<SupplierDTO> call, Response<SupplierDTO> response) {
if (response.isSuccessful() && response.body() != null) {
data.setValue(Resource.success(response.body()));
} else {
data.setValue(Resource.error("Error: " + response.message(), null));
}
}
supplierApi.updateSupplier(id, supplier).enqueue(RetrofitUtils.createSilentCallback(TAG,
result -> resultData.setValue(Resource.success(result))));
@Override
public void onFailure(Call<SupplierDTO> call, Throwable t) {
data.setValue(Resource.error(t.getMessage(), null));
}
});
return data;
return resultData;
}
/**
@@ -135,21 +83,8 @@ public class SupplierRepository {
MutableLiveData<Resource<Void>> data = new MutableLiveData<>();
data.setValue(Resource.loading(null));
supplierApi.deleteSupplier(id).enqueue(new Callback<Void>() {
@Override
public void onResponse(Call<Void> call, Response<Void> response) {
if (response.isSuccessful()) {
data.setValue(Resource.success(null));
} else {
data.setValue(Resource.error("Error: " + response.message(), null));
}
}
@Override
public void onFailure(Call<Void> call, Throwable t) {
data.setValue(Resource.error(t.getMessage(), null));
}
});
supplierApi.deleteSupplier(id).enqueue(RetrofitUtils.createSilentCallback(TAG,
result -> data.setValue(Resource.success(null))));
return data;
}

View File

@@ -14,6 +14,7 @@ import com.example.petstoremobile.dtos.CustomerDTO;
import com.example.petstoremobile.dtos.MessageDTO;
import com.example.petstoremobile.dtos.PageResponse;
import com.example.petstoremobile.utils.NotificationHelper;
import com.example.petstoremobile.utils.RetrofitUtils;
import com.example.petstoremobile.websocket.StompChatManager;
import java.util.HashMap;
import java.util.HashSet;
@@ -63,54 +64,31 @@ public class ChatNotificationService extends Service {
currentUserId = tokenManager.getUserId();
if (token != null && stompChatManager == null) {
customerApi.getAllCustomers(0, 1000).enqueue(new Callback<PageResponse<CustomerDTO>>() {
@Override
public void onResponse(@NonNull Call<PageResponse<CustomerDTO>> call, @NonNull Response<PageResponse<CustomerDTO>> response) {
if (response.isSuccessful() && response.body() != null) {
for (CustomerDTO customer : response.body().getContent()) {
customerIdToName.put(customer.getCustomerId(), customer.getFullName());
}
}
loadConversationsAndStartStomp(token, role);
customerApi.getAllCustomers(0, 1000).enqueue(RetrofitUtils.createSilentCallback(TAG, result -> {
for (CustomerDTO customer : result.getContent()) {
customerIdToName.put(customer.getCustomerId(), customer.getFullName());
}
@Override
public void onFailure(@NonNull Call<PageResponse<CustomerDTO>> call, @NonNull Throwable t) {
Log.e(TAG, "Failed to load customers", t);
loadConversationsAndStartStomp(token, role);
}
});
loadConversationsAndStartStomp(token, role);
}));
}
}
private void loadConversationsAndStartStomp(String token, String role) {
// Fetch existing conversations
chatApi.getAllConversations().enqueue(new Callback<List<ConversationDTO>>() {
@Override
public void onResponse(@NonNull Call<List<ConversationDTO>> call, @NonNull Response<List<ConversationDTO>> response) {
if (response.isSuccessful() && response.body() != null) {
for (ConversationDTO conversation : response.body()) {
if (conversation.getId() != null) {
knownConversationIds.add(conversation.getId());
conversationToCustomerId.put(conversation.getId(), conversation.getCustomerId());
// subscribe to existing conversations to get message notifications
if (stompChatManager != null) {
stompChatManager.subscribeToConversation(conversation.getId());
}
}
chatApi.getAllConversations().enqueue(RetrofitUtils.createSilentCallback(TAG, result -> {
for (ConversationDTO conversation : result) {
if (conversation.getId() != null) {
knownConversationIds.add(conversation.getId());
conversationToCustomerId.put(conversation.getId(), conversation.getCustomerId());
// subscribe to existing conversations to get message notifications
if (stompChatManager != null) {
stompChatManager.subscribeToConversation(conversation.getId());
}
Log.d(TAG, "Loaded " + knownConversationIds.size() + " existing conversations");
}
startStomp(token, role);
}
@Override
public void onFailure(@NonNull Call<List<ConversationDTO>> call, @NonNull Throwable t) {
Log.e(TAG, "Failed to load existing conversations", t);
//tries to connect if loading fails
startStomp(token, role);
}
});
Log.d(TAG, "Loaded " + knownConversationIds.size() + " existing conversations");
startStomp(token, role);
}));
}
private void startStomp(String token, String role) {
@@ -199,19 +177,9 @@ public class ChatNotificationService extends Service {
// Helper function to fetch customer name for a conversation
private void fetchCustomerName(Long customerId) {
customerApi.getCustomerById(customerId).enqueue(new Callback<CustomerDTO>() {
@Override
public void onResponse(@NonNull Call<CustomerDTO> call, @NonNull Response<CustomerDTO> response) {
if (response.isSuccessful() && response.body() != null) {
customerIdToName.put(customerId, response.body().getFullName());
}
}
@Override
public void onFailure(@NonNull Call<CustomerDTO> call, @NonNull Throwable t) {
Log.e(TAG, "Failed to fetch customer name", t);
}
});
customerApi.getCustomerById(customerId).enqueue(RetrofitUtils.createSilentCallback(TAG, result -> {
customerIdToName.put(customerId, result.getFullName());
}));
}
//When the service is destroyed, disconnect from the websocket
@@ -228,4 +196,4 @@ public class ChatNotificationService extends Service {
public IBinder onBind(Intent intent) {
return null;
}
}
}

View File

@@ -0,0 +1,74 @@
package com.example.petstoremobile.utils;
import android.content.Context;
import android.util.Log;
import android.widget.Toast;
import androidx.annotation.NonNull;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
/**
* Utility class for common Retrofit operations and standardized callbacks.
*/
public class RetrofitUtils {
/**
* Interface for handling successful API responses.
* @param <T> The type of the response body.
*/
public interface SuccessCallback<T> {
void onSuccess(T result);
}
/**
* Creates a callback for Retrofit calls that handles errors and logging.
*/
public static <T> Callback<T> createCallback(Context context, String tag, String successMsg, SuccessCallback<T> successCallback) {
return new Callback<T>() {
@Override
public void onResponse(@NonNull Call<T> call, @NonNull Response<T> response) {
if (response.isSuccessful()) {
if (successMsg != null) {
Toast.makeText(context, successMsg, Toast.LENGTH_SHORT).show();
}
if (successCallback != null) {
successCallback.onSuccess(response.body());
}
} else {
ErrorUtils.showErrorMessage(context, response, "Operation failed");
Log.e(tag, "API Error: " + response.code());
}
}
@Override
public void onFailure(@NonNull Call<T> call, @NonNull Throwable t) {
Log.e(tag, "Network Error: " + t.getMessage());
Toast.makeText(context, "Network error. Please try again.", Toast.LENGTH_SHORT).show();
}
};
}
/**
* Creates a callback that doesn't show toasts
*/
public static <T> Callback<T> createSilentCallback(String tag, SuccessCallback<T> successCallback) {
return new Callback<T>() {
@Override
public void onResponse(@NonNull Call<T> call, @NonNull Response<T> response) {
if (response.isSuccessful() && successCallback != null) {
successCallback.onSuccess(response.body());
} else {
Log.e(tag, "API Error: " + response.code());
}
}
@Override
public void onFailure(@NonNull Call<T> call, @NonNull Throwable t) {
Log.e(tag, "Network Error: " + t.getMessage());
}
};
}
}

View File

@@ -0,0 +1,37 @@
package com.example.petstoremobile.viewmodels;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.ViewModel;
import com.example.petstoremobile.dtos.CustomerDTO;
import com.example.petstoremobile.dtos.PageResponse;
import com.example.petstoremobile.repositories.CustomerRepository;
import com.example.petstoremobile.utils.Resource;
import javax.inject.Inject;
import dagger.hilt.android.lifecycle.HiltViewModel;
@HiltViewModel
public class CustomerViewModel extends ViewModel {
private final CustomerRepository repository;
@Inject
public CustomerViewModel(CustomerRepository repository) {
this.repository = repository;
}
/**
* Fetches a paginated list of all customers.
*/
public LiveData<Resource<PageResponse<CustomerDTO>>> getAllCustomers(int page, int size) {
return repository.getAllCustomers(page, size);
}
/**
* Retrieves a single customer by their ID.
*/
public LiveData<Resource<CustomerDTO>> getCustomerById(Long id) {
return repository.getCustomerById(id);
}
}

View File

@@ -0,0 +1,30 @@
package com.example.petstoremobile.viewmodels;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.ViewModel;
import com.example.petstoremobile.dtos.PageResponse;
import com.example.petstoremobile.dtos.StoreDTO;
import com.example.petstoremobile.repositories.StoreRepository;
import com.example.petstoremobile.utils.Resource;
import javax.inject.Inject;
import dagger.hilt.android.lifecycle.HiltViewModel;
@HiltViewModel
public class StoreViewModel extends ViewModel {
private final StoreRepository repository;
@Inject
public StoreViewModel(StoreRepository repository) {
this.repository = repository;
}
/**
* Fetches a paginated list of all stores.
*/
public LiveData<Resource<PageResponse<StoreDTO>>> getAllStores(int page, int size) {
return repository.getAllStores(page, size);
}
}