Add close chat and closed status
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -48,11 +48,21 @@
|
||||
<Insets bottom="18.0" left="18.0" right="18.0" top="18.0" />
|
||||
</padding>
|
||||
<children>
|
||||
<Label fx:id="lblConversationTitle" text="Select a conversation" textFill="#0f172a">
|
||||
<font>
|
||||
<Font name="System Bold" size="24.0" />
|
||||
</font>
|
||||
</Label>
|
||||
<HBox alignment="CENTER_LEFT" spacing="12.0">
|
||||
<children>
|
||||
<Label fx:id="lblConversationTitle" text="Select a conversation" textFill="#0f172a">
|
||||
<font>
|
||||
<Font name="System Bold" size="24.0" />
|
||||
</font>
|
||||
</Label>
|
||||
<Region HBox.hgrow="ALWAYS" />
|
||||
<Button fx:id="btnClose" mnemonicParsing="false" onAction="#btnCloseClicked" style="-fx-background-color: #dc2626; -fx-background-radius: 10; -fx-text-fill: white; -fx-cursor: hand;" text="Close Chat" visible="false" managed="false">
|
||||
<padding>
|
||||
<Insets bottom="8.0" left="14.0" right="14.0" top="8.0" />
|
||||
</padding>
|
||||
</Button>
|
||||
</children>
|
||||
</HBox>
|
||||
<ScrollPane fx:id="spMessages" fitToWidth="true" hbarPolicy="NEVER" styleClass="chat-messages-scroll-pane" style="-fx-background-color: transparent; -fx-background: transparent;" VBox.vgrow="ALWAYS">
|
||||
<content>
|
||||
<VBox fx:id="vbMessages" spacing="10.0" style="-fx-background-color: rgba(255,255,255,0.72); -fx-background-radius: 18; -fx-padding: 18;" />
|
||||
|
||||
Reference in New Issue
Block a user