webs-sdk 0.15.0 → 0.15.2

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 (67) hide show
  1. package/README.md +398 -398
  2. package/dist/client.d.ts +2 -0
  3. package/dist/client.d.ts.map +1 -0
  4. package/dist/client.js +7 -0
  5. package/dist/client.js.map +1 -0
  6. package/dist/components/ARFilters/ARFilters.js +52 -52
  7. package/dist/components/AvatarAI.js +4 -4
  8. package/dist/components/CookieConsent/constants.js +31 -31
  9. package/dist/components/CreativeFaceSwap.js +12 -12
  10. package/dist/components/MemeGenerator.js +12 -12
  11. package/dist/components/SpinningWheel/SpinningWheel.js +7 -7
  12. package/dist/components/esports/news/EsportsNews.d.ts.map +1 -1
  13. package/dist/components/esports/news/EsportsNews.js +13 -6
  14. package/dist/components/esports/news/EsportsNews.js.map +1 -1
  15. package/dist/components/esports/news/EsportsNewsDetail.d.ts +12 -0
  16. package/dist/components/esports/news/EsportsNewsDetail.d.ts.map +1 -0
  17. package/dist/components/esports/news/EsportsNewsDetail.js +100 -0
  18. package/dist/components/esports/news/EsportsNewsDetail.js.map +1 -0
  19. package/dist/components/esports/news/index.d.ts +2 -0
  20. package/dist/components/esports/news/index.d.ts.map +1 -1
  21. package/dist/components/esports/news/index.js +3 -1
  22. package/dist/components/esports/news/index.js.map +1 -1
  23. package/dist/components/esports/news/types.d.ts +4 -1
  24. package/dist/components/esports/news/types.d.ts.map +1 -1
  25. package/dist/components/esports/utils.d.ts +1 -0
  26. package/dist/components/esports/utils.d.ts.map +1 -1
  27. package/dist/components/esports/utils.js +23 -0
  28. package/dist/components/esports/utils.js.map +1 -1
  29. package/dist/components/esports/videos/EsportsVideos.d.ts.map +1 -1
  30. package/dist/components/esports/videos/EsportsVideos.js +13 -6
  31. package/dist/components/esports/videos/EsportsVideos.js.map +1 -1
  32. package/dist/components/esports/videos/api.d.ts.map +1 -1
  33. package/dist/components/esports/videos/api.js +36 -8
  34. package/dist/components/esports/videos/api.js.map +1 -1
  35. package/dist/components/esports/videos/types.d.ts +4 -1
  36. package/dist/components/esports/videos/types.d.ts.map +1 -1
  37. package/dist/components/ui/VideoPlayer.d.ts +11 -0
  38. package/dist/components/ui/VideoPlayer.d.ts.map +1 -0
  39. package/dist/components/ui/VideoPlayer.js +171 -0
  40. package/dist/components/ui/VideoPlayer.js.map +1 -0
  41. package/dist/context/TranslationContext.d.ts +12 -0
  42. package/dist/context/TranslationContext.d.ts.map +1 -0
  43. package/dist/context/TranslationContext.js +60 -0
  44. package/dist/context/TranslationContext.js.map +1 -0
  45. package/dist/index.d.ts +0 -4
  46. package/dist/index.d.ts.map +1 -1
  47. package/dist/index.js +1 -8
  48. package/dist/index.js.map +1 -1
  49. package/index.js +83 -0
  50. package/package.json +42 -43
  51. package/public/spin2win/assets/border-afristream.svg +26 -26
  52. package/public/spin2win/assets/border-efc.svg +23 -23
  53. package/public/spin2win/assets/border-totalgym.svg +27 -27
  54. package/public/spin2win/assets/border-womantoday.svg +26 -26
  55. package/public/spin2win/assets/indicator-afristream.svg +28 -28
  56. package/public/spin2win/assets/indicator-efc.svg +29 -29
  57. package/public/spin2win/assets/indicator-totalgym.svg +29 -29
  58. package/public/spin2win/fonts/switzer/README.md +22 -22
  59. package/types/index.d.ts +415 -0
  60. package/dist/components/Quiz.d.ts +0 -91
  61. package/dist/components/Quiz.d.ts.map +0 -1
  62. package/dist/components/Quiz.js +0 -748
  63. package/dist/components/Quiz.js.map +0 -1
  64. package/dist/components/Stickers.d.ts +0 -68
  65. package/dist/components/Stickers.d.ts.map +0 -1
  66. package/dist/components/Stickers.js +0 -303
  67. package/dist/components/Stickers.js.map +0 -1
