@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(options) {
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(enabled);
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
- }, [enabled]);
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
- }, [enabled, fetchMessages]);
58
+ }, [fetchMessages]);
79
59
  return {
80
60
  messages,
81
61
  unreadCount,
82
62
  hasNew,
83
63
  isLoading,
84
64
  error,
85
- refresh: enabled ? fetchMessages : async () => {
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 type UseMessagesPollOptions = {\n enabled?: boolean\n}\n\nexport function useMessagesPoll(options?: UseMessagesPollOptions): UseMessagesPollResult {\n const enabled = options?.enabled ?? true\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(enabled)\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 if (!enabled) return\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 const accessDenied = listResult.status === 403 || countResult.status === 403\n if (accessDenied) {\n setMessages([])\n setUnreadCount(0)\n setHasNew(false)\n setError(null)\n return\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 }, [enabled])\n\n React.useEffect(() => {\n if (!enabled) {\n setMessages([])\n setUnreadCount(0)\n setHasNew(false)\n setError(null)\n setIsLoading(false)\n lastMessageIdRef.current = null\n return\n }\n\n setIsLoading(true)\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 }, [enabled, fetchMessages])\n\n return {\n messages,\n unreadCount,\n hasNew,\n isLoading,\n error,\n refresh: enabled ? fetchMessages : async () => {},\n }\n}\n"],
5
- "mappings": ";AAEA,YAAY,WAAW;AACvB,SAAS,eAAe;AAgCxB,MAAM,gBAAgB;AAMf,SAAS,gBAAgB,SAAyD;AACvF,QAAM,UAAU,SAAS,WAAW;AACpC,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,OAAO;AACxD,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,CAAC,QAAS;AACd,QAAI;AACF,YAAM,CAAC,YAAY,WAAW,IAAI,MAAM,QAAQ,IAAI;AAAA,QAClD,QAAuC,+CAA+C;AAAA,QACtF,QAAkC,4BAA4B;AAAA,MAChE,CAAC;AAED,YAAM,eAAe,WAAW,WAAW,OAAO,YAAY,WAAW;AACzE,UAAI,cAAc;AAChB,oBAAY,CAAC,CAAC;AACd,uBAAe,CAAC;AAChB,kBAAU,KAAK;AACf,iBAAS,IAAI;AACb;AAAA,MACF;AAEA,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,OAAO,CAAC;AAEZ,QAAM,UAAU,MAAM;AACpB,QAAI,CAAC,SAAS;AACZ,kBAAY,CAAC,CAAC;AACd,qBAAe,CAAC;AAChB,gBAAU,KAAK;AACf,eAAS,IAAI;AACb,mBAAa,KAAK;AAClB,uBAAiB,UAAU;AAC3B;AAAA,IACF;AAEA,iBAAa,IAAI;AACjB,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,SAAS,aAAa,CAAC;AAE3B,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,SAAS,UAAU,gBAAgB,YAAY;AAAA,IAAC;AAAA,EAClD;AACF;",
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-06c0791dc9",
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-06c0791dc9",
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 type UseMessagesPollOptions = {
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(enabled)
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
- }, [enabled])
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
- }, [enabled, fetchMessages])
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: enabled ? fetchMessages : async () => {},
108
+ refresh: fetchMessages,
135
109
  }
136
110
  }