@kodiak-finance/orderly-ui-notification 2.8.18-rc.0

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.
package/dist/index.mjs ADDED
@@ -0,0 +1,859 @@
1
+ import { useMemo, useState, useEffect, useCallback } from 'react';
2
+ import { useTranslation } from '@kodiak-finance/orderly-i18n';
3
+ import { Flex, Text, cn, ChevronDownIcon, ScrollArea, Divider, Icon, ExtensionSlot, ExtensionPositionEnum, ChevronLeftIcon, ChevronRightIcon } from '@kodiak-finance/orderly-ui';
4
+ import { AnnouncementType, EMPTY_LIST } from '@kodiak-finance/orderly-types';
5
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
6
+ import { UTCDate, UTCDateMini } from '@date-fns/utc';
7
+ import { differenceInHours, differenceInMinutes, format } from 'date-fns';
8
+ import { produce } from 'immer';
9
+ import { useOrderlyContext, useLocalStorage, useWS, useMaintenanceStatus, useQuery, MaintenanceStatus } from '@kodiak-finance/orderly-hooks';
10
+ import { useAppContext } from '@kodiak-finance/orderly-react-app';
11
+
12
+ // src/components/announcementCenter/announcementCenter.ui.tsx
13
+ var BattleIcon = (props) => {
14
+ return /* @__PURE__ */ jsxs(Icon, { size: 18, viewBox: "0 0 18 18", ...props, children: [
15
+ /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs(
16
+ "linearGradient",
17
+ {
18
+ id: "paint0_linear_555_7374",
19
+ x1: "17.0157",
20
+ y1: "9.26513",
21
+ x2: "0.969849",
22
+ y2: "9.26513",
23
+ gradientUnits: "userSpaceOnUse",
24
+ children: [
25
+ /* @__PURE__ */ jsx("stop", { stopColor: "rgb(var(--oui-gradient-brand-end))" }),
26
+ /* @__PURE__ */ jsx("stop", { offset: "1", stopColor: "rgb(var(--oui-gradient-brand-start))" })
27
+ ]
28
+ }
29
+ ) }),
30
+ /* @__PURE__ */ jsx(
31
+ "path",
32
+ {
33
+ fill: "url(#paint0_linear_555_7374)",
34
+ fillOpacity: 1,
35
+ d: "m1.5 1.5.75 3 4.843 4.56-1.808 1.919-.63-.633-1.06 1.06.665.665-1.88 1.996-.35-.346-1.06 1.06 2.25 2.25 1.06-1.06-.348-.349 1.998-1.878.665.662 1.06-1.06-.63-.63L9 10.852l1.969 1.854-.639.639 1.06 1.06.672-.67 1.998 1.877-.358.358 1.064 1.06 2.25-2.25-1.06-1.06-.34.34-1.881-1.998.656-.657-1.06-1.06-.625.624-1.799-1.91.003-.003L9 7.03 4.5 2.25zm15 0-3 .75-3.636 3.861 2.022 2.025L15.75 4.5z"
36
+ }
37
+ )
38
+ ] });
39
+ };
40
+ var CampaignIcon = (props) => {
41
+ return /* @__PURE__ */ jsx(Icon, { size: 18, viewBox: "0 0 18 18", ...props, children: /* @__PURE__ */ jsx(
42
+ "path",
43
+ {
44
+ fill: "currentcolor",
45
+ fillOpacity: 1,
46
+ d: "m1.5 1.5.75 3 4.843 4.56-1.808 1.919-.63-.633-1.06 1.06.665.665-1.88 1.996-.35-.346-1.06 1.06 2.25 2.25 1.06-1.06-.348-.349 1.998-1.878.665.662 1.06-1.06-.63-.63L9 10.852l1.969 1.854-.639.639 1.06 1.06.672-.67 1.998 1.877-.358.358 1.064 1.06 2.25-2.25-1.06-1.06-.34.34-1.881-1.998.656-.657-1.06-1.06-.625.624-1.799-1.91.003-.003L9 7.03 4.5 2.25zm15 0-3 .75-3.636 3.861 2.022 2.025L15.75 4.5z"
47
+ }
48
+ ) });
49
+ };
50
+ var ArrowRightShortIcon = (props) => {
51
+ return /* @__PURE__ */ jsxs(Icon, { size: 18, viewBox: "0 0 18 18", ...props, children: [
52
+ /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs(
53
+ "linearGradient",
54
+ {
55
+ id: "paint0_linear_555_7374",
56
+ x1: "17.0157",
57
+ y1: "9.26513",
58
+ x2: "0.969849",
59
+ y2: "9.26513",
60
+ gradientUnits: "userSpaceOnUse",
61
+ children: [
62
+ /* @__PURE__ */ jsx("stop", { stopColor: "rgb(var(--oui-gradient-brand-end))" }),
63
+ /* @__PURE__ */ jsx("stop", { offset: "1", stopColor: "rgb(var(--oui-gradient-brand-start))" })
64
+ ]
65
+ }
66
+ ) }),
67
+ /* @__PURE__ */ jsx(
68
+ "path",
69
+ {
70
+ fill: "url(#paint0_linear_555_7374)",
71
+ fillOpacity: 1,
72
+ d: "M4.509 8.995a.75.75 0 0 1 .75-.75h5.666L8.7 5.998l1.054-1.054 3.535 3.512c.147.146.22.343.22.54a.76.76 0 0 1-.22.537l-3.535 3.512L8.7 11.992l2.225-2.248H5.258a.75.75 0 0 1-.749-.75"
73
+ }
74
+ )
75
+ ] });
76
+ };
77
+ var FundIcon = (props) => {
78
+ return /* @__PURE__ */ jsx(Icon, { size: 18, viewBox: "0 0 18 18", ...props, children: /* @__PURE__ */ jsx(
79
+ "path",
80
+ {
81
+ fill: "currentcolor",
82
+ fillOpacity: 0.8,
83
+ d: "M15.694 7.087c-.788-.393-1.857-.618-2.925-.618-1.125 0-2.138.225-2.925.618-.056 0-.113.057-.113.057V3.769c0-.9-.731-1.575-1.462-1.913-.788-.394-1.857-.619-2.925-.619-1.069 0-2.25.225-3.038.62C1.575 2.193.844 2.868.844 3.768v10.519c0 .9.731 1.575 1.462 1.912.788.394 1.856.619 2.925.619s2.138-.225 2.925-.619c.281-.169.563-.337.788-.562.225.225.506.393.787.562.788.394 1.857.619 2.925.619 1.125 0 2.138-.225 2.925-.619.732-.394 1.463-1.012 1.463-1.912V9c.112-.9-.619-1.519-1.35-1.913m-7.369 7.144c0 .113-.112.45-.731.732-.563.28-1.407.506-2.363.506s-1.8-.169-2.362-.506c-.619-.282-.731-.62-.731-.732V13.5c.056 0 .112 0 .168.056.788.394 1.856.619 2.925.619s2.138-.225 2.925-.619c.056 0 .113-.056.113-.056v.731zm0-2.587c0 .112-.112.45-.731.731-.563.281-1.407.506-2.363.506s-1.8-.168-2.362-.506c-.619-.281-.731-.619-.731-.731v-.788c.056 0 .112.056.112.056.788.394 1.856.62 2.925.62s2.138-.226 2.925-.62c.056 0 .113-.056.113-.056v.788zm0-2.644c0 .112-.112.45-.731.731-.563.281-1.407.507-2.363.507s-1.8-.17-2.362-.507C2.25 9.45 2.138 9.112 2.138 9v-.788c.056 0 .112.057.112.057.788.393 1.856.618 2.925.618S7.313 8.662 8.1 8.27c.056 0 .113-.057.113-.057V9zm0-2.644c0 .113-.112.45-.731.731-.563.282-1.407.507-2.363.507s-1.8-.169-2.362-.507c-.619-.28-.731-.618-.731-.73v-.732c.056 0 .112 0 .168.056.788.394 1.856.619 2.925.619s2.138-.225 2.925-.619c.056 0 .113-.056.113-.056v.731zM7.594 4.5c-.563.281-1.407.506-2.363.506S3.488 4.781 2.925 4.5c-.619-.338-.731-.619-.731-.731 0-.113.112-.45.731-.732.563-.28 1.406-.506 2.363-.506.956 0 1.8.169 2.362.506.619.282.731.62.731.732-.056.112-.168.393-.787.731m8.212 9.731c0 .113-.112.45-.731.732-.562.28-1.406.506-2.362.506s-1.8-.169-2.363-.506c-.619-.282-.731-.62-.731-.732V13.5c.056 0 .112.056.112.056.788.394 1.857.619 2.925.619 1.125 0 2.138-.225 2.925-.619.056 0 .113-.056.113-.056v.731zm0-2.587c0 .112-.112.45-.731.731-.562.281-1.406.506-2.362.506s-1.8-.168-2.363-.506c-.619-.281-.731-.619-.731-.731v-.788c.056 0 .112.056.112.056.788.394 1.857.62 2.925.62 1.125 0 2.138-.226 2.925-.62.056 0 .113-.056.113-.056v.788zm-.675-1.913c-.562.281-1.406.507-2.362.507s-1.8-.17-2.363-.507c-.619-.281-.731-.619-.731-.731 0-.113.112-.45.731-.731.563-.282 1.406-.507 2.363-.507.956 0 1.8.17 2.362.507.619.281.732.618.732.731-.057.112-.17.45-.732.731"
84
+ }
85
+ ) });
86
+ };
87
+ var AnnouncementIcon = (props) => {
88
+ return /* @__PURE__ */ jsx(Icon, { size: 18, viewBox: "0 0 18 18", ...props, children: /* @__PURE__ */ jsx(
89
+ "path",
90
+ {
91
+ fill: "currentcolor",
92
+ fillOpacity: 0.8,
93
+ d: "M11.53 2.255a.745.745 0 0 0-.82.165c-.525.524-1.188.959-1.947 1.284-.77.33-2.353.757-3.508.75-2.248-.015-3.756 1.259-3.756 3.726 0 2.163 1.228 3.42 2.994 3.703l.006 1.565a2.25 2.25 0 0 0 2.25 2.247c1.142 0 2.083-.883 2.228-1.988.007-.053.022-.26.022-1.01.674.315 1.232.812 1.711 1.29.473.472 1.29.13 1.29-.538 0-.678-.004-1.906-.004-3.13.884-.327 1.503-1.165 1.503-2.115s-.585-1.81-1.496-2.129c0-1.225-.004-2.439-.004-3.117a.76.76 0 0 0-.469-.703m1.805 1.335a.73.73 0 0 0-.445.351.75.75 0 0 0 .258 1.03 3.74 3.74 0 0 1 1.851 3.233 3.74 3.74 0 0 1-1.851 3.231.76.76 0 0 0-.282 1.03.754.754 0 0 0 1.032.258 5.24 5.24 0 0 0 2.601-4.52 5.24 5.24 0 0 0-2.601-4.519.74.74 0 0 0-.563-.094m-2.832.884c0 .694-.004 1.417-.004 2.231v2.997c0 .815.003 1.508.003 2.202-1.52-.896-3.085-1.294-4.501-1.421 0-1.144-.004-3.406-.004-4.584.147-.007.318-.026.565-.06a11.2 11.2 0 0 0 2.812-.773c.43-.184.75-.35 1.129-.592m-6.005 1.55-.001 4.34c-.976-.27-1.498-.959-1.498-2.184 0-1.21.47-1.928 1.499-2.155M6 11.998c.238.008 1.098.161 1.493.261l.007 1.19a.75.75 0 0 1-1.5 0z"
94
+ }
95
+ ) });
96
+ };
97
+ var SecurityIcon = (props) => {
98
+ return /* @__PURE__ */ jsxs(Icon, { size: 18, viewBox: "0 0 18 18", ...props, children: [
99
+ /* @__PURE__ */ jsx(
100
+ "path",
101
+ {
102
+ d: "M6.563 7.678V6.603c0-1.153 1.09-2.088 2.437-2.088s2.438.935 2.438 2.088v1.075c.448 0 .812.311.812.696v3.479c0 .384-.364.696-.812.696H6.563c-.449 0-.813-.312-.813-.696v-3.48c0-.384.364-.695.813-.695m1.187-.006 1.431.006h1.07V6.564c0-.64-.504-1.104-1.25-1.104-.748 0-1.25.465-1.25 1.104zm1.956 2.14c0-.335-.317-.605-.706-.605-.39 0-.706.27-.706.604v.77c0 .335.316.605.706.605s.706-.27.706-.604z",
103
+ fill: "currentcolor",
104
+ fillOpacity: ".8"
105
+ }
106
+ ),
107
+ /* @__PURE__ */ jsx(
108
+ "path",
109
+ {
110
+ d: "M2 3.607c.003 5.606.146 11.651 6.879 13.378.078.02.164.02.242 0C15.854 15.258 15.997 9.213 16 3.607c0-.217-.14-.41-.345-.477L9.31 1.05a1 1 0 0 0-.62 0L2.345 3.13A.5.5 0 0 0 2 3.607m2.326 7.63c-.707-1.954-.81-4.33-.824-6.902L9 2.532l5.498 1.803c-.014 2.573-.117 4.948-.824 6.901-.697 1.93-1.987 3.463-4.674 4.222-2.687-.759-3.977-2.293-4.674-4.222",
111
+ fill: "currentcolor",
112
+ fillOpacity: ".8"
113
+ }
114
+ )
115
+ ] });
116
+ };
117
+ var AnnouncementItem = (props) => {
118
+ const { t } = useTranslation();
119
+ const Icon2 = useMemo(() => {
120
+ switch (props.type) {
121
+ case AnnouncementType.Campaign:
122
+ return CampaignIcon;
123
+ case AnnouncementType.Listing:
124
+ return FundIcon;
125
+ case AnnouncementType.Maintenance:
126
+ return SecurityIcon;
127
+ case AnnouncementType.Delisting:
128
+ default:
129
+ return AnnouncementIcon;
130
+ }
131
+ }, [props.type]);
132
+ const title = useMemo(() => {
133
+ switch (props.type) {
134
+ case AnnouncementType.Campaign:
135
+ return t("notification.campaign");
136
+ case AnnouncementType.Delisting:
137
+ return t("notification.delisting");
138
+ case AnnouncementType.Listing:
139
+ return t("notification.listing");
140
+ case AnnouncementType.Maintenance:
141
+ return t("notification.maintenance");
142
+ default:
143
+ return t("notification.general");
144
+ }
145
+ }, [props.type, t]);
146
+ const action = useMemo(() => {
147
+ if (props.type === AnnouncementType.Campaign && typeof props.url === "string" && props.url !== "" && typeof props.onItemClick === "function") {
148
+ return /* @__PURE__ */ jsxs(
149
+ Flex,
150
+ {
151
+ gap: 1,
152
+ itemAlign: "center",
153
+ className: "oui-cursor-pointer",
154
+ onClick: (event) => {
155
+ event.stopPropagation();
156
+ props.onItemClick(props.url);
157
+ },
158
+ children: [
159
+ /* @__PURE__ */ jsx(
160
+ Text,
161
+ {
162
+ size: "xs",
163
+ color: "buy",
164
+ className: "oui-bg-clip-text oui-text-transparent oui-gradient-brand",
165
+ children: t("notification.joinNow")
166
+ }
167
+ ),
168
+ /* @__PURE__ */ jsx(ArrowRightShortIcon, { size: 18 })
169
+ ]
170
+ }
171
+ );
172
+ }
173
+ return null;
174
+ }, [props.type, props.url, t]);
175
+ const updateTime = useMemo(() => {
176
+ if (props.type === AnnouncementType.Maintenance) {
177
+ return /* @__PURE__ */ jsx(Text, { size: "2xs", intensity: 36, children: t("notification.recentlyUpdated") });
178
+ }
179
+ return /* @__PURE__ */ jsx(
180
+ Text.formatted,
181
+ {
182
+ size: "2xs",
183
+ intensity: 36,
184
+ rule: "date",
185
+ formatString: "yyyy-MM-dd HH:mm:ss",
186
+ children: props.updatedTime
187
+ }
188
+ );
189
+ }, [props.updatedTime, props.type, t]);
190
+ return /* @__PURE__ */ jsxs(
191
+ Flex,
192
+ {
193
+ gap: 2,
194
+ itemAlign: "start",
195
+ className: cn(
196
+ "oui-px-2 oui-py-[6px] oui-text-base-contrast-80",
197
+ !props.showDivider && "oui-rounded-md hover:oui-bg-base-6",
198
+ !props.showDivider && props.expanded && "oui-bg-base-6",
199
+ props.className
200
+ ),
201
+ onClick: () => {
202
+ props.onExpandToggle?.();
203
+ },
204
+ children: [
205
+ /* @__PURE__ */ jsx(Icon2, { color: "white", className: "oui-mt-3 oui-shrink-0" }),
206
+ /* @__PURE__ */ jsxs(Flex, { direction: "column", itemAlign: "start", grow: true, children: [
207
+ /* @__PURE__ */ jsx(Text, { size: "xs", intensity: 80, weight: "bold", children: title }),
208
+ updateTime,
209
+ /* @__PURE__ */ jsx(
210
+ "div",
211
+ {
212
+ className: "oui-grid oui-transition-all oui-duration-300 oui-ease-in-out",
213
+ style: {
214
+ gridTemplateRows: props.expanded ? "1fr" : "0fr"
215
+ },
216
+ children: /* @__PURE__ */ jsxs("div", { className: "oui-flex oui-flex-col oui-gap-2 oui-overflow-hidden", children: [
217
+ /* @__PURE__ */ jsx(Text, { size: "2xs", intensity: 80, as: "div", className: "oui-pt-2", children: props.message }),
218
+ action
219
+ ] })
220
+ }
221
+ )
222
+ ] }),
223
+ /* @__PURE__ */ jsx("div", { className: "oui-pt-3", children: /* @__PURE__ */ jsx(
224
+ ChevronDownIcon,
225
+ {
226
+ color: "white",
227
+ size: 18,
228
+ className: `oui-transition-transform oui-duration-300 oui-ease-in-out ${props.expanded ? "oui-rotate-180" : "oui-rotate-0"}`
229
+ }
230
+ ) })
231
+ ]
232
+ }
233
+ );
234
+ };
235
+ var AnnouncementContent = (props) => {
236
+ const { dataSource, current, onExpandToggle, onItemClick } = props;
237
+ const { t } = useTranslation();
238
+ if (!Array.isArray(dataSource) || dataSource.length === 0) {
239
+ return /* @__PURE__ */ jsx("div", { className: "oui-flex oui-h-[160px] oui-items-center oui-justify-center", children: /* @__PURE__ */ jsx(
240
+ ExtensionSlot,
241
+ {
242
+ position: ExtensionPositionEnum.EmptyDataIdentifier,
243
+ title: t("notification.empty")
244
+ }
245
+ ) });
246
+ }
247
+ return /* @__PURE__ */ jsx(
248
+ "div",
249
+ {
250
+ className: cn(
251
+ "oui-flex oui-flex-col oui-space-y-1",
252
+ props.showDivider && "[&>*:not(:first-child)]:oui-border-t [&>*:not(:first-child)]:oui-border-line-12 [&>*:not(:first-child)]:oui-pt-1"
253
+ ),
254
+ children: dataSource.map((item) => /* @__PURE__ */ jsx(
255
+ AnnouncementItem,
256
+ {
257
+ url: item.url,
258
+ onItemClick,
259
+ message: item.message,
260
+ updatedTime: item.updated_time ?? 0,
261
+ expanded: current === item.announcement_id,
262
+ type: item.type,
263
+ showDivider: props.showDivider,
264
+ onExpandToggle: () => {
265
+ if (current === item.announcement_id) {
266
+ onExpandToggle(null);
267
+ } else {
268
+ onExpandToggle(item.announcement_id);
269
+ }
270
+ }
271
+ },
272
+ item.announcement_id
273
+ ))
274
+ }
275
+ );
276
+ };
277
+ var AnnouncementCenterUI = (props) => {
278
+ const { t } = useTranslation();
279
+ const [expanded, setExpanded] = useState(null);
280
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
281
+ /* @__PURE__ */ jsx("div", { className: "oui-px-5 oui-pt-4", children: /* @__PURE__ */ jsx(Text, { intensity: 80, weight: "bold", children: t("notification.title") }) }),
282
+ /* @__PURE__ */ jsx(ScrollArea, { className: "oui-flex oui-h-[300px] oui-flex-col oui-space-y-1 oui-p-3", children: /* @__PURE__ */ jsx(
283
+ AnnouncementContent,
284
+ {
285
+ dataSource: props.dataSource,
286
+ current: expanded,
287
+ onExpandToggle: setExpanded,
288
+ onItemClick: props.onItemClick
289
+ }
290
+ ) })
291
+ ] });
292
+ };
293
+ var CampaignContentCard = ({ message, coverImage, url, onItemClick }) => {
294
+ const { t } = useTranslation();
295
+ return /* @__PURE__ */ jsxs("div", { className: "oui-flex oui-flex-col oui-gap-5", children: [
296
+ /* @__PURE__ */ jsx(Text, { size: "sm", weight: "bold", children: message }),
297
+ /* @__PURE__ */ jsx(
298
+ "div",
299
+ {
300
+ className: "oui-rounded-xl oui-bg-base-9 oui-bg-cover oui-bg-center oui-bg-no-repeat",
301
+ style: {
302
+ backgroundImage: `url(${coverImage})`,
303
+ height: "100px"
304
+ }
305
+ }
306
+ ),
307
+ typeof url === "string" && url !== "" && typeof onItemClick === "function" && /* @__PURE__ */ jsxs(
308
+ "button",
309
+ {
310
+ className: "oui-flex oui-items-center oui-gap-1",
311
+ onClick: () => onItemClick(url),
312
+ children: [
313
+ /* @__PURE__ */ jsx(
314
+ Text,
315
+ {
316
+ size: "xs",
317
+ color: "buy",
318
+ className: "oui-bg-clip-text oui-text-transparent oui-gradient-brand",
319
+ children: t("notification.joinNow")
320
+ }
321
+ ),
322
+ /* @__PURE__ */ jsx(ArrowRightShortIcon, { size: 18, color: "success" })
323
+ ]
324
+ }
325
+ )
326
+ ] });
327
+ };
328
+ var MaintenanceContentCard = ({ message, startTime, endTime }) => {
329
+ const { t } = useTranslation();
330
+ const formattedMessage = useMemo(() => {
331
+ const hours = differenceInHours(endTime, startTime);
332
+ const minutes = differenceInMinutes(endTime, startTime) - hours * 60;
333
+ const startUtc = new UTCDate(startTime);
334
+ const endUtc = new UTCDate(endTime);
335
+ const startTimeFormatted = format(startUtc, "HH:mm");
336
+ const endTimeFormatted = format(endUtc, "hh:mm a");
337
+ if (hours > 0) {
338
+ return t("notification.maintenanceDuration.hours", {
339
+ hours: minutes > 0 ? (hours + minutes / 60).toFixed(1) : hours,
340
+ startTimeFormatted,
341
+ endTimeFormatted
342
+ });
343
+ }
344
+ return t("notification.maintenanceDuration.minutes", {
345
+ minutes,
346
+ startTimeFormatted,
347
+ endTimeFormatted
348
+ });
349
+ }, [startTime, endTime, t]);
350
+ return /* @__PURE__ */ jsxs("div", { className: "oui-flex oui-flex-col oui-gap-1", children: [
351
+ /* @__PURE__ */ jsx(Text, { size: "xs", intensity: 54, children: t("notification.recentlyUpdated") }),
352
+ /* @__PURE__ */ jsx(Flex, { itemAlign: "center", children: /* @__PURE__ */ jsx(Text, { size: "xs", weight: "bold", children: formattedMessage }) }),
353
+ message && /* @__PURE__ */ jsx(Text, { size: "2xs", intensity: 80, as: "div", className: "oui-mt-2", children: message })
354
+ ] });
355
+ };
356
+ var DelistingContentCard = ({ message, updateTime }) => {
357
+ return /* @__PURE__ */ jsxs("div", { className: "oui-flex oui-flex-col oui-gap-1", children: [
358
+ /* @__PURE__ */ jsx(
359
+ Text.formatted,
360
+ {
361
+ rule: "date",
362
+ intensity: 54,
363
+ formatString: "yyyy-MM-dd HH:mm:ss",
364
+ size: "xs",
365
+ children: updateTime
366
+ }
367
+ ),
368
+ /* @__PURE__ */ jsx(Text, { size: "sm", weight: "bold", children: message })
369
+ ] });
370
+ };
371
+ var ListingContentCard = ({ message, updateTime }) => {
372
+ return /* @__PURE__ */ jsxs("div", { className: "oui-flex oui-flex-col oui-gap-1", children: [
373
+ /* @__PURE__ */ jsx(
374
+ Text.formatted,
375
+ {
376
+ rule: "date",
377
+ intensity: 54,
378
+ formatString: "yyyy-MM-dd HH:mm:ss",
379
+ size: "xs",
380
+ children: updateTime
381
+ }
382
+ ),
383
+ /* @__PURE__ */ jsx(Text, { size: "sm", weight: "bold", children: message })
384
+ ] });
385
+ };
386
+ var NotificationHeader = (props) => {
387
+ const { t } = useTranslation();
388
+ const { expanded } = props;
389
+ const { type } = props.dataSource[props.current];
390
+ const title = useMemo(() => {
391
+ switch (type) {
392
+ case AnnouncementType.Campaign:
393
+ return /* @__PURE__ */ jsx(
394
+ Text,
395
+ {
396
+ size: "sm",
397
+ className: "oui-text-transparent oui-bg-clip-text oui-gradient-brand",
398
+ children: t("notification.campaign")
399
+ }
400
+ );
401
+ case AnnouncementType.Delisting:
402
+ return /* @__PURE__ */ jsx(Text, { size: "sm", children: t("notification.delistingTitle") });
403
+ case AnnouncementType.Listing:
404
+ return /* @__PURE__ */ jsx(Text, { size: "sm", color: "buy", children: t("notification.listing") });
405
+ case AnnouncementType.Maintenance:
406
+ return /* @__PURE__ */ jsx(Text, { size: "sm", color: "warning", children: t("notification.maintenanceTitle") });
407
+ default:
408
+ return /* @__PURE__ */ jsx(Text, { size: "sm", color: "inherit", children: t("notification.generalTitle") });
409
+ }
410
+ }, [type, t]);
411
+ const icon = useMemo(() => {
412
+ switch (type) {
413
+ case AnnouncementType.Campaign:
414
+ return /* @__PURE__ */ jsx(BattleIcon, { color: "white" });
415
+ case AnnouncementType.Listing:
416
+ return /* @__PURE__ */ jsx(FundIcon, { color: "success" });
417
+ case AnnouncementType.Maintenance:
418
+ return /* @__PURE__ */ jsx(SecurityIcon, { color: "warning" });
419
+ case AnnouncementType.Delisting:
420
+ default:
421
+ return /* @__PURE__ */ jsx(AnnouncementIcon, { color: "white" });
422
+ }
423
+ }, [type]);
424
+ return /* @__PURE__ */ jsxs(Flex, { itemAlign: "center", justify: "between", className: "oui-px-4 oui-py-3", children: [
425
+ /* @__PURE__ */ jsxs("div", { className: "orderly-notification-header oui-flex oui-items-center oui-gap-2", children: [
426
+ icon,
427
+ title
428
+ ] }),
429
+ /* @__PURE__ */ jsx(
430
+ "button",
431
+ {
432
+ onClick: props.onExpandToggle,
433
+ className: "oui-transition-transform oui-duration-300",
434
+ style: {
435
+ transform: !expanded ? "rotate(180deg)" : "rotate(0deg)"
436
+ },
437
+ children: /* @__PURE__ */ jsx(ChevronDownIcon, { size: 18, color: "white" })
438
+ }
439
+ )
440
+ ] });
441
+ };
442
+ var NotificationFooter = (props) => {
443
+ const { total, current, onCloseAll, onPrev, onNext } = props;
444
+ const { t } = useTranslation();
445
+ return /* @__PURE__ */ jsxs(
446
+ Flex,
447
+ {
448
+ className: "orderly-notification-footer oui-px-4 oui-py-2",
449
+ itemAlign: "center",
450
+ justify: "between",
451
+ children: [
452
+ /* @__PURE__ */ jsxs(Flex, { gap: 2, children: [
453
+ /* @__PURE__ */ jsx(
454
+ "button",
455
+ {
456
+ disabled: current - 1 < 0,
457
+ onClick: onPrev,
458
+ className: "oui-flex oui-size-[18px] oui-items-center oui-justify-center oui-rounded-full oui-bg-base-6 hover:oui-bg-base-5 disabled:oui-opacity-50",
459
+ children: /* @__PURE__ */ jsx(ChevronLeftIcon, { size: 14, color: "white" })
460
+ }
461
+ ),
462
+ /* @__PURE__ */ jsxs(Text, { intensity: 54, size: "sm", children: [
463
+ current + 1,
464
+ "/",
465
+ total
466
+ ] }),
467
+ /* @__PURE__ */ jsx(
468
+ "button",
469
+ {
470
+ disabled: current + 1 >= total,
471
+ onClick: onNext,
472
+ className: "oui-flex oui-size-[18px] oui-items-center oui-justify-center oui-rounded-full oui-bg-base-6 hover:oui-bg-base-5 disabled:oui-opacity-50",
473
+ children: /* @__PURE__ */ jsx(ChevronRightIcon, { size: 14, color: "white" })
474
+ }
475
+ )
476
+ ] }),
477
+ /* @__PURE__ */ jsx("button", { onClick: onCloseAll, children: /* @__PURE__ */ jsx(Text, { size: "xs", color: "primary", children: t("notification.closeAll", { total }) }) })
478
+ ]
479
+ }
480
+ );
481
+ };
482
+ var NotificationContent = (props) => {
483
+ const elements = useMemo(() => {
484
+ return props.dataSource.map((message) => {
485
+ const { type } = message;
486
+ switch (type) {
487
+ case AnnouncementType.Campaign:
488
+ return /* @__PURE__ */ jsx(
489
+ CampaignContentCard,
490
+ {
491
+ message: message.message,
492
+ coverImage: message.coverImage ?? "",
493
+ updateTime: message.updated_time ?? 0,
494
+ url: message.url ?? "",
495
+ onItemClick: props.onItemClick
496
+ }
497
+ );
498
+ case AnnouncementType.Maintenance:
499
+ return /* @__PURE__ */ jsx(
500
+ MaintenanceContentCard,
501
+ {
502
+ message: message.message,
503
+ startTime: message.startTime ?? 0,
504
+ endTime: message.endTime ?? 0
505
+ }
506
+ );
507
+ case AnnouncementType.Delisting:
508
+ return /* @__PURE__ */ jsx(
509
+ DelistingContentCard,
510
+ {
511
+ message: message.message,
512
+ updateTime: message.updated_time ?? 0
513
+ }
514
+ );
515
+ default:
516
+ return /* @__PURE__ */ jsx(
517
+ ListingContentCard,
518
+ {
519
+ message: message.message,
520
+ updateTime: message.updated_time ?? 0
521
+ }
522
+ );
523
+ }
524
+ });
525
+ }, [props.dataSource]);
526
+ return /* @__PURE__ */ jsx(Fragment, { children: elements[props.current] });
527
+ };
528
+ var NotificationUI = (props) => {
529
+ const [expanded, setExpanded] = useState(true);
530
+ const [current, setCurrent] = useState(0);
531
+ const len = useMemo(() => props.dataSource?.length ?? 0, [props.dataSource]);
532
+ if (len === 0) {
533
+ return null;
534
+ }
535
+ return /* @__PURE__ */ jsxs("div", { className: "orderly-notification oui-w-full ", children: [
536
+ /* @__PURE__ */ jsx(
537
+ NotificationHeader,
538
+ {
539
+ dataSource: props.dataSource ?? [],
540
+ current,
541
+ expanded,
542
+ onExpandToggle: () => {
543
+ setExpanded(!expanded);
544
+ }
545
+ }
546
+ ),
547
+ /* @__PURE__ */ jsx(Divider, { className: "oui-mx-4" }),
548
+ /* @__PURE__ */ jsx(
549
+ "div",
550
+ {
551
+ className: "oui-grid oui-transition-all oui-duration-300 oui-ease-in-out",
552
+ style: {
553
+ gridTemplateRows: expanded ? "1fr" : "0fr"
554
+ },
555
+ children: /* @__PURE__ */ jsx("div", { className: "oui-min-h-0 oui-overflow-hidden ", children: /* @__PURE__ */ jsx("div", { className: "oui-px-4 oui-py-3", children: /* @__PURE__ */ jsx(
556
+ NotificationContent,
557
+ {
558
+ dataSource: props.dataSource ?? [],
559
+ current,
560
+ onItemClick: props.onItemClick
561
+ }
562
+ ) }) })
563
+ }
564
+ ),
565
+ /* @__PURE__ */ jsx(
566
+ NotificationFooter,
567
+ {
568
+ total: len,
569
+ current,
570
+ onCloseAll: props.onClose ?? (() => {
571
+ }),
572
+ onPrev: () => {
573
+ if (current - 1 < 0) {
574
+ return;
575
+ }
576
+ setCurrent(current - 1);
577
+ },
578
+ onNext: () => {
579
+ if (current + 1 >= len) {
580
+ return;
581
+ }
582
+ setCurrent(current + 1);
583
+ }
584
+ }
585
+ )
586
+ ] });
587
+ };
588
+ var maintentanceId = "-1";
589
+ var ORDERLY_ANNOUNCEMENT_KEY = "orderly_announcement";
590
+ var getTimeString = (timestamp) => {
591
+ const date = format(new UTCDateMini(timestamp), "MMM dd");
592
+ const time = format(new UTCDateMini(timestamp), "h:mm aa");
593
+ return `${time} (UTC) on ${date}`;
594
+ };
595
+ var sortDataByUpdatedTime = (ori) => {
596
+ return produce(ori, (draft) => {
597
+ if (Array.isArray(draft.rows)) {
598
+ draft.rows.sort((a, b) => {
599
+ if (a.updated_time && b.updated_time) {
600
+ return b.updated_time - a.updated_time;
601
+ }
602
+ return 0;
603
+ });
604
+ }
605
+ });
606
+ };
607
+ var useAnnouncementData = () => {
608
+ const ws = useWS();
609
+ const [announcementStore, setStore] = useLocalStorage(
610
+ ORDERLY_ANNOUNCEMENT_KEY,
611
+ {}
612
+ );
613
+ const [tips, setTips] = useState({});
614
+ const [maintenanceDialogInfo, setMaintenanceDialogInfo] = useState();
615
+ const { startTime, endTime, status, brokerName } = useMaintenanceStatus();
616
+ const { t } = useTranslation();
617
+ const { data: announcements } = useQuery(
618
+ `/v2/public/announcement`,
619
+ {
620
+ revalidateOnFocus: false,
621
+ refreshInterval: 60 * 60 * 1e3,
622
+ // refresh every 1 hour
623
+ formatter: (data) => data
624
+ }
625
+ );
626
+ const getMaintentTipsContent = (brokerName2, startDate, endDate) => t("maintenance.tips.description", { brokerName: brokerName2, startDate, endDate });
627
+ const getMaintentDialogContent = (brokerName2, endDate) => t("maintenance.dialog.description", { brokerName: brokerName2, endDate });
628
+ useEffect(() => {
629
+ const unsubscribe = ws.subscribe("announcement", {
630
+ onMessage(message) {
631
+ if (message) {
632
+ setTips((prev) => {
633
+ return produce(prev, (draft) => {
634
+ if (!Array.isArray(draft.rows)) {
635
+ draft.rows = [];
636
+ }
637
+ const idx = draft.rows.findIndex(
638
+ (tip) => tip.announcement_id === message.announcement_id
639
+ );
640
+ if (idx !== -1) {
641
+ draft.rows.splice(idx, 1);
642
+ }
643
+ draft.rows.push({
644
+ announcement_id: message.announcement_id,
645
+ message: message.message,
646
+ url: message.url,
647
+ i18n: message.i18n,
648
+ type: message.type,
649
+ updated_time: message.updated_time
650
+ });
651
+ });
652
+ });
653
+ setStore((prev) => ({ ...prev, show: true }));
654
+ }
655
+ },
656
+ onError(err) {
657
+ }
658
+ });
659
+ return () => {
660
+ unsubscribe?.();
661
+ };
662
+ }, [ws]);
663
+ useEffect(() => {
664
+ if (!announcements?.rows) {
665
+ return;
666
+ }
667
+ const apiTime = announcements.last_updated_time ?? 0;
668
+ const cachedTime = announcementStore.lastUpdateTime ?? 0;
669
+ if (cachedTime < apiTime) {
670
+ setTips((prev) => ({ ...prev, rows: announcements?.rows }));
671
+ setStore({ show: true, lastUpdateTime: apiTime });
672
+ } else {
673
+ setTips((prev) => {
674
+ return produce(prev, (draft) => {
675
+ if (announcements?.rows?.length) {
676
+ const existingIds = new Set(
677
+ prev.rows?.map((tip) => tip.announcement_id)
678
+ );
679
+ const maintenanceTip = prev.rows?.find(
680
+ (tip) => tip.announcement_id === maintentanceId
681
+ );
682
+ draft.rows = [];
683
+ announcements.rows.forEach((item) => {
684
+ if (!existingIds.has(item.announcement_id)) {
685
+ draft.rows?.push(item);
686
+ }
687
+ });
688
+ if (maintenanceTip) {
689
+ draft.rows.unshift(maintenanceTip);
690
+ }
691
+ } else {
692
+ const idx = draft.rows?.findIndex(
693
+ (tip) => tip.announcement_id === maintentanceId
694
+ );
695
+ if (idx !== void 0 && idx !== -1) {
696
+ draft.rows?.splice(idx, 1);
697
+ }
698
+ }
699
+ });
700
+ });
701
+ }
702
+ }, [announcements]);
703
+ useEffect(() => {
704
+ const startDate = startTime ? getTimeString(startTime) : "-";
705
+ const endDate = endTime ? getTimeString(endTime) : "-";
706
+ if (status === MaintenanceStatus.Maintenance) {
707
+ setMaintenanceDialogInfo(getMaintentDialogContent(brokerName, endDate));
708
+ return;
709
+ }
710
+ setMaintenanceDialogInfo(void 0);
711
+ if (startTime && endTime) {
712
+ setTips(
713
+ (prev) => produce(prev, (draft) => {
714
+ if (!Array.isArray(draft.rows)) {
715
+ draft.rows = [];
716
+ }
717
+ draft.rows = [
718
+ {
719
+ announcement_id: maintentanceId,
720
+ type: AnnouncementType.Maintenance,
721
+ /** @ts-ignore */
722
+ startTime,
723
+ /** @ts-ignore */
724
+ endTime,
725
+ message: getMaintentTipsContent(brokerName, startDate, endDate)
726
+ },
727
+ ...draft.rows.filter(
728
+ (tip) => tip.type !== AnnouncementType.Maintenance
729
+ )
730
+ ];
731
+ })
732
+ );
733
+ } else {
734
+ setTips((prev) => {
735
+ return produce(prev, (draft) => {
736
+ const index = draft.rows?.findIndex(
737
+ (tip) => tip.announcement_id === maintentanceId
738
+ );
739
+ if (index !== void 0 && index !== -1) {
740
+ draft.rows?.splice(index, 1);
741
+ }
742
+ });
743
+ });
744
+ }
745
+ }, [startTime, endTime, status, brokerName, t]);
746
+ const { customAnnouncements } = useAppContext();
747
+ const mergedTips = useMemo(() => {
748
+ const tipsCopy = { ...tips };
749
+ if (customAnnouncements && customAnnouncements.length > 0) {
750
+ tipsCopy.rows = [...customAnnouncements, ...tips.rows || []];
751
+ }
752
+ return sortDataByUpdatedTime(tipsCopy);
753
+ }, [tips, customAnnouncements]);
754
+ return {
755
+ tips: mergedTips,
756
+ maintenanceDialogInfo
757
+ };
758
+ };
759
+ var useAnnouncement = (options) => {
760
+ const { showAnnouncement, setShowAnnouncement } = useAppContext();
761
+ const { dataAdapter } = useOrderlyContext();
762
+ const { tips: mergedTips, maintenanceDialogInfo } = useAnnouncementData();
763
+ const memoizedTips = useMemo(() => {
764
+ if (typeof dataAdapter?.announcementList === "function") {
765
+ return dataAdapter.announcementList(
766
+ mergedTips?.rows ?? EMPTY_LIST
767
+ );
768
+ }
769
+ return mergedTips?.rows ?? EMPTY_LIST;
770
+ }, [dataAdapter?.announcementList, mergedTips?.rows]);
771
+ const [announcementStore, setStore] = useLocalStorage(
772
+ ORDERLY_ANNOUNCEMENT_KEY,
773
+ {}
774
+ );
775
+ const closeTips = () => {
776
+ setStore((prev) => ({ ...prev, show: false }));
777
+ };
778
+ useEffect(() => {
779
+ const len = memoizedTips.length;
780
+ setShowAnnouncement(
781
+ Boolean(len) && announcementStore.show && !options?.hideTips
782
+ );
783
+ }, [
784
+ memoizedTips,
785
+ announcementStore.show,
786
+ options?.hideTips,
787
+ setShowAnnouncement
788
+ ]);
789
+ return {
790
+ maintenanceDialogInfo,
791
+ tips: memoizedTips,
792
+ closeTips,
793
+ showAnnouncement
794
+ };
795
+ };
796
+
797
+ // src/pages/announcementCenter.script.tsx
798
+ var useAnnouncementCenterScript = () => {
799
+ const { tips } = useAnnouncement();
800
+ const [current, setCurrent] = useState(null);
801
+ return {
802
+ dataSource: tips,
803
+ current,
804
+ setCurrent
805
+ };
806
+ };
807
+ var AnnouncementCenterUI2 = (props) => {
808
+ const { dataSource, current, setCurrent, onItemClick } = props;
809
+ return /* @__PURE__ */ jsx("div", { className: "oui-m-1 oui-rounded-xl oui-bg-base-9 oui-p-2", children: /* @__PURE__ */ jsx(
810
+ AnnouncementContent,
811
+ {
812
+ dataSource,
813
+ current,
814
+ onExpandToggle: setCurrent,
815
+ onItemClick,
816
+ showDivider: true
817
+ }
818
+ ) });
819
+ };
820
+ var AnnouncementCenterWidget = (props) => {
821
+ const { dataSource, current, setCurrent } = useAnnouncementCenterScript();
822
+ const onItemClick = useCallback(
823
+ (url) => {
824
+ if (!url)
825
+ return;
826
+ props.onRouteChange(url);
827
+ },
828
+ [props.onRouteChange]
829
+ );
830
+ return /* @__PURE__ */ jsx(
831
+ AnnouncementCenterUI2,
832
+ {
833
+ dataSource,
834
+ current,
835
+ setCurrent,
836
+ onItemClick
837
+ }
838
+ );
839
+ };
840
+ var AnnouncementCenterPage = (props) => {
841
+ return /* @__PURE__ */ jsx(
842
+ AnnouncementCenterWidget,
843
+ {
844
+ onRouteChange: (url) => {
845
+ if (!url)
846
+ return;
847
+ props.routerAdapter?.onRouteChange({
848
+ href: url,
849
+ name: url,
850
+ target: "_blank"
851
+ });
852
+ }
853
+ }
854
+ );
855
+ };
856
+
857
+ export { AnnouncementCenterPage, AnnouncementCenterUI, AnnouncementItem, NotificationUI, useAnnouncement };
858
+ //# sourceMappingURL=out.js.map
859
+ //# sourceMappingURL=index.mjs.map