@droppii-org/chat-sdk 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (100) hide show
  1. package/dist/components/conversation/ConversationBySessionItem.d.ts.map +1 -1
  2. package/dist/components/conversation/ConversationBySessionItem.js +6 -2
  3. package/dist/components/mediaCollection/LinkCollection.js +1 -1
  4. package/dist/components/message/MediaPreviewIcon.d.ts +7 -0
  5. package/dist/components/message/MediaPreviewIcon.d.ts.map +1 -0
  6. package/dist/components/message/MediaPreviewIcon.js +24 -0
  7. package/dist/components/message/MessageHeader.js +1 -1
  8. package/dist/components/message/MessageList.d.ts.map +1 -1
  9. package/dist/components/message/MessageList.js +48 -5
  10. package/dist/components/message/footer/ActionBar.d.ts.map +1 -1
  11. package/dist/components/message/footer/ActionBar.js +15 -86
  12. package/dist/components/message/footer/EmojiPicker.d.ts.map +1 -1
  13. package/dist/components/message/footer/EmojiPicker.js +9 -5
  14. package/dist/components/message/footer/EnterHandler.d.ts.map +1 -1
  15. package/dist/components/message/footer/EnterHandler.js +16 -5
  16. package/dist/components/message/footer/FilePreview.d.ts +5 -0
  17. package/dist/components/message/footer/FilePreview.d.ts.map +1 -1
  18. package/dist/components/message/footer/FilePreview.js +15 -12
  19. package/dist/components/message/footer/MediaActions.d.ts +10 -0
  20. package/dist/components/message/footer/MediaActions.d.ts.map +1 -0
  21. package/dist/components/message/footer/MediaActions.js +78 -0
  22. package/dist/components/message/footer/QuotedMessage.d.ts +2 -0
  23. package/dist/components/message/footer/QuotedMessage.d.ts.map +1 -0
  24. package/dist/components/message/footer/QuotedMessage.js +24 -0
  25. package/dist/components/message/footer/editorConfig.d.ts +24 -0
  26. package/dist/components/message/footer/editorConfig.d.ts.map +1 -0
  27. package/dist/components/message/footer/editorConfig.js +33 -0
  28. package/dist/components/message/footer/index.d.ts.map +1 -1
  29. package/dist/components/message/footer/index.js +6 -27
  30. package/dist/components/message/item/QuoteMessage.d.ts +9 -0
  31. package/dist/components/message/item/QuoteMessage.d.ts.map +1 -0
  32. package/dist/components/message/item/QuoteMessage.js +22 -0
  33. package/dist/components/message/item/RevokeMessage.d.ts +5 -0
  34. package/dist/components/message/item/RevokeMessage.d.ts.map +1 -0
  35. package/dist/components/message/item/RevokeMessage.js +8 -0
  36. package/dist/components/message/item/TextMessage.js +1 -1
  37. package/dist/components/message/item/UrlTextMessage.d.ts.map +1 -1
  38. package/dist/components/message/item/UrlTextMessage.js +3 -3
  39. package/dist/components/message/item/index.d.ts +6 -1
  40. package/dist/components/message/item/index.d.ts.map +1 -1
  41. package/dist/components/message/item/index.js +79 -25
  42. package/dist/components/richTextEditor/RichTextEditor.d.ts +12 -0
  43. package/dist/components/richTextEditor/RichTextEditor.d.ts.map +1 -0
  44. package/dist/components/richTextEditor/RichTextEditor.js +62 -0
  45. package/dist/components/searchConversation/SearchDrawer.js +1 -1
  46. package/dist/components/searchConversation/item/SearchItemAsMessage.d.ts +3 -1
  47. package/dist/components/searchConversation/item/SearchItemAsMessage.d.ts.map +1 -1
  48. package/dist/components/searchConversation/item/SearchItemAsMessage.js +5 -2
  49. package/dist/components/thread/AssignConfirmModal.d.ts +12 -0
  50. package/dist/components/thread/AssignConfirmModal.d.ts.map +1 -0
  51. package/dist/components/thread/AssignConfirmModal.js +11 -0
  52. package/dist/components/thread/ManualAssignPopover.d.ts +14 -0
  53. package/dist/components/thread/ManualAssignPopover.d.ts.map +1 -0
  54. package/dist/components/thread/ManualAssignPopover.js +83 -0
  55. package/dist/components/thread/SessionSection.d.ts.map +1 -1
  56. package/dist/components/thread/SessionSection.js +11 -6
  57. package/dist/components/thread/UserSection.js +1 -1
  58. package/dist/hooks/message/useMessage.d.ts.map +1 -1
  59. package/dist/hooks/message/useMessage.js +1 -0
  60. package/dist/hooks/message/useRevokeMessage.d.ts +5 -0
  61. package/dist/hooks/message/useRevokeMessage.d.ts.map +1 -0
  62. package/dist/hooks/message/useRevokeMessage.js +16 -0
  63. package/dist/hooks/message/useSendMessage.d.ts +1 -0
  64. package/dist/hooks/message/useSendMessage.d.ts.map +1 -1
  65. package/dist/hooks/message/useSendMessage.js +40 -9
  66. package/dist/hooks/session/useAssignSession.d.ts +8 -0
  67. package/dist/hooks/session/useAssignSession.d.ts.map +1 -0
  68. package/dist/hooks/session/useAssignSession.js +15 -0
  69. package/dist/hooks/session/useCreateNote.d.ts.map +1 -1
  70. package/dist/hooks/session/useCreateNote.js +2 -1
  71. package/dist/hooks/session/useGetTeamSupporters.d.ts +8 -0
  72. package/dist/hooks/session/useGetTeamSupporters.d.ts.map +1 -0
  73. package/dist/hooks/session/useGetTeamSupporters.js +20 -0
  74. package/dist/index.d.ts +1 -0
  75. package/dist/index.d.ts.map +1 -1
  76. package/dist/index.js +1 -0
  77. package/dist/locales/vi/common.json +48 -53
  78. package/dist/services/query.d.ts +2 -0
  79. package/dist/services/query.d.ts.map +1 -1
  80. package/dist/services/query.js +2 -0
  81. package/dist/services/routes.d.ts +2 -0
  82. package/dist/services/routes.d.ts.map +1 -1
  83. package/dist/services/routes.js +2 -0
  84. package/dist/store/conversation.d.ts.map +1 -1
  85. package/dist/store/conversation.js +7 -1
  86. package/dist/styles/global.css +1 -1
  87. package/dist/tsconfig.tsbuildinfo +1 -0
  88. package/dist/types/chat.d.ts +1 -1
  89. package/dist/types/chat.d.ts.map +1 -1
  90. package/dist/types/dto.d.ts +26 -0
  91. package/dist/types/dto.d.ts.map +1 -1
  92. package/dist/utils/common.d.ts +3 -2
  93. package/dist/utils/common.d.ts.map +1 -1
  94. package/dist/utils/common.js +43 -19
  95. package/dist/utils/fileValidation.d.ts.map +1 -1
  96. package/dist/utils/fileValidation.js +2 -8
  97. package/dist/utils/queryHelpers.d.ts +3 -0
  98. package/dist/utils/queryHelpers.d.ts.map +1 -0
  99. package/dist/utils/queryHelpers.js +11 -0
  100. package/package.json +1 -1
@@ -26,7 +26,7 @@ const SearchDrawer = () => {
26
26
  padding: 0,
27
27
  height: "100%",
28
28
  },
