@orderly.network/trading-points 1.0.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.
Files changed (81) hide show
  1. package/README.md +98 -0
  2. package/dist/chunk-QKQ47GQZ.js +11 -0
  3. package/dist/chunk-QKQ47GQZ.js.map +1 -0
  4. package/dist/chunk-XNMUIY72.mjs +9 -0
  5. package/dist/chunk-XNMUIY72.mjs.map +1 -0
  6. package/dist/de-K5HENMOT.mjs +48 -0
  7. package/dist/de-K5HENMOT.mjs.map +1 -0
  8. package/dist/de-M4RLZ65B.js +50 -0
  9. package/dist/de-M4RLZ65B.js.map +1 -0
  10. package/dist/en-LJLDUQVE.mjs +48 -0
  11. package/dist/en-LJLDUQVE.mjs.map +1 -0
  12. package/dist/en-V7OJRAEG.js +50 -0
  13. package/dist/en-V7OJRAEG.js.map +1 -0
  14. package/dist/es-GC6OLMOU.js +50 -0
  15. package/dist/es-GC6OLMOU.js.map +1 -0
  16. package/dist/es-WKVHRKSR.mjs +48 -0
  17. package/dist/es-WKVHRKSR.mjs.map +1 -0
  18. package/dist/fr-XMT3HUWZ.js +50 -0
  19. package/dist/fr-XMT3HUWZ.js.map +1 -0
  20. package/dist/fr-YXNQ5BX2.mjs +48 -0
  21. package/dist/fr-YXNQ5BX2.mjs.map +1 -0
  22. package/dist/id-5OI6YOIW.mjs +48 -0
  23. package/dist/id-5OI6YOIW.mjs.map +1 -0
  24. package/dist/id-RMBTTLNO.js +50 -0
  25. package/dist/id-RMBTTLNO.js.map +1 -0
  26. package/dist/index.d.mts +14 -0
  27. package/dist/index.d.ts +14 -0
  28. package/dist/index.js +1950 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/index.mjs +1948 -0
  31. package/dist/index.mjs.map +1 -0
  32. package/dist/it-5HUE25IQ.js +50 -0
  33. package/dist/it-5HUE25IQ.js.map +1 -0
  34. package/dist/it-FU4DAFK5.mjs +48 -0
  35. package/dist/it-FU4DAFK5.mjs.map +1 -0
  36. package/dist/ja-KNZVN3N7.mjs +48 -0
  37. package/dist/ja-KNZVN3N7.mjs.map +1 -0
  38. package/dist/ja-X3VXUMBA.js +50 -0
  39. package/dist/ja-X3VXUMBA.js.map +1 -0
  40. package/dist/ko-KG32EYC7.js +50 -0
  41. package/dist/ko-KG32EYC7.js.map +1 -0
  42. package/dist/ko-SUWRSMGZ.mjs +48 -0
  43. package/dist/ko-SUWRSMGZ.mjs.map +1 -0
  44. package/dist/nl-4U5KKRP6.mjs +48 -0
  45. package/dist/nl-4U5KKRP6.mjs.map +1 -0
  46. package/dist/nl-CQ5PEOAO.js +50 -0
  47. package/dist/nl-CQ5PEOAO.js.map +1 -0
  48. package/dist/pl-CVHBNRM4.mjs +48 -0
  49. package/dist/pl-CVHBNRM4.mjs.map +1 -0
  50. package/dist/pl-M7ZCG667.js +50 -0
  51. package/dist/pl-M7ZCG667.js.map +1 -0
  52. package/dist/pt-NQRWOJW2.mjs +48 -0
  53. package/dist/pt-NQRWOJW2.mjs.map +1 -0
  54. package/dist/pt-RXSAJZP6.js +50 -0
  55. package/dist/pt-RXSAJZP6.js.map +1 -0
  56. package/dist/ru-5LNO3PAB.js +50 -0
  57. package/dist/ru-5LNO3PAB.js.map +1 -0
  58. package/dist/ru-MRDWLFFN.mjs +48 -0
  59. package/dist/ru-MRDWLFFN.mjs.map +1 -0
  60. package/dist/styles.css +1 -0
  61. package/dist/tc-AWNFS2UX.js +50 -0
  62. package/dist/tc-AWNFS2UX.js.map +1 -0
  63. package/dist/tc-E5EMOQRW.mjs +48 -0
  64. package/dist/tc-E5EMOQRW.mjs.map +1 -0
  65. package/dist/tr-PKGFWNLE.js +50 -0
  66. package/dist/tr-PKGFWNLE.js.map +1 -0
  67. package/dist/tr-XQG34EBR.mjs +48 -0
  68. package/dist/tr-XQG34EBR.mjs.map +1 -0
  69. package/dist/uk-J6HX5IAD.mjs +48 -0
  70. package/dist/uk-J6HX5IAD.mjs.map +1 -0
  71. package/dist/uk-QA44TYO4.js +50 -0
  72. package/dist/uk-QA44TYO4.js.map +1 -0
  73. package/dist/vi-EJDUONJ6.mjs +48 -0
  74. package/dist/vi-EJDUONJ6.mjs.map +1 -0
  75. package/dist/vi-EK2GO4RO.js +50 -0
  76. package/dist/vi-EK2GO4RO.js.map +1 -0
  77. package/dist/zh-EAO7UXG4.mjs +48 -0
  78. package/dist/zh-EAO7UXG4.mjs.map +1 -0
  79. package/dist/zh-SXH3BWY7.js +50 -0
  80. package/dist/zh-SXH3BWY7.js.map +1 -0
  81. package/package.json +48 -0
