@anker-in/ui 0.1.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/README.md +83 -0
- package/dist/DemoRoom-CZyrsxWe.d.mts +30 -0
- package/dist/DemoRoom-CZyrsxWe.d.ts +30 -0
- package/dist/demo-room.css +33 -0
- package/dist/demo-room.css.map +1 -0
- package/dist/demo-room.d.mts +198 -0
- package/dist/demo-room.d.ts +198 -0
- package/dist/demo-room.js +1727 -0
- package/dist/demo-room.js.map +1 -0
- package/dist/demo-room.mjs +1713 -0
- package/dist/demo-room.mjs.map +1 -0
- package/dist/index.css +33 -0
- package/dist/index.css.map +1 -0
- package/dist/index.d.mts +283 -0
- package/dist/index.d.ts +283 -0
- package/dist/index.js +3077 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +3052 -0
- package/dist/index.mjs.map +1 -0
- package/dist/styles.css +1 -0
- package/dist/theme.d.mts +126 -0
- package/dist/theme.d.ts +126 -0
- package/dist/theme.js +147 -0
- package/dist/theme.js.map +1 -0
- package/dist/theme.mjs +144 -0
- package/dist/theme.mjs.map +1 -0
- package/package.json +83 -0
|
@@ -0,0 +1,1727 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var React2 = require('react');
|
|
4
|
+
var clsx = require('clsx');
|
|
5
|
+
var tailwindMerge = require('tailwind-merge');
|
|
6
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
7
|
+
var headlessUi = require('@anker-in/headless-ui');
|
|
8
|
+
var IndexBar = require('antd-mobile/es/components/index-bar');
|
|
9
|
+
var List = require('antd-mobile/es/components/list');
|
|
10
|
+
require('antd-mobile/es/components/index-bar/index-bar.css');
|
|
11
|
+
require('antd-mobile/es/components/list/list.css');
|
|
12
|
+
|
|
13
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
14
|
+
|
|
15
|
+
var React2__default = /*#__PURE__*/_interopDefault(React2);
|
|
16
|
+
var IndexBar__default = /*#__PURE__*/_interopDefault(IndexBar);
|
|
17
|
+
var List__default = /*#__PURE__*/_interopDefault(List);
|
|
18
|
+
|
|
19
|
+
function cn(...inputs) {
|
|
20
|
+
return tailwindMerge.twMerge(clsx.clsx(inputs));
|
|
21
|
+
}
|
|
22
|
+
var defaultTabs = [
|
|
23
|
+
{ id: "upcoming-events", label: "Upcoming Events" },
|
|
24
|
+
{ id: "find-demoroom", label: "Find Demoroom" },
|
|
25
|
+
{ id: "4-easy-steps", label: "4 Easy Steps" },
|
|
26
|
+
{ id: "faq", label: "FAQ" }
|
|
27
|
+
];
|
|
28
|
+
var HelpNav = ({
|
|
29
|
+
tabs = defaultTabs,
|
|
30
|
+
activeTabId: controlledActiveTabId,
|
|
31
|
+
onTabChange,
|
|
32
|
+
activeBorderColor = "#3ADB67",
|
|
33
|
+
className,
|
|
34
|
+
...props
|
|
35
|
+
}) => {
|
|
36
|
+
const [internalActiveTabId, setInternalActiveTabId] = React2.useState(
|
|
37
|
+
tabs[1]?.id || tabs[0]?.id
|
|
38
|
+
);
|
|
39
|
+
const activeTabId = controlledActiveTabId ?? internalActiveTabId;
|
|
40
|
+
const handleTabClick = (tabId) => {
|
|
41
|
+
if (!controlledActiveTabId) {
|
|
42
|
+
setInternalActiveTabId(tabId);
|
|
43
|
+
}
|
|
44
|
+
onTabChange?.(tabId);
|
|
45
|
+
};
|
|
46
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
47
|
+
"div",
|
|
48
|
+
{
|
|
49
|
+
className: cn(
|
|
50
|
+
"w-full pt-5 flex items-center justify-center gap-8 pb-8",
|
|
51
|
+
className
|
|
52
|
+
),
|
|
53
|
+
...props,
|
|
54
|
+
children: tabs.map((tab) => {
|
|
55
|
+
const isActive = tab.id === activeTabId;
|
|
56
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
57
|
+
"button",
|
|
58
|
+
{
|
|
59
|
+
onClick: () => handleTabClick(tab.id),
|
|
60
|
+
className: cn(
|
|
61
|
+
"relative text-[#080A0F]",
|
|
62
|
+
"pb-4",
|
|
63
|
+
"flex items-center gap-2",
|
|
64
|
+
"transition-all duration-200",
|
|
65
|
+
"outline-none focus:outline-none"
|
|
66
|
+
),
|
|
67
|
+
style: {
|
|
68
|
+
fontSize: "18px",
|
|
69
|
+
fontWeight: 600,
|
|
70
|
+
letterSpacing: "-0.36px",
|
|
71
|
+
lineHeight: "25.2px"
|
|
72
|
+
},
|
|
73
|
+
children: [
|
|
74
|
+
tab.label,
|
|
75
|
+
isActive && /* @__PURE__ */ jsxRuntime.jsx(
|
|
76
|
+
"span",
|
|
77
|
+
{
|
|
78
|
+
className: "absolute bottom-0 left-0 right-0 h-1 rounded-t",
|
|
79
|
+
style: {
|
|
80
|
+
backgroundColor: activeBorderColor,
|
|
81
|
+
height: "4px"
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
)
|
|
85
|
+
]
|
|
86
|
+
},
|
|
87
|
+
tab.id
|
|
88
|
+
);
|
|
89
|
+
})
|
|
90
|
+
}
|
|
91
|
+
);
|
|
92
|
+
};
|
|
93
|
+
HelpNav.displayName = "HelpNav";
|
|
94
|
+
var EventCard = ({
|
|
95
|
+
title,
|
|
96
|
+
description,
|
|
97
|
+
backgroundImage,
|
|
98
|
+
aspectRatio,
|
|
99
|
+
variant = "medium",
|
|
100
|
+
buttons = [],
|
|
101
|
+
subtitle,
|
|
102
|
+
className,
|
|
103
|
+
...props
|
|
104
|
+
}) => {
|
|
105
|
+
const isLarge = variant === "large";
|
|
106
|
+
const isMedium = variant === "medium";
|
|
107
|
+
const isProduct = variant === "product";
|
|
108
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
109
|
+
"div",
|
|
110
|
+
{
|
|
111
|
+
className: cn("rounded-3xl overflow-hidden relative", className),
|
|
112
|
+
style: {
|
|
113
|
+
backgroundImage: backgroundImage ? `url(${backgroundImage})` : void 0,
|
|
114
|
+
backgroundSize: "cover",
|
|
115
|
+
backgroundPosition: "center",
|
|
116
|
+
aspectRatio
|
|
117
|
+
},
|
|
118
|
+
...props,
|
|
119
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
120
|
+
"div",
|
|
121
|
+
{
|
|
122
|
+
className: cn(
|
|
123
|
+
"relative h-full flex flex-col",
|
|
124
|
+
isLarge && "justify-center pl-8",
|
|
125
|
+
!isLarge && "justify-end pl-8 pb-8"
|
|
126
|
+
),
|
|
127
|
+
children: [
|
|
128
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
129
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
130
|
+
"h3",
|
|
131
|
+
{
|
|
132
|
+
className: cn(
|
|
133
|
+
"font-semibold mb-3",
|
|
134
|
+
isLarge && "text-3xl text-gray-900",
|
|
135
|
+
isMedium && "text-2xl text-white",
|
|
136
|
+
isProduct && "text-2xl text-gray-900"
|
|
137
|
+
),
|
|
138
|
+
children: title
|
|
139
|
+
}
|
|
140
|
+
),
|
|
141
|
+
subtitle && isProduct && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-600 mb-4", children: subtitle }),
|
|
142
|
+
description && /* @__PURE__ */ jsxRuntime.jsx(
|
|
143
|
+
"p",
|
|
144
|
+
{
|
|
145
|
+
className: cn(
|
|
146
|
+
"text-sm leading-relaxed",
|
|
147
|
+
isMedium && "text-white/90",
|
|
148
|
+
(isLarge || isProduct) && "text-gray-600"
|
|
149
|
+
),
|
|
150
|
+
children: description
|
|
151
|
+
}
|
|
152
|
+
)
|
|
153
|
+
] }),
|
|
154
|
+
buttons.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex gap-3 mt-6", children: buttons.map((button, index) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
155
|
+
"button",
|
|
156
|
+
{
|
|
157
|
+
onClick: button.onClick,
|
|
158
|
+
className: cn(
|
|
159
|
+
"px-6 py-3 rounded-full font-medium text-sm transition-all duration-200",
|
|
160
|
+
button.variant === "primary" && "bg-gray-900 text-white hover:bg-gray-800",
|
|
161
|
+
button.variant === "secondary" && "bg-white text-gray-900 border border-gray-300 hover:bg-gray-50"
|
|
162
|
+
),
|
|
163
|
+
children: button.label
|
|
164
|
+
},
|
|
165
|
+
index
|
|
166
|
+
)) })
|
|
167
|
+
]
|
|
168
|
+
}
|
|
169
|
+
)
|
|
170
|
+
}
|
|
171
|
+
);
|
|
172
|
+
};
|
|
173
|
+
EventCard.displayName = "EventCard";
|
|
174
|
+
var Title = ({
|
|
175
|
+
title = "",
|
|
176
|
+
...props
|
|
177
|
+
}) => {
|
|
178
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("w-full"), ...props, children: /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-[48px] font-semibold mb-12 text-[#080A0F]", children: title }) });
|
|
179
|
+
};
|
|
180
|
+
Title.displayName = "Title";
|
|
181
|
+
var defaultEvents = [
|
|
182
|
+
{
|
|
183
|
+
variant: "large",
|
|
184
|
+
title: "IFA 2025 Event Name Event Name",
|
|
185
|
+
description: "Corem ipsum dolor sit amet, consectetur adipiscing elit.",
|
|
186
|
+
backgroundImage: "https://cdn.shopify.com/s/files/1/0569/5147/2268/files/Component_3_1.png?v=1765274638",
|
|
187
|
+
buttons: [
|
|
188
|
+
{
|
|
189
|
+
label: "Schedule Now",
|
|
190
|
+
variant: "primary"
|
|
191
|
+
}
|
|
192
|
+
],
|
|
193
|
+
aspectRatio: "1664 / 640"
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
variant: "medium",
|
|
197
|
+
title: "Local Event Name Local Event Name Local Event Name",
|
|
198
|
+
description: "Norem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac aliquet odio mattis.",
|
|
199
|
+
backgroundImage: "https://cdn.shopify.com/s/files/1/0569/5147/2268/files/Component_3_1.png?v=1765274638",
|
|
200
|
+
buttons: [
|
|
201
|
+
{
|
|
202
|
+
label: "Schedule Now",
|
|
203
|
+
variant: "primary"
|
|
204
|
+
}
|
|
205
|
+
],
|
|
206
|
+
aspectRatio: "824 / 640"
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
variant: "product",
|
|
210
|
+
title: "Anker Prime",
|
|
211
|
+
subtitle: "Anker Prime 240W GaN Desktop Charger (4 Ports) Feb. 5th - 16th",
|
|
212
|
+
backgroundImage: "https://cdn.shopify.com/s/files/1/0569/5147/2268/files/Component_3_1.png?v=1765274638",
|
|
213
|
+
buttons: [
|
|
214
|
+
{
|
|
215
|
+
label: "Learn More",
|
|
216
|
+
variant: "secondary"
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
label: "Shop Now",
|
|
220
|
+
variant: "primary"
|
|
221
|
+
}
|
|
222
|
+
],
|
|
223
|
+
aspectRatio: "824 / 640"
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
variant: "medium",
|
|
227
|
+
title: "Local Event Name Local Event Name Local Event Name",
|
|
228
|
+
description: "Norem ipsum dolor sit amet, consectetur adipiscing elit. Nunc vulputate libero et velit interdum, ac aliquet odio mattis.",
|
|
229
|
+
backgroundImage: "https://cdn.shopify.com/s/files/1/0569/5147/2268/files/Component_3_1.png?v=1765274638",
|
|
230
|
+
buttons: [
|
|
231
|
+
{
|
|
232
|
+
label: "Schedule Now",
|
|
233
|
+
variant: "primary"
|
|
234
|
+
}
|
|
235
|
+
],
|
|
236
|
+
aspectRatio: "824 / 640"
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
variant: "product",
|
|
240
|
+
title: "Anker Prime",
|
|
241
|
+
subtitle: "Anker Prime 240W GaN Desktop Charger (4 Ports) Feb. 5th - 16th",
|
|
242
|
+
backgroundImage: "https://cdn.shopify.com/s/files/1/0569/5147/2268/files/Component_3_1.png?v=1765274638",
|
|
243
|
+
buttons: [
|
|
244
|
+
{
|
|
245
|
+
label: "Learn More",
|
|
246
|
+
variant: "secondary"
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
label: "Shop Now",
|
|
250
|
+
variant: "primary"
|
|
251
|
+
}
|
|
252
|
+
],
|
|
253
|
+
aspectRatio: "824 / 640"
|
|
254
|
+
}
|
|
255
|
+
];
|
|
256
|
+
var UpcomingEvents = ({
|
|
257
|
+
title = "Upcoming Events",
|
|
258
|
+
events = defaultEvents,
|
|
259
|
+
showViewMore = true,
|
|
260
|
+
onViewMore,
|
|
261
|
+
className,
|
|
262
|
+
...props
|
|
263
|
+
}) => {
|
|
264
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("w-full", className), ...props, children: [
|
|
265
|
+
/* @__PURE__ */ jsxRuntime.jsx(Title, { title }),
|
|
266
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-2 gap-6 mb-[64px]", children: events.map((event, index) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn(index === 0 ? "col-span-2" : ""), children: /* @__PURE__ */ jsxRuntime.jsx(EventCard, { ...event }) }, index)) }),
|
|
267
|
+
showViewMore && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex justify-center", children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
268
|
+
"button",
|
|
269
|
+
{
|
|
270
|
+
onClick: onViewMore,
|
|
271
|
+
className: "inline-flex items-center gap-2 text-gray-700 hover:text-gray-900 transition-colors duration-200",
|
|
272
|
+
children: [
|
|
273
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-base font-bold", children: "View More" }),
|
|
274
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
275
|
+
"svg",
|
|
276
|
+
{
|
|
277
|
+
width: "16",
|
|
278
|
+
height: "16",
|
|
279
|
+
viewBox: "0 0 16 16",
|
|
280
|
+
fill: "none",
|
|
281
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
282
|
+
className: "transition-transform duration-200 group-hover:translate-y-0.5",
|
|
283
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
284
|
+
"path",
|
|
285
|
+
{
|
|
286
|
+
d: "M8 3L8 13M8 13L12 9M8 13L4 9",
|
|
287
|
+
stroke: "currentColor",
|
|
288
|
+
strokeWidth: "2",
|
|
289
|
+
strokeLinecap: "round",
|
|
290
|
+
strokeLinejoin: "round"
|
|
291
|
+
}
|
|
292
|
+
)
|
|
293
|
+
}
|
|
294
|
+
)
|
|
295
|
+
]
|
|
296
|
+
}
|
|
297
|
+
) })
|
|
298
|
+
] });
|
|
299
|
+
};
|
|
300
|
+
UpcomingEvents.displayName = "UpcomingEvents";
|
|
301
|
+
var defaultBannerData = {
|
|
302
|
+
title: "See it. Touch it. Make it Locally.",
|
|
303
|
+
subTitle: "Visit your local studio right around the corner.",
|
|
304
|
+
backgroundImage: "https://cdn.shopify.com/s/files/1/0569/5147/2268/files/Component_3_1.png?v=1765274638",
|
|
305
|
+
backgroundImageMobile: "https://cdn.shopify.com/s/files/1/0569/5147/2268/files/Component_3_1.png?v=1765274638"
|
|
306
|
+
};
|
|
307
|
+
var Banner = ({
|
|
308
|
+
data = defaultBannerData,
|
|
309
|
+
className,
|
|
310
|
+
style,
|
|
311
|
+
...props
|
|
312
|
+
}) => {
|
|
313
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
314
|
+
"div",
|
|
315
|
+
{
|
|
316
|
+
className: cn("relative"),
|
|
317
|
+
style: { aspectRatio: "1920/480", ...style },
|
|
318
|
+
...props,
|
|
319
|
+
children: [
|
|
320
|
+
data?.backgroundImage && /* @__PURE__ */ jsxRuntime.jsx(
|
|
321
|
+
"img",
|
|
322
|
+
{
|
|
323
|
+
src: data.backgroundImage,
|
|
324
|
+
alt: "",
|
|
325
|
+
className: "inset-0 h-full w-full object-cover"
|
|
326
|
+
}
|
|
327
|
+
),
|
|
328
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
329
|
+
"div",
|
|
330
|
+
{
|
|
331
|
+
className: cn(
|
|
332
|
+
"absolute flex flex-col gap-4 justify-center m-auto top-0 bottom-0 left-0 right-0 z-10",
|
|
333
|
+
className
|
|
334
|
+
),
|
|
335
|
+
children: [
|
|
336
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
337
|
+
headlessUi.Text,
|
|
338
|
+
{
|
|
339
|
+
className: "text-[48px] font-bold text-white leading-[1]",
|
|
340
|
+
html: data?.title
|
|
341
|
+
}
|
|
342
|
+
),
|
|
343
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
344
|
+
headlessUi.Text,
|
|
345
|
+
{
|
|
346
|
+
className: "text-[18px] font-bold text-white leading-[1.4]",
|
|
347
|
+
html: data?.subTitle
|
|
348
|
+
}
|
|
349
|
+
)
|
|
350
|
+
]
|
|
351
|
+
}
|
|
352
|
+
)
|
|
353
|
+
]
|
|
354
|
+
}
|
|
355
|
+
);
|
|
356
|
+
};
|
|
357
|
+
Banner.displayName = "Banner";
|
|
358
|
+
var BreadCrumbs = ({
|
|
359
|
+
items,
|
|
360
|
+
className,
|
|
361
|
+
...props
|
|
362
|
+
}) => {
|
|
363
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex items-center py-6 gap-1 text-[18px]", className), ...props, children: items?.map((item, i) => {
|
|
364
|
+
const isLast = i === items?.length - 1;
|
|
365
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
366
|
+
headlessUi.Link,
|
|
367
|
+
{
|
|
368
|
+
className: cn(
|
|
369
|
+
"flex items-center gap-1 text-[#6D6D6F] no-underline",
|
|
370
|
+
isLast && "text-[#080A0F]",
|
|
371
|
+
item?.link ? "cursor-pointer" : "cursor-default hover:text-[#080A0F]"
|
|
372
|
+
),
|
|
373
|
+
href: item?.link,
|
|
374
|
+
children: [
|
|
375
|
+
item?.label,
|
|
376
|
+
!isLast && /* @__PURE__ */ jsxRuntime.jsx("span", { children: "/" })
|
|
377
|
+
]
|
|
378
|
+
},
|
|
379
|
+
i
|
|
380
|
+
);
|
|
381
|
+
}) });
|
|
382
|
+
};
|
|
383
|
+
BreadCrumbs.displayName = "BreadCrumbs";
|
|
384
|
+
var defaultSteps = [
|
|
385
|
+
{
|
|
386
|
+
stepNumber: 1,
|
|
387
|
+
title: 'Find a demo room you would like to visit, and click "Schedule Now"',
|
|
388
|
+
description: 'Find a demo room you would like to visit, and click "Schedule Now"',
|
|
389
|
+
mapImage: "https://cdn.shopify.com/s/files/1/0569/5147/2268/files/Component_3_1.png?v=1765274638"
|
|
390
|
+
},
|
|
391
|
+
{
|
|
392
|
+
stepNumber: 2,
|
|
393
|
+
title: "Fill out the form and confirm your time of visit",
|
|
394
|
+
description: "Fill out the form and confirm your time of visit",
|
|
395
|
+
mapImage: "https://cdn.shopify.com/s/files/1/0569/5147/2268/files/Component_3_1.png?v=1765274638"
|
|
396
|
+
},
|
|
397
|
+
{
|
|
398
|
+
stepNumber: 3,
|
|
399
|
+
title: "Once you arrive at the demo room, scan the QR code to check in",
|
|
400
|
+
description: "Once you arrive at the demo room, scan the QR code to check in",
|
|
401
|
+
mapImage: "https://cdn.shopify.com/s/files/1/0569/5147/2268/files/Component_3_1.png?v=1765274638"
|
|
402
|
+
},
|
|
403
|
+
{
|
|
404
|
+
stepNumber: 4,
|
|
405
|
+
title: "Have fun!",
|
|
406
|
+
description: "Have fun!",
|
|
407
|
+
mapImage: "https://cdn.shopify.com/s/files/1/0569/5147/2268/files/Component_3_1.png?v=1765274638"
|
|
408
|
+
}
|
|
409
|
+
];
|
|
410
|
+
var EasySteps = ({
|
|
411
|
+
title = "Schedule in 4 Easy Steps",
|
|
412
|
+
steps = defaultSteps,
|
|
413
|
+
className,
|
|
414
|
+
...props
|
|
415
|
+
}) => {
|
|
416
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("w-full", className), ...props, children: [
|
|
417
|
+
/* @__PURE__ */ jsxRuntime.jsx(Title, { title }),
|
|
418
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-2 md:grid-cols-2 gap-6", children: steps.map((step) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
419
|
+
"div",
|
|
420
|
+
{
|
|
421
|
+
className: cn(
|
|
422
|
+
"bg-white rounded-2xl overflow-hidden",
|
|
423
|
+
"border border-gray-200",
|
|
424
|
+
"hover:shadow-lg transition-shadow duration-200"
|
|
425
|
+
),
|
|
426
|
+
children: [
|
|
427
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "p-6 pb-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-3 mb-3", children: [
|
|
428
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-sm font-semibold text-gray-900", children: [
|
|
429
|
+
"Step ",
|
|
430
|
+
step.stepNumber,
|
|
431
|
+
":"
|
|
432
|
+
] }),
|
|
433
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-900 font-medium flex-1", children: step.title })
|
|
434
|
+
] }) }),
|
|
435
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative w-full aspect-[356/220] bg-gray-100", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
436
|
+
"img",
|
|
437
|
+
{
|
|
438
|
+
src: step.mapImage,
|
|
439
|
+
alt: `Step ${step.stepNumber} - ${step.title}`,
|
|
440
|
+
className: "w-full h-full object-cover"
|
|
441
|
+
}
|
|
442
|
+
) })
|
|
443
|
+
]
|
|
444
|
+
},
|
|
445
|
+
step.stepNumber
|
|
446
|
+
)) })
|
|
447
|
+
] });
|
|
448
|
+
};
|
|
449
|
+
EasySteps.displayName = "EasySteps";
|
|
450
|
+
var StudioCard = ({
|
|
451
|
+
code,
|
|
452
|
+
name,
|
|
453
|
+
availableTime,
|
|
454
|
+
address,
|
|
455
|
+
city,
|
|
456
|
+
state,
|
|
457
|
+
zipCode,
|
|
458
|
+
country = "United States",
|
|
459
|
+
euifyMakeModel,
|
|
460
|
+
onSchedule,
|
|
461
|
+
className,
|
|
462
|
+
...props
|
|
463
|
+
}) => {
|
|
464
|
+
const fullAddress = `${address}, ${city}, ${state} ${country} ${zipCode}`;
|
|
465
|
+
const handleScheduleClick = () => {
|
|
466
|
+
onSchedule?.(code);
|
|
467
|
+
};
|
|
468
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
469
|
+
"div",
|
|
470
|
+
{
|
|
471
|
+
className: cn(
|
|
472
|
+
"p-6",
|
|
473
|
+
"hover:shadow-lg transition-shadow duration-200",
|
|
474
|
+
className
|
|
475
|
+
),
|
|
476
|
+
...props,
|
|
477
|
+
children: [
|
|
478
|
+
/* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-xl font-semibold text-gray-900 mb-4", children: name }),
|
|
479
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-3 mb-3", children: [
|
|
480
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
481
|
+
"svg",
|
|
482
|
+
{
|
|
483
|
+
width: "20",
|
|
484
|
+
height: "20",
|
|
485
|
+
viewBox: "0 0 20 20",
|
|
486
|
+
fill: "none",
|
|
487
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
488
|
+
className: "flex-shrink-0 mt-0.5",
|
|
489
|
+
children: [
|
|
490
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
491
|
+
"rect",
|
|
492
|
+
{
|
|
493
|
+
x: "3",
|
|
494
|
+
y: "4",
|
|
495
|
+
width: "14",
|
|
496
|
+
height: "13",
|
|
497
|
+
rx: "2",
|
|
498
|
+
stroke: "currentColor",
|
|
499
|
+
strokeWidth: "1.5"
|
|
500
|
+
}
|
|
501
|
+
),
|
|
502
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
503
|
+
"path",
|
|
504
|
+
{
|
|
505
|
+
d: "M3 8H17",
|
|
506
|
+
stroke: "currentColor",
|
|
507
|
+
strokeWidth: "1.5",
|
|
508
|
+
strokeLinecap: "round"
|
|
509
|
+
}
|
|
510
|
+
),
|
|
511
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
512
|
+
"path",
|
|
513
|
+
{
|
|
514
|
+
d: "M6 2V4",
|
|
515
|
+
stroke: "currentColor",
|
|
516
|
+
strokeWidth: "1.5",
|
|
517
|
+
strokeLinecap: "round"
|
|
518
|
+
}
|
|
519
|
+
),
|
|
520
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
521
|
+
"path",
|
|
522
|
+
{
|
|
523
|
+
d: "M14 2V4",
|
|
524
|
+
stroke: "currentColor",
|
|
525
|
+
strokeWidth: "1.5",
|
|
526
|
+
strokeLinecap: "round"
|
|
527
|
+
}
|
|
528
|
+
)
|
|
529
|
+
]
|
|
530
|
+
}
|
|
531
|
+
),
|
|
532
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-sm text-gray-600", children: [
|
|
533
|
+
"Available ",
|
|
534
|
+
availableTime
|
|
535
|
+
] }) })
|
|
536
|
+
] }),
|
|
537
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-3 mb-3", children: [
|
|
538
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
539
|
+
"svg",
|
|
540
|
+
{
|
|
541
|
+
width: "20",
|
|
542
|
+
height: "20",
|
|
543
|
+
viewBox: "0 0 20 20",
|
|
544
|
+
fill: "none",
|
|
545
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
546
|
+
className: "flex-shrink-0 mt-0.5",
|
|
547
|
+
children: [
|
|
548
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
549
|
+
"path",
|
|
550
|
+
{
|
|
551
|
+
d: "M10 10C11.1046 10 12 9.10457 12 8C12 6.89543 11.1046 6 10 6C8.89543 6 8 6.89543 8 8C8 9.10457 8.89543 10 10 10Z",
|
|
552
|
+
stroke: "currentColor",
|
|
553
|
+
strokeWidth: "1.5"
|
|
554
|
+
}
|
|
555
|
+
),
|
|
556
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
557
|
+
"path",
|
|
558
|
+
{
|
|
559
|
+
d: "M10 18C10 18 16 13 16 8C16 4.68629 13.3137 2 10 2C6.68629 2 4 4.68629 4 8C4 13 10 18 10 18Z",
|
|
560
|
+
stroke: "currentColor",
|
|
561
|
+
strokeWidth: "1.5"
|
|
562
|
+
}
|
|
563
|
+
)
|
|
564
|
+
]
|
|
565
|
+
}
|
|
566
|
+
),
|
|
567
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-600", children: fullAddress }) })
|
|
568
|
+
] }),
|
|
569
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-3 mb-6", children: [
|
|
570
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
571
|
+
"svg",
|
|
572
|
+
{
|
|
573
|
+
width: "20",
|
|
574
|
+
height: "20",
|
|
575
|
+
viewBox: "0 0 20 20",
|
|
576
|
+
fill: "none",
|
|
577
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
578
|
+
className: "flex-shrink-0 mt-0.5",
|
|
579
|
+
children: [
|
|
580
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
581
|
+
"rect",
|
|
582
|
+
{
|
|
583
|
+
x: "3",
|
|
584
|
+
y: "5",
|
|
585
|
+
width: "14",
|
|
586
|
+
height: "10",
|
|
587
|
+
rx: "1.5",
|
|
588
|
+
stroke: "currentColor",
|
|
589
|
+
strokeWidth: "1.5"
|
|
590
|
+
}
|
|
591
|
+
),
|
|
592
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
593
|
+
"path",
|
|
594
|
+
{
|
|
595
|
+
d: "M7 15V17",
|
|
596
|
+
stroke: "currentColor",
|
|
597
|
+
strokeWidth: "1.5",
|
|
598
|
+
strokeLinecap: "round"
|
|
599
|
+
}
|
|
600
|
+
),
|
|
601
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
602
|
+
"path",
|
|
603
|
+
{
|
|
604
|
+
d: "M13 15V17",
|
|
605
|
+
stroke: "currentColor",
|
|
606
|
+
strokeWidth: "1.5",
|
|
607
|
+
strokeLinecap: "round"
|
|
608
|
+
}
|
|
609
|
+
),
|
|
610
|
+
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "10", cy: "10", r: "1.5", fill: "currentColor" })
|
|
611
|
+
]
|
|
612
|
+
}
|
|
613
|
+
),
|
|
614
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-600", children: euifyMakeModel }) })
|
|
615
|
+
] }),
|
|
616
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
617
|
+
"button",
|
|
618
|
+
{
|
|
619
|
+
onClick: handleScheduleClick,
|
|
620
|
+
className: cn(
|
|
621
|
+
"w-full px-6 py-3 rounded-full",
|
|
622
|
+
"bg-white text-gray-900 border border-gray-900",
|
|
623
|
+
"font-medium text-sm",
|
|
624
|
+
"hover:bg-gray-900 hover:text-white",
|
|
625
|
+
"transition-all duration-200"
|
|
626
|
+
),
|
|
627
|
+
children: "Schedule Now"
|
|
628
|
+
}
|
|
629
|
+
)
|
|
630
|
+
]
|
|
631
|
+
}
|
|
632
|
+
);
|
|
633
|
+
};
|
|
634
|
+
StudioCard.displayName = "StudioCard";
|
|
635
|
+
var defaultLocations = [
|
|
636
|
+
{
|
|
637
|
+
id: "1",
|
|
638
|
+
name: "Design District Demo Room",
|
|
639
|
+
address: "111 8th St",
|
|
640
|
+
city: "San Francisco",
|
|
641
|
+
state: "CA",
|
|
642
|
+
zipCode: "94108",
|
|
643
|
+
country: "United States",
|
|
644
|
+
lat: 37.7749,
|
|
645
|
+
lng: -122.4194,
|
|
646
|
+
availableTime: "Oct 28, 2:00 PM",
|
|
647
|
+
euifyMakeModel: "euifyMake E1, euifyMake M5"
|
|
648
|
+
}
|
|
649
|
+
];
|
|
650
|
+
var StudioMap = ({
|
|
651
|
+
googleMapsApiKey,
|
|
652
|
+
locations = defaultLocations,
|
|
653
|
+
defaultCenter = { lat: 39.8283, lng: -98.5795 },
|
|
654
|
+
// US center
|
|
655
|
+
defaultZoom = 4,
|
|
656
|
+
mapHeight = "600px",
|
|
657
|
+
onSchedule,
|
|
658
|
+
className,
|
|
659
|
+
...props
|
|
660
|
+
}) => {
|
|
661
|
+
const [_selectedLocation, setSelectedLocation] = React2.useState(null);
|
|
662
|
+
const [isLoaded, setIsLoaded] = React2.useState(false);
|
|
663
|
+
const mapRef = React2__default.default.useRef(null);
|
|
664
|
+
const googleMapRef = React2__default.default.useRef(null);
|
|
665
|
+
const markersRef = React2__default.default.useRef([]);
|
|
666
|
+
const infoWindowRef = React2__default.default.useRef(null);
|
|
667
|
+
React2__default.default.useEffect(() => {
|
|
668
|
+
if (!googleMapsApiKey) {
|
|
669
|
+
console.error("Google Maps API Key is required");
|
|
670
|
+
return;
|
|
671
|
+
}
|
|
672
|
+
if (window.google && window.google.maps) {
|
|
673
|
+
setIsLoaded(true);
|
|
674
|
+
return;
|
|
675
|
+
}
|
|
676
|
+
const script = document.createElement("script");
|
|
677
|
+
script.src = `https://maps.googleapis.com/maps/api/js?key=${googleMapsApiKey}&libraries=places`;
|
|
678
|
+
script.async = true;
|
|
679
|
+
script.defer = true;
|
|
680
|
+
script.onload = () => setIsLoaded(true);
|
|
681
|
+
script.onerror = () => console.error("Failed to load Google Maps script");
|
|
682
|
+
document.head.appendChild(script);
|
|
683
|
+
return () => {
|
|
684
|
+
if (script.parentNode) {
|
|
685
|
+
script.parentNode.removeChild(script);
|
|
686
|
+
}
|
|
687
|
+
};
|
|
688
|
+
}, [googleMapsApiKey]);
|
|
689
|
+
React2__default.default.useEffect(() => {
|
|
690
|
+
if (!isLoaded || !mapRef.current || googleMapRef.current) return;
|
|
691
|
+
const map = new google.maps.Map(mapRef.current, {
|
|
692
|
+
center: defaultCenter,
|
|
693
|
+
zoom: defaultZoom,
|
|
694
|
+
styles: [
|
|
695
|
+
{
|
|
696
|
+
featureType: "all",
|
|
697
|
+
elementType: "geometry",
|
|
698
|
+
stylers: [{ color: "#E0F2F1" }]
|
|
699
|
+
},
|
|
700
|
+
{
|
|
701
|
+
featureType: "water",
|
|
702
|
+
elementType: "geometry",
|
|
703
|
+
stylers: [{ color: "#B2EBF2" }]
|
|
704
|
+
},
|
|
705
|
+
{
|
|
706
|
+
featureType: "road",
|
|
707
|
+
elementType: "geometry",
|
|
708
|
+
stylers: [{ color: "#ffffff" }]
|
|
709
|
+
}
|
|
710
|
+
],
|
|
711
|
+
mapTypeControl: false,
|
|
712
|
+
streetViewControl: false,
|
|
713
|
+
fullscreenControl: true
|
|
714
|
+
});
|
|
715
|
+
googleMapRef.current = map;
|
|
716
|
+
infoWindowRef.current = new google.maps.InfoWindow();
|
|
717
|
+
}, [isLoaded, defaultCenter, defaultZoom]);
|
|
718
|
+
React2__default.default.useEffect(() => {
|
|
719
|
+
if (!googleMapRef.current || !isLoaded) return;
|
|
720
|
+
markersRef.current.forEach((marker) => marker.setMap(null));
|
|
721
|
+
markersRef.current = [];
|
|
722
|
+
const validLocations = locations.filter((location) => {
|
|
723
|
+
const lat = Number(location.lat);
|
|
724
|
+
const lng = Number(location.lng);
|
|
725
|
+
const isValid = !isNaN(lat) && !isNaN(lng) && isFinite(lat) && isFinite(lng) && lat >= -90 && lat <= 90 && lng >= -180 && lng <= 180;
|
|
726
|
+
if (!isValid) {
|
|
727
|
+
console.warn("Invalid location coordinates:", location);
|
|
728
|
+
}
|
|
729
|
+
return isValid;
|
|
730
|
+
});
|
|
731
|
+
validLocations.forEach((location) => {
|
|
732
|
+
const lat = Number(location.lat);
|
|
733
|
+
const lng = Number(location.lng);
|
|
734
|
+
const marker = new google.maps.Marker({
|
|
735
|
+
position: { lat, lng },
|
|
736
|
+
map: googleMapRef.current,
|
|
737
|
+
title: location.name,
|
|
738
|
+
icon: {
|
|
739
|
+
path: google.maps.SymbolPath.CIRCLE,
|
|
740
|
+
scale: 10,
|
|
741
|
+
fillColor: "#000000",
|
|
742
|
+
fillOpacity: 1,
|
|
743
|
+
strokeColor: "#ffffff",
|
|
744
|
+
strokeWeight: 2
|
|
745
|
+
}
|
|
746
|
+
});
|
|
747
|
+
marker.addListener("click", () => {
|
|
748
|
+
setSelectedLocation(location);
|
|
749
|
+
const content = `
|
|
750
|
+
<div style="padding: 16px; max-width: 300px; font-family: system-ui, sans-serif;">
|
|
751
|
+
<h3 style="margin: 0 0 12px 0; font-size: 18px; font-weight: 600;">${location.name}</h3>
|
|
752
|
+
${location.availableTime ? `<div style="margin-bottom: 8px; color: #666;">
|
|
753
|
+
<svg style="display: inline-block; width: 16px; height: 16px; margin-right: 4px; vertical-align: middle;" fill="currentColor" viewBox="0 0 20 20">
|
|
754
|
+
<path d="M6 2a1 1 0 00-1 1v1H4a2 2 0 00-2 2v10a2 2 0 002 2h12a2 2 0 002-2V6a2 2 0 00-2-2h-1V3a1 1 0 10-2 0v1H7V3a1 1 0 00-1-1zm0 5a1 1 0 000 2h8a1 1 0 100-2H6z"/>
|
|
755
|
+
</svg>
|
|
756
|
+
<span style="vertical-align: middle;">Available ${location.availableTime}</span>
|
|
757
|
+
</div>` : ""}
|
|
758
|
+
<div style="margin-bottom: 8px; color: #666;">
|
|
759
|
+
<svg style="display: inline-block; width: 16px; height: 16px; margin-right: 4px; vertical-align: middle;" fill="currentColor" viewBox="0 0 20 20">
|
|
760
|
+
<path fill-rule="evenodd" d="M5.05 4.05a7 7 0 119.9 9.9L10 18.9l-4.95-4.95a7 7 0 010-9.9zM10 11a2 2 0 100-4 2 2 0 000 4z" clip-rule="evenodd"/>
|
|
761
|
+
</svg>
|
|
762
|
+
<span style="vertical-align: middle;">${location.address}, ${location.city}, ${location.state} ${location.country} ${location.zipCode}</span>
|
|
763
|
+
</div>
|
|
764
|
+
${location.euifyMakeModel ? `<div style="margin-bottom: 12px; color: #666;">
|
|
765
|
+
<svg style="display: inline-block; width: 16px; height: 16px; margin-right: 4px; vertical-align: middle;" fill="currentColor" viewBox="0 0 20 20">
|
|
766
|
+
<path d="M3 4a1 1 0 011-1h12a1 1 0 011 1v2a1 1 0 01-1 1H4a1 1 0 01-1-1V4zM3 10a1 1 0 011-1h6a1 1 0 011 1v6a1 1 0 01-1 1H4a1 1 0 01-1-1v-6zM14 9a1 1 0 00-1 1v6a1 1 0 001 1h2a1 1 0 001-1v-6a1 1 0 00-1-1h-2z"/>
|
|
767
|
+
</svg>
|
|
768
|
+
<span style="vertical-align: middle;">${location.euifyMakeModel}</span>
|
|
769
|
+
</div>` : ""}
|
|
770
|
+
<button
|
|
771
|
+
id="schedule-btn-${location.id}"
|
|
772
|
+
style="
|
|
773
|
+
width: 100%;
|
|
774
|
+
padding: 10px 16px;
|
|
775
|
+
background: #000;
|
|
776
|
+
color: #fff;
|
|
777
|
+
border: none;
|
|
778
|
+
border-radius: 6px;
|
|
779
|
+
font-weight: 500;
|
|
780
|
+
cursor: pointer;
|
|
781
|
+
font-size: 14px;
|
|
782
|
+
"
|
|
783
|
+
onmouseover="this.style.background='#333'"
|
|
784
|
+
onmouseout="this.style.background='#000'"
|
|
785
|
+
>
|
|
786
|
+
Schedule Now
|
|
787
|
+
</button>
|
|
788
|
+
</div>
|
|
789
|
+
`;
|
|
790
|
+
if (infoWindowRef.current) {
|
|
791
|
+
infoWindowRef.current.setContent(content);
|
|
792
|
+
infoWindowRef.current.open(googleMapRef.current, marker);
|
|
793
|
+
google.maps.event.addListenerOnce(
|
|
794
|
+
infoWindowRef.current,
|
|
795
|
+
"domready",
|
|
796
|
+
() => {
|
|
797
|
+
const btn = document.getElementById(`schedule-btn-${location.id}`);
|
|
798
|
+
if (btn) {
|
|
799
|
+
btn.addEventListener("click", () => {
|
|
800
|
+
if (onSchedule) {
|
|
801
|
+
onSchedule(location);
|
|
802
|
+
}
|
|
803
|
+
});
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
);
|
|
807
|
+
}
|
|
808
|
+
googleMapRef.current?.panTo({ lat: location.lat, lng: location.lng });
|
|
809
|
+
});
|
|
810
|
+
markersRef.current.push(marker);
|
|
811
|
+
});
|
|
812
|
+
if (validLocations.length > 0 && googleMapRef.current) {
|
|
813
|
+
const bounds = new google.maps.LatLngBounds();
|
|
814
|
+
validLocations.forEach((location) => {
|
|
815
|
+
const lat = Number(location.lat);
|
|
816
|
+
const lng = Number(location.lng);
|
|
817
|
+
bounds.extend({ lat, lng });
|
|
818
|
+
});
|
|
819
|
+
googleMapRef.current.fitBounds(bounds);
|
|
820
|
+
}
|
|
821
|
+
}, [isLoaded, locations, onSchedule]);
|
|
822
|
+
if (!googleMapsApiKey) {
|
|
823
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
824
|
+
"div",
|
|
825
|
+
{
|
|
826
|
+
className: cn(
|
|
827
|
+
"flex items-center justify-center bg-gray-100 rounded-lg",
|
|
828
|
+
className
|
|
829
|
+
),
|
|
830
|
+
style: { height: mapHeight },
|
|
831
|
+
...props,
|
|
832
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-gray-600", children: "Google Maps API Key is required" })
|
|
833
|
+
}
|
|
834
|
+
);
|
|
835
|
+
}
|
|
836
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
837
|
+
"div",
|
|
838
|
+
{
|
|
839
|
+
className: cn("relative w-full rounded-lg overflow-hidden", className),
|
|
840
|
+
...props,
|
|
841
|
+
children: [
|
|
842
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { ref: mapRef, style: { height: mapHeight } }),
|
|
843
|
+
!isLoaded && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute inset-0 flex items-center justify-center bg-gray-100", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center", children: [
|
|
844
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "inline-block animate-spin rounded-full h-8 w-8 border-4 border-gray-300 border-t-gray-900 mb-2" }),
|
|
845
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-gray-600", children: "Loading map..." })
|
|
846
|
+
] }) })
|
|
847
|
+
]
|
|
848
|
+
}
|
|
849
|
+
);
|
|
850
|
+
};
|
|
851
|
+
StudioMap.displayName = "StudioMap";
|
|
852
|
+
|
|
853
|
+
// src/api/types.ts
|
|
854
|
+
var ApiError = class extends Error {
|
|
855
|
+
constructor(code, message, request_id) {
|
|
856
|
+
super(message);
|
|
857
|
+
this.code = code;
|
|
858
|
+
this.request_id = request_id;
|
|
859
|
+
this.name = "ApiError";
|
|
860
|
+
}
|
|
861
|
+
};
|
|
862
|
+
|
|
863
|
+
// src/api/hooks.ts
|
|
864
|
+
function useDemoRooms(client, params, options) {
|
|
865
|
+
const [state, setState] = React2.useState({
|
|
866
|
+
data: null,
|
|
867
|
+
loading: true,
|
|
868
|
+
error: null
|
|
869
|
+
});
|
|
870
|
+
const enabled = options?.enabled !== false;
|
|
871
|
+
React2.useEffect(() => {
|
|
872
|
+
let cancelled = false;
|
|
873
|
+
const fetchData = async () => {
|
|
874
|
+
setState((prev) => ({ ...prev, loading: true, error: null }));
|
|
875
|
+
try {
|
|
876
|
+
const data = await client.getDemoRooms(params);
|
|
877
|
+
if (!cancelled) {
|
|
878
|
+
setState({ data, loading: false, error: null });
|
|
879
|
+
}
|
|
880
|
+
} catch (error) {
|
|
881
|
+
if (!cancelled) {
|
|
882
|
+
setState({
|
|
883
|
+
data: null,
|
|
884
|
+
loading: false,
|
|
885
|
+
error: error instanceof ApiError ? error : new ApiError(1006, "Unknown error")
|
|
886
|
+
});
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
};
|
|
890
|
+
fetchData();
|
|
891
|
+
return () => {
|
|
892
|
+
cancelled = true;
|
|
893
|
+
};
|
|
894
|
+
}, [client, params.team_code, params.brand_website, params.locale, enabled]);
|
|
895
|
+
return state;
|
|
896
|
+
}
|
|
897
|
+
var AntdMobileIsolated = ({
|
|
898
|
+
children,
|
|
899
|
+
className,
|
|
900
|
+
style
|
|
901
|
+
}) => {
|
|
902
|
+
const containerRef = React2.useRef(null);
|
|
903
|
+
React2.useEffect(() => {
|
|
904
|
+
if (!containerRef.current) return;
|
|
905
|
+
const container = containerRef.current;
|
|
906
|
+
const originalStyles = {
|
|
907
|
+
fontSize: container.style.fontSize,
|
|
908
|
+
fontFamily: container.style.fontFamily,
|
|
909
|
+
lineHeight: container.style.lineHeight,
|
|
910
|
+
color: container.style.color
|
|
911
|
+
};
|
|
912
|
+
container.style.fontSize = "14px";
|
|
913
|
+
container.style.fontFamily = '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif';
|
|
914
|
+
container.style.lineHeight = "1.5";
|
|
915
|
+
container.style.color = "#333";
|
|
916
|
+
return () => {
|
|
917
|
+
container.style.fontSize = originalStyles.fontSize;
|
|
918
|
+
container.style.fontFamily = originalStyles.fontFamily;
|
|
919
|
+
container.style.lineHeight = originalStyles.lineHeight;
|
|
920
|
+
container.style.color = originalStyles.color;
|
|
921
|
+
};
|
|
922
|
+
}, []);
|
|
923
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
924
|
+
"div",
|
|
925
|
+
{
|
|
926
|
+
ref: containerRef,
|
|
927
|
+
className: cn("antd-mobile-isolated", className),
|
|
928
|
+
style: {
|
|
929
|
+
// 使用 all: revert-layer 来隔离样式
|
|
930
|
+
isolation: "isolate",
|
|
931
|
+
contain: "layout style",
|
|
932
|
+
...style
|
|
933
|
+
},
|
|
934
|
+
children
|
|
935
|
+
}
|
|
936
|
+
);
|
|
937
|
+
};
|
|
938
|
+
AntdMobileIsolated.displayName = "AntdMobileIsolated";
|
|
939
|
+
|
|
940
|
+
// src/components/DemoRoom/utils/addressParser.ts
|
|
941
|
+
function parseAddress(address) {
|
|
942
|
+
const parts = address.split(",").map((part) => part.trim());
|
|
943
|
+
let country = "United States";
|
|
944
|
+
let state = "";
|
|
945
|
+
let city = "";
|
|
946
|
+
if (parts.length >= 3) {
|
|
947
|
+
city = parts[1] || "";
|
|
948
|
+
state = parts[2]?.split(" ")[0] || "";
|
|
949
|
+
country = parts[3] || country;
|
|
950
|
+
} else if (parts.length === 2) {
|
|
951
|
+
city = parts[0] || "";
|
|
952
|
+
state = parts[1]?.split(" ")[0] || "";
|
|
953
|
+
} else if (parts.length === 1) {
|
|
954
|
+
city = parts[0] || "";
|
|
955
|
+
}
|
|
956
|
+
return {
|
|
957
|
+
country: country.trim(),
|
|
958
|
+
state: state.trim(),
|
|
959
|
+
city: city.trim()
|
|
960
|
+
};
|
|
961
|
+
}
|
|
962
|
+
function groupByAlphabet(items) {
|
|
963
|
+
const groups = /* @__PURE__ */ new Map();
|
|
964
|
+
items.forEach((item) => {
|
|
965
|
+
const firstChar = item.name.charAt(0).toUpperCase();
|
|
966
|
+
const key = /[A-Z]/.test(firstChar) ? firstChar : "#";
|
|
967
|
+
if (!groups.has(key)) {
|
|
968
|
+
groups.set(key, []);
|
|
969
|
+
}
|
|
970
|
+
groups.get(key).push(item);
|
|
971
|
+
});
|
|
972
|
+
return Array.from(groups.entries()).sort(([a], [b]) => {
|
|
973
|
+
if (a === "#") return 1;
|
|
974
|
+
if (b === "#") return -1;
|
|
975
|
+
return a.localeCompare(b);
|
|
976
|
+
}).map(([title, items2]) => ({
|
|
977
|
+
title,
|
|
978
|
+
items: items2.sort((a, b) => a.name.localeCompare(b.name))
|
|
979
|
+
}));
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
// src/components/DemoRoom/components/RoomsList.module.css
|
|
983
|
+
var RoomsList_default = {};
|
|
984
|
+
var LocationFilter = ({
|
|
985
|
+
locations,
|
|
986
|
+
onSelect,
|
|
987
|
+
visible = false,
|
|
988
|
+
onClose
|
|
989
|
+
}) => {
|
|
990
|
+
const [currentLevel, setCurrentLevel] = React2.useState("country");
|
|
991
|
+
const [selectedCountry, setSelectedCountry] = React2.useState();
|
|
992
|
+
const [selectedState, setSelectedState] = React2.useState();
|
|
993
|
+
const [searchQuery, setSearchQuery] = React2.useState("");
|
|
994
|
+
const locationData = React2.useMemo(() => {
|
|
995
|
+
const countries = /* @__PURE__ */ new Map();
|
|
996
|
+
const states = /* @__PURE__ */ new Map();
|
|
997
|
+
const cities = /* @__PURE__ */ new Map();
|
|
998
|
+
locations.forEach((location) => {
|
|
999
|
+
const { country, state, city } = parseAddress(location.address);
|
|
1000
|
+
if (country) {
|
|
1001
|
+
const existing = countries.get(country);
|
|
1002
|
+
countries.set(country, {
|
|
1003
|
+
name: country,
|
|
1004
|
+
code: country,
|
|
1005
|
+
count: (existing?.count || 0) + 1
|
|
1006
|
+
});
|
|
1007
|
+
}
|
|
1008
|
+
if (state) {
|
|
1009
|
+
const stateKey = `${country}/${state}`;
|
|
1010
|
+
const existing = states.get(stateKey);
|
|
1011
|
+
states.set(stateKey, {
|
|
1012
|
+
name: state,
|
|
1013
|
+
code: stateKey,
|
|
1014
|
+
count: (existing?.count || 0) + 1,
|
|
1015
|
+
parentCode: country
|
|
1016
|
+
});
|
|
1017
|
+
}
|
|
1018
|
+
if (city) {
|
|
1019
|
+
const cityKey = `${country}/${state}/${city}`;
|
|
1020
|
+
const existing = cities.get(cityKey);
|
|
1021
|
+
cities.set(cityKey, {
|
|
1022
|
+
name: city,
|
|
1023
|
+
code: cityKey,
|
|
1024
|
+
count: (existing?.count || 0) + 1,
|
|
1025
|
+
parentCode: `${country}/${state}`
|
|
1026
|
+
});
|
|
1027
|
+
}
|
|
1028
|
+
});
|
|
1029
|
+
return {
|
|
1030
|
+
countries: Array.from(countries.values()),
|
|
1031
|
+
states: Array.from(states.values()),
|
|
1032
|
+
cities: Array.from(cities.values())
|
|
1033
|
+
};
|
|
1034
|
+
}, [locations]);
|
|
1035
|
+
const filteredItems = React2.useMemo(() => {
|
|
1036
|
+
let items = [];
|
|
1037
|
+
switch (currentLevel) {
|
|
1038
|
+
case "country":
|
|
1039
|
+
items = locationData.countries;
|
|
1040
|
+
break;
|
|
1041
|
+
case "state":
|
|
1042
|
+
items = selectedCountry ? locationData.states.filter(
|
|
1043
|
+
(s) => s.parentCode === selectedCountry
|
|
1044
|
+
) : [];
|
|
1045
|
+
break;
|
|
1046
|
+
case "city":
|
|
1047
|
+
items = selectedState ? locationData.cities.filter((c) => c.parentCode === selectedState) : [];
|
|
1048
|
+
break;
|
|
1049
|
+
}
|
|
1050
|
+
if (searchQuery) {
|
|
1051
|
+
items = items.filter(
|
|
1052
|
+
(item) => item.name.toLowerCase().includes(searchQuery.toLowerCase())
|
|
1053
|
+
);
|
|
1054
|
+
}
|
|
1055
|
+
return items;
|
|
1056
|
+
}, [currentLevel, selectedCountry, selectedState, locationData, searchQuery]);
|
|
1057
|
+
const groupedItems = React2.useMemo(
|
|
1058
|
+
() => groupByAlphabet(filteredItems),
|
|
1059
|
+
[filteredItems]
|
|
1060
|
+
);
|
|
1061
|
+
const handleItemClick = (item) => {
|
|
1062
|
+
if (currentLevel === "country") {
|
|
1063
|
+
setSelectedCountry(item.code);
|
|
1064
|
+
setCurrentLevel("state");
|
|
1065
|
+
} else if (currentLevel === "state") {
|
|
1066
|
+
setSelectedState(item.code);
|
|
1067
|
+
setCurrentLevel("city");
|
|
1068
|
+
} else if (currentLevel === "city") {
|
|
1069
|
+
const parts = item.code.split("/");
|
|
1070
|
+
onSelect?.({
|
|
1071
|
+
level: "city",
|
|
1072
|
+
country: parts[0],
|
|
1073
|
+
state: parts[1],
|
|
1074
|
+
city: parts[2]
|
|
1075
|
+
});
|
|
1076
|
+
onClose?.();
|
|
1077
|
+
}
|
|
1078
|
+
};
|
|
1079
|
+
const handleTabClick = (level) => {
|
|
1080
|
+
setCurrentLevel(level);
|
|
1081
|
+
if (level === "country") {
|
|
1082
|
+
setSelectedCountry(void 0);
|
|
1083
|
+
setSelectedState(void 0);
|
|
1084
|
+
} else if (level === "state") {
|
|
1085
|
+
setSelectedState(void 0);
|
|
1086
|
+
}
|
|
1087
|
+
};
|
|
1088
|
+
if (!visible) return null;
|
|
1089
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1090
|
+
"div",
|
|
1091
|
+
{
|
|
1092
|
+
style: { height: "794px" },
|
|
1093
|
+
className: cn(
|
|
1094
|
+
"w-full rounded-[12px] absolute z-10 top-0 left-0 bg-white border border-[#E4E5E6]",
|
|
1095
|
+
RoomsList_default.antdMobileScope
|
|
1096
|
+
),
|
|
1097
|
+
children: [
|
|
1098
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1099
|
+
"div",
|
|
1100
|
+
{
|
|
1101
|
+
style: { background: "#F8F8F8" },
|
|
1102
|
+
className: "rounded-[12px] rounded-b-none h-[72px] font-bold text-[14px] flex flex-col",
|
|
1103
|
+
children: [
|
|
1104
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between px-[20px] pt-[12px] pb-[8px]", children: [
|
|
1105
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1106
|
+
"input",
|
|
1107
|
+
{
|
|
1108
|
+
type: "text",
|
|
1109
|
+
placeholder: "Please enter the search city",
|
|
1110
|
+
value: searchQuery,
|
|
1111
|
+
onChange: (e) => setSearchQuery(e.target.value),
|
|
1112
|
+
className: "flex-1 h-[32px] px-[12px] rounded-[6px] border border-[#E4E5E6] text-[14px] outline-none focus:border-[#2E8B57]"
|
|
1113
|
+
}
|
|
1114
|
+
),
|
|
1115
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1116
|
+
"button",
|
|
1117
|
+
{
|
|
1118
|
+
onClick: onClose,
|
|
1119
|
+
className: "ml-[12px] w-[24px] h-[24px] flex items-center justify-center",
|
|
1120
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1121
|
+
"svg",
|
|
1122
|
+
{
|
|
1123
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1124
|
+
width: "24",
|
|
1125
|
+
height: "24",
|
|
1126
|
+
viewBox: "0 0 24 24",
|
|
1127
|
+
fill: "none",
|
|
1128
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1129
|
+
"path",
|
|
1130
|
+
{
|
|
1131
|
+
d: "M6.4 19L5 17.6L10.6 12L5 6.4L6.4 5L12 10.6L17.6 5L19 6.4L13.4 12L19 17.6L17.6 19L12 13.4L6.4 19Z",
|
|
1132
|
+
fill: "#1D1D1F"
|
|
1133
|
+
}
|
|
1134
|
+
)
|
|
1135
|
+
}
|
|
1136
|
+
)
|
|
1137
|
+
}
|
|
1138
|
+
)
|
|
1139
|
+
] }),
|
|
1140
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center px-[20px] gap-[16px] pb-[8px]", children: [
|
|
1141
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1142
|
+
"button",
|
|
1143
|
+
{
|
|
1144
|
+
onClick: () => handleTabClick("country"),
|
|
1145
|
+
className: cn(
|
|
1146
|
+
"pb-[4px] transition-colors",
|
|
1147
|
+
currentLevel === "country" ? "text-[#1D1D1F] border-b-2 border-[#2E8B57]" : "text-[#767880]"
|
|
1148
|
+
),
|
|
1149
|
+
children: "Country"
|
|
1150
|
+
}
|
|
1151
|
+
),
|
|
1152
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1153
|
+
"button",
|
|
1154
|
+
{
|
|
1155
|
+
onClick: () => handleTabClick("state"),
|
|
1156
|
+
disabled: !selectedCountry,
|
|
1157
|
+
className: cn(
|
|
1158
|
+
"pb-[4px] transition-colors",
|
|
1159
|
+
currentLevel === "state" ? "text-[#1D1D1F] border-b-2 border-[#2E8B57]" : "text-[#767880]",
|
|
1160
|
+
!selectedCountry && "opacity-50 cursor-not-allowed"
|
|
1161
|
+
),
|
|
1162
|
+
children: "State"
|
|
1163
|
+
}
|
|
1164
|
+
),
|
|
1165
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1166
|
+
"button",
|
|
1167
|
+
{
|
|
1168
|
+
onClick: () => handleTabClick("city"),
|
|
1169
|
+
disabled: !selectedState,
|
|
1170
|
+
className: cn(
|
|
1171
|
+
"pb-[4px] transition-colors",
|
|
1172
|
+
currentLevel === "city" ? "text-[#1D1D1F] border-b-2 border-[#2E8B57]" : "text-[#767880]",
|
|
1173
|
+
!selectedState && "opacity-50 cursor-not-allowed"
|
|
1174
|
+
),
|
|
1175
|
+
children: "City"
|
|
1176
|
+
}
|
|
1177
|
+
)
|
|
1178
|
+
] })
|
|
1179
|
+
]
|
|
1180
|
+
}
|
|
1181
|
+
),
|
|
1182
|
+
/* @__PURE__ */ jsxRuntime.jsx(AntdMobileIsolated, { style: { height: "calc(100% - 72px)" }, children: /* @__PURE__ */ jsxRuntime.jsx(IndexBar__default.default, { style: { height: "100%" }, children: groupedItems.map((group) => {
|
|
1183
|
+
const { title, items } = group;
|
|
1184
|
+
return /* @__PURE__ */ jsxRuntime.jsx(IndexBar__default.default.Panel, { index: title, title, children: /* @__PURE__ */ jsxRuntime.jsx(List__default.default, { children: items.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
1185
|
+
List__default.default.Item,
|
|
1186
|
+
{
|
|
1187
|
+
clickable: true,
|
|
1188
|
+
onClick: () => handleItemClick(item),
|
|
1189
|
+
extra: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-[8px]", children: [
|
|
1190
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[#767880] text-[14px]", children: item.count }),
|
|
1191
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1192
|
+
"svg",
|
|
1193
|
+
{
|
|
1194
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1195
|
+
width: "16",
|
|
1196
|
+
height: "16",
|
|
1197
|
+
viewBox: "0 0 16 16",
|
|
1198
|
+
fill: "none",
|
|
1199
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1200
|
+
"path",
|
|
1201
|
+
{
|
|
1202
|
+
d: "M6.4 12L5.6 11.2L9.06667 7.73333L5.6 4.26667L6.4 3.46667L10.6667 7.73333L6.4 12Z",
|
|
1203
|
+
fill: "#767880"
|
|
1204
|
+
}
|
|
1205
|
+
)
|
|
1206
|
+
}
|
|
1207
|
+
)
|
|
1208
|
+
] }),
|
|
1209
|
+
children: item.name
|
|
1210
|
+
},
|
|
1211
|
+
item.code
|
|
1212
|
+
)) }) }, title);
|
|
1213
|
+
}) }) })
|
|
1214
|
+
]
|
|
1215
|
+
}
|
|
1216
|
+
);
|
|
1217
|
+
};
|
|
1218
|
+
LocationFilter.displayName = "LocationFilter";
|
|
1219
|
+
var defaultStudioLocations = [
|
|
1220
|
+
{
|
|
1221
|
+
id: "1",
|
|
1222
|
+
name: "Design District Demo Room",
|
|
1223
|
+
address: "111 8th St",
|
|
1224
|
+
city: "San Francisco",
|
|
1225
|
+
state: "CA",
|
|
1226
|
+
zipCode: "94108",
|
|
1227
|
+
country: "United States",
|
|
1228
|
+
lat: 37.7749,
|
|
1229
|
+
lng: -122.4194,
|
|
1230
|
+
availableTime: "Oct 28, 2:00 PM",
|
|
1231
|
+
euifyMakeModel: "euifyMake E1, euifyMake M5"
|
|
1232
|
+
},
|
|
1233
|
+
{
|
|
1234
|
+
id: "2",
|
|
1235
|
+
name: "Brooklyn Creative Studio",
|
|
1236
|
+
address: "456 Broadway",
|
|
1237
|
+
city: "Brooklyn",
|
|
1238
|
+
state: "NY",
|
|
1239
|
+
zipCode: "11211",
|
|
1240
|
+
country: "United States",
|
|
1241
|
+
lat: 40.7128,
|
|
1242
|
+
lng: -74.006,
|
|
1243
|
+
availableTime: "Oct 29, 3:00 PM",
|
|
1244
|
+
euifyMakeModel: "euifyMake E1, euifyMake M5"
|
|
1245
|
+
},
|
|
1246
|
+
{
|
|
1247
|
+
id: "3",
|
|
1248
|
+
name: "Austin Innovation Hub",
|
|
1249
|
+
address: "789 Tech Blvd",
|
|
1250
|
+
city: "Austin",
|
|
1251
|
+
state: "TX",
|
|
1252
|
+
zipCode: "78701",
|
|
1253
|
+
country: "United States",
|
|
1254
|
+
lat: 30.2672,
|
|
1255
|
+
lng: -97.7431,
|
|
1256
|
+
availableTime: "Oct 30, 1:00 PM",
|
|
1257
|
+
euifyMakeModel: "euifyMake M5"
|
|
1258
|
+
},
|
|
1259
|
+
{
|
|
1260
|
+
id: "4",
|
|
1261
|
+
name: "Seattle Maker Space",
|
|
1262
|
+
address: "321 Pine St",
|
|
1263
|
+
city: "Seattle",
|
|
1264
|
+
state: "WA",
|
|
1265
|
+
zipCode: "98101",
|
|
1266
|
+
country: "United States",
|
|
1267
|
+
lat: 47.6062,
|
|
1268
|
+
lng: -122.3321,
|
|
1269
|
+
availableTime: "Oct 31, 11:00 AM",
|
|
1270
|
+
euifyMakeModel: "euifyMake E1"
|
|
1271
|
+
},
|
|
1272
|
+
{
|
|
1273
|
+
id: "5",
|
|
1274
|
+
name: "Chicago Design Center",
|
|
1275
|
+
address: "654 Michigan Ave",
|
|
1276
|
+
city: "Chicago",
|
|
1277
|
+
state: "IL",
|
|
1278
|
+
zipCode: "60611",
|
|
1279
|
+
country: "United States",
|
|
1280
|
+
lat: 41.8781,
|
|
1281
|
+
lng: -87.6298,
|
|
1282
|
+
availableTime: "Nov 1, 2:30 PM",
|
|
1283
|
+
euifyMakeModel: "euifyMake E1, euifyMake M5"
|
|
1284
|
+
},
|
|
1285
|
+
{
|
|
1286
|
+
id: "6",
|
|
1287
|
+
name: "Miami Beach Studio",
|
|
1288
|
+
address: "987 Ocean Drive",
|
|
1289
|
+
city: "Miami Beach",
|
|
1290
|
+
state: "FL",
|
|
1291
|
+
zipCode: "33139",
|
|
1292
|
+
country: "United States",
|
|
1293
|
+
lat: 25.7617,
|
|
1294
|
+
lng: -80.1918,
|
|
1295
|
+
availableTime: "Nov 2, 10:00 AM",
|
|
1296
|
+
euifyMakeModel: "euifyMake M5"
|
|
1297
|
+
},
|
|
1298
|
+
{
|
|
1299
|
+
id: "7",
|
|
1300
|
+
name: "Denver Mountain Studio",
|
|
1301
|
+
address: "147 16th St",
|
|
1302
|
+
city: "Denver",
|
|
1303
|
+
state: "CO",
|
|
1304
|
+
zipCode: "80202",
|
|
1305
|
+
country: "United States",
|
|
1306
|
+
lat: 39.7392,
|
|
1307
|
+
lng: -104.9903,
|
|
1308
|
+
availableTime: "Nov 3, 4:00 PM",
|
|
1309
|
+
euifyMakeModel: "euifyMake E1"
|
|
1310
|
+
},
|
|
1311
|
+
{
|
|
1312
|
+
id: "8",
|
|
1313
|
+
name: "Los Angeles Creative Lab",
|
|
1314
|
+
address: "258 Main St",
|
|
1315
|
+
city: "Los Angeles",
|
|
1316
|
+
state: "CA",
|
|
1317
|
+
zipCode: "90012",
|
|
1318
|
+
country: "United States",
|
|
1319
|
+
lat: 34.0522,
|
|
1320
|
+
lng: -118.2437,
|
|
1321
|
+
availableTime: "Nov 4, 1:00 PM",
|
|
1322
|
+
euifyMakeModel: "euifyMake E1, euifyMake M5"
|
|
1323
|
+
}
|
|
1324
|
+
];
|
|
1325
|
+
var RoomsList = ({
|
|
1326
|
+
googleMapsApiKey,
|
|
1327
|
+
className,
|
|
1328
|
+
apiClient,
|
|
1329
|
+
teamCode,
|
|
1330
|
+
brandWebsite,
|
|
1331
|
+
onSchedule,
|
|
1332
|
+
...props
|
|
1333
|
+
}) => {
|
|
1334
|
+
const [showLocationFilter, setShowLocationFilter] = React2.useState(false);
|
|
1335
|
+
const [selectedLocation, setSelectedLocation] = React2.useState();
|
|
1336
|
+
const {
|
|
1337
|
+
data: demoRooms,
|
|
1338
|
+
loading,
|
|
1339
|
+
error
|
|
1340
|
+
} = useDemoRooms(apiClient, {
|
|
1341
|
+
team_code: teamCode,
|
|
1342
|
+
brand_website: brandWebsite
|
|
1343
|
+
});
|
|
1344
|
+
console.log(demoRooms);
|
|
1345
|
+
const studioLocations = React2.useMemo(() => {
|
|
1346
|
+
if (!demoRooms) return defaultStudioLocations;
|
|
1347
|
+
return demoRooms.map((room) => {
|
|
1348
|
+
const timeslots = [
|
|
1349
|
+
{
|
|
1350
|
+
id: 130,
|
|
1351
|
+
start_time: "2026-01-13T09:00:00-05:00",
|
|
1352
|
+
end_time: "2026-01-13T10:00:00-05:00",
|
|
1353
|
+
capacity: 5,
|
|
1354
|
+
booked_count: 2,
|
|
1355
|
+
status: "available"
|
|
1356
|
+
},
|
|
1357
|
+
{
|
|
1358
|
+
id: 131,
|
|
1359
|
+
start_time: "2026-01-13T14:00:00-05:00",
|
|
1360
|
+
end_time: "2026-01-13T15:00:00-05:00",
|
|
1361
|
+
capacity: 5,
|
|
1362
|
+
booked_count: 5,
|
|
1363
|
+
status: "full"
|
|
1364
|
+
}
|
|
1365
|
+
];
|
|
1366
|
+
const nextAvailableTimeslot = (room.timeslots?.length ? room.timeslots : timeslots)?.find((slot) => slot.status === "available");
|
|
1367
|
+
const { country, state, city } = parseAddress(room.address);
|
|
1368
|
+
return {
|
|
1369
|
+
id: room.code,
|
|
1370
|
+
name: room.name,
|
|
1371
|
+
address: room.address,
|
|
1372
|
+
city,
|
|
1373
|
+
state,
|
|
1374
|
+
zipCode: "",
|
|
1375
|
+
country,
|
|
1376
|
+
lat: Number(room.latitude) || 34.0522,
|
|
1377
|
+
lng: Number(room.longitude) || -118.2437,
|
|
1378
|
+
availableTime: nextAvailableTimeslot ? `${nextAvailableTimeslot.start_time}` : "No available time",
|
|
1379
|
+
euifyMakeModel: room?.description
|
|
1380
|
+
};
|
|
1381
|
+
});
|
|
1382
|
+
}, [demoRooms]);
|
|
1383
|
+
const filteredStudioLocations = React2.useMemo(() => {
|
|
1384
|
+
if (!selectedLocation) return studioLocations;
|
|
1385
|
+
return studioLocations.filter((location) => {
|
|
1386
|
+
const { country, state, city } = parseAddress(location.address);
|
|
1387
|
+
if (selectedLocation.city) {
|
|
1388
|
+
return country === selectedLocation.country && state === selectedLocation.state && city === selectedLocation.city;
|
|
1389
|
+
}
|
|
1390
|
+
if (selectedLocation.state) {
|
|
1391
|
+
return country === selectedLocation.country && state === selectedLocation.state;
|
|
1392
|
+
}
|
|
1393
|
+
if (selectedLocation.country) {
|
|
1394
|
+
return country === selectedLocation.country;
|
|
1395
|
+
}
|
|
1396
|
+
return true;
|
|
1397
|
+
});
|
|
1398
|
+
}, [studioLocations, selectedLocation]);
|
|
1399
|
+
const getSelectedLocationName = () => {
|
|
1400
|
+
if (!selectedLocation) return "All Locations";
|
|
1401
|
+
if (selectedLocation.city) return selectedLocation.city;
|
|
1402
|
+
if (selectedLocation.state) return selectedLocation.state;
|
|
1403
|
+
if (selectedLocation.country) return selectedLocation.country;
|
|
1404
|
+
return "All Locations";
|
|
1405
|
+
};
|
|
1406
|
+
const handleLocationSelect = (selection) => {
|
|
1407
|
+
setSelectedLocation(selection);
|
|
1408
|
+
setShowLocationFilter(false);
|
|
1409
|
+
};
|
|
1410
|
+
const handleClearFilter = () => {
|
|
1411
|
+
setSelectedLocation(void 0);
|
|
1412
|
+
};
|
|
1413
|
+
console.log(filteredStudioLocations);
|
|
1414
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className, ...props, children: [
|
|
1415
|
+
/* @__PURE__ */ jsxRuntime.jsx(Title, { title: "Find a Studio Near You" }),
|
|
1416
|
+
loading && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center h-[794px]", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-center", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-lg font-medium", children: "Loading demo rooms..." }) }) }),
|
|
1417
|
+
error && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center h-[794px]", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center text-red-600", children: [
|
|
1418
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-lg font-medium", children: "Failed to load demo rooms" }),
|
|
1419
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm mt-2", children: error.message })
|
|
1420
|
+
] }) }),
|
|
1421
|
+
!loading && !error && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex h-[794px] overflow-auto gap-4", children: [
|
|
1422
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1423
|
+
"div",
|
|
1424
|
+
{
|
|
1425
|
+
className: "flex-none relative w-[420px]",
|
|
1426
|
+
style: { height: "794px" },
|
|
1427
|
+
children: [
|
|
1428
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-[12px] items-center h-[72px] mb-4 font-bold text-[16px] gap-10 flex bg-white border border-[#E4E5E6] px-[20px] py-[16px]", children: [
|
|
1429
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1430
|
+
"button",
|
|
1431
|
+
{
|
|
1432
|
+
className: "flex cursor-pointer items-center hover:text-[#2E8B57] transition-colors",
|
|
1433
|
+
onClick: () => setShowLocationFilter(true),
|
|
1434
|
+
children: [
|
|
1435
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "mr-1", children: getSelectedLocationName() }),
|
|
1436
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1437
|
+
"svg",
|
|
1438
|
+
{
|
|
1439
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1440
|
+
width: "24",
|
|
1441
|
+
height: "24",
|
|
1442
|
+
viewBox: "0 0 24 24",
|
|
1443
|
+
fill: "none",
|
|
1444
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1445
|
+
"path",
|
|
1446
|
+
{
|
|
1447
|
+
d: "M16.7661 9.23364C17.078 9.5455 17.0779 10.0516 16.7661 10.3635L12.5991 14.5305C12.2874 14.842 11.782 14.8418 11.4702 14.5305L7.30322 10.3635C6.99135 10.0516 6.99135 9.54552 7.30322 9.23364C7.615 8.9221 8.1203 8.92219 8.43213 9.23364L12.0347 12.8362L15.6362 9.23364C15.9481 8.92183 16.4543 8.92181 16.7661 9.23364Z",
|
|
1448
|
+
fill: "currentColor"
|
|
1449
|
+
}
|
|
1450
|
+
)
|
|
1451
|
+
}
|
|
1452
|
+
)
|
|
1453
|
+
]
|
|
1454
|
+
}
|
|
1455
|
+
),
|
|
1456
|
+
selectedLocation && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1457
|
+
"button",
|
|
1458
|
+
{
|
|
1459
|
+
onClick: handleClearFilter,
|
|
1460
|
+
className: "ml-auto text-[14px] text-[#2E8B57] hover:underline",
|
|
1461
|
+
children: "Clear"
|
|
1462
|
+
}
|
|
1463
|
+
),
|
|
1464
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex text-[#767880] cursor-not-allowed", children: [
|
|
1465
|
+
"eufymake E1",
|
|
1466
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1467
|
+
"svg",
|
|
1468
|
+
{
|
|
1469
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1470
|
+
width: "24",
|
|
1471
|
+
height: "24",
|
|
1472
|
+
viewBox: "0 0 24 24",
|
|
1473
|
+
fill: "none",
|
|
1474
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1475
|
+
"path",
|
|
1476
|
+
{
|
|
1477
|
+
d: "M16.7661 9.23364C17.078 9.5455 17.0779 10.0516 16.7661 10.3635L12.5991 14.5305C12.2874 14.842 11.782 14.8418 11.4702 14.5305L7.30322 10.3635C6.99135 10.0516 6.99135 9.54552 7.30322 9.23364C7.615 8.9221 8.1203 8.92219 8.43213 9.23364L12.0347 12.8362L15.6362 9.23364C15.9481 8.92183 16.4543 8.92181 16.7661 9.23364Z",
|
|
1478
|
+
fill: "currentColor"
|
|
1479
|
+
}
|
|
1480
|
+
)
|
|
1481
|
+
}
|
|
1482
|
+
)
|
|
1483
|
+
] })
|
|
1484
|
+
] }),
|
|
1485
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1486
|
+
"div",
|
|
1487
|
+
{
|
|
1488
|
+
style: { maxHeight: "706px", overflow: "auto" },
|
|
1489
|
+
className: "rounded-[12px] bg-white border border-[#E4E5E6]",
|
|
1490
|
+
children: filteredStudioLocations.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center h-[200px] text-[#767880]", children: "No studios found in this location" }) : filteredStudioLocations.map((item) => {
|
|
1491
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1492
|
+
StudioCard,
|
|
1493
|
+
{
|
|
1494
|
+
code: item.id,
|
|
1495
|
+
name: item?.name,
|
|
1496
|
+
availableTime: item?.availableTime || "",
|
|
1497
|
+
address: item?.address,
|
|
1498
|
+
city: item?.city,
|
|
1499
|
+
state: item?.state,
|
|
1500
|
+
zipCode: item?.zipCode,
|
|
1501
|
+
euifyMakeModel: item?.euifyMakeModel || "",
|
|
1502
|
+
onSchedule
|
|
1503
|
+
},
|
|
1504
|
+
item.id
|
|
1505
|
+
);
|
|
1506
|
+
})
|
|
1507
|
+
}
|
|
1508
|
+
),
|
|
1509
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1510
|
+
LocationFilter,
|
|
1511
|
+
{
|
|
1512
|
+
locations: studioLocations.map((loc) => ({
|
|
1513
|
+
address: loc.address,
|
|
1514
|
+
id: loc.id
|
|
1515
|
+
})),
|
|
1516
|
+
visible: showLocationFilter,
|
|
1517
|
+
onSelect: handleLocationSelect,
|
|
1518
|
+
onClose: () => setShowLocationFilter(false)
|
|
1519
|
+
}
|
|
1520
|
+
)
|
|
1521
|
+
]
|
|
1522
|
+
}
|
|
1523
|
+
),
|
|
1524
|
+
googleMapsApiKey && /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex-1"), children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1525
|
+
StudioMap,
|
|
1526
|
+
{
|
|
1527
|
+
googleMapsApiKey,
|
|
1528
|
+
locations: filteredStudioLocations,
|
|
1529
|
+
onSchedule: () => {
|
|
1530
|
+
console.log(111);
|
|
1531
|
+
},
|
|
1532
|
+
mapHeight: "794px"
|
|
1533
|
+
}
|
|
1534
|
+
) })
|
|
1535
|
+
] })
|
|
1536
|
+
] });
|
|
1537
|
+
};
|
|
1538
|
+
RoomsList.displayName = "RoomsList";
|
|
1539
|
+
|
|
1540
|
+
// src/api/client.ts
|
|
1541
|
+
var DemoRoomApiClient = class {
|
|
1542
|
+
constructor(config) {
|
|
1543
|
+
this.config = {
|
|
1544
|
+
timeout: 3e4,
|
|
1545
|
+
...config
|
|
1546
|
+
};
|
|
1547
|
+
}
|
|
1548
|
+
async request(endpoint, options = {}) {
|
|
1549
|
+
const url = `${this.config.baseUrl}${endpoint}`;
|
|
1550
|
+
const headers = {
|
|
1551
|
+
"X-API-Key": this.config.apiKey,
|
|
1552
|
+
"Content-Type": "application/json",
|
|
1553
|
+
...options.headers
|
|
1554
|
+
};
|
|
1555
|
+
if (this.config.locale) {
|
|
1556
|
+
headers["Accept-Language"] = this.config.locale;
|
|
1557
|
+
}
|
|
1558
|
+
try {
|
|
1559
|
+
const controller = new AbortController();
|
|
1560
|
+
const timeoutId = setTimeout(() => controller.abort(), this.config.timeout);
|
|
1561
|
+
const response = await fetch(url, {
|
|
1562
|
+
...options,
|
|
1563
|
+
headers,
|
|
1564
|
+
signal: controller.signal
|
|
1565
|
+
});
|
|
1566
|
+
clearTimeout(timeoutId);
|
|
1567
|
+
const data = await response.json();
|
|
1568
|
+
if (data.code !== 0 /* SUCCESS */) {
|
|
1569
|
+
throw new ApiError(data.code, data.message, data.request_id);
|
|
1570
|
+
}
|
|
1571
|
+
return data.data;
|
|
1572
|
+
} catch (error) {
|
|
1573
|
+
if (error instanceof ApiError) {
|
|
1574
|
+
throw error;
|
|
1575
|
+
}
|
|
1576
|
+
if (error instanceof Error) {
|
|
1577
|
+
if (error.name === "AbortError") {
|
|
1578
|
+
throw new ApiError(1006 /* INTERNAL_ERROR */, "Request timeout");
|
|
1579
|
+
}
|
|
1580
|
+
throw new ApiError(1006 /* INTERNAL_ERROR */, error.message);
|
|
1581
|
+
}
|
|
1582
|
+
throw new ApiError(1006 /* INTERNAL_ERROR */, "Unknown error");
|
|
1583
|
+
}
|
|
1584
|
+
}
|
|
1585
|
+
/**
|
|
1586
|
+
* 获取门店列表
|
|
1587
|
+
* @param params.team_code 团队编码
|
|
1588
|
+
* @param params.brand_website 品牌站点
|
|
1589
|
+
* @param params.locale 语言偏好(可选)
|
|
1590
|
+
*/
|
|
1591
|
+
async getDemoRooms(params) {
|
|
1592
|
+
const searchParams = new URLSearchParams();
|
|
1593
|
+
if (params.team_code) {
|
|
1594
|
+
searchParams.append("team_code", params.team_code);
|
|
1595
|
+
}
|
|
1596
|
+
if (params.brand_website) {
|
|
1597
|
+
searchParams.append("brand_website", params.brand_website);
|
|
1598
|
+
}
|
|
1599
|
+
if (params.locale) {
|
|
1600
|
+
searchParams.append("locale", params.locale);
|
|
1601
|
+
}
|
|
1602
|
+
const response = await this.request(
|
|
1603
|
+
`/api/v1/store/demorooms?${searchParams.toString()}`
|
|
1604
|
+
);
|
|
1605
|
+
return response.demorooms;
|
|
1606
|
+
}
|
|
1607
|
+
/**
|
|
1608
|
+
* 获取门店详情
|
|
1609
|
+
* @param code 门店编码
|
|
1610
|
+
* @param locale 语言偏好(可选)
|
|
1611
|
+
*/
|
|
1612
|
+
async getDemoRoom(code, locale) {
|
|
1613
|
+
const searchParams = new URLSearchParams();
|
|
1614
|
+
if (locale) {
|
|
1615
|
+
searchParams.append("locale", locale);
|
|
1616
|
+
}
|
|
1617
|
+
const query = searchParams.toString();
|
|
1618
|
+
return this.request(
|
|
1619
|
+
`/api/v1/store/demorooms/${code}${query ? `?${query}` : ""}`
|
|
1620
|
+
);
|
|
1621
|
+
}
|
|
1622
|
+
/**
|
|
1623
|
+
* 查询门店时段
|
|
1624
|
+
* @param code 门店编码
|
|
1625
|
+
* @param params.start_date 开始日期 (YYYY-MM-DD)
|
|
1626
|
+
* @param params.end_date 结束日期 (YYYY-MM-DD)
|
|
1627
|
+
* @param params.timezone 时区(可选)
|
|
1628
|
+
*/
|
|
1629
|
+
async getTimeslots(code, params) {
|
|
1630
|
+
const searchParams = new URLSearchParams({
|
|
1631
|
+
start_date: params.start_date,
|
|
1632
|
+
end_date: params.end_date
|
|
1633
|
+
});
|
|
1634
|
+
if (params.timezone) {
|
|
1635
|
+
searchParams.append("timezone", params.timezone);
|
|
1636
|
+
}
|
|
1637
|
+
return this.request(
|
|
1638
|
+
`/api/v1/store/demorooms/${code}/timeslots?${searchParams.toString()}`
|
|
1639
|
+
);
|
|
1640
|
+
}
|
|
1641
|
+
/**
|
|
1642
|
+
* 查询门店问卷
|
|
1643
|
+
* @param code 门店编码
|
|
1644
|
+
* @param questionnaire_id 问卷ID
|
|
1645
|
+
* @param locale 语言偏好(可选)
|
|
1646
|
+
*/
|
|
1647
|
+
async getQuestionnaire(code, questionnaire_id, locale) {
|
|
1648
|
+
const searchParams = new URLSearchParams();
|
|
1649
|
+
if (locale) {
|
|
1650
|
+
searchParams.append("locale", locale);
|
|
1651
|
+
}
|
|
1652
|
+
const query = searchParams.toString();
|
|
1653
|
+
return this.request(
|
|
1654
|
+
`/api/v1/store/demorooms/${code}/questionnaires/${questionnaire_id}${query ? `?${query}` : ""}`
|
|
1655
|
+
);
|
|
1656
|
+
}
|
|
1657
|
+
/**
|
|
1658
|
+
* 提交预约
|
|
1659
|
+
* @param data 预约数据
|
|
1660
|
+
*/
|
|
1661
|
+
async createBooking(data) {
|
|
1662
|
+
return this.request("/api/v1/store/bookings", {
|
|
1663
|
+
method: "POST",
|
|
1664
|
+
body: JSON.stringify(data)
|
|
1665
|
+
});
|
|
1666
|
+
}
|
|
1667
|
+
/**
|
|
1668
|
+
* 根据 token 获取预约信息
|
|
1669
|
+
* @param token 预约 token
|
|
1670
|
+
*/
|
|
1671
|
+
async getBooking(token) {
|
|
1672
|
+
return this.request(`/api/v1/store/bookings/${token}`);
|
|
1673
|
+
}
|
|
1674
|
+
};
|
|
1675
|
+
function createDemoRoomApi(config) {
|
|
1676
|
+
return new DemoRoomApiClient(config);
|
|
1677
|
+
}
|
|
1678
|
+
var DemoRoom = ({
|
|
1679
|
+
className,
|
|
1680
|
+
layoutClassName = "w-safe11",
|
|
1681
|
+
googleMapsApiKey,
|
|
1682
|
+
apiConfig,
|
|
1683
|
+
teamCode,
|
|
1684
|
+
brandWebsite,
|
|
1685
|
+
onSchedule,
|
|
1686
|
+
...props
|
|
1687
|
+
}) => {
|
|
1688
|
+
const apiClient = React2.useMemo(
|
|
1689
|
+
() => createDemoRoomApi(apiConfig),
|
|
1690
|
+
[apiConfig]
|
|
1691
|
+
);
|
|
1692
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn(className), ...props, children: [
|
|
1693
|
+
/* @__PURE__ */ jsxRuntime.jsx(Banner, { className: layoutClassName }),
|
|
1694
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1695
|
+
BreadCrumbs,
|
|
1696
|
+
{
|
|
1697
|
+
className: layoutClassName,
|
|
1698
|
+
items: [{ label: "Home", link: "/" }, { label: "Demo Room" }]
|
|
1699
|
+
}
|
|
1700
|
+
),
|
|
1701
|
+
/* @__PURE__ */ jsxRuntime.jsx(HelpNav, {}),
|
|
1702
|
+
/* @__PURE__ */ jsxRuntime.jsx(UpcomingEvents, { className: layoutClassName }),
|
|
1703
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1704
|
+
RoomsList,
|
|
1705
|
+
{
|
|
1706
|
+
className: layoutClassName,
|
|
1707
|
+
googleMapsApiKey,
|
|
1708
|
+
apiClient,
|
|
1709
|
+
teamCode,
|
|
1710
|
+
brandWebsite,
|
|
1711
|
+
onSchedule
|
|
1712
|
+
}
|
|
1713
|
+
),
|
|
1714
|
+
/* @__PURE__ */ jsxRuntime.jsx(EasySteps, { className: layoutClassName })
|
|
1715
|
+
] });
|
|
1716
|
+
};
|
|
1717
|
+
DemoRoom.displayName = "DemoRoom";
|
|
1718
|
+
|
|
1719
|
+
exports.DemoRoom = DemoRoom;
|
|
1720
|
+
exports.EasySteps = EasySteps;
|
|
1721
|
+
exports.EventCard = EventCard;
|
|
1722
|
+
exports.HelpNav = HelpNav;
|
|
1723
|
+
exports.StudioCard = StudioCard;
|
|
1724
|
+
exports.StudioMap = StudioMap;
|
|
1725
|
+
exports.UpcomingEvents = UpcomingEvents;
|
|
1726
|
+
//# sourceMappingURL=demo-room.js.map
|
|
1727
|
+
//# sourceMappingURL=demo-room.js.map
|