29
- }, getContainer: false, width: isMobile ? "100%" : 360, children: _jsxs("div", { className: "flex flex-col h-full", children: [_jsxs("div", { className: "flex items-center justify-between p-3", children: [_jsx("span", { className: "text-lg font-medium", children: "T\u00ECm ki\u1EBFm tin nh\u1EAFn" }), _jsx(Button, { type: "text", shape: "default", className: "text-gray-500 w-8 h-8 p-0", onClick: toggle, children: _jsx(Icon, { icon: "close-b", size: 22 }) })] }), _jsx("div", { className: "px-3", children: _jsx(Input, { ref: searchInputRef, placeholder: t("search"), prefix: _jsx(Icon, { icon: "search-o", size: 18, className: "text-gray-400" }), onChange: (e) => {
29
+ }, getContainer: false, width: isMobile ? "100%" : 360, children: _jsxs("div", { className: "flex flex-col h-full", children: [_jsxs("div", { className: "flex items-center justify-between p-3", children: [_jsx("span", { className: "text-lg font-medium", children: t("search_message_title") }), _jsx(Button, { type: "text", shape: "default", className: "text-gray-500 w-8 h-8 p-0", onClick: toggle, children: _jsx(Icon, { icon: "close-b", size: 22 }) })] }), _jsx("div", { className: "px-3", children: _jsx(Input, { ref: searchInputRef, placeholder: t("search"), prefix: _jsx(Icon, { icon: "search-o", size: 18, className: "text-gray-400" }), onChange: (e) => {
30
30
  setSearch(e.target.value);
31
31
  }, className: "rounded-lg text-sm", size: "large", allowClear: true, value: search, autoFocus: false }) }), _jsx("div", { className: "flex-1 py-3 overflow-auto", children: _jsx(SearchMessageOnCurrentConversation, { searchTerm: search, onClose: toggle }) })] }) })] }));
32
32
  };
@@ -1,6 +1,8 @@
1
1
  import { MessageItem } from "@openim/wasm-client-sdk";
2
2
  interface SearchItemAsMessageProps {
3
- message: MessageItem;
3
+ message: MessageItem & {
4
+ isRevoked?: boolean;
5
+ };
4
6
  searchTerm: string;
5
7
  onClick?: () => void;
6
8
  }