package/dist/index.mjs ADDED
@@ -0,0 +1,1948 @@
1
+ import { __glob } from './chunk-XNMUIY72.mjs';
2
+ import './styles.css';
3
+ import { createContext, useState, useEffect, useMemo, useCallback, useContext, useRef } from 'react';
4
+ import { useConfig, useQuery, usePrivateQuery, noCacheConfig, useInfiniteQuery } from '@orderly.network/hooks';
5
+ import { commify, numberToHumanStyle } from '@orderly.network/utils';
6
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
7
+ import { useScreen, Flex, cn, Box, Text, DropdownMenuRoot, DropdownMenuTrigger, ChevronDownIcon, DropdownMenuPortal, DropdownMenuContent, Divider, CopyIcon, Tooltip, Button, toast, usePagination, DataTable, Spinner } from '@orderly.network/ui';
8
+ import { isBefore, addDays, isAfter, isWithinInterval, subDays, differenceInDays, format } from 'date-fns';
9
+ import { ExternalLocaleProvider, LocaleEnum, useTranslation } from '@orderly.network/i18n';
10
+
11
+ function usePointsData() {
12
+ const brokerId = useConfig("brokerId");
13
+ const [currentStage, setCurrentStage] = useState(
14
+ void 0
15
+ );
16
+ const [selectedTimeRange, setSelectedTimeRange] = useState("this_week");
17
+ const { data: stages, isLoading: isStagesLoading } = useQuery(
18
+ brokerId ? `/v1/public/points/stages?broker_id=${brokerId}` : null,
19
+ {
20
+ formatter: (res) => {
21
+ if (res?.rows) {
22
+ res.rows.sort(
23
+ (a, b) => b.epoch_period - a.epoch_period
24
+ );
25
+ }
26
+ return res;
27
+ },
28
+ revalidateOnFocus: false
29
+ }
30
+ );
31
+ useEffect(() => {
32
+ if (!stages?.rows || stages.rows.length === 0 || currentStage !== void 0) {
33
+ return;
34
+ }
35
+ let selectedStage = stages.rows[0];
36
+ const activeStage = stages.rows.find((stage) => stage.status === "active");
37
+ if (activeStage) {
38
+ selectedStage = activeStage;
39
+ } else {
40
+ const pendingStage = [...stages.rows].reverse().find((stage) => stage.status === "pending");
41
+ if (pendingStage) {
42
+ selectedStage = pendingStage;
43
+ } else {
44
+ const completedStage = stages.rows.find(
45
+ (stage) => stage.status === "completed"
46
+ );
47
+ if (completedStage) {
48
+ selectedStage = completedStage;
49
+ }
50
+ }
51
+ }
52
+ setCurrentStage(selectedStage);
53
+ }, [stages, currentStage]);
54
+ const { data: userStatistics, isLoading: isUserStatisticsLoading } = usePrivateQuery(
55
+ currentStage !== void 0 ? `/v1/client/points/user_statistics?stage=${currentStage.stage_id}` : null,
56
+ {
57
+ formatter: (res) => res,
58
+ revalidateOnFocus: false
59
+ }
60
+ );
61
+ const { data: referralInfo } = usePrivateQuery(
62
+ "/v1/referral/info",
63
+ {
64
+ revalidateOnFocus: true,
65
+ errorRetryCount: 3,
66
+ ...noCacheConfig
67
+ }
68
+ );
69
+ const firstCode = useMemo(() => {
70
+ const codes = referralInfo?.referrer_info?.referral_codes;
71
+ if (!codes || codes.length === 0) {
72
+ return void 0;
73
+ }
74
+ return codes[0];
75
+ }, [referralInfo?.referrer_info?.referral_codes]);
76
+ const refCode = useMemo(() => {
77
+ return firstCode?.code || "--";
78
+ }, [firstCode]);
79
+ const refLink = useMemo(() => {
80
+ if (!firstCode || !firstCode.code) {
81
+ return "--";
82
+ }
83
+ const referralLinkUrl = window.location.origin;
84
+ return `${referralLinkUrl}?ref=${firstCode.code}`;
85
+ }, [firstCode]);
86
+ const getRankingUrl = useCallback(
87
+ (args) => {
88
+ if (!currentStage || !brokerId) return null;
89
+ const searchParams = new URLSearchParams();
90
+ searchParams.set("page", args.page.toString());
91
+ searchParams.set("size", args.pageSize.toString());
92
+ searchParams.set("stage", String(currentStage.stage_id));
93
+ searchParams.set("period", args.timeRange || selectedTimeRange);
94
+ searchParams.set("broker_id", String(brokerId));
95
+ return `/v1/public/points/rankings?${searchParams.toString()}`;
96
+ },
97
+ [brokerId, currentStage, selectedTimeRange]
98
+ );
99
+ const isLoading = isStagesLoading || isUserStatisticsLoading;
100
+ const isNoCampaign = !isStagesLoading && (!stages?.rows || stages.rows.length === 0);
101
+ const formatPoints = (value) => {
102
+ if (value === void 0 || value === null) {
103
+ return "--";
104
+ }
105
+ return numberToHumanStyle(value, 2);
106
+ };
107
+ const calculateTotalPoints = useCallback(
108
+ (breakdown) => {
109
+ if (!breakdown) return void 0;
110
+ return breakdown.trading_point + breakdown.pnl_point + breakdown.referral_point;
111
+ },
112
+ []
113
+ );
114
+ const pointsDisplay = useMemo(() => {
115
+ if (!userStatistics) {
116
+ return {
117
+ currentPointsDisplay: "--",
118
+ tradingPointsDisplay: "--",
119
+ pnlPointsDisplay: "--",
120
+ referralPointsDisplay: "--",
121
+ rankingDisplay: "--"
122
+ };
123
+ }
124
+ const breakdownThisWeek = userStatistics.weekly_breakdown?.this_week;
125
+ const breakdownLastWeek = userStatistics.weekly_breakdown?.last_week;
126
+ let selectedBreakdown;
127
+ let ranking;
128
+ if (selectedTimeRange === "all_time") {
129
+ selectedBreakdown = {
130
+ trading_point: userStatistics.trading_point,
131
+ pnl_point: userStatistics.pnl_point,
132
+ referral_point: userStatistics.referral_point
133
+ };
134
+ ranking = userStatistics.stage_rank;
135
+ } else if (selectedTimeRange === "this_week") {
136
+ selectedBreakdown = breakdownThisWeek;
137
+ ranking = breakdownThisWeek?.rank;
138
+ } else {
139
+ selectedBreakdown = breakdownLastWeek;
140
+ ranking = breakdownLastWeek?.rank;
141
+ }
142
+ const currentPoints = calculateTotalPoints(selectedBreakdown) ?? 0;
143
+ return {
144
+ currentPointsDisplay: formatPoints(currentPoints),
145
+ tradingPointsDisplay: formatPoints(selectedBreakdown?.trading_point),
146
+ pnlPointsDisplay: formatPoints(selectedBreakdown?.pnl_point),
147
+ referralPointsDisplay: formatPoints(selectedBreakdown?.referral_point),
148
+ rankingDisplay: ranking === null || ranking === void 0 ? "--" : commify(ranking)
149
+ };
150
+ }, [userStatistics, selectedTimeRange, calculateTotalPoints]);
151
+ const allTimePointsDisplay = useMemo(() => {
152
+ if (!userStatistics) {
153
+ return {
154
+ currentPointsDisplay: "--",
155
+ tradingPointsDisplay: "--",
156
+ pnlPointsDisplay: "--",
157
+ referralPointsDisplay: "--",
158
+ rankingDisplay: "--"
159
+ };
160
+ }
161
+ const currentPoints = calculateTotalPoints({
162
+ trading_point: userStatistics.trading_point,
163
+ pnl_point: userStatistics.pnl_point,
164
+ referral_point: userStatistics.referral_point
165
+ }) ?? 0;
166
+ return {
167
+ currentPointsDisplay: formatPoints(currentPoints),
168
+ tradingPointsDisplay: formatPoints(userStatistics.trading_point),
169
+ pnlPointsDisplay: formatPoints(userStatistics.pnl_point),
170
+ referralPointsDisplay: formatPoints(userStatistics.referral_point),
171
+ rankingDisplay: userStatistics.stage_rank === null || userStatistics.stage_rank === void 0 ? "--" : commify(userStatistics.stage_rank)
172
+ };
173
+ }, [userStatistics, calculateTotalPoints]);
174
+ return {
175
+ stages,
176
+ userStatistics,
177
+ currentStage,
178
+ setCurrentStage,
179
+ isLoading,
180
+ isStagesLoading,
181
+ isUserStatisticsLoading,
182
+ isNoCampaign,
183
+ refLink,
184
+ refCode,
185
+ selectedTimeRange,
186
+ setSelectedTimeRange,
187
+ getRankingUrl,
188
+ brokerId,
189
+ pointsDisplay,
190
+ allTimePointsDisplay,
191
+ isCurrentStagePending: currentStage?.status === "pending",
192
+ isCurrentStageCompleted: currentStage?.status === "completed"
193
+ };
194
+ }
195
+ var PointsContext = createContext(void 0);
196
+ var PointsProvider = ({ children }) => {
197
+ const value = usePointsData();
198
+ return /* @__PURE__ */ jsx(PointsContext.Provider, { value, children });
199
+ };
200
+ function usePoints() {
201
+ const context = useContext(PointsContext);
202
+ if (context === void 0) {
203
+ throw new Error("usePoints must be used within a PointsProvider");
204
+ }
205
+ return context;
206
+ }
207
+ var getDateRange = (offsetDay) => {
208
+ return {
209
+ from: subDays(/* @__PURE__ */ new Date(), offsetDay - 1),
210
+ to: /* @__PURE__ */ new Date()
211
+ };
212
+ };
213
+ var formatDateRange = (date) => {
214
+ return format(date, "yyyy-MM-dd");
215
+ };
216
+ function splitCampaignByWeeks(campaignDateRange) {
217
+ const startDate = typeof campaignDateRange.start_time === "string" ? new Date(campaignDateRange.start_time) : campaignDateRange.start_time;
218
+ const endDate = typeof campaignDateRange.end_time === "string" ? new Date(campaignDateRange.end_time) : campaignDateRange.end_time;
219
+ const result = [];
220
+ let currentWeekStart = new Date(startDate);
221
+ let weekNumber = 1;
222
+ while (isBefore(currentWeekStart, endDate)) {
223
+ const currentWeekEnd = addDays(currentWeekStart, 6);
224
+ const actualWeekEnd = isAfter(currentWeekEnd, endDate) ? new Date(endDate.getTime() - 1) : currentWeekEnd;
225
+ result.push({
226
+ from: new Date(currentWeekStart),
227
+ to: actualWeekEnd,
228
+ label: `Week ${weekNumber}`
229
+ });
230
+ if (!isBefore(actualWeekEnd, endDate)) {
231
+ break;
232
+ }
233
+ if (weekNumber === 1) {
234
+ const nextDayStart = addDays(currentWeekEnd, 1);
235
+ const year = nextDayStart.getUTCFullYear();
236
+ const month = nextDayStart.getUTCMonth();
237
+ const date = nextDayStart.getUTCDate();
238
+ currentWeekStart = new Date(Date.UTC(year, month, date, 0, 0, 0, 0));
239
+ } else {
240
+ const nextDayStart = addDays(currentWeekEnd, 1);
241
+ const year = nextDayStart.getUTCFullYear();
242
+ const month = nextDayStart.getUTCMonth();
243
+ const date = nextDayStart.getUTCDate();
244
+ currentWeekStart = new Date(Date.UTC(year, month, date, 0, 0, 0, 0));
245
+ }
246
+ weekNumber++;
247
+ if (weekNumber > 100) {
248
+ break;
249
+ }
250
+ }
251
+ return result;
252
+ }
253
+ function getCurrentWeeklyRange(weeklyRanges, targetDate = /* @__PURE__ */ new Date()) {
254
+ const weeklyOnlyRanges = weeklyRanges.filter(
255
+ (range) => range.label !== "All time"
256
+ );
257
+ for (const range of weeklyOnlyRanges) {
258
+ const rangeFrom = new Date(range.from);
259
+ const rangeTo = new Date(range.to);
260
+ if (isWithinInterval(targetDate, { start: rangeFrom, end: rangeTo })) {
261
+ return range;
262
+ }
263
+ }
264
+ const targetTime = targetDate.getTime();
265
+ let closestFutureRange = null;
266
+ let smallestGap = Infinity;
267
+ for (const range of weeklyOnlyRanges) {
268
+ const rangeFrom = new Date(range.from);
269
+ const rangeFromTime = rangeFrom.getTime();
270
+ if (rangeFromTime > targetTime) {
271
+ const gap = rangeFromTime - targetTime;
272
+ if (gap < smallestGap) {
273
+ smallestGap = gap;
274
+ closestFutureRange = range;
275
+ }
276
+ }
277
+ }
278
+ const ONE_DAY_MS = 24 * 60 * 60 * 1e3;
279
+ if (closestFutureRange && smallestGap <= ONE_DAY_MS) {
280
+ return closestFutureRange;
281
+ }
282
+ return null;
283
+ }
284
+ function getCurrentOrAllTimeRange(weeklyRanges, targetDate = /* @__PURE__ */ new Date()) {
285
+ const currentWeekly = getCurrentWeeklyRange(weeklyRanges, targetDate);
286
+ if (currentWeekly) {
287
+ return currentWeekly;
288
+ }
289
+ return weeklyRanges.find((range) => range.label === "All time") || weeklyRanges[weeklyRanges.length - 1];
290
+ }
291
+
292
+ // src/components/leaderboard/generalLeaderboard/generalLeaderboard.script.ts
293
+ function useGeneralLeaderboardScript(options) {
294
+ const { campaignDateRange } = options || {};
295
+ const weeklyRanges = useMemo(() => {
296
+ if (!campaignDateRange) return [];
297
+ return splitCampaignByWeeks(campaignDateRange);
298
+ }, [campaignDateRange]);
299
+ const currentOrAllTimeRange = useMemo(() => {
300
+ return getCurrentOrAllTimeRange(weeklyRanges);
301
+ }, [weeklyRanges]);
302
+ const [activeTab, setActiveTab] = useState(
303
+ "volume" /* Volume */
304
+ );
305
+ const filterState = useFilter({ defaultRange: currentOrAllTimeRange });
306
+ const searchState = useSearch();
307
+ const useCampaignDateRange = useMemo(() => {
308
+ return !!campaignDateRange;
309
+ }, [campaignDateRange]);
310
+ return {
311
+ ...filterState,
312
+ ...searchState,
313
+ activeTab,
314
+ onTabChange: setActiveTab,
315
+ useCampaignDateRange,
316
+ weeklyRanges,
317
+ currentOrAllTimeRange
318
+ };
319
+ }
320
+ function useFilter({ defaultRange }) {
321
+ const [filterDay, setFilterDay] = useState(90);
322
+ const [dateRange, setDateRange] = useState(getDateRange(90));
323
+ const updateFilterDay = (day) => {
324
+ setFilterDay(day);
325
+ setDateRange(getDateRange(day));
326
+ };
327
+ useEffect(() => {
328
+ setDateRange(defaultRange ?? getDateRange(90));
329
+ }, [defaultRange]);
330
+ const onFilter = (filter) => {
331
+ if (filter.name === "dateRange") {
332
+ const newDateRange = filter.value;
333
+ setDateRange(newDateRange);
334
+ if (newDateRange.from && newDateRange.to) {
335
+ const offsetDay = Math.abs(differenceInDays(newDateRange.from, newDateRange.to)) + 1;
336
+ const dateRange2 = getDateRange(offsetDay);
337
+ if (formatDateRange(dateRange2.from) === formatDateRange(newDateRange.from) && formatDateRange(dateRange2.to) === formatDateRange(newDateRange.to)) {
338
+ setFilterDay(offsetDay);
339
+ } else {
340
+ setFilterDay(null);
341
+ }
342
+ }
343
+ }
344
+ };
345
+ const filterItems = useMemo(() => {
346
+ const dateRangeFilter = {
347
+ type: "range",
348
+ name: "dateRange",
349
+ value: dateRange,
350
+ max: 90
351
+ };
352
+ return [dateRangeFilter];
353
+ }, [dateRange]);
354
+ return {
355
+ filterItems,
356
+ onFilter,
357
+ dateRange,
358
+ filterDay,
359
+ updateFilterDay,
360
+ setDateRange
361
+ };
362
+ }
363
+ function useSearch() {
364
+ const [searchValue, setSearchValue] = useState("");
365
+ const onSearchValueChange = useCallback((value) => {
366
+ setSearchValue(value);
367
+ }, []);
368
+ const clearSearchValue = useCallback(() => {
369
+ setSearchValue("");
370
+ }, []);
371
+ return {
372
+ searchValue,
373
+ onSearchValueChange,
374
+ clearSearchValue
375
+ };
376
+ }
377
+
378
+ // src/components/ranking/shared/util.ts
379
+ function isSameAddress(address1, address2) {
380
+ return address1.toLowerCase() === address2.toLowerCase();
381
+ }
382
+ function getCurrentAddressRowKey(address) {
383
+ return `current-address-${address?.toLowerCase()}`;
384
+ }
385
+ var useRankingColumns = (fields, address, enableSort, type) => {
386
+ const { t } = useTranslation();
387
+ const { isMobile } = useScreen();
388
+ return useMemo(() => {
389
+ const columns = [
390
+ {
391
+ title: t("tradingLeaderboard.rank"),
392
+ dataIndex: "rank",
393
+ width: 50,
394
+ render: (value, record) => {
395
+ const isYou = record.key === getCurrentAddressRowKey(address);
396
+ let rankIcon;
397
+ let badgeImg = null;
398
+ if (!isYou) {
399
+ if (value === 1) {
400
+ rankIcon = /* @__PURE__ */ jsx(FirstRankIcon, {});
401
+ badgeImg = "https://oss.orderly.network/static/sdk/leaderboard/first_badge.png";
402
+ } else if (value === 2) {
403
+ rankIcon = /* @__PURE__ */ jsx(SecondRankIcon, {});
404
+ badgeImg = "https://oss.orderly.network/static/sdk/leaderboard/second_badge.png";
405
+ } else if (value === 3) {
406
+ rankIcon = /* @__PURE__ */ jsx(ThirdRankIcon, {});
407
+ badgeImg = "https://oss.orderly.network/static/sdk/leaderboard/third_badge.png";
408
+ }
409
+ }
410
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
411
+ badgeImg && /* @__PURE__ */ jsx(
412
+ "img",
413
+ {
414
+ src: badgeImg,
415
+ alt: `${value}th badge`,
416
+ className: cn(
417
+ "oui-z-0 oui-h-[38px] oui-opacity-30 md:oui-h-[46px]",
418
+ "oui-absolute oui-left-0 oui-top-0",
419
+ "oui-mix-blend-luminosity",
420
+ // force create a separate layer in order to fix mix-blend-luminosity not working on ios
421
+ "oui-transform-gpu"
422
+ )
423
+ }
424
+ ),
425
+ /* @__PURE__ */ jsx("div", { className: "oui-relative", children: rankIcon || /* @__PURE__ */ jsx(Box, { width: 20, pl: 2, className: "oui-text-center", children: value }) })
426
+ ] });
427
+ }
428
+ },
429
+ {
430
+ title: t("common.address"),
431
+ dataIndex: "address",
432
+ render: (value, record) => {
433
+ const isYou = record.key === getCurrentAddressRowKey(address);
434
+ if (isMobile && isYou) {
435
+ return /* @__PURE__ */ jsx(Text, { children: "You" });
436
+ }
437
+ return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs(
438
+ "a",
439
+ {
440
+ className: "oui-flex oui-items-start oui-gap-1",
441
+ href: `https://orderly-dashboard.orderly.network/address/${value}?broker_id=${record.broker_id}`,
442
+ target: "_blank",
443
+ rel: "noreferrer",
444
+ children: [
445
+ /* @__PURE__ */ jsx(
446
+ Text.formatted,
447
+ {
448
+ rule: "address",
449
+ onCopy: (e) => {
450
+ e.preventDefault();
451
+ e.stopPropagation();
452
+ navigator.clipboard.writeText(value);
453
+ toast.success(t("common.copy.copied"));
454
+ },
455
+ className: "oui-cursor-pointer",
456
+ children: value
457
+ },
458
+ record.rank
459
+ ),
460
+ isYou && /* @__PURE__ */ jsx(Text, { children: " (You)" })
461
+ ]
462
+ }
463
+ ) });
464
+ },
465
+ width: 90
466
+ },
467
+ {
468
+ title: "Points",
469
+ dataIndex: "points",
470
+ align: isMobile ? "right" : "left",
471
+ render: (value) => {
472
+ if (value === void 0 || value === null || value === "") {
473
+ return "-";
474
+ }
475
+ return /* @__PURE__ */ jsx(Text, { children: commify(value, 2) });
476
+ }
477
+ }
478
+ ];
479
+ return columns.filter(
480
+ (column) => fields?.includes(column.dataIndex)
481
+ );
482
+ }, [t, isMobile, address, fields, enableSort, type]);
483
+ };
484
+ var FirstRankIcon = () => {
485
+ return /* @__PURE__ */ jsxs(
486
+ "svg",
487
+ {
488
+ width: "25",
489
+ height: "25",
490
+ viewBox: "0 0 25 25",
491
+ fill: "none",
492
+ xmlns: "http://www.w3.org/2000/svg",
493
+ children: [
494
+ /* @__PURE__ */ jsx(
495
+ "path",
496
+ {
497
+ d: "M3.88281 2.5L7.78711 10.3105C6.38111 11.5855 5.5 13.427 5.5 15.5C5.5 19.4 8.6 22.5 12.5 22.5C16.4 22.5 19.5 19.4 19.5 15.5C19.5 13.427 18.6189 11.5855 17.2129 10.3105L21.1172 2.5H15.5L12.5 8.5L9.5 2.5H3.88281ZM12.5 10.5C15.3 10.5 17.5 12.7 17.5 15.5C17.5 18.3 15.3 20.5 12.5 20.5C9.7 20.5 7.5 18.3 7.5 15.5C7.5 12.7 9.7 10.5 12.5 10.5ZM12.5 12.5C12.4 12.8 11.9 13.6992 11 13.6992V14.6992H12.0996V18.5H13.4004H13.5V12.5H12.5Z",
498
+ fill: "url(#paint0_linear_21940_39199)"
499
+ }
500
+ ),
501
+ /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs(
502
+ "linearGradient",
503
+ {
504
+ id: "paint0_linear_21940_39199",
505
+ x1: "6.18073",
506
+ y1: "6",
507
+ x2: "20.1338",
508
+ y2: "18.1659",
509
+ gradientUnits: "userSpaceOnUse",
510
+ children: [
511
+ /* @__PURE__ */ jsx("stop", { stopColor: "#8C421D" }),
512
+ /* @__PURE__ */ jsx("stop", { offset: "0.325272", stopColor: "#FBE67B" }),
513
+ /* @__PURE__ */ jsx("stop", { offset: "0.535488", stopColor: "#FCFBE7" }),
514
+ /* @__PURE__ */ jsx("stop", { offset: "0.769917", stopColor: "#F7D14E" }),
515
+ /* @__PURE__ */ jsx("stop", { offset: "1", stopColor: "#D4A041" })
516
+ ]
517
+ }
518
+ ) })
519
+ ]
520
+ }
521
+ );
522
+ };
523
+ var SecondRankIcon = () => {
524
+ return /* @__PURE__ */ jsxs(
525
+ "svg",
526
+ {
527
+ width: "25",
528
+ height: "25",
529
+ viewBox: "0 0 25 25",
530
+ fill: "none",
531
+ xmlns: "http://www.w3.org/2000/svg",
532
+ children: [
533
+ /* @__PURE__ */ jsx(
534
+ "path",
535
+ {
536
+ d: "M3.88281 2.5L7.78711 10.3105C6.38111 11.5855 5.5 13.427 5.5 15.5C5.5 19.4 8.6 22.5 12.5 22.5C16.4 22.5 19.5 19.4 19.5 15.5C19.5 13.427 18.6189 11.5855 17.2129 10.3105L21.1172 2.5H15.5L12.5 8.5L9.5 2.5H3.88281ZM12.5 10.5C15.3 10.5 17.5 12.7 17.5 15.5C17.5 18.3 15.3 20.5 12.5 20.5C9.7 20.5 7.5 18.3 7.5 15.5C7.5 12.7 9.7 10.5 12.5 10.5ZM12.5469 12.5C10.7729 12.5 10.481 13.901 10.5 14.5H11.6738C11.6738 14.357 11.809 13.5 12.5 13.5C13.163 13.5 13.291 14.0232 13.291 14.2852C13.291 15.0512 12.245 15.7623 10.5 17.6973V18.5L14.4883 18.4766L14.4863 17.5332H12.2285C13.8425 15.8792 14.5 15.1309 14.5 14.1719C14.5 13.4869 14.1149 12.5 12.5469 12.5Z",
537
+ fill: "url(#paint0_linear_21940_39214)"
538
+ }
539
+ ),
540
+ /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs(
541
+ "linearGradient",
542
+ {
543
+ id: "paint0_linear_21940_39214",
544
+ x1: "6.18073",
545
+ y1: "6",
546
+ x2: "20.1338",
547
+ y2: "18.1659",
548
+ gradientUnits: "userSpaceOnUse",
549
+ children: [
550
+ /* @__PURE__ */ jsx("stop", { stopColor: "#7F7F7F" }),
551
+ /* @__PURE__ */ jsx("stop", { offset: "0.325272", stopColor: "#D9D9D9" }),
552
+ /* @__PURE__ */ jsx("stop", { offset: "0.535488", stopColor: "#F7F6F4" }),
553
+ /* @__PURE__ */ jsx("stop", { offset: "0.769917", stopColor: "#D9D9D9" }),
554
+ /* @__PURE__ */ jsx("stop", { offset: "1", stopColor: "#7F7F7F" })
555
+ ]
556
+ }
557
+ ) })
558
+ ]
559
+ }
560
+ );
561
+ };
562
+ var ThirdRankIcon = () => {
563
+ return /* @__PURE__ */ jsxs(
564
+ "svg",
565
+ {
566
+ width: "29",
567
+ height: "25",
568
+ viewBox: "0 0 29 25",
569
+ fill: "none",
570
+ xmlns: "http://www.w3.org/2000/svg",
571
+ children: [
572
+ /* @__PURE__ */ jsx(
573
+ "path",
574
+ {
575
+ d: "M5.88281 2.5L9.78711 10.3105C8.38111 11.5855 7.5 13.427 7.5 15.5C7.5 19.4 10.6 22.5 14.5 22.5C18.4 22.5 21.5 19.4 21.5 15.5C21.5 13.427 20.6189 11.5855 19.2129 10.3105L23.1172 2.5H17.5L14.5 8.5L11.5 2.5H5.88281ZM14.5 10.5C17.3 10.5 19.5 12.7 19.5 15.5C19.5 18.3 17.3 20.5 14.5 20.5C11.7 20.5 9.5 18.3 9.5 15.5C9.5 12.7 11.7 10.5 14.5 10.5ZM14.4688 12.5C13.6927 12.5 12.5898 12.9348 12.5898 14.0918H13.7266C13.7266 13.9118 13.8461 13.4336 14.4941 13.4336C14.6251 13.4336 15.2715 13.4767 15.2715 14.1797C15.2715 14.8967 14.7109 14.9844 14.4219 14.9844H13.8145V15.8906H14.4219C14.5659 15.8906 15.3613 15.8537 15.3613 16.7637C15.3613 16.8837 15.3111 17.5625 14.4961 17.5625C13.8081 17.5625 13.6233 17.0284 13.6562 16.8164H12.5195C12.4615 17.4334 12.9757 18.4961 14.4688 18.4961C15.3018 18.4961 16.5 18.0942 16.5 16.7812C16.5 15.8643 15.8621 15.536 15.5391 15.418C15.6781 15.354 16.4082 14.9771 16.4082 14.1641C16.4082 13.7131 16.2127 12.5 14.4688 12.5Z",
576
+ fill: "url(#paint0_linear_21940_39224)"
577
+ }
578
+ ),
579
+ /* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs(
580
+ "linearGradient",
581
+ {
582
+ id: "paint0_linear_21940_39224",
583
+ x1: "8.61159",
584
+ y1: "5.33333",
585
+ x2: "22.7368",
586
+ y2: "20.4383",
587
+ gradientUnits: "userSpaceOnUse",
588
+ children: [
589
+ /* @__PURE__ */ jsx("stop", { stopColor: "#B6947E" }),
590
+ /* @__PURE__ */ jsx("stop", { offset: "0.2", stopColor: "#8F6959" }),
591
+ /* @__PURE__ */ jsx("stop", { offset: "0.475", stopColor: "#F8DAC8" }),
592
+ /* @__PURE__ */ jsx("stop", { offset: "0.67", stopColor: "#AC836E" }),
593
+ /* @__PURE__ */ jsx("stop", { offset: "0.83", stopColor: "#B6947E" }),
594
+ /* @__PURE__ */ jsx("stop", { offset: "1", stopColor: "#F8DCCB" })
595
+ ]
596
+ }
597
+ ) })
598
+ ]
599
+ }
600
+ );
601
+ };
602
+ var Ranking = (props) => {
603
+ const column = useRankingColumns(
604
+ props.fields,
605
+ props.address,
606
+ false,
607
+ props.type
608
+ );
609
+ const { isMobile } = useScreen();
610
+ const onRow = useCallback(
611
+ (record, index) => {
612
+ const isYou = record.key === getCurrentAddressRowKey(props.address);
613
+ const isFirst = record.rank === 1;
614
+ const isSecond = record.rank === 2;
615
+ const isThird = record.rank === 3;
616
+ const showBg = isFirst || isSecond || isThird;
617
+ return {
618
+ className: cn(
619
+ "oui-h-[40px] md:oui-h-[48px]",
620
+ // use oui-relative to let the background image position based on row
621
+ "oui-relative",
622
+ isYou ? (
623
+ // add 4px extra height to make row has 2px space
624
+ "oui-h-[44px] md:oui-h-[52px]"
625
+ ) : cn(
626
+ showBg && "oui-border-b-2 oui-border-b-transparent",
627
+ isFirst && "oui-bg-[linear-gradient(270deg,rgba(241,215,121,0.0225)_-2.05%,rgba(255,203,70,0.45)_100%)]",
628
+ isSecond && "oui-bg-[linear-gradient(270deg,rgba(255,255,255,0.0225)_-2.05%,rgba(199,199,199,0.45)_100%)]",
629
+ isThird && "oui-bg-[linear-gradient(270deg,rgba(255,233,157,0.0225)_-1.3%,rgba(160,101,46,0.45)_100%)]"
630
+ )
631
+ )
632
+ };
633
+ },
634
+ [props.address]
635
+ );
636
+ const onCell = useCallback(
637
+ (column2, record) => {
638
+ const isFirstColumn = column2.getIsFirstColumn();
639
+ const isLastColumn = column2.getIsLastColumn();
640
+ const isRank = [1, 2, 3].includes(record.rank);
641
+ return {
642
+ className: cn(
643
+ isFirstColumn && isRank && "oui-rounded-l-lg oui-mix-blend-luminosity",
644
+ isLastColumn && isRank && "oui-rounded-r-lg oui-mix-blend-luminosity"
645
+ )
646
+ };
647
+ },
648
+ [props.address]
649
+ );
650
+ if (isMobile) {
651
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
652
+ /* @__PURE__ */ jsx(
653
+ DataTable,
654
+ {
655
+ classNames: {
656
+ root: "oui-trading-leaderboard-ranking-table oui-bg-transparent",
657
+ body: "oui-text-2xs",
658
+ scroll: "oui-overflow-y-hidden oui-h-full"
659
+ },
660
+ loading: props.isLoading,
661
+ columns: column,
662
+ bordered: true,
663
+ dataSource: props.dataList,
664
+ generatedRowKey: (record) => record.key || record.address,
665
+ manualPagination: true,
666
+ manualSorting: true,
667
+ onRow,
668
+ onCell
669
+ }
670
+ ),
671
+ /* @__PURE__ */ jsx(
672
+ "div",
673
+ {
674
+ ref: props.sentinelRef,
675
+ className: "oui-invisible oui-relative oui-top-[-300px] oui-h-px"
676
+ }
677
+ ),
678
+ props.isLoading && props.dataList.length > 0 && /* @__PURE__ */ jsx(Flex, { itemAlign: "center", justify: "center", width: "100%", height: 40, children: /* @__PURE__ */ jsx(Spinner, { size: "sm" }) })
679
+ ] });
680
+ }
681
+ return /* @__PURE__ */ jsx(
682
+ DataTable,
683
+ {
684
+ loading: props.isLoading,
685
+ columns: column,
686
+ bordered: true,
687
+ dataSource: props.dataSource,
688
+ generatedRowKey: (record) => record.key || record.address,
689
+ manualPagination: true,
690
+ manualSorting: true,
691
+ pagination: props.pagination,
692
+ classNames: {
693
+ root: cn(
694
+ "oui-trading-leaderboard-ranking-table",
695
+ "oui-bg-transparent",
696
+ "oui-rounded-md",
697
+ "oui-overflow-hidden",
698
+ "!oui-h-[calc(100%_-_53px_-_8px)]"
699
+ ),
700
+ scroll: "oui-min-h-[600px] oui-max-h-[1250px]",
701
+ header: "oui-bg-base-9"
702
+ },
703
+ onRow,
704
+ onCell
705
+ }
706
+ );
707
+ };
708
+ function useEndReached(sentinelRef, onEndReached) {
709
+ const observer = useRef();
710
+ const cb = useRef(onEndReached);
711
+ cb.current = onEndReached;
712
+ useEffect(() => {
713
+ const options = {
714
+ root: null,
715
+ rootMargin: "0px",
716
+ threshold: 0
717
+ };
718
+ const handleObserver = (entries) => {
719
+ entries.forEach((entry) => {
720
+ if (entry.isIntersecting) {
721
+ cb.current?.();
722
+ }
723
+ });
724
+ };
725
+ observer.current = new IntersectionObserver(handleObserver, options);
726
+ return () => {
727
+ observer.current?.disconnect();
728
+ };
729
+ }, []);
730
+ useEffect(() => {
731
+ if (sentinelRef.current) {
732
+ observer.current?.observe(sentinelRef.current);
733
+ }
734
+ }, [sentinelRef.current]);
735
+ }
736
+
737
+ // src/components/ranking/generalRanking/generalRanking.script.ts
738
+ function useGeneralRankingScript(options) {
739
+ const { address: searchValue } = options || {};
740
+ const brokerId = useConfig("brokerId");
741
+ const { currentStage, userStatistics, getRankingUrl, selectedTimeRange } = usePoints();
742
+ const { isMobile } = useScreen();
743
+ const { page, pageSize, setPage, parsePagination } = usePagination({
744
+ pageSize: 10
745
+ });
746
+ const { data, isLoading } = useQuery(
747
+ currentStage && brokerId ? getRankingUrl({ page, pageSize, timeRange: selectedTimeRange }) : null,
748
+ {
749
+ formatter: (res) => res,
750
+ revalidateOnFocus: false
751
+ }
752
+ );
753
+ const {
754
+ data: infiniteData,
755
+ size,
756
+ setSize,
757
+ isValidating
758
+ } = useInfiniteQuery(
759
+ (pageIndex, previousPageData) => {
760
+ if (previousPageData && !previousPageData.rows?.length) return null;
761
+ if (!isMobile || !currentStage) return null;
762
+ return getRankingUrl({
763
+ page: pageIndex + 1,
764
+ pageSize,
765
+ timeRange: selectedTimeRange
766
+ });
767
+ },
768
+ {
769
+ initialSize: 1,
770
+ formatter: (res) => res,
771
+ revalidateOnFocus: false
772
+ }
773
+ );
774
+ const userDataList = useMemo(() => {
775
+ if (!userStatistics?.address) return [];
776
+ let rank = "-";
777
+ let points;
778
+ if (selectedTimeRange === "all_time") {
779
+ rank = userStatistics.stage_rank ?? "-";
780
+ points = userStatistics.stage_points;
781
+ } else if (selectedTimeRange === "this_week") {
782
+ rank = userStatistics.weekly_breakdown?.this_week?.rank ?? "-";
783
+ const breakdown = userStatistics.weekly_breakdown?.this_week;
784
+ points = breakdown ? breakdown.trading_point + breakdown.pnl_point + breakdown.referral_point : void 0;
785
+ } else if (selectedTimeRange === "last_week") {
786
+ rank = userStatistics.weekly_breakdown?.last_week?.rank ?? "-";
787
+ const breakdown = userStatistics.weekly_breakdown?.last_week;
788
+ points = breakdown ? breakdown.trading_point + breakdown.pnl_point + breakdown.referral_point : void 0;
789
+ }
790
+ return [
791
+ {
792
+ key: getCurrentAddressRowKey(userStatistics.address),
793
+ address: userStatistics.address,
794
+ rank,
795
+ points,
796
+ broker_id: brokerId ?? null
797
+ }
798
+ ];
799
+ }, [userStatistics, brokerId, selectedTimeRange]);
800
+ const addRankForList = useCallback(
801
+ (list) => {
802
+ return list?.map((item, index) => ({
803
+ ...item,
804
+ rank: index + 1 + (page - 1) * pageSize
805
+ }));
806
+ },
807
+ [page, pageSize]
808
+ );
809
+ const dataSource = useMemo(() => {
810
+ const mapped = (data?.rows || []).map((row) => ({
811
+ address: row.address,
812
+ points: row.total_points,
813
+ rank: row.rank,
814
+ broker_id: brokerId ?? null
815
+ }));
816
+ const filtered = searchValue ? mapped.filter((item) => isSameAddress(item.address, searchValue || "")) : mapped;
817
+ const finalList = addRankForList(filtered);
818
+ if (page === 1 && !searchValue && userDataList.length) {
819
+ return [...userDataList, ...finalList];
820
+ }
821
+ return finalList;
822
+ }, [data, brokerId, searchValue, addRankForList, page, userDataList]);
823
+ const dataList = useMemo(() => {
824
+ if (!infiniteData?.length) return [];
825
+ const flat = infiniteData.map((p) => p.rows).flat();
826
+ const mapped = flat.map((row) => ({
827
+ address: row.address,
828
+ points: row.total_points,
829
+ broker_id: brokerId ?? null
830
+ }));
831
+ const filtered = searchValue ? mapped.filter((item) => isSameAddress(item.address, searchValue)) : mapped;
832
+ const rankList = addRankForList(filtered);
833
+ if (!searchValue && userDataList.length) {
834
+ return [...userDataList, ...rankList];
835
+ }
836
+ return rankList;
837
+ }, [infiniteData, brokerId, searchValue, addRankForList, userDataList]);
838
+ const sentinelRef = useRef(null);
839
+ const pagination = useMemo(
840
+ () => parsePagination({
841
+ total: data?.meta?.total || 0,
842
+ current_page: data?.meta?.current_page || 1,
843
+ records_per_page: pageSize
844
+ }),
845
+ [data?.meta?.total, data?.meta?.current_page, pageSize]
846
+ );
847
+ useEndReached(sentinelRef, () => {
848
+ if (!isValidating && isMobile) {
849
+ setSize(size + 1);
850
+ }
851
+ });
852
+ useEffect(() => {
853
+ if (searchValue) setPage(1);
854
+ }, [searchValue, setPage]);
855
+ useEffect(() => {
856
+ setPage(1);
857
+ }, [currentStage?.stage_id, setPage]);
858
+ useEffect(() => {
859
+ setPage(1);
860
+ setSize(1);
861
+ }, [selectedTimeRange, setPage, setSize]);
862
+ return {
863
+ pagination,
864
+ dataSource,
865
+ isLoading: isLoading || isValidating,
866
+ isMobile,
867
+ sentinelRef,
868
+ dataList,
869
+ address: userStatistics?.address
870
+ };
871
+ }
872
+ var GeneralRankingWidget = (props) => {
873
+ const { address, fields, ...rest } = props;
874
+ const state = useGeneralRankingScript({ address });
875
+ return /* @__PURE__ */ jsx(Ranking, { ...state, ...rest, fields, type: "general" });
876
+ };
877
+ var GeneralLeaderboard = (props) => {
878
+ const { isMobile } = useScreen();
879
+ const fields = ["rank", "address", "points"];
880
+ if (isMobile) {
881
+ return /* @__PURE__ */ jsx(
882
+ Box,
883
+ {
884
+ pt: 2,
885
+ px: 3,
886
+ r: "2xl",
887
+ intensity: 900,
888
+ width: "100%",
889
+ className: cn(
890
+ "oui-trading-leaderboard-general-leaderboard oui-relative",
891
+ props.className
892
+ ),
893
+ style: props.style,
894
+ children: /* @__PURE__ */ jsx(GeneralRankingWidget, { address: props.searchValue, fields })
895
+ }
896
+ );
897
+ }
898
+ return /* @__PURE__ */ jsx(
899
+ Box,
900
+ {
901
+ pt: 2,
902
+ px: 6,
903
+ r: "2xl",
904
+ className: cn(
905
+ "oui-trading-leaderboard-general-leaderboard oui-relative",
906
+ "oui-mx-auto oui-max-w-[992px]",
907
+ props.className
908
+ ),
909
+ style: props.style,
910
+ children: /* @__PURE__ */ jsx(GeneralRankingWidget, { address: props.searchValue, fields })
911
+ }
912
+ );
913
+ };
914
+ var GeneralLeaderboardWidget = (props) => {
915
+ const state = useGeneralLeaderboardScript({
916
+ campaignDateRange: props.campaignDateRange
917
+ });
918
+ return /* @__PURE__ */ jsx(
919
+ GeneralLeaderboard,
920
+ {
921
+ ...state,
922
+ className: props.className,
923
+ style: props.style
924
+ }
925
+ );
926
+ };
927
+ var Countdown = ({ className }) => {
928
+ const { isMobile } = useScreen();
929
+ const { currentStage } = usePoints();
930
+ const { t } = useTranslation();
931
+ const [timeLeft, setTimeLeft] = useState({
932
+ days: 0,
933
+ hours: 0,
934
+ minutes: 0,
935
+ seconds: 0
936
+ });
937
+ useEffect(() => {
938
+ if (currentStage?.status !== "pending" || !currentStage?.start_time) {
939
+ return;
940
+ }
941
+ const calculateTimeLeft = () => {
942
+ const targetDate2 = currentStage.start_time * 1e3;
943
+ const now2 = (/* @__PURE__ */ new Date()).getTime();
944
+ const difference = targetDate2 - now2;
945
+ if (difference > 0) {
946
+ return {
947
+ days: Math.floor(difference / (1e3 * 60 * 60 * 24)),
948
+ hours: Math.floor(difference / (1e3 * 60 * 60) % 24),
949
+ minutes: Math.floor(difference / 1e3 / 60 % 60),
950
+ seconds: Math.floor(difference / 1e3 % 60)
951
+ };
952
+ }
953
+ return { days: 0, hours: 0, minutes: 0, seconds: 0 };
954
+ };
955
+ setTimeLeft(calculateTimeLeft());
956
+ const timer = setInterval(() => {
957
+ setTimeLeft(calculateTimeLeft());
958
+ }, 1e3);
959
+ return () => clearInterval(timer);
960
+ }, [currentStage]);
961
+ const formatNumber = (num) => {
962
+ return num.toString().padStart(2, "0");
963
+ };
964
+ if (currentStage?.status !== "pending" || !currentStage?.start_time) {
965
+ return null;
966
+ }
967
+ const targetDate = currentStage.start_time * 1e3;
968
+ const now = (/* @__PURE__ */ new Date()).getTime();
969
+ if (targetDate <= now) {
970
+ return null;
971
+ }
972
+ return /* @__PURE__ */ jsxs(
973
+ Flex,
974
+ {
975
+ gap: 4,
976
+ itemAlign: "center",
977
+ justify: "center",
978
+ px: 9,
979
+ className,
980
+ children: [
981
+ !isMobile && /* @__PURE__ */ jsx(
982
+ Box,
983
+ {
984
+ className: "oui-w-[200px] oui-h-[1px]",
985
+ style: {
986
+ background: `linear-gradient(123deg, rgba(176, 132, 233, 0.00) 0%, #DEC4FF 123.91%)`
987
+ }
988
+ }
989
+ ),
990
+ /* @__PURE__ */ jsx(Box, { className: "oui-rounded-2xl", p: 5, children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 2, itemAlign: "center", children: [
991
+ /* @__PURE__ */ jsx(Text, { className: "oui-text-base-contrast-36 oui-text-lg", children: t("tradingPoints.startsIn") }),
992
+ /* @__PURE__ */ jsxs(Flex, { gap: 2, itemAlign: "center", justify: "center", children: [
993
+ /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 1, itemAlign: "center", children: [
994
+ /* @__PURE__ */ jsx(Text, { className: "oui-text-base-contrast oui-text-4xl oui-font-bold oui-w-16 oui-text-center", children: formatNumber(timeLeft.days) }),
995
+ /* @__PURE__ */ jsx(Text, { className: "oui-text-base-contrast-80 oui-text-xs oui-w-16 oui-text-center", children: t("tradingPoints.days") })
996
+ ] }),
997
+ /* @__PURE__ */ jsx(Box, { className: "oui-w-1 oui-h-1 oui-rounded-full oui-bg-base-4" }),
998
+ /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 1, itemAlign: "center", children: [
999
+ /* @__PURE__ */ jsx(Text, { className: "oui-text-base-contrast oui-text-4xl oui-font-bold oui-w-16 oui-text-center", children: formatNumber(timeLeft.hours) }),
1000
+ /* @__PURE__ */ jsx(Text, { className: "oui-text-base-contrast-80 oui-text-xs oui-w-16 oui-text-center", children: t("tradingPoints.hours") })
1001
+ ] }),
1002
+ /* @__PURE__ */ jsx(Box, { className: "oui-w-1 oui-h-1 oui-rounded-full oui-bg-base-4" }),
1003
+ /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 1, itemAlign: "center", children: [
1004
+ /* @__PURE__ */ jsx(Text, { className: "oui-text-base-contrast oui-text-4xl oui-font-bold oui-w-16 oui-text-center", children: formatNumber(timeLeft.minutes) }),
1005
+ /* @__PURE__ */ jsx(Text, { className: "oui-text-base-contrast-80 oui-text-xs oui-w-16 oui-text-center", children: t("tradingPoints.minutes") })
1006
+ ] }),
1007
+ /* @__PURE__ */ jsx(Box, { className: "oui-w-1 oui-h-1 oui-rounded-full oui-bg-base-4" }),
1008
+ /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 1, itemAlign: "center", children: [
1009
+ /* @__PURE__ */ jsx(Text, { className: "oui-text-base-contrast oui-text-4xl oui-font-bold oui-w-16 oui-text-center", children: formatNumber(timeLeft.seconds) }),
1010
+ /* @__PURE__ */ jsx(Text, { className: "oui-text-base-contrast-80 oui-text-xs oui-w-16 oui-text-center", children: t("tradingPoints.seconds") })
1011
+ ] })
1012
+ ] })
1013
+ ] }) }),
1014
+ !isMobile && /* @__PURE__ */ jsx(
1015
+ Box,
1016
+ {
1017
+ className: "oui-w-[200px] oui-h-[1px]",
1018
+ style: {
1019
+ background: `linear-gradient(270deg, rgba(176, 132, 233, 0.00) 0%, #DEC4FF 123.91%)`
1020
+ }
1021
+ }
1022
+ )
1023
+ ]
1024
+ }
1025
+ );
1026
+ };
1027
+ var FAQItem = ({ question, answer }) => {
1028
+ const { isMobile } = useScreen();
1029
+ const [isOpen, setIsOpen] = useState(false);
1030
+ return /* @__PURE__ */ jsxs(
1031
+ Flex,
1032
+ {
1033
+ onClick: () => setIsOpen(!isOpen),
1034
+ direction: "column",
1035
+ className: "oui-w-full",
1036
+ itemAlign: "start",
1037
+ children: [
1038
+ /* @__PURE__ */ jsxs(
1039
+ Flex,
1040
+ {
1041
+ gap: 4,
1042
+ className: "oui-w-full oui-cursor-pointer hover:oui-opacity-80 oui-transition-opacity",
1043
+ children: [
1044
+ /* @__PURE__ */ jsx(
1045
+ Text,
1046
+ {
1047
+ className: cn(
1048
+ "oui-flex-1 oui-text-base-contrast oui-font-semibold oui-tracking-[0.03em]",
1049
+ isMobile ? "oui-text-lg oui-leading-[26px]" : "oui-text-xl oui-leading-8"
1050
+ ),
1051
+ children: question
1052
+ }
1053
+ ),
1054
+ /* @__PURE__ */ jsx(
1055
+ ChevronDownIcon,
1056
+ {
1057
+ size: 24,
1058
+ className: cn(
1059
+ "oui-text-base-contrast oui-transition-transform oui-duration-300 oui-flex-shrink-0",
1060
+ isOpen && "oui-rotate-180"
1061
+ )
1062
+ }
1063
+ )
1064
+ ]
1065
+ }
1066
+ ),
1067
+ /* @__PURE__ */ jsx(
1068
+ Box,
1069
+ {
1070
+ className: cn(
1071
+ "oui-overflow-hidden oui-transition-all oui-duration-300",
1072
+ isOpen && "oui-mt-4"
1073
+ ),
1074
+ style: {
1075
+ maxHeight: isOpen ? "500px" : "0px",
1076
+ opacity: isOpen ? 1 : 0
1077
+ },
1078
+ children: /* @__PURE__ */ jsx(
1079
+ Text,
1080
+ {
1081
+ className: "oui-text-base-contrast-54 oui-text-sm oui-leading-relaxed",
1082
+ style: { whiteSpace: "pre-line" },
1083
+ children: answer
1084
+ }
1085
+ )
1086
+ }
1087
+ )
1088
+ ]
1089
+ }
1090
+ );
1091
+ };
1092
+ var FAQSection = ({ className }) => {
1093
+ const brokerName = useConfig("brokerName");
1094
+ const { isMobile } = useScreen();
1095
+ const { t } = useTranslation();
1096
+ const faqData = [
1097
+ {
1098
+ question: t("tradingPoints.faq.whatArePoints.question"),
1099
+ answer: t("tradingPoints.faq.whatArePoints.answer", { brokerName })
1100
+ },
1101
+ {
1102
+ question: t("tradingPoints.faq.allocation.question"),
1103
+ answer: t("tradingPoints.faq.allocation.answer")
1104
+ },
1105
+ {
1106
+ question: t("tradingPoints.faq.distribution.question"),
1107
+ answer: t("tradingPoints.faq.distribution.answer")
1108
+ },
1109
+ {
1110
+ question: t("tradingPoints.faq.pnl.question"),
1111
+ answer: t("tradingPoints.faq.pnl.answer")
1112
+ },
1113
+ {
1114
+ question: t("tradingPoints.faq.referral.question"),
1115
+ answer: t("tradingPoints.faq.referral.answer")
1116
+ }
1117
+ ];
1118
+ return /* @__PURE__ */ jsxs(
1119
+ Flex,
1120
+ {
1121
+ direction: "column",
1122
+ gap: 6,
1123
+ className,
1124
+ itemAlign: "start",
1125
+ id: "points-faq",
1126
+ children: [
1127
+ /* @__PURE__ */ jsx(
1128
+ Text,
1129
+ {
1130
+ className: cn(
1131
+ "oui-text-base-contrast oui-font-normal oui-tracking-[0.03em]",
1132
+ isMobile ? "oui-text-2xl oui-leading-8" : "oui-text-3xl oui-leading-10"
1133
+ ),
1134
+ children: t("tradingPoints.faq.title")
1135
+ }
1136
+ ),
1137
+ /* @__PURE__ */ jsx(
1138
+ Flex,
1139
+ {
1140
+ direction: "column",
1141
+ gap: 8,
1142
+ className: "oui-w-full",
1143
+ itemAlign: "start",
1144
+ children: faqData.map((faq, index) => /* @__PURE__ */ jsxs("div", { className: "oui-w-full", children: [
1145
+ /* @__PURE__ */ jsx(FAQItem, { question: faq.question, answer: faq.answer }),
1146
+ index < faqData.length - 1 && /* @__PURE__ */ jsx(Divider, { className: "oui-mt-8", intensity: 8 })
1147
+ ] }, index))
1148
+ }
1149
+ )
1150
+ ]
1151
+ }
1152
+ );
1153
+ };
1154
+ var Intro = () => {
1155
+ const { isMobile } = useScreen();
1156
+ const {
1157
+ currentStage,
1158
+ stages,
1159
+ setCurrentStage,
1160
+ refLink,
1161
+ refCode,
1162
+ allTimePointsDisplay,
1163
+ isNoCampaign
1164
+ } = usePoints();
1165
+ const [isStageDropdownOpen, setIsStageDropdownOpen] = useState(false);
1166
+ const { t } = useTranslation();
1167
+ const onCopyCode = async () => {
1168
+ try {
1169
+ await navigator.clipboard.writeText(refCode);
1170
+ toast.success(t("common.copy.copied"));
1171
+ } catch (error) {
1172
+ }
1173
+ };
1174
+ const onCopyLink = async () => {
1175
+ try {
1176
+ await navigator.clipboard.writeText(refLink);
1177
+ toast.success(t("common.copy.copied"));
1178
+ } catch (error) {
1179
+ }
1180
+ };
1181
+ const handleLearnMore = () => {
1182
+ const faqElement = document.getElementById("points-faq");
1183
+ if (faqElement) {
1184
+ faqElement.scrollIntoView({ behavior: "smooth", block: "start" });
1185
+ }
1186
+ };
1187
+ const formatStageDate = (startTime, endTime) => {
1188
+ const formatDate = (timestamp) => {
1189
+ const date = new Date(timestamp * 1e3);
1190
+ const month = String(date.getUTCMonth() + 1).padStart(2, "0");
1191
+ const day = String(date.getUTCDate()).padStart(2, "0");
1192
+ const year = date.getUTCFullYear();
1193
+ return `${month}/${day}/${year}`;
1194
+ };
1195
+ const startDate = formatDate(startTime);
1196
+ const endDate = endTime ? formatDate(endTime) : "Recurring";
1197
+ return `${startDate} - ${endDate}`;
1198
+ };
1199
+ return /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 8, className: "oui-w-full", children: [
1200
+ isNoCampaign ? /* @__PURE__ */ jsxs(
1201
+ Flex,
1202
+ {
1203
+ direction: "column",
1204
+ gap: 6,
1205
+ itemAlign: "start",
1206
+ className: "oui-w-full",
1207
+ children: [
1208
+ /* @__PURE__ */ jsx(
1209
+ Flex,
1210
+ {
1211
+ direction: isMobile ? "column" : "row",
1212
+ gap: 4,
1213
+ itemAlign: isMobile ? "start" : "center",
1214
+ justify: "between",
1215
+ className: "oui-w-full",
1216
+ children: /* @__PURE__ */ jsx(
1217
+ Flex,
1218
+ {
1219
+ direction: isMobile ? "column" : "row",
1220
+ itemAlign: isMobile ? "start" : "center",
1221
+ className: isMobile ? "oui-w-full" : "",
1222
+ children: /* @__PURE__ */ jsx(
1223
+ Text,
1224
+ {
1225
+ className: cn(
1226
+ "oui-text-base-contrast",
1227
+ isMobile ? "oui-text-xl" : "oui-text-4xl",
1228
+ "oui-font-600 oui-leading-tight oui-tracking-[0.03em]"
1229
+ ),
1230
+ children: t("tradingPoints.noActiveCampaigns")
1231
+ }
1232
+ )
1233
+ }
1234
+ )
1235
+ }
1236
+ ),
1237
+ /* @__PURE__ */ jsx(
1238
+ Text,
1239
+ {
1240
+ className: cn(
1241
+ "oui-text-[14px]",
1242
+ "oui-leading-[20px]",
1243
+ "oui-font-semibold",
1244
+ "oui-text-base-contrast-54"
1245
+ ),
1246
+ children: t("tradingPoints.noActiveCampaignsDescription")
1247
+ }
1248
+ )
1249
+ ]
1250
+ }
1251
+ ) : /* @__PURE__ */ jsxs(
1252
+ Flex,
1253
+ {
1254
+ direction: "column",
1255
+ gap: 6,
1256
+ itemAlign: "start",
1257
+ className: "oui-w-full",
1258
+ children: [
1259
+ /* @__PURE__ */ jsxs(
1260
+ Flex,
1261
+ {
1262
+ direction: isMobile ? "column" : "row",
1263
+ gap: 4,
1264
+ itemAlign: isMobile ? "start" : "center",
1265
+ justify: "between",
1266
+ className: "oui-w-full",
1267
+ children: [
1268
+ /* @__PURE__ */ jsxs(
1269
+ Flex,
1270
+ {
1271
+ direction: isMobile ? "column" : "row",
1272
+ itemAlign: isMobile ? "start" : "center",
1273
+ className: isMobile ? "oui-w-full" : "",
1274
+ children: [
1275
+ /* @__PURE__ */ jsxs(
1276
+ Text,
1277
+ {
1278
+ className: cn(
1279
+ "oui-text-base-contrast",
1280
+ isMobile ? "oui-text-xl" : "oui-text-4xl",
1281
+ "oui-font-600 oui-leading-tight oui-tracking-[0.03em]"
1282
+ ),
1283
+ children: [
1284
+ t("tradingPoints.stage"),
1285
+ " ",
1286
+ currentStage?.epoch_period,
1287
+ " \xB7"
1288
+ ]
1289
+ }
1290
+ ),
1291
+ /* @__PURE__ */ jsxs(Flex, { gap: 3, itemAlign: "center", children: [
1292
+ /* @__PURE__ */ jsx(
1293
+ Text,
1294
+ {
1295
+ className: cn(
1296
+ isMobile ? "oui-text-xl" : "oui-text-4xl",
1297
+ "oui-text-primary",
1298
+ "oui-text-center",
1299
+ "oui-pl-2"
1300
+ ),
1301
+ children: currentStage?.stage_name
1302
+ }
1303
+ ),
1304
+ /* @__PURE__ */ jsx(
1305
+ "img",
1306
+ {
1307
+ src: "https://oss.woo.org/static/images/sdk/pt-hot.png",
1308
+ alt: "Hot",
1309
+ className: isMobile ? "oui-h-8 oui-w-8" : "oui-h-[48px] oui-w-[48px]"
1310
+ }
1311
+ )
1312
+ ] })
1313
+ ]
1314
+ }
1315
+ ),
1316
+ /* @__PURE__ */ jsxs(
1317
+ DropdownMenuRoot,
1318
+ {
1319
+ open: isStageDropdownOpen,
1320
+ onOpenChange: setIsStageDropdownOpen,
1321
+ children: [
1322
+ /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
1323
+ Flex,
1324
+ {
1325
+ gap: 2,
1326
+ itemAlign: "center",
1327
+ px: 3,
1328
+ py: 2,
1329
+ className: "oui-w-[230px] oui-bg-base-contrast-6 oui-border oui-border-line-12 oui-rounded-md hover:oui-cursor-pointer hover:oui-opacity-80 oui-transition-opacity",
1330
+ children: [
1331
+ /* @__PURE__ */ jsx(Text, { className: "oui-flex-1 oui-text-[11px] oui-tracking-[0.03em] oui-whitespace-nowrap oui-text-base-contrast-36", children: currentStage ? `Stage ${currentStage.epoch_period}: ${formatStageDate(
1332
+ currentStage.start_time,
1333
+ currentStage.end_time
1334
+ )}` : "" }),
1335
+ /* @__PURE__ */ jsx(
1336
+ ChevronDownIcon,
1337
+ {
1338
+ size: 12,
1339
+ className: cn(
1340
+ "oui-text-base-contrast-36",
1341
+ "oui-transition-transform",
1342
+ isStageDropdownOpen && "oui-rotate-180"
1343
+ )
1344
+ }
1345
+ )
1346
+ ]
1347
+ }
1348
+ ) }),
1349
+ /* @__PURE__ */ jsx(DropdownMenuPortal, { children: /* @__PURE__ */ jsx(
1350
+ DropdownMenuContent,
1351
+ {
1352
+ onCloseAutoFocus: (e) => e.preventDefault(),
1353
+ onClick: (e) => e.stopPropagation(),
1354
+ sideOffset: 4,
1355
+ collisionPadding: { right: 16 },
1356
+ className: cn(
1357
+ "oui-bg-base-8 oui-w-[230px] oui-p-1 oui-rounded-lg",
1358
+ "oui-border oui-border-line-6",
1359
+ "oui-font-semibold",
1360
+ "oui-shadow-[0px_3px_6px_0px_rgba(0,0,0,0.2)]"
1361
+ ),
1362
+ children: /* @__PURE__ */ jsx(
1363
+ Flex,
1364
+ {
1365
+ direction: "column",
1366
+ itemAlign: "start",
1367
+ gap: 0,
1368
+ className: "oui-w-full",
1369
+ children: stages?.rows?.map((stage) => {
1370
+ const isSelected = currentStage?.stage_id === stage.stage_id;
1371
+ stage.status !== "active";
1372
+ const isActive = stage.status === "active";
1373
+ return /* @__PURE__ */ jsxs(
1374
+ Flex,
1375
+ {
1376
+ gap: 2,
1377
+ itemAlign: "center",
1378
+ px: 2,
1379
+ py: 2,
1380
+ r: "sm",
1381
+ onClick: () => {
1382
+ setCurrentStage(stage);
1383
+ setIsStageDropdownOpen(false);
1384
+ },
1385
+ className: cn(
1386
+ "oui-rounded oui-relative oui-w-full",
1387
+ "hover:oui-cursor-pointer hover:oui-opacity-80",
1388
+ isSelected ? "oui-bg-base-5" : "hover:oui-bg-base-5/50"
1389
+ ),
1390
+ children: [
1391
+ /* @__PURE__ */ jsx(
1392
+ Text,
1393
+ {
1394
+ className: cn(
1395
+ "oui-text-[11px] oui-tracking-[0.03em] oui-whitespace-nowrap",
1396
+ isSelected ? "oui-text-base-contrast-54 oui-font-semibold" : "oui-text-base-contrast-36"
1397
+ ),
1398
+ children: `Stage ${stage.epoch_period}: ${formatStageDate(
1399
+ stage.start_time,
1400
+ stage.end_time
1401
+ )}`
1402
+ }
1403
+ ),
1404
+ isActive && /* @__PURE__ */ jsx(Box, { className: "oui-w-1 oui-h-1 oui-rounded-full oui-bg-primary oui-flex-shrink-0" })
1405
+ ]
1406
+ },
1407
+ stage.stage_id
1408
+ );
1409
+ })
1410
+ }
1411
+ )
1412
+ }
1413
+ ) })
1414
+ ]
1415
+ }
1416
+ )
1417
+ ]
1418
+ }
1419
+ ),
1420
+ /* @__PURE__ */ jsxs(
1421
+ Text,
1422
+ {
1423
+ className: cn(
1424
+ "oui-text-[14px]",
1425
+ "oui-leading-[20px]",
1426
+ "oui-font-semibold",
1427
+ "oui-text-base-contrast-54"
1428
+ ),
1429
+ children: [
1430
+ currentStage?.stage_description,
1431
+ /* @__PURE__ */ jsxs(
1432
+ "span",
1433
+ {
1434
+ className: "oui-text-primary hover:oui-underline oui-cursor-pointer",
1435
+ onClick: handleLearnMore,
1436
+ children: [
1437
+ " ",
1438
+ t("tradingPoints.learnMore")
1439
+ ]
1440
+ }
1441
+ )
1442
+ ]
1443
+ }
1444
+ )
1445
+ ]
1446
+ }
1447
+ ),
1448
+ /* @__PURE__ */ jsxs(
1449
+ Flex,
1450
+ {
1451
+ direction: isMobile ? "column" : "row",
1452
+ gap: 6,
1453
+ className: "oui-w-full",
1454
+ children: [
1455
+ /* @__PURE__ */ jsxs(
1456
+ Flex,
1457
+ {
1458
+ direction: isMobile ? "column" : "row",
1459
+ gap: 6,
1460
+ itemAlign: isMobile ? "stretch" : "center",
1461
+ p: 5,
1462
+ r: "2xl",
1463
+ style: { height: isMobile ? "" : 104 },
1464
+ className: cn(
1465
+ "oui-border oui-border-line",
1466
+ !isMobile && "oui-gap-12",
1467
+ isMobile ? "oui-w-full" : "oui-flex-1"
1468
+ ),
1469
+ children: [
1470
+ /* @__PURE__ */ jsxs(
1471
+ Flex,
1472
+ {
1473
+ direction: "column",
1474
+ gap: 2,
1475
+ className: "oui-flex-1",
1476
+ itemAlign: "start",
1477
+ children: [
1478
+ /* @__PURE__ */ jsx(Text, { className: "oui-text-base-contrast-54 oui-text-sm oui-tracking-[0.03em]", children: t("tradingPoints.stagePoints") }),
1479
+ /* @__PURE__ */ jsx(Text, { className: "oui-text-base-contrast oui-text-[28px] oui-tracking-[0.03em] oui-leading-9", children: allTimePointsDisplay.currentPointsDisplay })
1480
+ ]
1481
+ }
1482
+ ),
1483
+ !isMobile && /* @__PURE__ */ jsx(
1484
+ Box,
1485
+ {
1486
+ className: cn(
1487
+ "oui-w-[1px]",
1488
+ "oui-h-full",
1489
+ "oui-bg-base-contrast-10"
1490
+ )
1491
+ }
1492
+ ),
1493
+ isMobile && /* @__PURE__ */ jsx(Divider, { intensity: 8 }),
1494
+ /* @__PURE__ */ jsxs(
1495
+ Flex,
1496
+ {
1497
+ direction: "column",
1498
+ gap: 2,
1499
+ className: "oui-flex-1",
1500
+ itemAlign: "start",
1501
+ children: [
1502
+ /* @__PURE__ */ jsx(Text, { className: "oui-text-base-contrast-54 oui-text-sm oui-tracking-[0.03em]", children: t("tradingPoints.stageRanking") }),
1503
+ /* @__PURE__ */ jsx(Text, { className: "oui-text-base-contrast oui-text-[28px] oui-tracking-[0.03em] oui-leading-9", children: allTimePointsDisplay.rankingDisplay })
1504
+ ]
1505
+ }
1506
+ )
1507
+ ]
1508
+ }
1509
+ ),
1510
+ /* @__PURE__ */ jsx(
1511
+ Flex,
1512
+ {
1513
+ p: 5,
1514
+ r: "2xl",
1515
+ style: { height: 104 },
1516
+ className: cn(
1517
+ "oui-border oui-border-line",
1518
+ isMobile ? "oui-w-full" : "oui-flex-1",
1519
+ "oui-h-[128px]"
1520
+ ),
1521
+ children: /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 4, className: "oui-w-full", children: [
1522
+ /* @__PURE__ */ jsxs(Flex, { gap: 2, itemAlign: "center", className: "oui-w-full", children: [
1523
+ /* @__PURE__ */ jsx(Text, { className: "oui-text-base-contrast-54 oui-text-sm oui-tracking-[0.03em]", children: t("tradingPoints.referralCode") }),
1524
+ /* @__PURE__ */ jsxs(
1525
+ Flex,
1526
+ {
1527
+ gap: 2,
1528
+ itemAlign: "center",
1529
+ justify: "end",
1530
+ className: "oui-flex-1",
1531
+ children: [
1532
+ /* @__PURE__ */ jsx(Text, { className: "oui-text-base-contrast oui-text-sm oui-tracking-[0.03em]", children: refCode }),
1533
+ /* @__PURE__ */ jsx(
1534
+ CopyIcon,
1535
+ {
1536
+ size: 16,
1537
+ className: "oui-text-base-contrast hover:oui-cursor-pointer hover:oui-opacity-80 oui-transition-opacity",
1538
+ onClick: onCopyCode
1539
+ }
1540
+ )
1541
+ ]
1542
+ }
1543
+ )
1544
+ ] }),
1545
+ /* @__PURE__ */ jsxs(Flex, { gap: 2, itemAlign: "start", className: "oui-w-full", children: [
1546
+ /* @__PURE__ */ jsx(Text, { className: "oui-text-base-contrast-54 oui-text-sm oui-tracking-[0.03em] oui-flex-shrink-0", children: t("tradingPoints.referralLink") }),
1547
+ /* @__PURE__ */ jsxs(
1548
+ Flex,
1549
+ {
1550
+ gap: 2,
1551
+ itemAlign: "start",
1552
+ className: "oui-flex-1 oui-min-w-0",
1553
+ children: [
1554
+ /* @__PURE__ */ jsx(Text, { className: "oui-text-base-contrast oui-text-sm oui-tracking-[0.03em] oui-flex-1 oui-truncate oui-text-right", children: refLink }),
1555
+ /* @__PURE__ */ jsx(
1556
+ CopyIcon,
1557
+ {
1558
+ size: 16,
1559
+ className: "oui-text-base-contrast hover:oui-cursor-pointer hover:oui-opacity-80 oui-transition-opacity",
1560
+ onClick: onCopyLink
1561
+ }
1562
+ )
1563
+ ]
1564
+ }
1565
+ )
1566
+ ] })
1567
+ ] })
1568
+ }
1569
+ )
1570
+ ]
1571
+ }
1572
+ )
1573
+ ] });
1574
+ };
1575
+ var User = ({ onRouteChange }) => {
1576
+ const { t } = useTranslation();
1577
+ const { isMobile } = useScreen();
1578
+ const {
1579
+ refLink,
1580
+ selectedTimeRange,
1581
+ setSelectedTimeRange,
1582
+ pointsDisplay,
1583
+ userStatistics,
1584
+ isCurrentStageCompleted
1585
+ } = usePoints();
1586
+ const timeRangeOptions = [
1587
+ { value: "this_week", label: t("tradingPoints.thisWeek") },
1588
+ { value: "last_week", label: t("tradingPoints.lastWeek") },
1589
+ { value: "all_time", label: t("tradingPoints.all") }
1590
+ ];
1591
+ if (isCurrentStageCompleted) {
1592
+ if (selectedTimeRange !== "all_time") {
1593
+ setSelectedTimeRange("all_time");
1594
+ }
1595
+ timeRangeOptions.splice(0, 2);
1596
+ }
1597
+ const timeRangeButtonClass = cn(
1598
+ "oui-inline-flex oui-items-center oui-justify-center oui-whitespace-nowrap",
1599
+ "oui-box-content oui-rounded oui-px-3 oui-h-7",
1600
+ "oui-font-medium oui-text-2xs oui-text-base-contrast-36",
1601
+ "hover:oui-text-base-contrast-54 hover:oui-bg-base-5",
1602
+ "oui-bg-base-7",
1603
+ "data-[state=active]:oui-bg-base-5 data-[state=active]:oui-text-base-contrast",
1604
+ "oui-transition-all focus-visible:oui-outline-none",
1605
+ "focus-visible:oui-ring-2 focus-visible:oui-ring-ring focus-visible:oui-ring-offset-2",
1606
+ "disabled:oui-pointer-events-none disabled:oui-opacity-50"
1607
+ );
1608
+ const currentPointsDisplay = pointsDisplay.currentPointsDisplay;
1609
+ const rankingDisplay = pointsDisplay.rankingDisplay;
1610
+ const tradingPointsDisplay = pointsDisplay.tradingPointsDisplay;
1611
+ const pnlPointsDisplay = pointsDisplay.pnlPointsDisplay;
1612
+ const referralPointsDisplay = pointsDisplay.referralPointsDisplay;
1613
+ const formatReferralBoost = (value) => {
1614
+ return value !== null && value !== void 0 ? value : "--";
1615
+ };
1616
+ const goToPerp = useCallback(() => {
1617
+ onRouteChange({
1618
+ href: "/perp",
1619
+ name: "Perp"
1620
+ });
1621
+ }, [onRouteChange]);
1622
+ const onCopy = async () => {
1623
+ try {
1624
+ await navigator.clipboard.writeText(refLink);
1625
+ toast.success(t("common.copy.copied"));
1626
+ } catch (error) {
1627
+ }
1628
+ };
1629
+ const userStats = /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs(
1630
+ Flex,
1631
+ {
1632
+ direction: isMobile ? "column" : "row",
1633
+ gap: 4,
1634
+ itemAlign: "stretch",
1635
+ className: "oui-w-full",
1636
+ children: [
1637
+ /* @__PURE__ */ jsxs(
1638
+ Flex,
1639
+ {
1640
+ direction: "column",
1641
+ gap: 2,
1642
+ className: isMobile ? "oui-w-full" : "oui-w-[200px]",
1643
+ children: [
1644
+ /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 3, p: 4, r: "2xl", children: [
1645
+ /* @__PURE__ */ jsx(Text, { className: "oui-text-base-contrast-54 oui-text-sm oui-tracking-[0.03em] oui-decoration-dotted oui-text-center oui-w-full", children: t("tradingPoints.currentPoints") }),
1646
+ /* @__PURE__ */ jsx(Text, { className: "oui-text-transparent oui-bg-clip-text oui-gradient-brand oui-text-3xl oui-tracking-[0.03em] oui-text-center oui-w-full oui-h-10 oui-leading-10", children: currentPointsDisplay })
1647
+ ] }),
1648
+ /* @__PURE__ */ jsx(Divider, { className: "oui-w-full", intensity: 8 }),
1649
+ /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 3, p: 4, r: "2xl", children: [
1650
+ /* @__PURE__ */ jsx(Text, { className: "oui-text-base-contrast-54 oui-text-sm oui-tracking-[0.03em] oui-text-center oui-w-full", children: t("tradingPoints.ranking") }),
1651
+ /* @__PURE__ */ jsx(Text, { className: "oui-text-transparent oui-bg-clip-text oui-gradient-brand oui-text-3xl oui-tracking-[0.03em] oui-text-center oui-w-full oui-h-10 oui-leading-10", children: rankingDisplay })
1652
+ ] })
1653
+ ]
1654
+ }
1655
+ ),
1656
+ !isMobile && /* @__PURE__ */ jsx(
1657
+ Divider,
1658
+ {
1659
+ className: "oui-self-stretch",
1660
+ intensity: 8,
1661
+ direction: "vertical"
1662
+ }
1663
+ ),
1664
+ isMobile && /* @__PURE__ */ jsx(Divider, { intensity: 8 }),
1665
+ /* @__PURE__ */ jsx(
1666
+ Flex,
1667
+ {
1668
+ direction: "column",
1669
+ className: isMobile ? "oui-w-full" : "oui-flex-1",
1670
+ children: /* @__PURE__ */ jsxs(
1671
+ Flex,
1672
+ {
1673
+ direction: isMobile ? "column" : "row",
1674
+ gap: 6,
1675
+ className: "oui-w-full oui-h-full",
1676
+ children: [
1677
+ /* @__PURE__ */ jsxs(
1678
+ Flex,
1679
+ {
1680
+ direction: "column",
1681
+ gap: 3,
1682
+ itemAlign: "center",
1683
+ justify: "center",
1684
+ p: 4,
1685
+ r: "xl",
1686
+ intensity: 800,
1687
+ className: cn(
1688
+ "oui-backdrop-blur-sm",
1689
+ isMobile ? "oui-w-full" : "oui-flex-1 oui-h-full"
1690
+ ),
1691
+ children: [
1692
+ /* @__PURE__ */ jsx(
1693
+ Tooltip,
1694
+ {
1695
+ content: t("tradingPoints.tradePointsTooltip"),
1696
+ className: "oui-max-w-[300px] oui-bg-primary-darken",
1697
+ children: /* @__PURE__ */ jsx(
1698
+ Text,
1699
+ {
1700
+ className: "oui-text-base-contrast-54 oui-text-sm oui-tracking-[0.03em] oui-text-center oui-w-full\n ",
1701
+ style: {
1702
+ textDecorationLine: "underline",
1703
+ textDecorationStyle: "dotted",
1704
+ textUnderlineOffset: "30%"
1705
+ },
1706
+ children: t("tradingPoints.tradePoints")
1707
+ }
1708
+ )
1709
+ }
1710
+ ),
1711
+ /* @__PURE__ */ jsx(Text, { className: "oui-text-base-contrast oui-text-[28px] oui-tracking-[0.03em] oui-text-center oui-w-full oui-leading-9", children: tradingPointsDisplay }),
1712
+ /* @__PURE__ */ jsx(Button, { size: "md", onClick: goToPerp, children: /* @__PURE__ */ jsx(Text, { children: t("tradingPoints.tradeNow") }) })
1713
+ ]
1714
+ }
1715
+ ),
1716
+ /* @__PURE__ */ jsxs(
1717
+ Flex,
1718
+ {
1719
+ direction: "column",
1720
+ gap: 3,
1721
+ itemAlign: "center",
1722
+ justify: "center",
1723
+ p: 4,
1724
+ r: "xl",
1725
+ intensity: 800,
1726
+ className: cn(
1727
+ "oui-backdrop-blur-sm",
1728
+ isMobile ? "oui-w-full" : "oui-flex-1 oui-h-full"
1729
+ ),
1730
+ children: [
1731
+ /* @__PURE__ */ jsx(
1732
+ Tooltip,
1733
+ {
1734
+ content: t("tradingPoints.pnlPointsTooltip"),
1735
+ className: "oui-max-w-[300px] oui-bg-primary-darken",
1736
+ children: /* @__PURE__ */ jsx(
1737
+ Text,
1738
+ {
1739
+ className: "oui-text-base-contrast-54 oui-text-sm oui-tracking-[0.03em] oui-text-center oui-w-full",
1740
+ style: {
1741
+ textDecorationLine: "underline",
1742
+ textDecorationStyle: "dotted",
1743
+ textUnderlineOffset: "30%"
1744
+ },
1745
+ children: t("tradingPoints.pnlPoints")
1746
+ }
1747
+ )
1748
+ }
1749
+ ),
1750
+ /* @__PURE__ */ jsx(Text, { className: "oui-text-base-contrast oui-text-[28px] oui-tracking-[0.03em] oui-text-center oui-w-full oui-leading-9", children: pnlPointsDisplay }),
1751
+ /* @__PURE__ */ jsx(Button, { size: "md", onClick: goToPerp, children: /* @__PURE__ */ jsx(Text, { children: t("tradingPoints.tradeNow") }) })
1752
+ ]
1753
+ }
1754
+ ),
1755
+ /* @__PURE__ */ jsxs(
1756
+ Flex,
1757
+ {
1758
+ direction: "column",
1759
+ gap: 3,
1760
+ itemAlign: "center",
1761
+ justify: "center",
1762
+ p: 4,
1763
+ r: "xl",
1764
+ intensity: 800,
1765
+ className: cn(
1766
+ "oui-backdrop-blur-sm",
1767
+ isMobile ? "oui-w-full" : "oui-flex-1 oui-h-full"
1768
+ ),
1769
+ children: [
1770
+ /* @__PURE__ */ jsx(
1771
+ Tooltip,
1772
+ {
1773
+ content: t("tradingPoints.referralPointsTooltip", {
1774
+ l1: formatReferralBoost(userStatistics?.l1_referral_boost),
1775
+ l2: formatReferralBoost(userStatistics?.l2_referral_boost)
1776
+ }),
1777
+ className: "oui-max-w-[300px] oui-bg-primary-darken",
1778
+ children: /* @__PURE__ */ jsx(
1779
+ Text,
1780
+ {
1781
+ className: "oui-text-base-contrast-54 oui-text-sm oui-tracking-[0.03em] oui-text-center oui-w-full",
1782
+ style: {
1783
+ textDecorationLine: "underline",
1784
+ textDecorationStyle: "dotted",
1785
+ textUnderlineOffset: "30%"
1786
+ },
1787
+ children: t("tradingPoints.referralPoints")
1788
+ }
1789
+ )
1790
+ }
1791
+ ),
1792
+ /* @__PURE__ */ jsx(Text, { className: "oui-text-base-contrast oui-text-[28px] oui-tracking-[0.03em] oui-text-center oui-w-full oui-leading-9", children: referralPointsDisplay }),
1793
+ /* @__PURE__ */ jsx(Button, { variant: "outlined", size: "md", onClick: onCopy, children: /* @__PURE__ */ jsx(Text, { className: "oui-text-base-contrast-54", children: t("tradingPoints.copyLink") }) })
1794
+ ]
1795
+ }
1796
+ )
1797
+ ]
1798
+ }
1799
+ )
1800
+ }
1801
+ )
1802
+ ]
1803
+ }
1804
+ ) });
1805
+ return /* @__PURE__ */ jsxs(Flex, { direction: "column", gap: 6, className: "oui-w-full", children: [
1806
+ /* @__PURE__ */ jsxs(
1807
+ Flex,
1808
+ {
1809
+ direction: isMobile ? "column" : "row",
1810
+ gap: isMobile ? 4 : 0,
1811
+ itemAlign: isMobile ? "start" : "center",
1812
+ justify: "between",
1813
+ className: "oui-w-full",
1814
+ children: [
1815
+ /* @__PURE__ */ jsx(
1816
+ Text,
1817
+ {
1818
+ className: cn(
1819
+ "oui-text-base-contrast",
1820
+ isMobile ? "oui-text-2xl" : "oui-text-3xl",
1821
+ "oui-tracking-[0.03em]"
1822
+ ),
1823
+ children: t("tradingPoints.myPoints")
1824
+ }
1825
+ ),
1826
+ /* @__PURE__ */ jsx(Flex, { gap: 2, itemAlign: "center", children: timeRangeOptions.map((option) => /* @__PURE__ */ jsx(
1827
+ "button",
1828
+ {
1829
+ onClick: () => setSelectedTimeRange(option.value),
1830
+ "data-state": selectedTimeRange === option.value ? "active" : "inactive",
1831
+ className: timeRangeButtonClass,
1832
+ children: option.label
1833
+ },
1834
+ option.value
1835
+ )) })
1836
+ ]
1837
+ }
1838
+ ),
1839
+ /* @__PURE__ */ jsx(Box, { p: 6, r: "2xl", className: "oui-border oui-border-line oui-w-full", children: userStats })
1840
+ ] });
1841
+ };
1842
+ var Main = ({ onRouteChange }) => {
1843
+ const { isMobile } = useScreen();
1844
+ const { isNoCampaign, isCurrentStagePending } = usePoints();
1845
+ return /* @__PURE__ */ jsxs(
1846
+ Flex,
1847
+ {
1848
+ direction: "column",
1849
+ gap: isMobile ? 6 : 10,
1850
+ className: cn(
1851
+ "oui-w-full",
1852
+ isMobile ? "oui-px-5 oui-py-6" : "oui-max-w-[1200px] oui-mx-auto oui-py-[64px] oui-py-12"
1853
+ ),
1854
+ children: [
1855
+ /* @__PURE__ */ jsx(Countdown, {}),
1856
+ /* @__PURE__ */ jsx(Intro, {}),
1857
+ !isNoCampaign && /* @__PURE__ */ jsxs(Fragment, { children: [
1858
+ /* @__PURE__ */ jsx(User, { onRouteChange }),
1859
+ !isCurrentStagePending && /* @__PURE__ */ jsx(GeneralLeaderboardWidget, {})
1860
+ ] }),
1861
+ /* @__PURE__ */ jsx(FAQSection, { className: "oui-w-full" })
1862
+ ]
1863
+ }
1864
+ );
1865
+ };
1866
+ var main_default = Main;
1867
+
1868
+ // src/i18n/module.ts
1869
+ var LocaleMessages = {
1870
+ "tradingPoints.points": "Points",
1871
+ "tradingPoints.stage": "Stage",
1872
+ "tradingPoints.startsIn": "Starts in",
1873
+ "tradingPoints.days": "Days",
1874
+ "tradingPoints.hours": "Hours",
1875
+ "tradingPoints.minutes": "Minutes",
1876
+ "tradingPoints.seconds": "Seconds",
1877
+ "tradingPoints.learnMore": "Learn more",
1878
+ "tradingPoints.stagePoints": "Stage points",
1879
+ "tradingPoints.stageRanking": "Stage ranking",
1880
+ "tradingPoints.referralCode": "Referral code",
1881
+ "tradingPoints.referralLink": "Referral link",
1882
+ "tradingPoints.currentPoints": "Current points",
1883
+ "tradingPoints.ranking": "Ranking",
1884
+ "tradingPoints.myPoints": "My points",
1885
+ "tradingPoints.thisWeek": "This week",
1886
+ "tradingPoints.lastWeek": "Last week",
1887
+ "tradingPoints.all": "All",
1888
+ "tradingPoints.tradePoints": "Trade points",
1889
+ "tradingPoints.tradePointsTooltip": "Trade Points are calculated based on your perps trading volume.Updated daily.",
1890
+ "tradingPoints.tradeNow": "Trade now",
1891
+ "tradingPoints.pnlPoints": "PNL points",
1892
+ "tradingPoints.pnlPointsTooltip": "Both profit or loss of each trade will be recorded. Updated daily.",
1893
+ "tradingPoints.referralPoints": "Referral points",
1894
+ "tradingPoints.referralPointsTooltip": "First-level invitee's rebates: {{l1}}%, Second-level invitee's rebates: {{l2}}%, Update daily.",
1895
+ "tradingPoints.copyLink": "Copy Link",
1896
+ "tradingPoints.faq.title": "FAQ",
1897
+ "tradingPoints.faq.whatArePoints.question": "What are Points?",
1898
+ "tradingPoints.faq.whatArePoints.answer": "The Points program is designed to encourage genuine user engagement with products and to reward loyal users who actively contribute to the growth of the {{brokerName}} ecosystem. Rewards will be airdropped in the future based on users' point accumulation.",
1899
+ "tradingPoints.faq.allocation.question": "What is the points allocation criteria?",
1900
+ "tradingPoints.faq.allocation.answer": "Points = Trade points + PNL points + Referral points.\n\nThe page will update your points daily, calculating the points you are expected to receive based on your contribution.\n\nNote: Wash trading (e.g., self-trades) will not receive any points",
1901
+ "tradingPoints.faq.distribution.question": "When will points be distributed?",
1902
+ "tradingPoints.faq.distribution.answer": "Points are distributed at 08:00 UTC everyday.",
1903
+ "tradingPoints.faq.pnl.question": "How are PNL points calculated?",
1904
+ "tradingPoints.faq.pnl.answer": "Points are based on your net profit or loss each trading.",
1905
+ "tradingPoints.faq.referral.question": "How does the referral work?",
1906
+ "tradingPoints.faq.referral.answer": "Based on the total points of your invitees and their invitees. Points earned from first-level invitees are higher than those from second-level invitees. Updated daily.",
1907
+ "tradingPoints.noActiveCampaigns": "No Active Campaigns",
1908
+ "tradingPoints.noActiveCampaignsDescription": "There are currently no active point events. Please wait for the next update."
1909
+ };
1910
+
1911
+ // import("./locales/**/*.json") in src/i18n/provider.tsx
1912
+ var globImport_locales_json = __glob({
1913
+ "./locales/de.json": () => import('./de-K5HENMOT.mjs'),
1914
+ "./locales/en.json": () => import('./en-LJLDUQVE.mjs'),
1915
+ "./locales/es.json": () => import('./es-WKVHRKSR.mjs'),
1916
+ "./locales/fr.json": () => import('./fr-YXNQ5BX2.mjs'),
1917
+ "./locales/id.json": () => import('./id-5OI6YOIW.mjs'),
1918
+ "./locales/it.json": () => import('./it-FU4DAFK5.mjs'),
1919
+ "./locales/ja.json": () => import('./ja-KNZVN3N7.mjs'),
1920
+ "./locales/ko.json": () => import('./ko-SUWRSMGZ.mjs'),
1921
+ "./locales/nl.json": () => import('./nl-4U5KKRP6.mjs'),
1922
+ "./locales/pl.json": () => import('./pl-CVHBNRM4.mjs'),
1923
+ "./locales/pt.json": () => import('./pt-NQRWOJW2.mjs'),
1924
+ "./locales/ru.json": () => import('./ru-MRDWLFFN.mjs'),
1925
+ "./locales/tc.json": () => import('./tc-E5EMOQRW.mjs'),
1926
+ "./locales/tr.json": () => import('./tr-XQG34EBR.mjs'),
1927
+ "./locales/uk.json": () => import('./uk-J6HX5IAD.mjs'),
1928
+ "./locales/vi.json": () => import('./vi-EJDUONJ6.mjs'),
1929
+ "./locales/zh.json": () => import('./zh-EAO7UXG4.mjs')
1930
+ });
1931
+
1932
+ // src/i18n/provider.tsx
1933
+ var resources = async (lang) => {
1934
+ if (lang === LocaleEnum.en) {
1935
+ return LocaleMessages;
1936
+ }
1937
+ return globImport_locales_json(`./locales/${lang}.json`).then((res) => res.default);
1938
+ };
1939
+ var LocaleProvider = (props) => {
1940
+ return /* @__PURE__ */ jsx(ExternalLocaleProvider, { resources, children: props.children });
1941
+ };
1942
+ var PointSystemPage = (props) => {
1943
+ return /* @__PURE__ */ jsx(LocaleProvider, { children: /* @__PURE__ */ jsx(PointsProvider, { children: /* @__PURE__ */ jsx(main_default, { onRouteChange: props.onRouteChange }) }) });
1944
+ };
1945
+
1946
+ export { PointSystemPage };
1947
+ //# sourceMappingURL=index.mjs.map
1948
+ //# sourceMappingURL=index.mjs.map