@pubuduth-aplicy/chat-ui 2.1.73 → 2.1.75

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.
@@ -3,73 +3,98 @@ import { FileType } from "../components/common/FilePreview";
3
3
  import { getApiClient } from "../lib/api/apiClient";
4
4
  import { Path } from "../lib/api/endpoint";
5
5
 
6
- export const sendMessage = async ({ chatId,senderId, message,attachments }: { chatId: any; senderId:any; message: string,attachments: { type: FileType; url: string; name: string; size: number; }[] }) => {
7
- const apiClient = getApiClient();
8
- console.log("sendMessage", chatId, senderId, message, attachments); // Log the parameters
9
-
10
- const response = await apiClient.post(`${Path.sendmessage}/${chatId}/${senderId}`, {
11
- message:message,
12
- attachments:attachments
13
- })
14
- return response.data;
6
+ export const sendMessage = async (params: {
7
+ receiverId: string;
8
+ senderId: string;
9
+ message: string;
10
+ attachments: { type: FileType; url: string; name: string; size: number }[];
11
+ bookingId?: string;
12
+ serviceTitle?: string;
13
+ type?: "personal" | "service";
14
+ serviceId?: string;
15
+ }) => {
16
+ const {
17
+ receiverId,
18
+ senderId,
19
+ message,
20
+ attachments,
21
+ bookingId,
22
+ serviceTitle,
23
+ type,
24
+ serviceId,
25
+ } = params;
26
+ const apiClient = getApiClient();
27
+
28
+ const response = await apiClient.post(
29
+ `${Path.sendmessage}/${receiverId}/${senderId}`,
30
+ {
31
+ message,
32
+ attachments,
33
+ bookingId,
34
+ serviceTitle,
35
+ type,
36
+ serviceId,
37
+ }
38
+ );
39
+ return response.data;
15
40
  };
16
41
 
17
42
 
18
- export const fetchMessages = async (chatId: string|undefined, userid: string,pagenum:number) => {
19
- const apiClient = getApiClient();
20
- try {
21
- const response = await apiClient.get(`${Path.getmessage}/${chatId}/${userid}`,{
22
- params: { pagenum, limit: 20 },
23
- });
24
- console.log(response); // Check the full response
25
- return response.data; // Ensure 'data' exists or adjust accordingly
26
- } catch (error) {
27
- console.error("Error fetching messages:", error);
28
- return []; // Return a default empty array on error
29
- }
43
+ export const fetchMessages = async (chatId: string | undefined, userid: string, pagenum: number) => {
44
+ const apiClient = getApiClient();
45
+ try {
46
+ const response = await apiClient.get(`${Path.getmessage}/${chatId}/${userid}`, {
47
+ params: { pagenum, limit: 20 },
48
+ });
49
+ console.log(response);
50
+ return response.data;
51
+ } catch (error) {
52
+ console.error("Error fetching messages:", error);
53
+ return [];
54
+ }
30
55
  };
31
56
 
32
57
  export const setEditMessage = async ({
33
- messageId,
34
- userId,
35
- newMessage
36
- }: {
37
- messageId: string;
38
- userId: string;
39
- newMessage: string;
40
- }) => {
41
- const apiClient = getApiClient();
42
- try {
43
- const response = await apiClient.put(`${Path.editMessage}/${messageId}`, {
44
- userId,
45
- newMessage
46
- });
47
- return response.data;
48
- } catch (error) {
49
- console.error("Error editing message:", error);
50
- throw error;
51
- }
52
- };
58
+ messageId,
59
+ userId,
60
+ newMessage
61
+ }: {
62
+ messageId: string;
63
+ userId: string;
64
+ newMessage: string;
65
+ }) => {
66
+ const apiClient = getApiClient();
67
+ try {
68
+ const response = await apiClient.put(`${Path.editMessage}/${messageId}`, {
69
+ userId,
70
+ newMessage
71
+ });
72
+ return response.data;
73
+ } catch (error) {
74
+ console.error("Error editing message:", error);
75
+ throw error;
76
+ }
77
+ };
53
78
 
