From 1908558912eb5a1c227c8ce70ab694b333a87c75 Mon Sep 17 00:00:00 2001 From: Harkamal Randhawa Date: Fri, 10 Apr 2026 08:44:20 -0600 Subject: [PATCH] Add close chat and closed status --- .../dto/chat/UpdateConversationRequest.java | 13 +++++ .../petshopdesktop/api/endpoints/ChatApi.java | 5 ++ .../controllers/ChatController.java | 50 ++++++++++++++++++- .../petshopdesktop/modelviews/chat-view.fxml | 20 ++++++-- 4 files changed, 82 insertions(+), 6 deletions(-) create mode 100644 desktop/src/main/java/org/example/petshopdesktop/api/dto/chat/UpdateConversationRequest.java diff --git a/desktop/src/main/java/org/example/petshopdesktop/api/dto/chat/UpdateConversationRequest.java b/desktop/src/main/java/org/example/petshopdesktop/api/dto/chat/UpdateConversationRequest.java new file mode 100644 index 00000000..3bacbca9 --- /dev/null +++ b/desktop/src/main/java/org/example/petshopdesktop/api/dto/chat/UpdateConversationRequest.java @@ -0,0 +1,13 @@ +package org.example.petshopdesktop.api.dto.chat; + +public class UpdateConversationRequest { + private String status; + + public UpdateConversationRequest(String status) { + this.status = status; + } + + public String getStatus() { + return status; + } +} diff --git a/desktop/src/main/java/org/example/petshopdesktop/api/endpoints/ChatApi.java b/desktop/src/main/java/org/example/petshopdesktop/api/endpoints/ChatApi.java index 3fcb7372..37d3e2a5 100644 --- a/desktop/src/main/java/org/example/petshopdesktop/api/endpoints/ChatApi.java +++ b/desktop/src/main/java/org/example/petshopdesktop/api/endpoints/ChatApi.java @@ -6,6 +6,7 @@ import org.example.petshopdesktop.api.dto.chat.ConversationRequest; import org.example.petshopdesktop.api.dto.chat.ConversationResponse; import org.example.petshopdesktop.api.dto.chat.MessageRequest; import org.example.petshopdesktop.api.dto.chat.MessageResponse; +import org.example.petshopdesktop.api.dto.chat.UpdateConversationRequest; import java.util.List; public class ChatApi { @@ -41,4 +42,8 @@ public class ChatApi { public MessageResponse sendMessage(Long conversationId, MessageRequest request) throws Exception { return apiClient.post("/api/v1/chat/conversations/" + conversationId + "/messages", request, MessageResponse.class); } + + public ConversationResponse updateConversation(Long id, UpdateConversationRequest request) throws Exception { + return apiClient.put("/api/v1/chat/conversations/" + id, request, ConversationResponse.class); + } } diff --git a/desktop/src/main/java/org/example/petshopdesktop/controllers/ChatController.java b/desktop/src/main/java/org/example/petshopdesktop/controllers/ChatController.java index 02d05a93..7b1ed333 100644 --- a/desktop/src/main/java/org/example/petshopdesktop/controllers/ChatController.java +++ b/desktop/src/main/java/org/example/petshopdesktop/controllers/ChatController.java @@ -23,6 +23,7 @@ import org.example.petshopdesktop.api.ChatRealtimeClient; import org.example.petshopdesktop.api.dto.chat.ConversationResponse; import org.example.petshopdesktop.api.dto.chat.MessageRequest; import org.example.petshopdesktop.api.dto.chat.MessageResponse; +import org.example.petshopdesktop.api.dto.chat.UpdateConversationRequest; import org.example.petshopdesktop.api.dto.common.DropdownOption; import org.example.petshopdesktop.api.endpoints.ChatApi; import org.example.petshopdesktop.api.endpoints.DropdownApi; @@ -61,6 +62,9 @@ public class ChatController { @FXML private Button btnAttachment; + @FXML + private Button btnClose; + @FXML private Label lblConversationTitle; @@ -116,6 +120,7 @@ public class ChatController { lblConversationTitle.setText(getConversationTitle(newValue)); loadMessages(newValue.getId()); realtimeClient.subscribeToConversation(newValue.getId()); + updateChatState(newValue); } }); @@ -137,6 +142,7 @@ public class ChatController { loadCustomers(); loadConversations(); + updateChatState(null); } @FXML @@ -208,6 +214,42 @@ public class ChatController { lblChatStatus.setText("Attachment selected"); } + @FXML + void btnCloseClicked() { + if (selectedConversation == null || "CLOSED".equals(selectedConversation.getStatus())) return; + Long convId = selectedConversation.getId(); + btnClose.setDisable(true); + lblChatStatus.setText("Closing..."); + new Thread(() -> { + try { + ConversationResponse updated = ChatApi.getInstance().updateConversation(convId, new UpdateConversationRequest("CLOSED")); + Platform.runLater(() -> { + upsertConversation(updated); + updateChatState(updated); + lblChatStatus.setText("Conversation closed"); + }); + } catch (Exception e) { + Platform.runLater(() -> { + btnClose.setDisable(false); + lblChatStatus.setText("Close failed"); + ActivityLogger.getInstance().logException( + "ChatController.closeConversation", + e, + "Closing conversation " + convId); + }); + } + }).start(); + } + + private void updateChatState(ConversationResponse conv) { + boolean closed = conv == null || "CLOSED".equals(conv.getStatus()); + txtMessage.setDisable(closed); + btnSend.setDisable(closed); + btnAttachment.setDisable(closed); + btnClose.setVisible(!closed); + btnClose.setManaged(!closed); + } + private void clearLocalAttachment() { selectedAttachmentFile = null; btnAttachment.setText("📎"); @@ -323,6 +365,9 @@ public class ChatController { conversations.sort(Comparator.comparing(ChatController::conversationSortTime, Comparator.nullsLast(Comparator.reverseOrder()))); restoreSelection(); lvConversations.refresh(); + if (selectedConversation != null && selectedConversation.getId().equals(conversation.getId())) { + updateChatState(conversation); + } } private void upsertConversationForMessage(MessageResponse message) { @@ -419,6 +464,10 @@ public class ChatController { } private String buildConversationMeta(ConversationResponse conversation) { + String updated = conversation.getUpdatedAt() == null ? "" : TIME_FORMATTER.format(conversation.getUpdatedAt()); + if ("CLOSED".equals(conversation.getStatus())) { + return "Closed" + (updated.isBlank() ? "" : " · " + updated); + } String assignee; if (conversation.getStaffId() != null) { assignee = "Assigned"; @@ -429,7 +478,6 @@ public class ChatController { } else { assignee = "Open"; } - String updated = conversation.getUpdatedAt() == null ? "" : TIME_FORMATTER.format(conversation.getUpdatedAt()); return assignee + (updated.isBlank() ? "" : " · " + updated); } diff --git a/desktop/src/main/resources/org/example/petshopdesktop/modelviews/chat-view.fxml b/desktop/src/main/resources/org/example/petshopdesktop/modelviews/chat-view.fxml index b55fd5c9..c1294eab 100644 --- a/desktop/src/main/resources/org/example/petshopdesktop/modelviews/chat-view.fxml +++ b/desktop/src/main/resources/org/example/petshopdesktop/modelviews/chat-view.fxml @@ -48,11 +48,21 @@ - + + + + + + +