@open-mercato/ui 0.4.6-develop-06c0791dc9 → 0.4.6-develop-acc34d004a
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.
|
@@ -2,30 +2,20 @@
|
|
|
2
2
|
import * as React from "react";
|
|
3
3
|
import { apiCall } from "../utils/apiCall.js";
|
|
4
4
|
const POLL_INTERVAL = 5e3;
|
|
5
|
-
function useMessagesPoll(
|
|
6
|
-
const enabled = options?.enabled ?? true;
|
|
5
|
+
function useMessagesPoll() {
|
|
7
6
|
const [messages, setMessages] = React.useState([]);
|
|
8
7
|
const [unreadCount, setUnreadCount] = React.useState(0);
|
|
9
8
|
const [hasNew, setHasNew] = React.useState(false);
|
|
10
|
-
const [isLoading, setIsLoading] = React.useState(
|
|
9
|
+
const [isLoading, setIsLoading] = React.useState(true);
|
|
11
10
|
const [error, setError] = React.useState(null);
|
|
12
11
|
const lastMessageIdRef = React.useRef(null);
|
|
13
12
|
const pulseTimeoutRef = React.useRef(null);
|
|
14
13
|
const fetchMessages = React.useCallback(async () => {
|
|
15
|
-
if (!enabled) return;
|
|
16
14
|
try {
|
|
17
15
|
const [listResult, countResult] = await Promise.all([
|
|
18
16
|
apiCall("/api/messages?folder=inbox&page=1&pageSize=20"),
|
|
19
17
|
apiCall("/api/messages/unread-count")
|
|
20
18
|
]);
|
|
21
|
-
const accessDenied = listResult.status === 403 || countResult.status === 403;
|
|
22
|
-
if (accessDenied) {
|
|
23
|
-
setMessages([]);
|
|
24
|
-
setUnreadCount(0);
|
|
25
|
-
setHasNew(false);
|
|
26
|
-
setError(null);
|
|
27
|
-
return;
|
|
28
|
-
}
|
|
29
19
|
if (listResult.ok) {
|
|
30
20
|
const nextMessages = Array.isArray(listResult.result?.items) ? listResult.result?.items ?? [] : [];
|
|
31
21
|
const firstId = nextMessages[0]?.id ?? null;
|
|
@@ -53,18 +43,8 @@ function useMessagesPoll(options) {
|
|
|
53
43
|
} finally {
|
|
54
44
|
setIsLoading(false);
|
|
55
45
|
}
|
|
56
|
-
}, [
|
|
46
|
+
}, []);
|
|
57
47
|
React.useEffect(() => {
|
|
58
|
-
if (!enabled) {
|
|
59
|
-
setMessages([]);
|
|
60
|
-
setUnreadCount(0);
|
|
61
|
-
setHasNew(false);
|
|
62
|
-
setError(null);
|
|
63
|
-
setIsLoading(false);
|
|
64
|
-
lastMessageIdRef.current = null;
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
setIsLoading(true);
|
|
68
48
|
void fetchMessages();
|
|
69
49
|
const interval = window.setInterval(() => {
|
|
70
50
|
void fetchMessages();
|
|
@@ -75,15 +55,14 @@ function useMessagesPoll(options) {
|
|
|
75
55
|
window.clearTimeout(pulseTimeoutRef.current);
|
|
76
56
|
}
|
|
77
57
|
};
|
|
78
|
-
}, [
|
|
58
|
+
}, [fetchMessages]);
|
|
79
59
|
return {
|
|
80
60
|
messages,
|
|
81
61
|
unreadCount,
|
|
82
62
|
hasNew,
|
|
83
63
|
isLoading,
|
|
84
64
|
error,
|
|
85
|
-
refresh:
|
|
86
|
-
}
|
|
65
|
+
refresh: fetchMessages
|
|
87
66
|
};
|
|
88
67
|
}
|
|
89
68
|
export {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/backend/messages/useMessagesPoll.ts"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { apiCall } from '../utils/apiCall'\n\nexport type MessagePollItem = {\n id: string\n type: string\n subject: string\n bodyPreview: string\n senderUserId: string\n senderName?: string | null\n senderEmail?: string | null\n priority: string\n status: string\n hasObjects: boolean\n objectCount: number\n hasAttachments: boolean\n attachmentCount: number\n hasActions: boolean\n actionTaken?: string | null\n sentAt?: string | null\n readAt?: string | null\n threadId?: string | null\n}\n\nexport type UseMessagesPollResult = {\n messages: MessagePollItem[]\n unreadCount: number\n hasNew: boolean\n isLoading: boolean\n error: string | null\n refresh: () => Promise<void>\n}\n\nconst POLL_INTERVAL = 5000\n\nexport
|
|
5
|
-
"mappings": ";AAEA,YAAY,WAAW;AACvB,SAAS,eAAe;AAgCxB,MAAM,gBAAgB;
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { apiCall } from '../utils/apiCall'\n\nexport type MessagePollItem = {\n id: string\n type: string\n subject: string\n bodyPreview: string\n senderUserId: string\n senderName?: string | null\n senderEmail?: string | null\n priority: string\n status: string\n hasObjects: boolean\n objectCount: number\n hasAttachments: boolean\n attachmentCount: number\n hasActions: boolean\n actionTaken?: string | null\n sentAt?: string | null\n readAt?: string | null\n threadId?: string | null\n}\n\nexport type UseMessagesPollResult = {\n messages: MessagePollItem[]\n unreadCount: number\n hasNew: boolean\n isLoading: boolean\n error: string | null\n refresh: () => Promise<void>\n}\n\nconst POLL_INTERVAL = 5000\n\nexport function useMessagesPoll(): UseMessagesPollResult {\n const [messages, setMessages] = React.useState<MessagePollItem[]>([])\n const [unreadCount, setUnreadCount] = React.useState(0)\n const [hasNew, setHasNew] = React.useState(false)\n const [isLoading, setIsLoading] = React.useState(true)\n const [error, setError] = React.useState<string | null>(null)\n\n const lastMessageIdRef = React.useRef<string | null>(null)\n const pulseTimeoutRef = React.useRef<number | null>(null)\n\n const fetchMessages = React.useCallback(async () => {\n try {\n const [listResult, countResult] = await Promise.all([\n apiCall<{ items?: MessagePollItem[] }>('/api/messages?folder=inbox&page=1&pageSize=20'),\n apiCall<{ unreadCount?: number }>('/api/messages/unread-count'),\n ])\n\n if (listResult.ok) {\n const nextMessages = Array.isArray(listResult.result?.items) ? listResult.result?.items ?? [] : []\n const firstId = nextMessages[0]?.id ?? null\n\n if (lastMessageIdRef.current && firstId && firstId !== lastMessageIdRef.current) {\n setHasNew(true)\n if (pulseTimeoutRef.current) {\n window.clearTimeout(pulseTimeoutRef.current)\n }\n pulseTimeoutRef.current = window.setTimeout(() => {\n setHasNew(false)\n pulseTimeoutRef.current = null\n }, 3000)\n }\n\n lastMessageIdRef.current = firstId\n setMessages(nextMessages)\n }\n\n if (countResult.ok) {\n const nextCount = Number(countResult.result?.unreadCount ?? 0)\n setUnreadCount(Number.isFinite(nextCount) ? Math.max(0, nextCount) : 0)\n }\n\n setError(null)\n } catch (err) {\n const message = err instanceof Error ? err.message : 'Failed to poll messages'\n setError(message)\n } finally {\n setIsLoading(false)\n }\n }, [])\n\n React.useEffect(() => {\n void fetchMessages()\n const interval = window.setInterval(() => {\n void fetchMessages()\n }, POLL_INTERVAL)\n\n return () => {\n window.clearInterval(interval)\n if (pulseTimeoutRef.current) {\n window.clearTimeout(pulseTimeoutRef.current)\n }\n }\n }, [fetchMessages])\n\n return {\n messages,\n unreadCount,\n hasNew,\n isLoading,\n error,\n refresh: fetchMessages,\n }\n}\n"],
|
|
5
|
+
"mappings": ";AAEA,YAAY,WAAW;AACvB,SAAS,eAAe;AAgCxB,MAAM,gBAAgB;AAEf,SAAS,kBAAyC;AACvD,QAAM,CAAC,UAAU,WAAW,IAAI,MAAM,SAA4B,CAAC,CAAC;AACpE,QAAM,CAAC,aAAa,cAAc,IAAI,MAAM,SAAS,CAAC;AACtD,QAAM,CAAC,QAAQ,SAAS,IAAI,MAAM,SAAS,KAAK;AAChD,QAAM,CAAC,WAAW,YAAY,IAAI,MAAM,SAAS,IAAI;AACrD,QAAM,CAAC,OAAO,QAAQ,IAAI,MAAM,SAAwB,IAAI;AAE5D,QAAM,mBAAmB,MAAM,OAAsB,IAAI;AACzD,QAAM,kBAAkB,MAAM,OAAsB,IAAI;AAExD,QAAM,gBAAgB,MAAM,YAAY,YAAY;AAClD,QAAI;AACF,YAAM,CAAC,YAAY,WAAW,IAAI,MAAM,QAAQ,IAAI;AAAA,QAClD,QAAuC,+CAA+C;AAAA,QACtF,QAAkC,4BAA4B;AAAA,MAChE,CAAC;AAED,UAAI,WAAW,IAAI;AACjB,cAAM,eAAe,MAAM,QAAQ,WAAW,QAAQ,KAAK,IAAI,WAAW,QAAQ,SAAS,CAAC,IAAI,CAAC;AACjG,cAAM,UAAU,aAAa,CAAC,GAAG,MAAM;AAEvC,YAAI,iBAAiB,WAAW,WAAW,YAAY,iBAAiB,SAAS;AAC/E,oBAAU,IAAI;AACd,cAAI,gBAAgB,SAAS;AAC3B,mBAAO,aAAa,gBAAgB,OAAO;AAAA,UAC7C;AACA,0BAAgB,UAAU,OAAO,WAAW,MAAM;AAChD,sBAAU,KAAK;AACf,4BAAgB,UAAU;AAAA,UAC5B,GAAG,GAAI;AAAA,QACT;AAEA,yBAAiB,UAAU;AAC3B,oBAAY,YAAY;AAAA,MAC1B;AAEA,UAAI,YAAY,IAAI;AAClB,cAAM,YAAY,OAAO,YAAY,QAAQ,eAAe,CAAC;AAC7D,uBAAe,OAAO,SAAS,SAAS,IAAI,KAAK,IAAI,GAAG,SAAS,IAAI,CAAC;AAAA,MACxE;AAEA,eAAS,IAAI;AAAA,IACf,SAAS,KAAK;AACZ,YAAM,UAAU,eAAe,QAAQ,IAAI,UAAU;AACrD,eAAS,OAAO;AAAA,IAClB,UAAE;AACA,mBAAa,KAAK;AAAA,IACpB;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,UAAU,MAAM;AACpB,SAAK,cAAc;AACnB,UAAM,WAAW,OAAO,YAAY,MAAM;AACxC,WAAK,cAAc;AAAA,IACrB,GAAG,aAAa;AAEhB,WAAO,MAAM;AACX,aAAO,cAAc,QAAQ;AAC7B,UAAI,gBAAgB,SAAS;AAC3B,eAAO,aAAa,gBAAgB,OAAO;AAAA,MAC7C;AAAA,IACF;AAAA,EACF,GAAG,CAAC,aAAa,CAAC;AAElB,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,SAAS;AAAA,EACX;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-mercato/ui",
|
|
3
|
-
"version": "0.4.6-develop-
|
|
3
|
+
"version": "0.4.6-develop-acc34d004a",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -116,7 +116,7 @@
|
|
|
116
116
|
}
|
|
117
117
|
},
|
|
118
118
|
"dependencies": {
|
|
119
|
-
"@open-mercato/shared": "0.4.6-develop-
|
|
119
|
+
"@open-mercato/shared": "0.4.6-develop-acc34d004a",
|
|
120
120
|
"@radix-ui/react-popover": "^1.1.6",
|
|
121
121
|
"@radix-ui/react-tooltip": "^1.2.8",
|
|
122
122
|
"date-fns": "^4.1.0",
|
|
@@ -35,38 +35,23 @@ export type UseMessagesPollResult = {
|
|
|
35
35
|
|
|
36
36
|
const POLL_INTERVAL = 5000
|
|
37
37
|
|
|
38
|
-
export
|
|
39
|
-
enabled?: boolean
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export function useMessagesPoll(options?: UseMessagesPollOptions): UseMessagesPollResult {
|
|
43
|
-
const enabled = options?.enabled ?? true
|
|
38
|
+
export function useMessagesPoll(): UseMessagesPollResult {
|
|
44
39
|
const [messages, setMessages] = React.useState<MessagePollItem[]>([])
|
|
45
40
|
const [unreadCount, setUnreadCount] = React.useState(0)
|
|
46
41
|
const [hasNew, setHasNew] = React.useState(false)
|
|
47
|
-
const [isLoading, setIsLoading] = React.useState(
|
|
42
|
+
const [isLoading, setIsLoading] = React.useState(true)
|
|
48
43
|
const [error, setError] = React.useState<string | null>(null)
|
|
49
44
|
|
|
50
45
|
const lastMessageIdRef = React.useRef<string | null>(null)
|
|
51
46
|
const pulseTimeoutRef = React.useRef<number | null>(null)
|
|
52
47
|
|
|
53
48
|
const fetchMessages = React.useCallback(async () => {
|
|
54
|
-
if (!enabled) return
|
|
55
49
|
try {
|
|
56
50
|
const [listResult, countResult] = await Promise.all([
|
|
57
51
|
apiCall<{ items?: MessagePollItem[] }>('/api/messages?folder=inbox&page=1&pageSize=20'),
|
|
58
52
|
apiCall<{ unreadCount?: number }>('/api/messages/unread-count'),
|
|
59
53
|
])
|
|
60
54
|
|
|
61
|
-
const accessDenied = listResult.status === 403 || countResult.status === 403
|
|
62
|
-
if (accessDenied) {
|
|
63
|
-
setMessages([])
|
|
64
|
-
setUnreadCount(0)
|
|
65
|
-
setHasNew(false)
|
|
66
|
-
setError(null)
|
|
67
|
-
return
|
|
68
|
-
}
|
|
69
|
-
|
|
70
55
|
if (listResult.ok) {
|
|
71
56
|
const nextMessages = Array.isArray(listResult.result?.items) ? listResult.result?.items ?? [] : []
|
|
72
57
|
const firstId = nextMessages[0]?.id ?? null
|
|
@@ -98,20 +83,9 @@ export function useMessagesPoll(options?: UseMessagesPollOptions): UseMessagesPo
|
|
|
98
83
|
} finally {
|
|
99
84
|
setIsLoading(false)
|
|
100
85
|
}
|
|
101
|
-
}, [
|
|
86
|
+
}, [])
|
|
102
87
|
|
|
103
88
|
React.useEffect(() => {
|
|
104
|
-
if (!enabled) {
|
|
105
|
-
setMessages([])
|
|
106
|
-
setUnreadCount(0)
|
|
107
|
-
setHasNew(false)
|
|
108
|
-
setError(null)
|
|
109
|
-
setIsLoading(false)
|
|
110
|
-
lastMessageIdRef.current = null
|
|
111
|
-
return
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
setIsLoading(true)
|
|
115
89
|
void fetchMessages()
|
|
116
90
|
const interval = window.setInterval(() => {
|
|
117
91
|
void fetchMessages()
|
|
@@ -123,7 +97,7 @@ export function useMessagesPoll(options?: UseMessagesPollOptions): UseMessagesPo
|
|
|
123
97
|
window.clearTimeout(pulseTimeoutRef.current)
|
|
124
98
|
}
|
|
125
99
|
}
|
|
126
|
-
}, [
|
|
100
|
+
}, [fetchMessages])
|
|
127
101
|
|
|
128
102
|
return {
|
|
129
103
|
messages,
|
|
@@ -131,6 +105,6 @@ export function useMessagesPoll(options?: UseMessagesPollOptions): UseMessagesPo
|
|
|
131
105
|
hasNew,
|
|
132
106
|
isLoading,
|
|
133
107
|
error,
|
|
134
|
-
refresh:
|
|
108
|
+
refresh: fetchMessages,
|
|
135
109
|
}
|
|
136
110
|
}
|