54
79
 
55
80
  export const deleteMessage = async ({
56
- messageId,
57
- userId
58
- }: {
59
- messageId: string;
60
- userId: string;
61
- }) => {
62
- const apiClient = getApiClient();
63
- try {
64
- const response = await apiClient.delete(
65
- `${Path.deleteMessage}/${messageId}`,
66
- {
67
- data: { userId } // Sending userId in the request body
68
- }
69
- );
70
- return response.data;
71
- } catch (error) {
72
- console.error("Error deleting message:", error);
73
- throw error;
74
- }
75
- };
81
+ messageId,
82
+ userId
83
+ }: {
84
+ messageId: string;
85
+ userId: string;
86
+ }) => {
87
+ const apiClient = getApiClient();
88
+ try {
89
+ const response = await apiClient.delete(
90
+ `${Path.deleteMessage}/${messageId}`,
91
+ {
92
+ data: { userId }
93
+ }
94
+ );
95
+ return response.data;
96
+ } catch (error) {
97
+ console.error("Error deleting message:", error);
98
+ throw error;
99
+ }
100
+ };
@@ -9,19 +9,16 @@ export const getAllConversationData = async (userid: string) => {
9
9
  try {
10
10
  const {role} = getChatConfig();
11
11
  const apiClient = getApiClient();
12
- //create common variable and assign the value of role
13
- // check if the user is an admin
14
- //create url for admon and user
12
+
15
13
  const endpoint = role === 'admin'
16
14
  ? `${Path.getConversationListByAdmin}`
17
15
  : `${Path.getconversation}/${userid}`;
18
- //create url for admon and user
16
+
19
17
  const res = await apiClient.get<ApiResponse>(endpoint);
20
18
  if (res.data) {
21
19
  console.log("API Response: ", res.data);
22
20
 
23
21
  }
24
- // Access conversations with participant details from the API response
25
22
  const conversationsWithParticipantDetails = res.data.serviceInfo;
26
23
  console.log("conversationsWithParticipantDetails", res.data.serviceInfo);
27
24
 
@@ -14,6 +14,11 @@ interface ChatUIState {
14
14
  };
15
15
  unreadMessageIds?: string[];
16
16
  _id: string;
17
+ type?: 'personal' | 'service';
18
+ bookingId?: string;
19
+ title?: string;
20
+ serviceId?: string;
21
+ serviceTitle?: string;
17
22
  } | null;
18
23
  setSelectedConversation: (
19
24
  selectedConversation: ChatUIState["selectedConversation"]
@@ -39,10 +44,10 @@ interface ChatUIState {
39
44
  setMessages: (messages: ChatUIState["messages"] | ((prev: ChatUIState["messages"]) => ChatUIState["messages"])) => void;
40
45
  updateMessageStatus: (messageId: string, status: string) => void;
41
46
  toggleChat: () => void;
42
- incrementUnreadCount: () => void;
43
47
  onlineUsers: string[];
44
48
  setOnlineUsers: (users: string[]) => void;
45
- resetUnreadCount: () => void;
49
+ searchTerm: string;
50
+ setSearchTerm: (searchTerm: string) => void;
46
51
  }
47
52
 
48
53
  const useChatUIStore = create<ChatUIState>((set) => ({
@@ -64,8 +69,8 @@ const useChatUIStore = create<ChatUIState>((set) => ({
64
69
  toggleChat: () => set((state) => ({ isChatOpen: !state.isChatOpen })),
65
70
  onlineUsers: [],
66
71
  setOnlineUsers: (users) => set({ onlineUsers: users }),
67
- incrementUnreadCount: () => set((state) => ({ unreadCount: state.unreadCount + 1 })),
68
- resetUnreadCount: () => set({ unreadCount: 0 }),
72
+ searchTerm: "",
73
+ setSearchTerm: (searchTerm) => set({ searchTerm }),
69
74
  }));
70
75
 
71
76
  export default useChatUIStore;
@@ -1645,4 +1645,264 @@
1645
1645
  margin: 16px auto;
1646
1646
  padding: 20px;
1647
1647
  }
1648
+ }
1649
+
1650
+ .circular-progress-container {
1651
+ position: relative;
1652
+ width: 100%;
1653
+ height: 120px;
1654
+ border-radius: 12px;
1655
+ overflow: hidden;
1656
+ display: flex;
1657
+ align-items: center;
1658
+ justify-content: center;
1659
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
1660
+ }
1661
+
1662
+ .media-preview-background {
1663
+ position: absolute;
1664
+ top: 0;
1665
+ left: 0;
1666
+ width: 100%;
1667
+ height: 100%;
1668
+ /* z-index: 1; */
1669
+ }
1670
+
1671
+ .blurred-preview {
1672
+ width: 100%;
1673
+ object-fit: cover;
1674
+ filter: blur(3px) brightness(0.6);
1675
+ }
1676
+
1677
+ .circular-progress {
1678
+ position: relative;
1679
+ z-index: 2;
1680
+ display: flex;
1681
+ align-items: center;
1682
+ justify-content: center;
1683
+ width: 80px;
1684
+ height: 80px;
1685
+ }
1686
+
1687
+ .circular-progress-svg {
1688
+ width: 100%;
1689
+ height: 100%;
1690
+ transform: rotate(-90deg);
1691
+ }
1692
+
1693
+ .circular-progress-track {
1694
+ fill: none;
1695
+ stroke: rgba(255, 255, 255, 0.3);
1696
+ stroke-width: 3;
1697
+ }
1698
+
1699
+ .circular-progress-bar {
1700
+ fill: none;
1701
+ stroke: #ffffff;
1702
+ stroke-width: 3;
1703
+ stroke-linecap: round;
1704
+ transition: stroke-dasharray 0.5s ease-in-out;
1705
+ filter: drop-shadow(0 0 4px rgba(255, 255, 255, 0.5));
1706
+ }
1707
+
1708
+ .circular-progress-text {
1709
+ position: absolute;
1710
+ top: 50%;
1711
+ left: 50%;
1712
+ transform: translate(-50%, -50%);
1713
+ color: #ffffff;
1714
+ font-size: 16px;
1715
+ font-weight: 700;
1716
+ text-shadow: 0 2px 4px rgba(0, 0, 0, 0.8);
1717
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
1718
+ }
1719
+
1720
+ /* Smooth animation for progress updates */
1721
+ .circular-progress-bar {
1722
+ animation: progress-smooth 0.3s ease-out;
1723
+ }
1724
+
1725
+ @keyframes progress-smooth {
1726
+ from {
1727
+ opacity: 0.7;
1728
+ }
1729
+
1730
+ to {
1731
+ opacity: 1;
1732
+ }
1733
+ }
1734
+
1735
+ /* Pulse animation while uploading */
1736
+ .circular-progress-container:not([data-complete="true"]) .circular-progress {
1737
+ animation: upload-pulse 2s ease-in-out infinite;
1738
+ }
1739
+
1740
+ @keyframes upload-pulse {
1741
+
1742
+ 0%,
1743
+ 100% {
1744
+ transform: scale(1);
1745
+ opacity: 1;
1746
+ }
1747
+
1748
+ 50% {
1749
+ transform: scale(1.05);
1750
+ opacity: 0.9;
1751
+ }
1752
+ }
1753
+
1754
+ /* Completion state */
1755
+ .circular-progress-container[data-complete="true"] .circular-progress-bar {
1756
+ stroke: #22c55e;
1757
+ animation: completion-flash 0.6s ease-out;
1758
+ }
1759
+
1760
+ .circular-progress-container[data-complete="true"] .circular-progress-text {
1761
+ color: #22c55e;
1762
+ }
1763
+
1764
+ @keyframes completion-flash {
1765
+ 0% {
1766
+ stroke: #ffffff;
1767
+ }
1768
+
1769
+ 50% {
1770
+ stroke: #22c55e;
1771
+ filter: drop-shadow(0 0 8px rgba(34, 197, 94, 0.8));
1772
+ }
1773
+
1774
+ 100% {
1775
+ stroke: #22c55e;
1776
+ filter: drop-shadow(0 0 4px rgba(34, 197, 94, 0.5));
1777
+ }
1778
+ }
1779
+
1780
+ /* Error state */
1781
+ .circular-progress-container[data-error="true"] .circular-progress-bar {
1782
+ stroke: #ef4444;
1783
+ }
1784
+
1785
+ .circular-progress-container[data-error="true"] .circular-progress-text {
1786
+ color: #ef4444;
1787
+ }
1788
+
1789
+ /* Responsive adjustments */
1790
+ @media (max-width: 768px) {
1791
+ .circular-progress-container {
1792
+ width: 100px;
1793
+ height: 100px;
1794
+ }
1795
+
1796
+ .circular-progress {
1797
+ width: 70px;
1798
+ height: 70px;
1799
+ }
1800
+
1801
+ .circular-progress-text {
1802
+ font-size: 14px;
1803
+ }
1804
+ }
1805
+
1806
+ /* Optional: Add a subtle background overlay */
1807
+ .circular-progress-container::before {
1808
+ content: '';
1809
+ position: absolute;
1810
+ top: 0;
1811
+ left: 0;
1812
+ width: 100%;
1813
+ height: 100%;
1814
+ background: rgba(0, 0, 0, 0.2);
1815
+ /* z-index: 1; */
1816
+ }
1817
+
1818
+ .confirm-button {
1819
+ background: linear-gradient(135deg, #2AA8A6, #1E9C9A);
1820
+ color: white;
1821
+ border: none;
1822
+ padding: 12px 24px;
1823
+ border-radius: 8px;
1824
+ font-weight: 600;
1825
+ font-size: 16px;
1826
+ cursor: pointer;
1827
+ display: flex;
1828
+ align-items: center;
1829
+ justify-content: center;
1830
+ gap: 8px;
1831
+ margin-top: 16px;
1832
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
1833
+ transition: all 0.3s ease;
1834
+ position: relative;
1835
+ overflow: hidden;
1836
+ }
1837
+
1838
+ .confirm-button:hover {
1839
+ background: linear-gradient(135deg, #1E9C9A, #168A88);
1840
+ transform: translateY(-2px);
1841
+ box-shadow: 0 6px 8px rgba(0, 0, 0, 0.15);
1842
+ }
1843
+
1844
+ .confirm-button:active {
1845
+ transform: translateY(0);
1846
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
1847
+ }
1848
+
1849
+ .confirm-button::before {
1850
+ content: '';
1851
+ position: absolute;
1852
+ top: 0;
1853
+ left: -100%;
1854
+ width: 100%;
1855
+ height: 100%;
1856
+ background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent);
1857
+ transition: 0.5s;
1858
+ }
1859
+
1860
+ .confirm-button:hover::before {
1861
+ left: 100%;
1862
+ }
1863
+
1864
+ .confirm-button svg {
1865
+ transition: transform 0.3s ease;
1866
+ }
1867
+
1868
+ .confirm-button:hover svg {
1869
+ transform: scale(1.1);
1870
+ }
1871
+
1872
+
1873
+ .message-option-btn.disabled {
1874
+ opacity: 0.5;
1875
+ cursor: not-allowed;
1876
+ pointer-events: none;
1877
+ }
1878
+
1879
+ .message-option-btn[disabled] {
1880
+ opacity: 0.5;
1881
+ cursor: not-allowed;
1882
+ }
1883
+
1884
+ /* Tooltip styles */
1885
+ .message-option-btn {
1886
+ position: relative;
1887
+ overflow: hidden;
1888
+ }
1889
+
1890
+ .message-option-btn:hover::before {
1891
+ content: attr(title);
1892
+ position: absolute;
1893
+ bottom: 100%;
1894
+ left: 50%;
1895
+ transform: translateX(-50%);
1896
+ background: #333;
1897
+ color: white;
1898
+ padding: 4px 8px;
1899
+ border-radius: 4px;
1900
+ font-size: 12px;
1901
+ white-space: nowrap;
1902
+ z-index: 10;
1903
+ margin-bottom: 5px;
1904
+ }
1905
+
1906
+ .message-option-btn.disabled:hover::before {
1907
+ background: #666;
1648
1908
  }
package/src/types/type.ts CHANGED
@@ -25,50 +25,47 @@ export interface Conversation {
25
25
  _id: string;
26
26
  senderId: string;
27
27
  message: string;
28
+ media: string[];
29
+ type?: 'user' | 'system' | 'system-completion';
30
+ status: MessageStatus;
28
31
  chatId: string;
29
32
  createdAt: string;
30
33
  updatedAt: string;
31
34
  __v: number;
32
- },
35
+ };
33
36
  updatedAt: string;
34
37
  __v: number;
35
38
  participantDetails: ParticipantDetails;
39
+ participants?: string[];
40
+ // readReceipts?: string[] | [];
41
+ unreadMessageIds: string[];
42
+ type?: string | undefined;
43
+ bookingId?: string;
44
+ serviceId?: string;
45
+ unreadMessageCount?: number
46
+ serviceTitle?: string;
47
+ }
48
+
49
+ export interface ServiceConversationGroup {
50
+ serviceId: string;
51
+ serviceTitle: string;
52
+ conversations: Conversation[];
36
53
  }
37
54
 
38
- export interface ServiceInfo {
39
- conversationsWithParticipantDetails: Conversation[];
55
+ export interface ParticipantGroup {
56
+ participantDetails: ParticipantDetails;
57
+ personalConversation: Conversation | null;
58
+ serviceConversations: ServiceConversationGroup[];
40
59
  }
41
60
 
42
61
  export interface ApiResponse {
43
62
  success: boolean;
44
63
  message: string;
45
- serviceInfo: Conversation[];
64
+ serviceInfo: ParticipantGroup[];
46
65
  }
47
66
 
48
67
  export interface ConversationProps {
49
- conversation: {
50
- lastMessage: {
51
- _id: string;
52
- senderId: string;
53
- message: string;
54
- media: string[];
55
- type?: 'user' | 'system' | 'system-completion';
56
- status: MessageStatus;
57
- chatId: string;
58
- createdAt: string;
59
- updatedAt: string;
60
- __v: number;
61
- },
62
- participantDetails: {
63
- _id: string;
64
- profilePic: string;
65
- firstname: string;
66
- idpic: string;
67
-
68
- },
69
- unreadMessageIds: string[];
70
- _id: string;
71
- };
68
+ conversation: Conversation;
72
69
  lastIdx: boolean;
73
70
  }
74
71
 
@@ -1,15 +0,0 @@
1
- // import { ChatWindowProps } from "./types/type";
2
-
3
-
4
- // export const ChatWindow: React.FC<ChatWindowProps> = ({ userId}) => {
5
- // // const { messages, sendMessage, sendFile } = useChat(userId);
6
- // // const [file, setFile] = useState<File | null>(null);
7
-
8
- // return (
9
- // <div className="w-full max-w-lg border p-4 rounded-lg shadow-lg bg-white">
10
- // <MessageList messages={messages} />
11
- // <FileUploader file={file} setFile={setFile} onUpload={sendFile} />
12
- // <MessageInput onSend={sendMessage} />
13
- // </div>
14
- // );
15
- // };