From 5ecf322f0c0785d19915f110ae4798529b804348 Mon Sep 17 00:00:00 2001 From: Alex <78383757+Lextical@users.noreply.github.com> Date: Fri, 10 Apr 2026 07:36:54 -0600 Subject: [PATCH] added close chat option to chat --- .../example/petstoremobile/api/ChatApi.java | 6 +- .../petstoremobile/dtos/CouponDTO.java | 2 +- .../dtos/UpdateConversationStatusRequest.java | 17 + .../fragments/ChatFragment.java | 26 ++ .../fragments/ListFragment.java | 12 +- .../repositories/ChatRepository.java | 8 + .../viewmodels/ChatListViewModel.java | 5 + .../app/src/main/res/layout/fragment_chat.xml | 13 +- .../app/src/main/res/layout/fragment_list.xml | 345 ++++++++++-------- 9 files changed, 267 insertions(+), 167 deletions(-) create mode 100644 android/app/src/main/java/com/example/petstoremobile/dtos/UpdateConversationStatusRequest.java diff --git a/android/app/src/main/java/com/example/petstoremobile/api/ChatApi.java b/android/app/src/main/java/com/example/petstoremobile/api/ChatApi.java index 63f5ac51..7a4ab393 100644 --- a/android/app/src/main/java/com/example/petstoremobile/api/ChatApi.java +++ b/android/app/src/main/java/com/example/petstoremobile/api/ChatApi.java @@ -2,13 +2,14 @@ package com.example.petstoremobile.api; import com.example.petstoremobile.dtos.ConversationDTO; import com.example.petstoremobile.dtos.MessageDTO; +import com.example.petstoremobile.dtos.UpdateConversationStatusRequest; import java.util.List; import retrofit2.Call; import retrofit2.http.Body; import retrofit2.http.GET; -import retrofit2.http.POST; +import retrofit2.http.PUT; import retrofit2.http.Path; //api calls to get conversations @@ -20,4 +21,7 @@ public interface ChatApi { @GET("api/v1/chat/conversations/{conversationId}") Call getConversationById(@Path("conversationId") Long conversationId); + @PUT("api/v1/chat/conversations/{conversationId}") + Call updateConversationStatus(@Path("conversationId") Long conversationId, @Body UpdateConversationStatusRequest request); + } \ No newline at end of file diff --git a/android/app/src/main/java/com/example/petstoremobile/dtos/CouponDTO.java b/android/app/src/main/java/com/example/petstoremobile/dtos/CouponDTO.java index 87b3eb7e..e2ecb2c4 100644 --- a/android/app/src/main/java/com/example/petstoremobile/dtos/CouponDTO.java +++ b/android/app/src/main/java/com/example/petstoremobile/dtos/CouponDTO.java @@ -5,7 +5,7 @@ import java.math.BigDecimal; public class CouponDTO { private Long couponId; private String couponCode; - private String discountType; // FIXED, PERCENT + private String discountType; private BigDecimal discountValue; private BigDecimal minOrderAmount; private Boolean active; diff --git a/android/app/src/main/java/com/example/petstoremobile/dtos/UpdateConversationStatusRequest.java b/android/app/src/main/java/com/example/petstoremobile/dtos/UpdateConversationStatusRequest.java new file mode 100644 index 00000000..4d7987e1 --- /dev/null +++ b/android/app/src/main/java/com/example/petstoremobile/dtos/UpdateConversationStatusRequest.java @@ -0,0 +1,17 @@ +package com.example.petstoremobile.dtos; + +public class UpdateConversationStatusRequest { + private String status; + + public UpdateConversationStatusRequest(String status) { + this.status = status; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } +} diff --git a/android/app/src/main/java/com/example/petstoremobile/fragments/ChatFragment.java b/android/app/src/main/java/com/example/petstoremobile/fragments/ChatFragment.java index 3c6a9d6c..5b59de80 100644 --- a/android/app/src/main/java/com/example/petstoremobile/fragments/ChatFragment.java +++ b/android/app/src/main/java/com/example/petstoremobile/fragments/ChatFragment.java @@ -127,6 +127,7 @@ public class ChatFragment extends Fragment implements ChatAdapter.OnChatClickLis binding.btnAttach.setOnClickListener(v -> selectAttachment()); binding.btnRemoveAttachment.setOnClickListener(v -> removeAttachment()); + binding.btnCloseChat.setOnClickListener(v -> closeChat()); setupDrawerToggles(); setupRecyclerViews(); @@ -356,6 +357,30 @@ public class ChatFragment extends Fragment implements ChatAdapter.OnChatClickLis viewModel.loadMessageHistory(activeConversationId); } + private void closeChat() { + if (activeConversationId == null) return; + + DialogUtils.showConfirmDialog(requireContext(), "Close Chat", + "Are you sure you want to close this chat? This will notify the customer.", () -> { + viewModel.sendMessage(activeConversationId, "The Chat has been closed").observe(getViewLifecycleOwner(), resource -> { + if (resource != null && resource.status == Resource.Status.SUCCESS) { + viewModel.addMessageLocally(resource.data); + + viewModel.closeConversation(activeConversationId).observe(getViewLifecycleOwner(), statusResource -> { + if (statusResource == null) return; + setLoading(statusResource.status == Resource.Status.LOADING); + if (statusResource.status == Resource.Status.SUCCESS) { + viewModel.loadConversations(); + setConversationActive(true, "CLOSED"); + } else if (statusResource.status == Resource.Status.ERROR) { + Toast.makeText(requireContext(), "Failed to close chat: " + statusResource.message, Toast.LENGTH_SHORT).show(); + } + }); + } + }); + }); + } + private void sendMessage() { if (activeConversationId == null) return; String text = binding.etMessage.getText().toString().trim(); @@ -489,6 +514,7 @@ public class ChatFragment extends Fragment implements ChatAdapter.OnChatClickLis private void setConversationActive(boolean active, String status) { boolean isClosed = "CLOSED".equalsIgnoreCase(status); UIUtils.setViewsEnabled(active && !isClosed, binding.btnSend, binding.etMessage, binding.btnAttach); + binding.btnCloseChat.setVisibility(active && !isClosed ? View.VISIBLE : View.GONE); if (!active) { activeConversationId = null; diff --git a/android/app/src/main/java/com/example/petstoremobile/fragments/ListFragment.java b/android/app/src/main/java/com/example/petstoremobile/fragments/ListFragment.java index 0daf21e9..e7180292 100644 --- a/android/app/src/main/java/com/example/petstoremobile/fragments/ListFragment.java +++ b/android/app/src/main/java/com/example/petstoremobile/fragments/ListFragment.java @@ -43,15 +43,13 @@ public class ListFragment extends Fragment { // Check user role and restrict access for STAFF String role = tokenManager.getRole(); if ("STAFF".equalsIgnoreCase(role)) { - binding.drawerSuppliers.setVisibility(View.GONE); - binding.drawerInventory.setVisibility(View.GONE); - } - - // Only show for ADMIN - if ("ADMIN".equalsIgnoreCase(role)) { + binding.sectionAdmin.setVisibility(View.GONE); + } else if ("ADMIN".equalsIgnoreCase(role)) { + binding.sectionAdmin.setVisibility(View.VISIBLE); binding.drawerStaff.setVisibility(View.VISIBLE); } else { - binding.drawerStaff.setVisibility(View.GONE); + // Default or other roles + binding.sectionAdmin.setVisibility(View.GONE); } //add Listeners to the drawer so user won't be able to interact with the innerContainer (the list fragments) diff --git a/android/app/src/main/java/com/example/petstoremobile/repositories/ChatRepository.java b/android/app/src/main/java/com/example/petstoremobile/repositories/ChatRepository.java index bdc250c4..ec8e32b6 100644 --- a/android/app/src/main/java/com/example/petstoremobile/repositories/ChatRepository.java +++ b/android/app/src/main/java/com/example/petstoremobile/repositories/ChatRepository.java @@ -10,6 +10,7 @@ import com.example.petstoremobile.dtos.CustomerDTO; import com.example.petstoremobile.dtos.MessageDTO; import com.example.petstoremobile.dtos.PageResponse; import com.example.petstoremobile.dtos.SendMessageRequest; +import com.example.petstoremobile.dtos.UpdateConversationStatusRequest; import com.example.petstoremobile.utils.Resource; import java.util.List; @@ -73,6 +74,13 @@ public class ChatRepository extends BaseRepository { return executeCall(messageApi.downloadAttachment(messageId)); } + /** + * Updates the status of a conversation (e.g., OPEN to CLOSED). + */ + public LiveData> updateConversationStatus(Long conversationId, UpdateConversationStatusRequest request) { + return executeCall(chatApi.updateConversationStatus(conversationId, request)); + } + /** * Fetches a paginated list of customers. */ diff --git a/android/app/src/main/java/com/example/petstoremobile/viewmodels/ChatListViewModel.java b/android/app/src/main/java/com/example/petstoremobile/viewmodels/ChatListViewModel.java index 0422561d..88123907 100644 --- a/android/app/src/main/java/com/example/petstoremobile/viewmodels/ChatListViewModel.java +++ b/android/app/src/main/java/com/example/petstoremobile/viewmodels/ChatListViewModel.java @@ -9,6 +9,7 @@ import com.example.petstoremobile.dtos.CustomerDTO; import com.example.petstoremobile.dtos.MessageDTO; import com.example.petstoremobile.dtos.PageResponse; import com.example.petstoremobile.dtos.SendMessageRequest; +import com.example.petstoremobile.dtos.UpdateConversationStatusRequest; import com.example.petstoremobile.models.Chat; import com.example.petstoremobile.models.Message; import com.example.petstoremobile.repositories.ChatRepository; @@ -126,6 +127,10 @@ public class ChatListViewModel extends ViewModel { return chatRepository.downloadAttachment(messageId); } + public LiveData> closeConversation(Long conversationId) { + return chatRepository.updateConversationStatus(conversationId, new UpdateConversationStatusRequest("CLOSED")); + } + public void addMessageLocally(MessageDTO dto) { List current = new ArrayList<>(messageList.getValue()); current.add(dtoToModel(dto)); diff --git a/android/app/src/main/res/layout/fragment_chat.xml b/android/app/src/main/res/layout/fragment_chat.xml index 8fe36d1a..67b62bf8 100644 --- a/android/app/src/main/res/layout/fragment_chat.xml +++ b/android/app/src/main/res/layout/fragment_chat.xml @@ -34,8 +34,9 @@ +