@@ -1 +1 @@
1
- {"version":3,"file":"SearchItemAsMessage.d.ts","sourceRoot":"","sources":["../../../../src/components/searchConversation/item/SearchItemAsMessage.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAe,MAAM,yBAAyB,CAAC;AAWnE,UAAU,wBAAwB;IAChC,OAAO,EAAE,WAAW,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,QAAA,MAAM,mBAAmB,GAAI,OAAO,wBAAwB,4CA+F3D,CAAC;AAEF,eAAe,mBAAmB,CAAC"}
1
+ {"version":3,"file":"SearchItemAsMessage.d.ts","sourceRoot":"","sources":["../../../../src/components/searchConversation/item/SearchItemAsMessage.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAA4B,MAAM,yBAAyB,CAAC;AAehF,UAAU,wBAAwB;IAChC,OAAO,EAAE,WAAW,GAAG;QAAE,SAAS,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IAC/C,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,QAAA,MAAM,mBAAmB,GAAI,OAAO,wBAAwB,4CAkG3D,CAAC;AAEF,eAAe,mBAAmB,CAAC"}
@@ -2,7 +2,7 @@
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { SessionType } from "@openim/wasm-client-sdk";
4
4
  import { Avatar } from "antd";
5
- import { formatTimestamp, highlightSearch, sanitizeHtml } from "../../../utils/common";
5
+ import { formatTimestamp, highlightSearch, sanitizeHtml, } from "../../../utils/common";
6
6
  import { DChatSDK } from "../../../constants/sdk";
7
7
  import { useChatContext } from "../../../context/ChatContext";
8
8
  import { message as antdMessage } from "antd";
@@ -44,7 +44,10 @@ const SearchItemAsMessage = (props) => {
44
44
  };
45
45
  let msgContent = "";
46
46
  try {
47
- msgContent = ((_a = JSON.parse((message === null || message === void 0 ? void 0 : message.content) || "{}")) === null || _a === void 0 ? void 0 : _a.content) || "";
47
+ msgContent =
48
+ (message === null || message === void 0 ? void 0 : message.isRevoked) === true
49
+ ? t("revoked")
50
+ : ((_a = JSON.parse((message === null || message === void 0 ? void 0 : message.content) || "{}")) === null || _a === void 0 ? void 0 : _a.content) || "";
48
51
  }
49
52
  catch (error) {
50
53
  console.error("Failed to parse message content", error);
@@ -0,0 +1,12 @@
1
+ import { ISupporterResponse } from "../../types/dto";
2
+ interface AssignConfirmModalProps {
3
+ open: boolean;
4
+ agent: ISupporterResponse | null;
5
+ loading: boolean;
6
+ onCancel: () => void;
7
+ onConfirm: () => void;
8
+ afterClose?: () => void;
9
+ }
10
+ declare const AssignConfirmModal: ({ open, agent, loading, onCancel, onConfirm, afterClose, }: AssignConfirmModalProps) => import("react/jsx-runtime").JSX.Element;
11
+ export default AssignConfirmModal;
12
+ //# sourceMappingURL=AssignConfirmModal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AssignConfirmModal.d.ts","sourceRoot":"","sources":["../../../src/components/thread/AssignConfirmModal.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAGrD,UAAU,uBAAuB;IAC/B,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,kBAAkB,GAAG,IAAI,CAAC;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;CACzB;AAED,QAAA,MAAM,kBAAkB,GAAI,4DAOzB,uBAAuB,4CAwDzB,CAAC;AAEF,eAAe,kBAAkB,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Modal, Button, Avatar } from "antd";
3
+ import { useTranslation, Trans } from "react-i18next";
4
+ const AssignConfirmModal = ({ open, agent, loading, onCancel, onConfirm, afterClose, }) => {
5
+ var _a;
6
+ const { t } = useTranslation();
7
+ return (_jsx(Modal, { open: open, onCancel: onCancel, footer: null, closable: !loading, centered: true, forceRender: true, width: 400, maskClosable: !loading, keyboard: !loading, afterClose: afterClose, children: _jsxs("div", { className: "flex flex-col items-center gap-4 pt-2", role: "alertdialog", "aria-label": t("manual_assign_confirm_question", {
8
+ name: agent === null || agent === void 0 ? void 0 : agent.displayName,
9
+ }), children: [_jsx(Avatar, { src: agent === null || agent === void 0 ? void 0 : agent.avatar, size: 48, children: ((_a = agent === null || agent === void 0 ? void 0 : agent.displayName) === null || _a === void 0 ? void 0 : _a.charAt(0)) || "A" }), _jsx("p", { className: "text-base text-center", children: _jsx(Trans, { i18nKey: "manual_assign_confirm_question", values: { name: agent === null || agent === void 0 ? void 0 : agent.displayName }, components: { bold: _jsx("strong", {}) } }) }), _jsxs("div", { className: "flex gap-3 w-full", children: [_jsx(Button, { className: "flex-1", size: "large", onClick: onCancel, disabled: loading, children: t("cancel") }), _jsx(Button, { type: "primary", className: "flex-1", size: "large", onClick: onConfirm, loading: loading, disabled: !agent, children: t("manual_assign_button_reassign") })] })] }) }));
10
+ };
11
+ export default AssignConfirmModal;
@@ -0,0 +1,14 @@
1
+ interface SupporterInfo {
2
+ avatar: string;
3
+ username: string;
4
+ fullName: string;
5
+ id: string;
6
+ }
7
+ interface ManualAssignPopoverProps {
8
+ sessionId: string;
9
+ supporter: SupporterInfo;
10
+ teamId?: string;
11
+ }
12
+ declare const ManualAssignPopover: ({ sessionId, supporter, teamId: propTeamId, }: ManualAssignPopoverProps) => import("react/jsx-runtime").JSX.Element;
13
+ export default ManualAssignPopover;
14
+ //# sourceMappingURL=ManualAssignPopover.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ManualAssignPopover.d.ts","sourceRoot":"","sources":["../../../src/components/thread/ManualAssignPopover.tsx"],"names":[],"mappings":"AAgBA,UAAU,aAAa;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,UAAU,wBAAwB;IAChC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,aAAa,CAAC;IACzB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AA0CD,QAAA,MAAM,mBAAmB,GAAI,+CAI1B,wBAAwB,4CA8J1B,CAAC;AAEF,eAAe,mBAAmB,CAAC"}
@@ -0,0 +1,83 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useState } from "react";
3
+ import { Popover, Input, Avatar, Spin, Badge } from "antd";
4
+ import { useTranslation } from "react-i18next";
5
+ import clsx from "clsx";
6
+ import { Icon } from "../icon";
7
+ import { useGetTeamSupporters } from "../../hooks/session/useGetTeamSupporters";
8
+ import { useAssignSession } from "../../hooks/session/useAssignSession";
9
+ import { useQueryClient } from "@tanstack/react-query";
10
+ import { message as antdMessage } from "antd";
11
+ import { invalidateSessionQueries } from "../../utils/queryHelpers";
12
+ import AssignConfirmModal from "./AssignConfirmModal";
13
+ import { useDebounce } from "ahooks";
14
+ const SEARCH_DEBOUNCE_WAIT = 300;
15
+ const SupporterItem = ({ supporter, onClick, isCurrentAssignee, }) => {
16
+ var _a;
17
+ const { t } = useTranslation();
18
+ const isOnline = supporter.status === "ONLINE";
19
+ return (_jsxs("div", { role: "option", tabIndex: 0, "aria-selected": isCurrentAssignee, className: clsx("flex items-center gap-3 px-3 py-2 rounded-md transition-colors", isCurrentAssignee
20
+ ? "bg-blue-50 border border-blue-200 pointer-events-none"
21
+ : "cursor-pointer hover:bg-gray-50"), onClick: () => onClick(supporter), children: [_jsx(Badge, { dot: true, color: isOnline ? "#52c41a" : "#d9d9d9", offset: [-2, 24], children: _jsx(Avatar, { src: supporter.avatar, size: 32, children: ((_a = supporter.displayName) === null || _a === void 0 ? void 0 : _a.charAt(0)) || "A" }) }), _jsx("span", { className: "text-sm truncate flex-1", children: supporter.displayName }), isCurrentAssignee && (_jsx("span", { className: "text-xs text-blue-500 shrink-0", children: t("manual_assign_current") }))] }));
22
+ };
23
+ const ManualAssignPopover = ({ sessionId, supporter, teamId: propTeamId, }) => {
24
+ var _a, _b;
25
+ const { t } = useTranslation();
26
+ const queryClient = useQueryClient();
27
+ const [open, setOpen] = useState(false);
28
+ const [searchText, setSearchText] = useState("");
29
+ const [selectedAgent, setSelectedAgent] = useState(null);
30
+ const [confirmModalOpen, setConfirmModalOpen] = useState(false);
31
+ const debouncedSearch = useDebounce(searchText, {
32
+ wait: SEARCH_DEBOUNCE_WAIT,
33
+ });
34
+ const teamId = propTeamId || "";
35
+ const { data: supporters, isLoading, isFetching, } = useGetTeamSupporters({
36
+ teamId,
37
+ search: debouncedSearch || undefined,
38
+ });
39
+ const { mutate: assignSession, isPending: isAssigning } = useAssignSession();
40
+ const handleSelectAgent = (agent) => {
41
+ if (isAssigning)
42
+ return;
43
+ setSelectedAgent(agent);
44
+ setConfirmModalOpen(true);
45
+ };
46
+ const handleConfirmAssign = () => {
47
+ if (!selectedAgent || isAssigning)
48
+ return;
49
+ assignSession({ sessionId, supporterId: selectedAgent.memberId }, {
50
+ onSuccess: () => {
51
+ antdMessage.success(t("manual_assign_success"));
52
+ setConfirmModalOpen(false);
53
+ setOpen(false);
54
+ setSearchText("");
55
+ invalidateSessionQueries(queryClient);
56
+ },
57
+ onError: () => {
58
+ antdMessage.error(t("manual_assign_failed"));
59
+ },
60
+ });
61
+ };
62
+ const handleCancelConfirm = () => {
63
+ setConfirmModalOpen(false);
64
+ };
65
+ const handleAfterClose = () => {
66
+ setSelectedAgent(null);
67
+ };
68
+ const handleOpenChange = (newOpen) => {
69
+ if (isAssigning)
70
+ return;
71
+ if (!newOpen && confirmModalOpen)
72
+ return;
73
+ setOpen(newOpen);
74
+ if (!newOpen) {
75
+ setSearchText("");
76
+ }
77
+ };
78
+ const popoverContent = (_jsxs("div", { className: "w-64", children: [_jsx("div", { className: "mb-2", children: _jsx(Input, { autoFocus: true, placeholder: t("manual_assign_search_placeholder"), value: searchText, onChange: (e) => setSearchText(e.target.value), prefix: _jsx(Icon, { icon: "search-o", size: 16, className: "text-gray-400" }), className: "rounded-lg border-gray-300 focus-within:border-[#3278f7] focus-within:shadow-[0_0_0_2px_rgba(50,120,247,0.12)]", allowClear: true }) }), _jsx("div", { className: "max-h-72 overflow-y-auto", role: "listbox", children: isLoading ? (_jsx("div", { className: "flex items-center justify-center py-8", children: _jsx(Spin, {}) })) : supporters && supporters.length > 0 ? (_jsx("div", { className: clsx("flex flex-col transition-opacity duration-200", isFetching && "opacity-50 pointer-events-none"), children: supporters.map((item) => (_jsx(SupporterItem, { supporter: item, onClick: handleSelectAgent, isCurrentAssignee: item.memberId === (supporter === null || supporter === void 0 ? void 0 : supporter.id) }, item.memberId))) })) : (_jsx("div", { className: "flex items-center justify-center py-8", children: _jsx("span", { className: "text-sm text-gray-400", children: t("manual_assign_no_results") }) })) })] }));
79
+ return (_jsxs(_Fragment, { children: [_jsx(Popover, { content: popoverContent, trigger: "click", open: open, onOpenChange: handleOpenChange, placement: "topLeft", arrow: false, children: _jsxs("div", { role: "button", tabIndex: 0, "aria-label": t("manual_assign_button_reassign"), className: clsx("flex items-center border border-gray-200 rounded-lg p-1 gap-1 transition-opacity", isAssigning
80
+ ? "opacity-50 pointer-events-none"
81
+ : "cursor-pointer hover:opacity-80"), children: [_jsx(Avatar, { src: supporter === null || supporter === void 0 ? void 0 : supporter.avatar, size: 28, children: ((_b = (_a = supporter === null || supporter === void 0 ? void 0 : supporter.fullName) === null || _a === void 0 ? void 0 : _a.charAt) === null || _b === void 0 ? void 0 : _b.call(_a, 0)) || "A" }), _jsx("span", { className: "text-purple-500", children: _jsx(Icon, { icon: "shuffle-b", size: 20 }) })] }) }), _jsx(AssignConfirmModal, { open: confirmModalOpen, agent: selectedAgent, loading: isAssigning, onCancel: handleCancelConfirm, onConfirm: handleConfirmAssign, afterClose: handleAfterClose })] }));
82
+ };
83
+ export default ManualAssignPopover;
@@ -1 +1 @@
1
- {"version":3,"file":"SessionSection.d.ts","sourceRoot":"","sources":["../../../src/components/thread/SessionSection.tsx"],"names":[],"mappings":"AASA,OAAO,EAAkB,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAmBnE,eAAO,MAAM,iBAAiB,GAAI,wBAG/B;IACD,OAAO,EAAE,gBAAgB,CAAC;IAC1B,QAAQ,EAAE,OAAO,CAAC;CACnB,4CAsMA,CAAC;AA8CF,UAAU,mBAAmB;IAC3B,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAC7B,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,QAAA,MAAM,cAAc,GAAI,yBAAyB,mBAAmB,4CAkDnE,CAAC;AAEF,eAAe,cAAc,CAAC"}
1
+ {"version":3,"file":"SessionSection.d.ts","sourceRoot":"","sources":["../../../src/components/thread/SessionSection.tsx"],"names":[],"mappings":"AAUA,OAAO,EAAkB,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAoBnE,eAAO,MAAM,iBAAiB,GAAI,wBAG/B;IACD,OAAO,EAAE,gBAAgB,CAAC;IAC1B,QAAQ,EAAE,OAAO,CAAC;CACnB,4CA6MA,CAAC;AA+CF,UAAU,mBAAmB;IAC3B,QAAQ,EAAE,gBAAgB,EAAE,CAAC;IAC7B,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,QAAA,MAAM,cAAc,GAAI,yBAAyB,mBAAmB,4CAmDnE,CAAC;AAEF,eAAe,cAAc,CAAC"}
@@ -2,12 +2,14 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useBoolean, useDebounce } from "ahooks";
3
3
  import { Icon } from "../icon";
4
4
  import { Button, Select, Spin, Tag, Input, message, Avatar } from "antd";
5
+ import ManualAssignPopover from "./ManualAssignPopover";
5
6
  import { useGetLabelSession } from "../../hooks/session/useGetLabelSession";
6
7
  import { useUpdateSessionInfo } from "../../hooks/session/useUpdateSessionInfo";
7
8
  import { useCloseSession } from "../../hooks/session/useCloseSession";
8
9
  import { useQueryClient } from "@tanstack/react-query";
9
10
  import { QUERY_KEYS } from "../../services/query";
10
11
  import { useEffect, useState } from "react";
12
+ import { useTranslation } from "react-i18next";
11
13
  const { TextArea } = Input;
12
14
  const formatSessionDate = (dateString) => {
13
15
  if (!dateString)
@@ -22,6 +24,7 @@ const formatSessionDate = (dateString) => {
22
24
  export const SessionDetailCard = ({ session, isActive, }) => {
23
25
  var _a, _b, _c, _d, _e;
24
26
  const queryClient = useQueryClient();
27
+ const { t } = useTranslation("common");
25
28
  const { data: availableLabels, isLoading: isLoadingLabels } = useGetLabelSession();
26
29
  const { mutate: updateSession } = useUpdateSessionInfo();
27
30
  const { mutate: closeSession, isPending: isClosing } = useCloseSession();
@@ -95,13 +98,13 @@ export const SessionDetailCard = ({ session, isActive, }) => {
95
98
  const handleCloseSession = () => {
96
99
  closeSession(session.id, {
97
100
  onSuccess: () => {
98
- message.success("Đóng phiên chat thành công");
101
+ message.success(t("close_session_success"));
99
102
  queryClient.invalidateQueries({
100
103
  queryKey: [QUERY_KEYS.GET_LIST_SESSION_BY_CONVERSATION],
101
104
  });
102
105
  },
103
106
  onError: () => {
104
- message.error("Đóng phiên chat thất bại");
107
+ message.error(t("close_session_failed"));
105
108
  },
106
109
  });
107
110
  };
@@ -109,13 +112,14 @@ export const SessionDetailCard = ({ session, isActive, }) => {
109
112
  value: label.id,
110
113
  label: label.name,
111
114
  }));
112
- return (_jsxs("div", { className: `p-3 border rounded-lg shadow-md ${isActive ? "border-blue-500" : "border-gray-300"}`, children: [_jsxs("div", { className: "flex justify-between items-start mb-3", children: [_jsx("div", { className: "flex items-center gap-2", children: _jsxs("div", { className: "flex flex-col", children: [_jsxs("div", { className: "flex items-center gap-1", children: [_jsx(Icon, { icon: "chat-square-b", size: 16, className: "text-gray-500" }), _jsxs("p", { className: "font-semibold text-sm", children: ["Session ", session.order] })] }), _jsx("p", { className: "text-xs text-gray-400", children: formatSessionDate(session.closedDate || session.createdDate) })] }) }), isActive ? (_jsx(Tag, { color: "processing", children: "\u0110ang ho\u1EA1t \u0111\u1ED9ng" })) : (_jsx(Avatar, { src: (_a = session.supporter) === null || _a === void 0 ? void 0 : _a.avatar, size: 24, children: ((_d = (_c = (_b = session.supporter) === null || _b === void 0 ? void 0 : _b.username) === null || _c === void 0 ? void 0 : _c.charAt) === null || _d === void 0 ? void 0 : _d.call(_c, 0)) || "A" }))] }), _jsxs("div", { className: "flex flex-col gap-3 text-sm", children: [_jsxs("div", { className: "flex items-center gap-2 text-gray-500", children: [_jsx(Icon, { icon: "tag-o", size: 16, className: "mt-1" }), _jsx(Select, { mode: "multiple", loading: isLoadingLabels, className: "w-full", placeholder: "Th\u00EAm th\u1EBB...", options: labelOptions, value: (_e = session.labels) === null || _e === void 0 ? void 0 : _e.map((label) => label.id), onChange: handleUpdateLabels, removeIcon: true })] }), _jsxs("div", { className: "flex items-start gap-2 text-gray-500", children: [_jsx(Icon, { icon: "info-circle-o", size: 16, className: "mt-1" }), _jsx(TextArea, { value: issueDetailInput.value, onChange: (e) => setIssueDetailInput({
115
+ return (_jsxs("div", { className: `p-3 border rounded-lg shadow-md ${isActive ? "border-blue-500" : "border-gray-300"}`, children: [_jsxs("div", { className: "flex justify-between items-start mb-3", children: [_jsx("div", { className: "flex items-center gap-2", children: _jsxs("div", { className: "flex flex-col", children: [_jsxs("div", { className: "flex items-center gap-1", children: [_jsx(Icon, { icon: "chat-square-b", size: 16, className: "text-gray-500" }), _jsx("p", { className: "font-semibold text-sm", children: t("session_label", { order: session.order }) })] }), _jsx("p", { className: "text-xs text-gray-400", children: formatSessionDate(session.closedDate || session.createdDate) })] }) }), isActive ? (_jsx(Tag, { color: "processing", children: t("session_active") })) : (_jsx(Avatar, { src: (_a = session.supporter) === null || _a === void 0 ? void 0 : _a.avatar, size: 24, children: ((_d = (_c = (_b = session.supporter) === null || _b === void 0 ? void 0 : _b.fullName) === null || _c === void 0 ? void 0 : _c.charAt) === null || _d === void 0 ? void 0 : _d.call(_c, 0)) || "A" }))] }), _jsxs("div", { className: "flex flex-col gap-3 text-sm", children: [_jsxs("div", { className: "flex items-center gap-2 text-gray-500", children: [_jsx(Icon, { icon: "tag-o", size: 16, className: "mt-1" }), _jsx(Select, { mode: "multiple", loading: isLoadingLabels, className: "w-full", placeholder: t("session_add_tag_placeholder"), options: labelOptions, value: (_e = session.labels) === null || _e === void 0 ? void 0 : _e.map((label) => label.id), onChange: handleUpdateLabels, removeIcon: true })] }), _jsxs("div", { className: "flex items-start gap-2 text-gray-500", children: [_jsx(Icon, { icon: "info-circle-o", size: 16, className: "mt-1" }), _jsx(TextArea, { value: issueDetailInput.value, onChange: (e) => setIssueDetailInput({
113
116
  value: e.target.value,
114
117
  sessionId: session.id,
115
- }), placeholder: "V\u1EA5n \u0111\u1EC1 c\u1EE5 th\u1EC3...", className: "border-none !shadow-none py-0 px-2", autoSize: { minRows: 1, maxRows: 3 } })] }), _jsxs("div", { className: "flex items-start gap-2 text-gray-500", children: [_jsx(Icon, { icon: "paper-o", size: 16, className: "mt-1" }), _jsx(TextArea, { value: noteInput.value, onChange: (e) => setNoteInput({ value: e.target.value, sessionId: session.id }), placeholder: "Ghi ch\u00FA...", className: "border-none !shadow-none py-0 px-2", autoSize: { minRows: 1, maxRows: 3 } })] })] }), isActive && (_jsx(Button, { type: "primary", block: true, className: "mt-4", onClick: handleCloseSession, loading: isClosing, children: "\u0110\u00F3ng" }))] }));
118
+ }), placeholder: t("session_issue_detail_placeholder"), className: "border-none !shadow-none py-0 px-2", autoSize: { minRows: 1, maxRows: 3 } })] }), _jsxs("div", { className: "flex items-start gap-2 text-gray-500", children: [_jsx(Icon, { icon: "paper-o", size: 16, className: "mt-1" }), _jsx(TextArea, { value: noteInput.value, onChange: (e) => setNoteInput({ value: e.target.value, sessionId: session.id }), placeholder: t("session_note_placeholder"), className: "border-none !shadow-none py-0 px-2", autoSize: { minRows: 1, maxRows: 3 } })] })] }), isActive && (_jsxs("div", { className: "flex items-center gap-2 mt-4 border-t border-gray-200 pt-4", children: [_jsx(ManualAssignPopover, { sessionId: session.id, supporter: session.supporter, teamId: session.teamId }), _jsx(Button, { type: "primary", className: "flex-1", onClick: handleCloseSession, loading: isClosing, children: t("session_close_button") })] }))] }));
116
119
  };
117
120
  const ClosedSessionItem = ({ session, expandedSessionId, onToggleExpand, }) => {
118
121
  var _a, _b, _c, _d;
122
+ const { t } = useTranslation("common");
119
123
  const isExpanded = session.id === expandedSessionId;
120
124
  const handleClick = () => {
121
125
  onToggleExpand(session.id);
@@ -123,9 +127,10 @@ const ClosedSessionItem = ({ session, expandedSessionId, onToggleExpand, }) => {
123
127
  if (isExpanded) {
124
128
  return (_jsx("div", { children: _jsx(SessionDetailCard, { session: session, isActive: false }) }));
125
129
  }
126
- return (_jsxs("div", { className: "flex justify-between items-center p-2 rounded-md hover:bg-gray-100 cursor-pointer", onClick: handleClick, children: [_jsxs("div", { className: "flex items-center gap-2 text-sm", children: [_jsx(Icon, { icon: "chat-square-b", size: 16, className: "text-gray-500" }), _jsxs("span", { className: "font-semibold", children: ["Session ", session.order] }), _jsx("span", { className: "text-gray-400 text-xs", children: formatSessionDate(session.closedDate || session.createdDate) })] }), _jsx(Avatar, { src: (_a = session.supporter) === null || _a === void 0 ? void 0 : _a.avatar, size: 24, children: ((_d = (_c = (_b = session.supporter) === null || _b === void 0 ? void 0 : _b.username) === null || _c === void 0 ? void 0 : _c.charAt) === null || _d === void 0 ? void 0 : _d.call(_c, 0)) || "A" })] }));
130
+ return (_jsxs("div", { className: "flex justify-between items-center p-2 rounded-md hover:bg-gray-100 cursor-pointer", onClick: handleClick, children: [_jsxs("div", { className: "flex items-center gap-2 text-sm", children: [_jsx(Icon, { icon: "chat-square-b", size: 16, className: "text-gray-500" }), _jsx("span", { className: "font-semibold", children: t("session_label", { order: session.order }) }), _jsx("span", { className: "text-gray-400 text-xs", children: formatSessionDate(session.closedDate || session.createdDate) })] }), _jsx(Avatar, { src: (_a = session.supporter) === null || _a === void 0 ? void 0 : _a.avatar, size: 24, children: ((_d = (_c = (_b = session.supporter) === null || _b === void 0 ? void 0 : _b.fullName) === null || _c === void 0 ? void 0 : _c.charAt) === null || _d === void 0 ? void 0 : _d.call(_c, 0)) || "A" })] }));
127
131
  };
128
132
  const SessionSection = ({ sessions, isLoading }) => {
133
+ const { t } = useTranslation("common");
129
134
  const [isOpen, { toggle }] = useBoolean(true);
130
135
  const [expandedSessionId, setExpandedSessionId] = useState(null);
131
136
  const handleToggleExpand = (sessionId) => {
@@ -136,6 +141,6 @@ const SessionSection = ({ sessions, isLoading }) => {
136
141
  setExpandedSessionId(null);
137
142
  }
138
143
  }, [isOpen]);
139
- return (_jsxs("div", { className: "flex flex-col border-b", children: [_jsxs("div", { role: "button", onClick: toggle, className: "flex items-center justify-between px-4 py-2 rounded-md hover:bg-gray-100 sticky top-0 bg-white z-10", children: [_jsx("h3", { className: "font-bold text-gray-500 text-xs tracking-wider", children: "SESSIONS" }), _jsx(Icon, { icon: isOpen ? "angle-up-o" : "angle-down-o", size: 18 })] }), isOpen && (_jsx("div", { className: "px-4 pt-2 pb-4", children: isLoading ? (_jsx("div", { className: "text-center mt-4", children: _jsx(Spin, {}) })) : (_jsx("div", { className: "flex flex-col gap-1", children: sessions.map((session) => (_jsx(ClosedSessionItem, { session: session, expandedSessionId: expandedSessionId, onToggleExpand: handleToggleExpand }, session.id))) })) }))] }));
144
+ return (_jsxs("div", { className: "flex flex-col border-b", children: [_jsxs("div", { role: "button", onClick: toggle, className: "flex items-center justify-between px-4 py-2 rounded-md hover:bg-gray-100 sticky top-0 bg-white z-10", children: [_jsx("h3", { className: "font-bold text-gray-500 text-xs tracking-wider", children: t("sessions_heading") }), _jsx(Icon, { icon: isOpen ? "angle-up-o" : "angle-down-o", size: 18 })] }), isOpen && (_jsx("div", { className: "px-4 pt-2 pb-4", children: isLoading ? (_jsx("div", { className: "text-center mt-4", children: _jsx(Spin, {}) })) : (_jsx("div", { className: "flex flex-col gap-1", children: sessions.map((session) => (_jsx(ClosedSessionItem, { session: session, expandedSessionId: expandedSessionId, onToggleExpand: handleToggleExpand }, session.id))) })) }))] }));
140
145
  };
141
146
  export default SessionSection;
@@ -70,7 +70,7 @@ const UserSection = () => {
70
70
  navigator.clipboard.writeText((data === null || data === void 0 ? void 0 : data.id) || "");
71
71
  message.success(t("copied_to_clipboard"));
72
72
  } })] }), _jsxs("div", { className: "flex justify-between items-center gap-2", children: [_jsxs("p", { className: "text-sm truncate flex gap-3", children: [_jsx("span", { className: "font-light text-gray-400 w-16", children: "Username" }), (data === null || data === void 0 ? void 0 : data.username) || ""] }), _jsx(Icon, { icon: "copy-o", size: 16, onClick: () => {
73
- navigator.clipboard.writeText((data === null || data === void 0 ? void 0 : data.id) || "");
73
+ navigator.clipboard.writeText((data === null || data === void 0 ? void 0 : data.username) || "");
74
74
  message.success(t("copied_to_clipboard"));
75
75
  } })] }), _jsxs("div", { className: "flex justify-between", children: [_jsx("p", { className: "text-sm flex gap-3", children: _jsx("span", { className: "font-light text-gray-400 w-16", children: "Note" }) }), _jsx(TextArea, { value: noteValue, placeholder: t("add_note"), className: "border-none py-0", autoSize: { minRows: 1, maxRows: 6 }, onChange: (e) => {
76
76
  const v = e.target.value;
@@ -1 +1 @@
1
- {"version":3,"file":"useMessage.d.ts","sourceRoot":"","sources":["../../../src/hooks/message/useMessage.ts"],"names":[],"mappings":"AACA,OAAO,EAAY,WAAW,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAQ7E,eAAO,MAAM,kBAAkB,eAc9B,CAAC;AAEF,eAAO,MAAM,UAAU,GACrB,iBAAiB,MAAM,EACvB,oBAAoB,MAAM;;;;;qBAML,WAAW,EAAE;;;;;;qBAAb,WAAW,EAAE;;;;;;CAkNnC,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,SAAS,WAAW,SACpB,CAAC;AAChC,eAAO,MAAM,gBAAgB,GAAI,SAAS,WAAW,SACpB,CAAC;AAClC,eAAO,MAAM,gBAAgB,GAAI,aAAa,MAAM,SACf,CAAC;AAEtC,eAAO,MAAM,kBAAkB,GAC7B,aAAa,WAAW,EAAE,EAC1B,SAAS,WAAW,EACpB,WAAW,MAAM,GAAG,MAAM,KACzB,WAAW,GAAG,SAkBhB,CAAC"}
1
+ {"version":3,"file":"useMessage.d.ts","sourceRoot":"","sources":["../../../src/hooks/message/useMessage.ts"],"names":[],"mappings":"AACA,OAAO,EAAY,WAAW,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAQ7E,eAAO,MAAM,kBAAkB,eAe9B,CAAC;AAEF,eAAO,MAAM,UAAU,GACrB,iBAAiB,MAAM,EACvB,oBAAoB,MAAM;;;;;qBAML,WAAW,EAAE;;;;;;qBAAb,WAAW,EAAE;;;;;;CAkNnC,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,SAAS,WAAW,SACpB,CAAC;AAChC,eAAO,MAAM,gBAAgB,GAAI,SAAS,WAAW,SACpB,CAAC;AAClC,eAAO,MAAM,gBAAgB,GAAI,aAAa,MAAM,SACf,CAAC;AAEtC,eAAO,MAAM,kBAAkB,GAC7B,aAAa,WAAW,EAAE,EAC1B,SAAS,WAAW,EACpB,WAAW,MAAM,GAAG,MAAM,KACzB,WAAW,GAAG,SAkBhB,CAAC"}
@@ -19,6 +19,7 @@ export const visibleTypeMessage = [
19
19
  MessageType.QuoteMessage,
20
20
  MessageType.FaceMessage,
21
21
  MessageType.UrlTextMessage,
22
+ MessageType.RevokeMessage,
22
23
  ];
23
24
  export const useMessage = (conversationId, searchClientMsgID) => {
24
25
  const [loadState, setLoadState] = useState({
@@ -0,0 +1,5 @@
1
+ export declare const useRevokeMessage: () => {
2
+ revokeMessage: (conversationID: string, clientMsgID: string) => Promise<void>;
3
+ loading: boolean;
4
+ };
5
+ //# sourceMappingURL=useRevokeMessage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useRevokeMessage.d.ts","sourceRoot":"","sources":["../../../src/hooks/message/useRevokeMessage.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,gBAAgB;;;CAiB5B,CAAC"}
@@ -0,0 +1,16 @@
1
+ import { DChatSDK } from "../../constants/sdk";
2
+ import { useRequest } from "ahooks";
3
+ export const useRevokeMessage = () => {
4
+ const { loading, runAsync: revokeMessage } = useRequest(async (conversationID, clientMsgID) => {
5
+ await DChatSDK.revokeMessage({
6
+ conversationID,
7
+ clientMsgID,
8
+ });
9
+ }, {
10
+ manual: true,
11
+ });
12
+ return {
13
+ revokeMessage,
14
+ loading,
15
+ };
16
+ };
@@ -12,6 +12,7 @@ export declare const createMergerMessage: (mergerMsgParams: MergerMsgParams) =>
12
12
  export declare const createVideoMessageByFile: (file: VideoMsgParamsByFile) => Promise<MessageItem | null>;
13
13
  export declare const createFileMessageByFile: (file: FileMsgParamsByFile) => Promise<MessageItem | null>;
14
14
  export declare const createUrlTextMessage: (text: string, urls: string[]) => Promise<MessageItem | null>;
15
+ export declare const createQuoteMessage: (text: string, quotedMessage: MessageItem) => Promise<MessageItem | null>;
15
16
  export declare const useSendMessage: () => {
16
17
  sendTextMessage: ({ plainText, richText, currentSession, }: {
17
18
  plainText: string;
@@ -1 +1 @@
1
- {"version":3,"file":"useSendMessage.d.ts","sourceRoot":"","sources":["../../../src/hooks/message/useSendMessage.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,WAAW,EAGZ,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,oBAAoB,EACpB,oBAAoB,EACrB,MAAM,kBAAkB,CAAC;AAM1B,OAAO,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAQlC,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAepD,eAAO,MAAM,iBAAiB,GAAI,SAAS;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,YACK,CAAC;AAE7F,eAAO,MAAM,iBAAiB,GAAU,MAAM,MAAM,gCAanD,CAAC;AAEF,eAAO,MAAM,wBAAwB,GAAU,MAAM,oBAAoB,gCAaxE,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAAU,iBAAiB,eAAe,gCAazE,CAAC;AAEF,eAAO,MAAM,wBAAwB,GAAU,MAAM,oBAAoB,gCAaxE,CAAC;AAEF,eAAO,MAAM,uBAAuB,GAAU,MAAM,mBAAmB,gCAatE,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAU,MAAM,MAAM,EAAE,MAAM,MAAM,EAAE,gCActE,CAAC;AAEF,eAAO,MAAM,cAAc;gEAmJpB;QACD,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;QACjB,cAAc,CAAC,EAAE,gBAAgB,CAAC;KACnC;wEA+BE;QACD,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;QAClB,KAAK,EAAE,UAAU,EAAE,CAAC;QACpB,cAAc,CAAC,EAAE,gBAAgB,CAAC;KACnC;mCAtIqB,WAAW;CA+PpC,CAAC;AAEF,eAAO,MAAM,yBAAyB,GAAI,+BAGvC;IACD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,gBAAgB,CAAC;CACnC,KAWM,iBACN,CAAC"}
1
+ {"version":3,"file":"useSendMessage.d.ts","sourceRoot":"","sources":["../../../src/hooks/message/useSendMessage.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,WAAW,EAGZ,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,oBAAoB,EACpB,oBAAoB,EACrB,MAAM,kBAAkB,CAAC;AAW1B,OAAO,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAQlC,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAepD,eAAO,MAAM,iBAAiB,GAAI,SAAS;IACzC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;CACrB,YAE0C,CAAC;AAE5C,eAAO,MAAM,iBAAiB,GAAU,MAAM,MAAM,gCAanD,CAAC;AAEF,eAAO,MAAM,wBAAwB,GAAU,MAAM,oBAAoB,gCAaxE,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAAU,iBAAiB,eAAe,gCAazE,CAAC;AAEF,eAAO,MAAM,wBAAwB,GAAU,MAAM,oBAAoB,gCAaxE,CAAC;AAEF,eAAO,MAAM,uBAAuB,GAAU,MAAM,mBAAmB,gCAatE,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAAU,MAAM,MAAM,EAAE,MAAM,MAAM,EAAE,gCActE,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAC7B,MAAM,MAAM,EACZ,eAAe,WAAW,gCAc3B,CAAC;AAEF,eAAO,MAAM,cAAc;gEAgKpB;QACD,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;QACjB,cAAc,CAAC,EAAE,gBAAgB,CAAC;KACnC;wEAkCE;QACD,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;QAClB,KAAK,EAAE,UAAU,EAAE,CAAC;QACpB,cAAc,CAAC,EAAE,gBAAgB,CAAC;KACnC;mCAhJqB,WAAW;CAgRpC,CAAC;AAEF,eAAO,MAAM,yBAAyB,GAAI,+BAGvC;IACD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,gBAAgB,CAAC;CACnC,KAWM,iBACN,CAAC"}
@@ -3,7 +3,8 @@ import { DChatSDK } from "../../constants/sdk";
3
3
  import { v4 as uuidv4 } from "uuid";
4
4
  import { useChatContext } from "../../context/ChatContext";
5
5
  import { useCallback } from "react";
6
- import { pushNewMessage, removeOneMessage, updateOneMessage } from "./useMessage";
6
+ import { useTranslation } from "react-i18next";
7
+ import { pushNewMessage, removeOneMessage, updateOneMessage, } from "./useMessage";
7
8
  import { emit } from "../../utils/events";
8
9
  import useConversationStore from "../../store/conversation";
9
10
  import useAuthStore from "../../store/auth";
@@ -14,7 +15,8 @@ const MEDIA_CONTENT_TYPES = new Set([
14
15
  MessageType.VideoMessage,
15
16
  MessageType.FileMessage,
16
17
  ]);
17
- export const isMediaResendable = (message) => !MEDIA_CONTENT_TYPES.has(message.contentType) || messageFileStore.has(message.clientMsgID);
18
+ export const isMediaResendable = (message) => !MEDIA_CONTENT_TYPES.has(message.contentType) ||
19
+ messageFileStore.has(message.clientMsgID);
18
20
  export const createTextMessage = async (text) => {
19
21
  let textMessage = await DChatSDK.createTextMessage(text, new Date().getTime().toString())
20
22
  .then(({ data }) => {
@@ -81,13 +83,30 @@ export const createUrlTextMessage = async (text, urls) => {
81
83
  });
82
84
  return textMessage;
83
85
  };
86
+ export const createQuoteMessage = async (text, quotedMessage) => {
87
+ let textMessage = await DChatSDK.createQuoteMessage({
88
+ text,
89
+ message: JSON.stringify(quotedMessage),
90
+ })
91
+ .then(({ data }) => {
92
+ return data;
93
+ })
94
+ .catch(({ errCode, errMsg }) => {
95
+ console.error("createQuoteMessage", errCode, errMsg);
96
+ return null;
97
+ });
98
+ return textMessage;
99
+ };
84
100
  export const useSendMessage = () => {
85
101
  const { user } = useChatContext();
102
+ const { t } = useTranslation("common");
86
103
  const conversationData = useConversationStore((state) => state.conversationData);
104
+ const quotedMessage = useConversationStore((state) => state.quotedMessage);
105
+ const setQuotedMessage = useConversationStore((state) => state.setQuotedMessage);
87
106
  const { userID: recvID, groupID } = conversationData || {};
88
107
  const dispatchMessage = useCallback(async (message) => {
89
108
  var _a;
90
- const desc = generateContentBasedOnMessageType(message.contentType, ((_a = message === null || message === void 0 ? void 0 : message.textElem) === null || _a === void 0 ? void 0 : _a.content) || "") || "Bạn có tin nhắn mới";
109
+ const desc = generateContentBasedOnMessageType(message.contentType, ((_a = message === null || message === void 0 ? void 0 : message.textElem) === null || _a === void 0 ? void 0 : _a.content) || "") || t("new_message");
91
110
  const { data: successMessage } = await DChatSDK.sendMessage({
92
111
  recvID: recvID || "",
93
112
  groupID: groupID || "",
@@ -124,7 +143,8 @@ export const useSendMessage = () => {
124
143
  if (!storedFiles) {
125
144
  let newTextPayload = null;
126
145
  const textContent = ((_a = failedMessage.textElem) === null || _a === void 0 ? void 0 : _a.content) || failedMessage.content || "";
127
- if (failedMessage.contentType === MessageType.UrlTextMessage && failedMessage.urlTextElem) {
146
+ if (failedMessage.contentType === MessageType.UrlTextMessage &&
147
+ failedMessage.urlTextElem) {
128
148
  newTextPayload = await createUrlTextMessage(textContent, failedMessage.urlTextElem.urls);
129
149
  }
130
150
  else {
@@ -204,7 +224,11 @@ export const useSendMessage = () => {
204
224
  const urls = extractLinks(plainText);
205
225
  const isUrlMessage = urls.length > 0;
206
226
  let message = null;
207
- if (isUrlMessage) {
227
+ if (!!(quotedMessage === null || quotedMessage === void 0 ? void 0 : quotedMessage.clientMsgID)) {
228
+ message = await createQuoteMessage(plainText, quotedMessage);
229
+ setQuotedMessage(null);
230
+ }
231
+ else if (isUrlMessage) {
208
232
  message = await createUrlTextMessage(plainText, urls);
209
233
  }
210
234
  else {
@@ -218,7 +242,7 @@ export const useSendMessage = () => {
218
242
  });
219
243
  let messageItem = Object.assign(Object.assign({}, message), { ex: JSON.stringify(extendMessageInfo) || "{}" });
220
244
  sendMessage(messageItem);
221
- }, [recvID, groupID, user, sendMessage]);
245
+ }, [recvID, groupID, user, sendMessage, quotedMessage, setQuotedMessage]);
222
246
  const sendMergeMessage = useCallback(async ({ richText, plainText, files, currentSession, }) => {
223
247
  if (!recvID && !groupID)
224
248
  return;
@@ -313,20 +337,27 @@ export const useSendMessage = () => {
313
337
  }
314
338
  }
315
339
  if (!!plainText && plainText.trim() !== "") {
316
- const textMessage = await createTextMessage(plainText);
340
+ let textMessage = null;
341
+ if (quotedMessage) {
342
+ textMessage = await createQuoteMessage(plainText, quotedMessage);
343
+ setQuotedMessage(null);
344
+ }
345
+ else {
346
+ textMessage = await createTextMessage(plainText);
347
+ }
317
348
  if (!textMessage)
318
349
  return;
319
350
  messageList.push(textMessage);
320
351
  }
321
352
  for (const message of messageList) {
322
353
  const extendMessageInfo = generateExtendMessageInfo({
323
- richText,
354
+ richText: (message === null || message === void 0 ? void 0 : message.contentType) === MessageType.TextMessage ? richText : "",
324
355
  currentSession,
325
356
  });
326
357
  const mMessage = Object.assign(Object.assign({}, message), { ex: JSON.stringify(extendMessageInfo) || "{}" });
327
358
  await sendMessage(mMessage);
328
359
  }
329
- }, [recvID, groupID, sendMessage]);
360
+ }, [recvID, groupID, sendMessage, quotedMessage, setQuotedMessage]);
330
361
  return {
331
362
  sendTextMessage,
332
363
  sendMergeMessage,
@@ -0,0 +1,8 @@
1
+ import { BaseResponse } from "../../types/dto";
2
+ interface AssignSessionParams {
3
+ sessionId: string;
4
+ supporterId: string;
5
+ }
6
+ export declare const useAssignSession: () => import("@tanstack/react-query").UseMutationResult<BaseResponse<boolean>, Error, AssignSessionParams, unknown>;
7
+ export {};
8
+ //# sourceMappingURL=useAssignSession.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAssignSession.d.ts","sourceRoot":"","sources":["../../../src/hooks/session/useAssignSession.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAG/C,UAAU,mBAAmB;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,eAAO,MAAM,gBAAgB,qHAazB,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { useMutation } from "@tanstack/react-query";
2
+ import { QUERY_KEYS } from "../../services/query";
3
+ import { apiInstance } from "../../services/api";
4
+ import { ENDPOINTS } from "../../services/routes";
5
+ import useAuthStore from "../../store/auth";
6
+ export const useAssignSession = () => useMutation({
7
+ mutationKey: [QUERY_KEYS.ASSIGN_SESSION],
8
+ mutationFn: async ({ sessionId, supporterId }) => {
9
+ const res = await apiInstance.post(ENDPOINTS.chatService.assignSession(sessionId), {
10
+ applicationType: useAuthStore.getState().applicationType,
11
+ supporterId,
12
+ });
13
+ return res === null || res === void 0 ? void 0 : res.data;
14
+ },
15
+ });
@@ -1 +1 @@
1
- {"version":3,"file":"useCreateNote.d.ts","sourceRoot":"","sources":["../../../src/hooks/session/useCreateNote.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,eAAO,MAAM,aAAa;oBAQJ,MAAM;aACb,MAAM;cACL,MAAM;WAgBlB,CAAC"}
1
+ {"version":3,"file":"useCreateNote.d.ts","sourceRoot":"","sources":["../../../src/hooks/session/useCreateNote.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAG/C,eAAO,MAAM,aAAa;oBAQJ,MAAM;aACb,MAAM;cACL,MAAM;WAgBlB,CAAC"}
@@ -2,6 +2,7 @@ import { useMutation } from "@tanstack/react-query";
2
2
  import { QUERY_KEYS } from "../../services/query";
3
3
  import { apiInstance } from "../../services/api";
4
4
  import { ENDPOINTS } from "../../services/routes";
5
+ import { DChatApplicationType } from "../../types/chat";
5
6
  export const useCreateNote = () => useMutation({
6
7
  mutationKey: [QUERY_KEYS.CREATE_NOTE],
7
8
  mutationFn: async ({ conversationId, content, targetId, }) => {
@@ -11,7 +12,7 @@ export const useCreateNote = () => useMutation({
11
12
  targetId,
12
13
  targetType: "USER",
13
14
  }, {
14
- params: { applicationType: "OBEFE" },
15
+ params: { applicationType: DChatApplicationType.OBEFE },
15
16
  });
16
17
  return res === null || res === void 0 ? void 0 : res.data;
17
18
  },
@@ -0,0 +1,8 @@
1
+ import { ISupporterResponse } from "../../types/dto";
2
+ interface UseGetTeamSupportersParams {
3
+ teamId: string;
4
+ search?: string;
5
+ }
6
+ export declare const useGetTeamSupporters: ({ teamId, search, }: UseGetTeamSupportersParams) => import("@tanstack/react-query").UseQueryResult<ISupporterResponse[], Error>;
7
+ export {};
8
+ //# sourceMappingURL=useGetTeamSupporters.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useGetTeamSupporters.d.ts","sourceRoot":"","sources":["../../../src/hooks/session/useGetTeamSupporters.ts"],"names":[],"mappings":"AAIA,OAAO,EAAgB,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAGnE,UAAU,0BAA0B;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,eAAO,MAAM,oBAAoB,GAAI,qBAGlC,0BAA0B,gFAiBzB,CAAC"}
@@ -0,0 +1,20 @@
1
+ import { useQuery, keepPreviousData } from "@tanstack/react-query";
2
+ import { QUERY_KEYS } from "../../services/query";
3
+ import { apiInstance } from "../../services/api";
4
+ import { ENDPOINTS } from "../../services/routes";
5
+ import useAuthStore from "../../store/auth";
6
+ export const useGetTeamSupporters = ({ teamId, search, }) => useQuery({
7
+ queryKey: [QUERY_KEYS.GET_TEAM_SUPPORTERS, teamId, search],
8
+ queryFn: async () => {
9
+ var _a;
10
+ const res = await apiInstance.get(ENDPOINTS.chatService.getTeamSupporters(teamId), {
11
+ params: {
12
+ applicationType: useAuthStore.getState().applicationType,
13
+ search: search || null,
14
+ },
15
+ });
16
+ return (_a = res === null || res === void 0 ? void 0 : res.data) === null || _a === void 0 ? void 0 : _a.data;
17
+ },
18
+ enabled: !!teamId,
19
+ placeholderData: keepPreviousData,
20
+ });
package/dist/index.d.ts CHANGED
@@ -12,6 +12,7 @@ export { default as qs } from "query-string";
12
12
  export * from "antd/es/table";
13
13
  export { ChatProvider, useChatContext } from "./context/ChatContext";
14
14
  export { DChatDeskMessage, DChatBubble, Icon };
15
+ export { default as RichTextEditor } from "./components/richTextEditor/RichTextEditor";
15
16
  export { useDChatAuth } from "./hooks/user/useAuth";
16
17
  export { useUpdateFcmToken } from "./hooks/user/useUpdateFcmToken";
17
18
  export { useUserStore, DChatApplicationType, useAuthStore };
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,gBAAgB,CAAC;AAExB,OAAO,gBAAgB,MAAM,uBAAuB,CAAC;AACrD,OAAO,WAAW,MAAM,sBAAsB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC1E,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACzC,OAAO,YAAY,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,uBAAuB,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAC7E,OAAO,YAAY,MAAM,cAAc,CAAC;AACxC,cAAc,QAAQ,CAAC;AACvB,OAAO,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAC/B,OAAO,EAAE,OAAO,IAAI,EAAE,EAAE,MAAM,cAAc,CAAC;AAC7C,cAAc,eAAe,CAAC;AAG9B,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAGrE,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;AAG/C,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AAGnE,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,YAAY,EAAE,CAAC;AAI5D,OAAO,EACL,QAAQ,IAAI,aAAa,EACzB,QAAQ,IAAI,aAAa,EACzB,WAAW,IAAI,gBAAgB,GAChC,CAAC;AAEF,YAAY,EAAE,uBAAuB,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,gBAAgB,CAAC;AAExB,OAAO,gBAAgB,MAAM,uBAAuB,CAAC;AACrD,OAAO,WAAW,MAAM,sBAAsB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC1E,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACzC,OAAO,YAAY,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,uBAAuB,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AAC7E,OAAO,YAAY,MAAM,cAAc,CAAC;AACxC,cAAc,QAAQ,CAAC;AACvB,OAAO,EAAE,KAAK,EAAE,MAAM,QAAQ,CAAC;AAC/B,OAAO,EAAE,OAAO,IAAI,EAAE,EAAE,MAAM,cAAc,CAAC;AAC7C,cAAc,eAAe,CAAC;AAG9B,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAGrE,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC;AAC/C,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,4CAA4C,CAAC;AAGvF,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AAGnE,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,YAAY,EAAE,CAAC;AAI5D,OAAO,EACL,QAAQ,IAAI,aAAa,EACzB,QAAQ,IAAI,aAAa,EACzB,WAAW,IAAI,gBAAgB,GAChC,CAAC;AAEF,YAAY,EAAE,uBAAuB,EAAE,CAAC"}
package/dist/index.js CHANGED
@@ -14,6 +14,7 @@ export * from "antd/es/table";
14
14
  export { ChatProvider, useChatContext } from "./context/ChatContext";
15
15
  //Components
16
16
  export { DChatDeskMessage, DChatBubble, Icon };
17
+ export { default as RichTextEditor } from "./components/richTextEditor/RichTextEditor";
17
18
  //Hooks
18
19
  export { useDChatAuth } from "./hooks/user/useAuth";
19
20
  export { useUpdateFcmToken } from "./hooks/user/useUpdateFcmToken";