@@ -1,748 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.Quiz = Quiz;
37
- exports.QuizForYouCard = QuizForYouCard;
38
- const react_1 = __importStar(require("react"));
39
- function parseMeta(raw) {
40
- if (!raw)
41
- return {};
42
- if (typeof raw === 'object')
43
- return raw;
44
- try {
45
- return JSON.parse(raw);
46
- }
47
- catch (_a) {
48
- return {};
49
- }
50
- }
51
- function formatLabel(template, vars) {
52
- return Object.entries(vars).reduce((acc, [key, val]) => acc.replace(`{${key}}`, String(val)), template);
53
- }
54
- function toQuizItem(item) {
55
- var _a, _b;
56
- const title = (item.title || item.name || '');
57
- if (!title)
58
- return null;
59
- const contentsId = String(item.contents || '');
60
- if (!contentsId)
61
- return null;
62
- const thumbnail = item.thumbnail ||
63
- item.image ||
64
- ((_b = (_a = item.files) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.url) ||
65
- '';
66
- return {
67
- id: item.id,
68
- title,
69
- description: item.description,
70
- thumbnail: thumbnail || undefined,
71
- contentsId,
72
- };
73
- }
74
- function extractResults(item, locale) {
75
- const meta = parseMeta(item.metadata);
76
- let quizConfig = meta.quiz_configuration;
77
- if (!quizConfig && 'quiz_configuration' in item) {
78
- quizConfig = item.quiz_configuration;
79
- }
80
- if (!quizConfig)
81
- return [];
82
- const langs = quizConfig.langs;
83
- if (!langs)
84
- return [];
85
- const localeUpper = locale.toUpperCase();
86
- const localeUpper2 = locale.substring(0, 2).toUpperCase();
87
- let langData = langs[localeUpper];
88
- if (!langData)
89
- langData = langs[localeUpper2];
90
- if (!langData)
91
- langData = langs[locale];
92
- if (!langData)
93
- return [];
94
- const resultados = langData.resultados;
95
- if (!Array.isArray(resultados))
96
- return [];
97
- return resultados
98
- .map(r => ({
99
- title: String(r.titulo || ''),
100
- description: String(r.titulo || ''),
101
- minPoints: typeof r.puntos_ini === 'number' ? r.puntos_ini : 0,
102
- maxPoints: typeof r.puntos_fin === 'number' ? r.puntos_fin : 0,
103
- }))
104
- .filter(r => r.description);
105
- }
106
- function extractQuestions(item, locale) {
107
- const meta = parseMeta(item.metadata);
108
- let quizConfig = meta.quiz_configuration;
109
- if (!quizConfig && 'quiz_configuration' in item) {
110
- quizConfig = item.quiz_configuration;
111
- }
112
- if (!quizConfig)
113
- return [];
114
- const langs = quizConfig.langs;
115
- if (!langs)
116
- return [];
117
- const localeUpper = locale.toUpperCase();
118
- const localeUpper2 = locale.substring(0, 2).toUpperCase();
119
- let langData = langs[localeUpper];
120
- if (!langData)
121
- langData = langs[localeUpper2];
122
- if (!langData)
123
- langData = langs[locale];
124
- if (!langData)
125
- return [];
126
- const preguntas = langData.preguntas;
127
- if (!Array.isArray(preguntas))
128
- return [];
129
- return preguntas
130
- .map((pregunta, idx) => {
131
- const titulo = String(pregunta.titulo || '');
132
- if (!titulo)
133
- return null;
134
- const respuestas = pregunta.respuestas;
135
- if (!Array.isArray(respuestas) || respuestas.length < 2)
136
- return null;
137
- const options = respuestas
138
- .map(r => ({
139
- text: String(r.titulo || ''),
140
- points: typeof r.puntos === 'number' ? r.puntos : 0,
141
- }))
142
- .filter(o => o.text);
143
- if (options.length < 2)
144
- return null;
145
- return {
146
- id: `${item.id}_q${idx}`,
147
- question: titulo,
148
- options,
149
- };
150
- })
151
- .filter(Boolean);
152
- }
153
- function normalizeResponse(json) {
154
- const j = json;
155
- if (Array.isArray(j))
156
- return j;
157
- if (j === null || j === void 0 ? void 0 : j.data) {
158
- const data = j.data;
159
- if (data.data && typeof data.data === 'object') {
160
- const dataData = data.data;
161
- if (dataData.data && typeof dataData.data === 'object') {
162
- const datDataData = dataData.data;
163
- if ('quiz_configuration' in datDataData) {
164
- return [datDataData];
165
- }
166
- if (Array.isArray(datDataData))
167
- return datDataData;
168
- }
169
- if (Array.isArray(dataData))
170
- return dataData;
171
- if (typeof dataData === 'object' && dataData !== null)
172
- return [dataData];
173
- }
174
- if (Array.isArray(data.data))
175
- return data.data;
176
- if (Array.isArray(data.contents))
177
- return data.contents;
178
- if (Array.isArray(data))
179
- return data;
180
- if (typeof data === 'object' && data !== null)
181
- return [data];
182
- }
183
- if (Array.isArray(j.contents))
184
- return j.contents;
185
- return [];
186
- }
187
- function QuizCard({ quiz, index, theme, texts, onClick }) {
188
- const [hovered, setHovered] = (0, react_1.useState)(false);
189
- return (react_1.default.createElement("div", { onClick: onClick, onMouseEnter: () => setHovered(true), onMouseLeave: () => setHovered(false), style: {
190
- backgroundColor: theme.cardBackground,
191
- border: `1.5px solid ${hovered ? theme.primaryColor : theme.cardBorderColor}`,
192
- borderRadius: '16px',
193
- overflow: 'hidden',
194
- cursor: 'pointer',
195
- transition: 'border-color 0.2s, transform 0.2s, box-shadow 0.2s',
196
- transform: hovered ? 'translateY(-2px)' : 'none',
197
- boxShadow: hovered ? '0 8px 24px rgba(0,0,0,0.12)' : '0 2px 8px rgba(0,0,0,0.06)',
198
- display: 'flex',
199
- flexDirection: 'column',
200
- } },
201
- react_1.default.createElement("div", { style: {
202
- width: '100%',
203
- aspectRatio: '16/9',
204
- backgroundColor: theme.backgroundColor,
205
- overflow: 'hidden',
206
- position: 'relative',
207
- display: 'flex',
208
- alignItems: 'center',
209
- justifyContent: 'center',
210
- } }, quiz.thumbnail ? (react_1.default.createElement("img", { src: quiz.thumbnail, alt: quiz.title, style: { width: '100%', height: '100%', objectFit: 'cover' } })) : (react_1.default.createElement("div", { style: {
211
- width: '56px',
212
- height: '56px',
213
- borderRadius: '50%',
214
- backgroundColor: theme.primaryColor,
215
- display: 'flex',
216
- alignItems: 'center',
217
- justifyContent: 'center',
218
- color: theme.buttonTextColor,
219
- fontSize: '24px',
220
- fontWeight: 700,
221
- } }, index + 1))),
222
- react_1.default.createElement("div", { style: { padding: '16px', flex: 1, display: 'flex', flexDirection: 'column', gap: '8px' } },
223
- react_1.default.createElement("p", { style: {
224
- color: theme.textColor,
225
- fontSize: '15px',
226
- lineHeight: 1.4,
227
- margin: 0,
228
- fontWeight: 700,
229
- display: '-webkit-box',
230
- WebkitLineClamp: 2,
231
- WebkitBoxOrient: 'vertical',
232
- overflow: 'hidden',
233
- } }, quiz.title),
234
- quiz.description && (react_1.default.createElement("p", { style: {
235
- color: theme.neutralMid,
236
- fontSize: '13px',
237
- lineHeight: 1.4,
238
- margin: 0,
239
- display: '-webkit-box',
240
- WebkitLineClamp: 2,
241
- WebkitBoxOrient: 'vertical',
242
- overflow: 'hidden',
243
- } }, quiz.description)),
244
- react_1.default.createElement("button", { style: {
245
- marginTop: 'auto',
246
- padding: '8px 16px',
247
- borderRadius: '20px',
248
- border: 'none',
249
- backgroundColor: theme.buttonColor,
250
- color: theme.buttonTextColor,
251
- fontSize: '13px',
252
- fontWeight: 600,
253
- cursor: 'pointer',
254
- transition: 'opacity 0.2s',
255
- }, onMouseEnter: (e) => { e.currentTarget.style.opacity = '0.85'; }, onMouseLeave: (e) => { e.currentTarget.style.opacity = '1'; } }, texts.startQuiz))));
256
- }
257
- function QuizModal({ questions, results, startIndex, theme, texts, onClose }) {
258
- var _a;
259
- const [currentIndex, setCurrentIndex] = (0, react_1.useState)(startIndex);
260
- const [answers, setAnswers] = (0, react_1.useState)(new Map());
261
- const [finished, setFinished] = (0, react_1.useState)(false);
262
- const current = questions[currentIndex];
263
- const total = questions.length;
264
- const isPointsBased = current.correctIndex === undefined;
265
- const selectedOption = (_a = answers.get(currentIndex)) !== null && _a !== void 0 ? _a : null;
266
- function handleSelect(optionIndex) {
267
- setAnswers(prev => new Map(prev).set(currentIndex, optionIndex));
268
- }
269
- function handlePrevious() {
270
- if (currentIndex > 0) {
271
- setCurrentIndex(i => i - 1);
272
- }
273
- }
274
- function handleNext() {
275
- if (currentIndex + 1 >= total) {
276
- setFinished(true);
277
- }
278
- else {
279
- setCurrentIndex((i) => i + 1);
280
- }
281
- }
282
- function handleRetry() {
283
- setCurrentIndex(startIndex);
284
- setAnswers(new Map());
285
- setFinished(false);
286
- }
287
- function handleOverlayClick(e) {
288
- if (e.target === e.currentTarget)
289
- onClose();
290
- }
291
- (0, react_1.useEffect)(() => {
292
- function handleKey(e) {
293
- if (e.key === 'Escape')
294
- onClose();
295
- }
296
- window.addEventListener('keydown', handleKey);
297
- return () => window.removeEventListener('keydown', handleKey);
298
- }, [onClose]);
299
- (0, react_1.useEffect)(() => {
300
- document.body.style.overflow = 'hidden';
301
- return () => { document.body.style.overflow = ''; };
302
- }, []);
303
- const overlayStyle = {
304
- position: 'fixed',
305
- inset: 0,
306
- zIndex: 9999,
307
- backgroundColor: 'rgba(0,0,0,0.6)',
308
- display: 'flex',
309
- alignItems: 'center',
310
- justifyContent: 'center',
311
- padding: '16px',
312
- };
313
- const modalStyle = {
314
- backgroundColor: theme.cardBackground,
315
- borderRadius: '20px',
316
- width: '100%',
317
- maxWidth: '560px',
318
- maxHeight: '90vh',
319
- overflowY: 'auto',
320
- padding: '32px 28px',
321
- position: 'relative',
322
- display: 'flex',
323
- flexDirection: 'column',
324
- gap: '20px',
325
- };
326
- if (finished) {
327
- let score = 0;
328
- answers.forEach((optionIdx, questionIdx) => {
329
- const question = questions[questionIdx];
330
- if (question.correctIndex === undefined) {
331
- score += question.options[optionIdx].points;
332
- }
333
- else {
334
- if (optionIdx === question.correctIndex) {
335
- score += 1;
336
- }
337
- }
338
- });
339
- let resultMessage;
340
- const firstQuestion = questions[0];
341
- const isQuizPointsBased = firstQuestion.correctIndex === undefined;
342
- if (isQuizPointsBased && results && results.length > 0) {
343
- const matchedResult = results.find(r => score >= r.minPoints && score <= r.maxPoints);
344
- resultMessage = matchedResult === null || matchedResult === void 0 ? void 0 : matchedResult.description;
345
- }
346
- return (react_1.default.createElement("div", { style: overlayStyle, onClick: handleOverlayClick },
347
- react_1.default.createElement("div", { style: modalStyle },
348
- react_1.default.createElement("button", { onClick: onClose, "aria-label": texts.closeButton, style: {
349
- position: 'absolute',
350
- top: '16px',
351
- right: '16px',
352
- background: 'none',
353
- border: 'none',
354
- cursor: 'pointer',
355
- color: theme.neutralMid,
356
- fontSize: '20px',
357
- lineHeight: 1,
358
- } }, "\u2715"),
359
- react_1.default.createElement("div", { style: { textAlign: 'center', paddingTop: '8px' } },
360
- react_1.default.createElement("div", { style: {
361
- width: '80px',
362
- height: '80px',
363
- borderRadius: '50%',
364
- backgroundColor: theme.primaryColor,
365
- margin: '0 auto 20px',
366
- display: 'flex',
367
- alignItems: 'center',
368
- justifyContent: 'center',
369
- fontSize: '32px',
370
- color: theme.buttonTextColor,
371
- } }, "\uD83C\uDFC6"),
372
- isQuizPointsBased ? (react_1.default.createElement(react_1.default.Fragment, null,
373
- react_1.default.createElement("p", { style: {
374
- fontSize: '18px',
375
- fontWeight: 600,
376
- color: theme.textColor,
377
- margin: '0 0 16px',
378
- } }, formatLabel(texts.scoreLabel, { score, total: score })),
379
- resultMessage && (react_1.default.createElement("p", { style: {
380
- fontSize: '15px',
381
- lineHeight: 1.6,
382
- color: theme.neutralMid,
383
- margin: 0,
384
- textAlign: 'left',
385
- } }, resultMessage)))) : (react_1.default.createElement("p", { style: {
386
- fontSize: '22px',
387
- fontWeight: 700,
388
- color: theme.textColor,
389
- margin: '0 0 8px',
390
- } }, formatLabel(texts.scoreLabel, { score, total })))),
391
- react_1.default.createElement("div", { style: { display: 'flex', gap: '12px', marginTop: '8px' } },
392
- react_1.default.createElement("button", { onClick: handleRetry, style: {
393
- flex: 1,
394
- padding: '12px',
395
- borderRadius: '12px',
396
- border: `1.5px solid ${theme.primaryColor}`,
397
- backgroundColor: 'transparent',
398
- color: theme.primaryColor,
399
- fontWeight: 600,
400
- cursor: 'pointer',
401
- fontSize: '14px',
402
- } }, texts.retryButton),
403
- react_1.default.createElement("button", { onClick: onClose, style: {
404
- flex: 1,
405
- padding: '12px',
406
- borderRadius: '12px',
407
- border: 'none',
408
- backgroundColor: theme.primaryColor,
409
- color: theme.buttonTextColor,
410
- fontWeight: 600,
411
- cursor: 'pointer',
412
- fontSize: '14px',
413
- } }, texts.closeButton)))));
414
- }
415
- const isCorrect = !isPointsBased && selectedOption !== null && selectedOption === current.correctIndex;
416
- return (react_1.default.createElement("div", { style: overlayStyle, onClick: handleOverlayClick },
417
- react_1.default.createElement("div", { style: modalStyle },
418
- react_1.default.createElement("button", { onClick: onClose, "aria-label": texts.closeButton, style: {
419
- position: 'absolute',
420
- top: '16px',
421
- right: '16px',
422
- background: 'none',
423
- border: 'none',
424
- cursor: 'pointer',
425
- color: theme.neutralMid,
426
- fontSize: '20px',
427
- lineHeight: 1,
428
- } }, "\u2715"),
429
- react_1.default.createElement("div", { style: { paddingTop: '4px' } },
430
- react_1.default.createElement("div", { style: {
431
- display: 'flex',
432
- justifyContent: 'space-between',
433
- alignItems: 'center',
434
- marginBottom: '8px',
435
- } },
436
- react_1.default.createElement("span", { style: { fontSize: '12px', color: theme.neutralMid } }, formatLabel(texts.questionLabel, { current: currentIndex + 1, total }))),
437
- react_1.default.createElement("div", { style: {
438
- height: '4px',
439
- borderRadius: '2px',
440
- backgroundColor: theme.cardBorderColor,
441
- overflow: 'hidden',
442
- } },
443
- react_1.default.createElement("div", { style: {
444
- height: '100%',
445
- width: `${((currentIndex + 1) / total) * 100}%`,
446
- backgroundColor: theme.primaryColor,
447
- transition: 'width 0.3s',
448
- } }))),
449
- current.thumbnail && (react_1.default.createElement("div", { style: {
450
- borderRadius: '12px',
451
- overflow: 'hidden',
452
- aspectRatio: '16/9',
453
- } },
454
- react_1.default.createElement("img", { src: current.thumbnail, alt: current.question, style: { width: '100%', height: '100%', objectFit: 'cover' } }))),
455
- react_1.default.createElement("p", { style: {
456
- fontSize: '18px',
457
- fontWeight: 700,
458
- color: theme.textColor,
459
- margin: 0,
460
- lineHeight: 1.45,
461
- } }, current.question),
462
- react_1.default.createElement("div", { style: { display: 'flex', flexDirection: 'column', gap: '10px' } }, current.options.map((option, idx) => {
463
- let bg = theme.cardBackground;
464
- let border = theme.cardBorderColor;
465
- let color = theme.textColor;
466
- const hasAnswer = selectedOption !== null;
467
- if (hasAnswer && !isPointsBased) {
468
- if (idx === current.correctIndex) {
469
- bg = '#E8F5E9';
470
- border = '#4CAF50';
471
- color = '#1B5E20';
472
- }
473
- else if (idx === selectedOption) {
474
- bg = '#FFEBEE';
475
- border = '#F44336';
476
- color = '#B71C1C';
477
- }
478
- }
479
- else if (idx === selectedOption) {
480
- bg = theme.primaryColor;
481
- color = theme.buttonTextColor;
482
- border = theme.primaryColor;
483
- }
484
- return (react_1.default.createElement("button", { key: idx, onClick: () => handleSelect(idx), style: {
485
- padding: '12px 16px',
486
- borderRadius: '12px',
487
- border: `1.5px solid ${border}`,
488
- backgroundColor: bg,
489
- color,
490
- fontSize: '14px',
491
- fontWeight: 500,
492
- textAlign: 'left',
493
- cursor: 'pointer',
494
- transition: 'all 0.2s',
495
- lineHeight: 1.5,
496
- } }, option.text));
497
- })),
498
- selectedOption !== null && !isPointsBased && (react_1.default.createElement("p", { style: {
499
- fontSize: '14px',
500
- fontWeight: 600,
501
- color: isCorrect ? '#2E7D32' : '#C62828',
502
- margin: 0,
503
- } },
504
- isCorrect ? texts.correctAnswer : texts.wrongAnswer,
505
- current.explanation && (react_1.default.createElement("span", { style: { fontWeight: 400, display: 'block', marginTop: 4 } }, current.explanation)))),
506
- react_1.default.createElement("div", { style: { display: 'flex', gap: '12px' } },
507
- currentIndex > 0 && (react_1.default.createElement("button", { onClick: handlePrevious, style: {
508
- flex: 1,
509
- padding: '14px',
510
- borderRadius: '12px',
511
- border: `1.5px solid ${theme.primaryColor}`,
512
- backgroundColor: 'transparent',
513
- color: theme.primaryColor,
514
- fontWeight: 700,
515
- fontSize: '15px',
516
- cursor: 'pointer',
517
- transition: 'opacity 0.2s',
518
- }, onMouseEnter: (e) => { e.currentTarget.style.opacity = '0.85'; }, onMouseLeave: (e) => { e.currentTarget.style.opacity = '1'; } },
519
- "\u2190 ",
520
- texts.previousButton)),
521
- react_1.default.createElement("button", { onClick: handleNext, disabled: selectedOption === null, style: {
522
- flex: currentIndex > 0 ? 1 : 'auto',
523
- width: currentIndex === 0 ? '100%' : 'auto',
524
- padding: '14px',
525
- borderRadius: '12px',
526
- border: 'none',
527
- backgroundColor: selectedOption === null ? theme.neutralMid : theme.primaryColor,
528
- color: theme.buttonTextColor,
529
- fontWeight: 700,
530
- fontSize: '15px',
531
- cursor: selectedOption === null ? 'not-allowed' : 'pointer',
532
- transition: 'opacity 0.2s',
533
- opacity: selectedOption === null ? 0.5 : 1,
534
- }, onMouseEnter: (e) => { if (selectedOption !== null)
535
- e.currentTarget.style.opacity = '0.85'; }, onMouseLeave: (e) => { if (selectedOption !== null)
536
- e.currentTarget.style.opacity = '1'; } }, currentIndex + 1 >= total ? texts.submitButton : texts.nextButton)))));
537
- }
538
- const DEFAULT_THEME = {
539
- primaryColor: '#FF2273',
540
- primaryHoverColor: '#E81F69',
541
- textColor: '#0F1F35',
542
- backgroundColor: '#F5F5F5',
543
- cardBackground: '#FFFFFF',
544
- buttonColor: '#FF2273',
545
- buttonTextColor: '#FFFFFF',
546
- neutralMid: '#8C8C8C',
547
- cardBorderColor: 'rgba(15,31,53,0.1)',
548
- titleDarkColor: '#210F5C',
549
- };
550
- const DEFAULT_TEXTS = {
551
- title: 'Quizzes',
552
- subtitle: 'Test your knowledge',
553
- loading: 'Loading quizzes...',
554
- noItems: 'No quizzes available',
555
- loadMore: 'Load More',
556
- startQuiz: 'Start Quiz',
557
- questionLabel: 'Question {current} of {total}',
558
- nextButton: 'Next',
559
- previousButton: 'Previous',
560
- submitButton: 'Submit',
561
- correctAnswer: 'Correct!',
562
- wrongAnswer: 'Incorrect',
563
- retryButton: 'Retry',
564
- closeButton: 'Close',
565
- scoreLabel: 'You got {score}/{total} correct',
566
- loadingQuestions: 'Loading questions...',
567
- };
568
- function Quiz({ config, theme: themeP, texts: textsP, onQuizStart, onQuizComplete }) {
569
- const theme = Object.assign(Object.assign({}, DEFAULT_THEME), themeP);
570
- const texts = Object.assign(Object.assign({}, DEFAULT_TEXTS), textsP);
571
- const { apiUrl, questionsApiUrl, tags, includeIds, locale, initialCount = 12, loadMoreCount = 8 } = config;
572
- const [quizItems, setQuizItems] = (0, react_1.useState)([]);
573
- const [loading, setLoading] = (0, react_1.useState)(true);
574
- const [visibleCount, setVisibleCount] = (0, react_1.useState)(initialCount);
575
- const [activeQuiz, setActiveQuiz] = (0, react_1.useState)(null);
576
- const [activeQuestions, setActiveQuestions] = (0, react_1.useState)([]);
577
- const [activeResults, setActiveResults] = (0, react_1.useState)([]);
578
- const [loadingQuestions, setLoadingQuestions] = (0, react_1.useState)(false);
579
- const fetchList = (0, react_1.useCallback)(async () => {
580
- setLoading(true);
581
- try {
582
- const res = await fetch(apiUrl, {
583
- method: 'POST',
584
- headers: { 'Content-Type': 'application/json' },
585
- body: JSON.stringify(Object.assign({ language: locale || 'en', tags: tags || [] }, (includeIds && includeIds.length > 0 ? { includeIds } : {}))),
586
- });
587
- if (!res.ok)
588
- throw new Error(`API error ${res.status}`);
589
- const json = await res.json();
590
- const raw = normalizeResponse(json);
591
- const parsed = raw.map(toQuizItem).filter((q) => q !== null);
592
- const uniqueIds = new Set();
593
- const unique = parsed.filter(item => {
594
- if (uniqueIds.has(item.id))
595
- return false;
596
- uniqueIds.add(item.id);
597
- return true;
598
- });
599
- setQuizItems(unique);
600
- }
601
- catch (err) {
602
- console.error('[Quiz] fetch error:', err);
603
- setQuizItems([]);
604
- }
605
- finally {
606
- setLoading(false);
607
- }
608
- }, [apiUrl, locale, tags, includeIds]);
609
- (0, react_1.useEffect)(() => {
610
- fetchList();
611
- }, [fetchList]);
612
- const handleCardClick = (0, react_1.useCallback)(async (quiz) => {
613
- setActiveQuiz(quiz);
614
- setLoadingQuestions(true);
615
- if (onQuizStart) {
616
- onQuizStart(quiz);
617
- }
618
- try {
619
- const url = questionsApiUrl || apiUrl;
620
- const res = await fetch(url, {
621
- method: 'POST',
622
- headers: { 'Content-Type': 'application/json' },
623
- body: JSON.stringify({
624
- preset: 'getQuiz',
625
- params: {
626
- quiz_id: quiz.contentsId,
627
- language: locale || 'en',
628
- },
629
- }),
630
- });
631
- if (!res.ok)
632
- throw new Error(`API error ${res.status}`);
633
- const json = await res.json();
634
- const raw = normalizeResponse(json);
635
- if (raw.length === 0) {
636
- console.error('[Quiz] No data returned from questions API');
637
- setLoadingQuestions(false);
638
- return;
639
- }
640
- const item = raw[0];
641
- const questions = extractQuestions(item, locale || 'en');
642
- const results = extractResults(item, locale || 'en');
643
- if (questions.length === 0) {
644
- console.error('[Quiz] No questions found');
645
- }
646
- setActiveQuestions(questions);
647
- setActiveResults(results);
648
- }
649
- catch (err) {
650
- console.error('[Quiz] fetch questions error:', err);
651
- setActiveQuestions([]);
652
- setActiveResults([]);
653
- }
654
- finally {
655
- setLoadingQuestions(false);
656
- }
657
- }, [apiUrl, questionsApiUrl, locale, onQuizStart]);
658
- const handleCloseModal = (0, react_1.useCallback)(() => {
659
- setActiveQuiz(null);
660
- setActiveQuestions([]);
661
- setActiveResults([]);
662
- }, []);
663
- const visible = quizItems.slice(0, visibleCount);
664
- const hasMore = visibleCount < quizItems.length;
665
- return (react_1.default.createElement("div", { style: { backgroundColor: theme.backgroundColor, minHeight: '100vh' } },
666
- react_1.default.createElement("div", { style: { padding: '40px 16px', maxWidth: '1200px', margin: '0 auto' } },
667
- react_1.default.createElement("div", { style: { textAlign: 'center', marginBottom: '32px' } },
668
- react_1.default.createElement("h2", { style: {
669
- fontSize: '28px',
670
- fontWeight: 700,
671
- color: theme.titleDarkColor,
672
- margin: '0 0 8px',
673
- } }, texts.title),
674
- texts.subtitle && (react_1.default.createElement("p", { style: {
675
- fontSize: '16px',
676
- color: theme.neutralMid,
677
- margin: 0,
678
- } }, texts.subtitle))),
679
- loading ? (react_1.default.createElement("div", { style: { textAlign: 'center', padding: '40px', color: theme.neutralMid } }, texts.loading)) : quizItems.length === 0 ? (react_1.default.createElement("div", { style: { textAlign: 'center', padding: '40px', color: theme.neutralMid } }, texts.noItems)) : (react_1.default.createElement(react_1.default.Fragment, null,
680
- react_1.default.createElement("div", { style: {
681
- display: 'grid',
682
- gridTemplateColumns: 'repeat(auto-fill, minmax(280px, 1fr))',
683
- gap: '20px',
684
- marginBottom: '32px',
685
- } }, visible.map((quiz, idx) => (react_1.default.createElement(QuizCard, { key: quiz.id, quiz: quiz, index: idx, theme: theme, texts: texts, onClick: () => handleCardClick(quiz) })))),
686
- hasMore && (react_1.default.createElement("div", { style: { textAlign: 'center' } },
687
- react_1.default.createElement("button", { onClick: () => setVisibleCount(v => v + loadMoreCount), style: {
688
- padding: '12px 32px',
689
- borderRadius: '24px',
690
- border: `1.5px solid ${theme.primaryColor}`,
691
- backgroundColor: 'transparent',
692
- color: theme.primaryColor,
693
- fontWeight: 600,
694
- fontSize: '15px',
695
- cursor: 'pointer',
696
- transition: 'all 0.2s',
697
- }, onMouseEnter: (e) => {
698
- e.currentTarget.style.backgroundColor = theme.primaryColor;
699
- e.currentTarget.style.color = theme.buttonTextColor;
700
- }, onMouseLeave: (e) => {
701
- e.currentTarget.style.backgroundColor = 'transparent';
702
- e.currentTarget.style.color = theme.primaryColor;
703
- } }, texts.loadMore)))))),
704
- activeQuiz && loadingQuestions && (react_1.default.createElement("div", { style: {
705
- position: 'fixed',
706
- inset: 0,
707
- zIndex: 9999,
708
- backgroundColor: 'rgba(0,0,0,0.6)',
709
- display: 'flex',
710
- alignItems: 'center',
711
- justifyContent: 'center',
712
- } },
713
- react_1.default.createElement("div", { style: {
714
- backgroundColor: theme.cardBackground,
715
- borderRadius: '20px',
716
- padding: '40px',
717
- textAlign: 'center',
718
- color: theme.textColor,
719
- } }, texts.loadingQuestions))),
720
- activeQuiz && !loadingQuestions && activeQuestions.length > 0 && (react_1.default.createElement(QuizModal, { questions: activeQuestions, results: activeResults, startIndex: 0, theme: theme, texts: texts, onClose: handleCloseModal }))));
721
- }
722
- function QuizForYouCard({ title, description, ctaText, ctaHref, desktopImage, mobileImage, imageAlt = '', imageOnRight = false, titleColor = '#210F5C', descriptionColor = '#0F1F35', ctaColor = '#FF2273', ctaHoverColor = '#E81F69', backgroundColor = '#FFFFFF', paddingClass = '', }) {
723
- return (react_1.default.createElement("div", { style: { backgroundColor, width: '100%' }, className: paddingClass },
724
- react_1.default.createElement("div", { style: {
725
- display: 'flex',
726
- flexDirection: imageOnRight ? 'row-reverse' : 'row',
727
- minHeight: '420px',
728
- alignItems: 'stretch',
729
- } },
730
- react_1.default.createElement("div", { style: { flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '40px' } },
731
- react_1.default.createElement("div", { style: { maxWidth: '400px', textAlign: 'center' } },
732
- react_1.default.createElement("h2", { style: { color: titleColor, fontSize: '32px', fontWeight: 700, marginBottom: '16px' } }, title),
733
- react_1.default.createElement("p", { style: { color: descriptionColor, fontSize: '16px', marginBottom: '24px' } }, description),
734
- react_1.default.createElement("a", { href: ctaHref, style: {
735
- display: 'inline-block',
736
- padding: '12px 32px',
737
- borderRadius: '24px',
738
- backgroundColor: ctaColor,
739
- color: '#fff',
740
- textDecoration: 'none',
741
- fontWeight: 600,
742
- transition: 'background-color 0.2s',
743
- }, onMouseEnter: (e) => { e.currentTarget.style.backgroundColor = ctaHoverColor; }, onMouseLeave: (e) => { e.currentTarget.style.backgroundColor = ctaColor; } }, ctaText))),
744
- react_1.default.createElement("div", { style: { flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center', padding: '20px' } },
745
- react_1.default.createElement("img", { src: desktopImage, alt: imageAlt, style: { maxWidth: '100%', height: 'auto' } })))));
746
- }
747
- exports.default = Quiz;
748
- //# sourceMappingURL=Quiz.js.map