fansunited-frontend-components 0.0.1-RC5 → 0.0.1-RC6

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 (88) hide show
  1. package/classic-quiz-play.es.js +4 -4
  2. package/classic-quiz-play.umd.js +1 -1
  3. package/package.json +1 -1
  4. package/src/components/ClassicQuizNotFound.d.ts +2 -1
  5. package/src/components/ClassicQuizPlay.d.ts +3 -2
  6. package/src/components/Leads/CollectLead.d.ts +2 -1
  7. package/src/components/Leads/LeadAgreementCheckbox.d.ts +3 -2
  8. package/src/components/Leads/LeadForm.d.ts +2 -1
  9. package/src/components/Shared/Answers/Answers.d.ts +3 -2
  10. package/src/components/Shared/Answers/Option.d.ts +3 -2
  11. package/src/components/Shared/Button.d.ts +2 -1
  12. package/src/components/Shared/MainCard.d.ts +2 -1
  13. package/src/components/Shared/Pagination.d.ts +3 -2
  14. package/src/components/Shared/PresentedBy.d.ts +2 -1
  15. package/src/components/Shared/ScoreStateWrapper.d.ts +4 -3
  16. package/src/components/Shared/Stepper.d.ts +3 -2
  17. package/src/components/Shared/Stopwatch.d.ts +2 -1
  18. package/src/components/Variants/Overlay/AuthError/OverlayAuthError.d.ts +3 -2
  19. package/src/components/Variants/Overlay/AuthError/OverlayAuthError.styles.d.ts +3 -2
  20. package/src/components/Variants/Overlay/OverlayVariant.d.ts +3 -2
  21. package/src/components/Variants/Overlay/OverlayVariant.styles.d.ts +4 -3
  22. package/src/components/Variants/Overlay/ScoreState/OverlayScoreState.d.ts +4 -3
  23. package/src/components/Variants/Overlay/ScoreState/OverlayScoreState.styles.d.ts +4 -3
  24. package/src/components/Variants/Split/AuthError/SplitAuthError.d.ts +3 -2
  25. package/src/components/Variants/Split/AuthError/SplitAuthError.styles.d.ts +3 -2
  26. package/src/components/Variants/Split/ScoreState/SplitScoreState.d.ts +4 -3
  27. package/src/components/Variants/Split/ScoreState/SplitScoreState.styles.d.ts +4 -3
  28. package/src/components/Variants/Split/SplitVariant.d.ts +3 -2
  29. package/src/components/Variants/Split/SplitVariant.styles.d.ts +4 -3
  30. package/src/components/Variants/Standard/AuthError/StandardAuthError.d.ts +3 -2
  31. package/src/components/Variants/Standard/AuthError/StandardAuthError.styles.d.ts +4 -3
  32. package/src/components/Variants/Standard/ScoreState/StandardScoreState.d.ts +4 -3
  33. package/src/components/Variants/Standard/ScoreState/StandardScoreState.styles.d.ts +4 -3
  34. package/src/components/Variants/Standard/StandardVariant.d.ts +4 -3
  35. package/src/components/Variants/Standard/StandardVariant.styles.d.ts +4 -3
  36. package/src/constants/constants.d.ts +2 -1
  37. package/src/hooks/useClassicQuizById.d.ts +2 -1
  38. package/src/hooks/useEmbedCodeContainer.d.ts +1 -1
  39. package/src/hooks/useMyParticipation.d.ts +2 -1
  40. package/src/hooks/useScoreStateHelpers.d.ts +3 -2
  41. package/src/index.d.ts +2 -1
  42. package/src/main.d.ts +3 -2
  43. package/src/main.d.ts.map +1 -1
  44. package/src/types/types.d.ts +3 -2
  45. package/src/components/ClassicQuizNotFound.js +0 -55
  46. package/src/components/ClassicQuizPlay.js +0 -321
  47. package/src/components/Leads/CollectLead.js +0 -20
  48. package/src/components/Leads/LeadAgreementCheckbox.js +0 -45
  49. package/src/components/Leads/LeadForm.js +0 -289
  50. package/src/components/Shared/AlertMessage.js +0 -37
  51. package/src/components/Shared/Answers/Answers.js +0 -31
  52. package/src/components/Shared/Answers/Option.js +0 -118
  53. package/src/components/Shared/Button.js +0 -43
  54. package/src/components/Shared/MainCard.js +0 -24
  55. package/src/components/Shared/Pagination.js +0 -118
  56. package/src/components/Shared/PresentedBy.js +0 -51
  57. package/src/components/Shared/ScoreStateWrapper.js +0 -254
  58. package/src/components/Shared/Stepper.js +0 -75
  59. package/src/components/Shared/Stopwatch.js +0 -103
  60. package/src/components/Variants/Overlay/AuthError/OverlayAuthError.js +0 -68
  61. package/src/components/Variants/Overlay/AuthError/OverlayAuthError.styles.js +0 -103
  62. package/src/components/Variants/Overlay/OverlayVariant.js +0 -100
  63. package/src/components/Variants/Overlay/OverlayVariant.styles.js +0 -266
  64. package/src/components/Variants/Overlay/ScoreState/OverlayScoreState.js +0 -90
  65. package/src/components/Variants/Overlay/ScoreState/OverlayScoreState.styles.js +0 -374
  66. package/src/components/Variants/Split/AuthError/SplitAuthError.js +0 -44
  67. package/src/components/Variants/Split/AuthError/SplitAuthError.styles.js +0 -95
  68. package/src/components/Variants/Split/ScoreState/SplitScoreState.js +0 -84
  69. package/src/components/Variants/Split/ScoreState/SplitScoreState.styles.js +0 -400
  70. package/src/components/Variants/Split/SplitVariant.js +0 -79
  71. package/src/components/Variants/Split/SplitVariant.styles.js +0 -216
  72. package/src/components/Variants/Standard/AuthError/StandardAuthError.js +0 -43
  73. package/src/components/Variants/Standard/AuthError/StandardAuthError.styles.js +0 -201
  74. package/src/components/Variants/Standard/ScoreState/StandardScoreState.js +0 -78
  75. package/src/components/Variants/Standard/ScoreState/StandardScoreState.styles.js +0 -349
  76. package/src/components/Variants/Standard/StandardVariant.js +0 -82
  77. package/src/components/Variants/Standard/StandardVariant.styles.js +0 -373
  78. package/src/constants/constants.js +0 -446
  79. package/src/hooks/useClassicQuizById.js +0 -20
  80. package/src/hooks/useEmbedCodeContainer.js +0 -38
  81. package/src/hooks/useMyParticipation.js +0 -22
  82. package/src/hooks/useScoreStateHelpers.js +0 -156
  83. package/src/index.js +0 -2
  84. package/src/main.js +0 -53
  85. package/src/services/service.js +0 -1
  86. package/src/styles/form.styles.js +0 -18
  87. package/src/types/types.js +0 -1
  88. package/tsconfig.tsbuildinfo +0 -1
@@ -1,289 +0,0 @@
1
- import { createElement as _createElement } from "react";
2
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
- import { Autocomplete, AutocompleteOption, Box, Button, FormControl, FormLabel, Input, ListItemContent, ListItemDecorator, Option, Select, Stack, Typography, useTheme, } from "@mui/joy";
4
- import { useState } from "react";
5
- import { useTranslation } from "react-i18next";
6
- import { countries, getDefaultCountryByCode, getDefaultCountryByLanguage, } from "../../constants/constants";
7
- import AlertMessage from "../Shared/AlertMessage";
8
- import { formStyles } from "../../styles/form.styles";
9
- import { ConstantsContext, useConstantContext, useColors, useCornerRadius, useFontFamily, } from "@fansunited/common";
10
- import LeadAgreementCheckbox from "./LeadAgreementCheckbox";
11
- const LeadForm = ({ sdk, brandingColors, brandingUrls, fields = ["fullName", "email"], campaignId = "", campaignName = "", contentType = "", contentId = "", contentName = "", customFields = {}, startGame, submitButtonCta, leadSuccessTitle, leadSuccessDescription, }) => {
12
- const { shadowRootElement, leadPhoneCountryCode, language } = useConstantContext(ConstantsContext);
13
- const [formData, setFormData] = useState({
14
- firstName: "",
15
- lastName: "",
16
- fullName: "",
17
- email: "",
18
- gender: "",
19
- country: "",
20
- phoneCountryCode: leadPhoneCountryCode
21
- ? getDefaultCountryByCode(leadPhoneCountryCode)
22
- : getDefaultCountryByLanguage(language || "en"),
23
- phoneNumber: "",
24
- });
25
- const [isLoading, setIsLoading] = useState(false);
26
- const [isSuccess, setIsSuccess] = useState(false);
27
- const [error, setError] = useState("");
28
- const { t } = useTranslation();
29
- const theme = useTheme();
30
- const textPrimary = useColors().textPrimary;
31
- const primaryColor = brandingColors?.primaryColor || useColors().palette?.primary?.plainColor;
32
- const onPrimaryColor = useColors().palette?.primary?.onPrimary;
33
- const primaryContainer = brandingColors?.primaryColor ||
34
- useColors().palette?.primary?.primaryContainer;
35
- const primaryFont = useFontFamily().primary;
36
- const smBorderRadius = useCornerRadius().sm;
37
- // Light theme colors for consistent styling
38
- const lightThemeColors = {
39
- background: {
40
- surface: theme.colorSchemes.light.palette.background.surface,
41
- popup: theme.colorSchemes.light.palette.background.popup,
42
- },
43
- neutral: {
44
- outlinedBorder: theme.colorSchemes.light.palette.neutral.outlinedBorder,
45
- outlinedColor: theme.colorSchemes.light.palette.neutral.outlinedColor,
46
- outlinedHoverBg: theme.colorSchemes.light.palette.neutral.outlinedHoverBg,
47
- plainActiveBg: theme.colorSchemes.light.palette.neutral.plainActiveBg,
48
- plainHoverBg: theme.colorSchemes.light.palette.neutral.plainHoverBg,
49
- plainHoverColor: theme.colorSchemes.light.palette.neutral.plainHoverColor,
50
- },
51
- };
52
- const genderOptions = [
53
- { value: "male", label: t("leads.form.genderOptions.male") },
54
- { value: "female", label: t("leads.form.genderOptions.female") },
55
- { value: "other", label: t("leads.form.genderOptions.other") },
56
- { value: "prefer_not_to_say", label: t("leads.form.genderOptions.notSay") },
57
- ];
58
- const labelStyles = {
59
- color: `${textPrimary} !important`,
60
- };
61
- const inputStyles = {
62
- fontFamily: primaryFont,
63
- borderRadius: smBorderRadius,
64
- bgcolor: lightThemeColors.background.surface,
65
- borderColor: lightThemeColors.neutral.outlinedBorder,
66
- color: lightThemeColors.neutral.outlinedColor,
67
- "&:hover": {
68
- bgcolor: lightThemeColors.neutral.outlinedHoverBg,
69
- },
70
- "&.Mui-disabled": {
71
- borderColor: lightThemeColors.neutral.outlinedBorder,
72
- },
73
- // Autofill styling override
74
- "& input:-webkit-autofill": {
75
- WebkitBoxShadow: `0 0 0 1000px ${lightThemeColors.background.surface} inset !important`,
76
- WebkitTextFillColor: `${lightThemeColors.neutral.outlinedColor} !important`,
77
- caretColor: lightThemeColors.neutral.outlinedColor,
78
- borderRadius: smBorderRadius,
79
- },
80
- "& input:-webkit-autofill:hover": {
81
- WebkitBoxShadow: `0 0 0 1000px ${lightThemeColors.background.surface} inset !important`,
82
- WebkitTextFillColor: `${lightThemeColors.neutral.outlinedColor} !important`,
83
- },
84
- "& input:-webkit-autofill:focus": {
85
- WebkitBoxShadow: `0 0 0 1000px ${lightThemeColors.background.surface} inset !important`,
86
- WebkitTextFillColor: `${lightThemeColors.neutral.outlinedColor} !important`,
87
- },
88
- "& input:-webkit-autofill:active": {
89
- WebkitBoxShadow: `0 0 0 1000px ${lightThemeColors.background.surface} inset !important`,
90
- WebkitTextFillColor: `${lightThemeColors.neutral.outlinedColor} !important`,
91
- },
92
- // For other browsers (Firefox, etc.)
93
- "& input:-moz-autofill": {
94
- backgroundColor: `${lightThemeColors.background.surface} !important`,
95
- color: `${lightThemeColors.neutral.outlinedColor} !important`,
96
- },
97
- // Additional autofill states
98
- "& input:autofill": {
99
- backgroundColor: `${lightThemeColors.background.surface} !important`,
100
- color: `${lightThemeColors.neutral.outlinedColor} !important`,
101
- },
102
- // "&:focus-within": {
103
- // borderColor:
104
- // brandingColors?.primaryColor ||
105
- // theme.colorSchemes.light.palette.primary.outlinedBorder, //TODO: Should we apply this?
106
- // },
107
- };
108
- const selectStyles = {
109
- root: {
110
- sx: {
111
- ...inputStyles,
112
- "&:hover": {
113
- bgcolor: lightThemeColors.neutral.outlinedHoverBg,
114
- },
115
- },
116
- },
117
- listbox: {
118
- container: shadowRootElement,
119
- sx: {
120
- zIndex: 10,
121
- bgcolor: lightThemeColors.background.popup,
122
- border: `1px solid ${lightThemeColors.neutral.outlinedBorder}`,
123
- borderRadius: smBorderRadius,
124
- boxShadow: "0 4px 6px -1px rgb(0 0 0 / 0.1)",
125
- },
126
- },
127
- };
128
- // Option styles for consistent light theme
129
- const optionStyles = {
130
- fontFamily: primaryFont,
131
- color: `${lightThemeColors.neutral.outlinedColor} !important`,
132
- bgcolor: "transparent",
133
- "&:hover": {
134
- bgcolor: `${lightThemeColors.neutral.plainHoverBg} !important`,
135
- color: `${lightThemeColors.neutral.plainHoverColor} !important`,
136
- },
137
- "&.Mui-selected": {
138
- bgcolor: `${lightThemeColors.neutral.plainActiveBg} !important`,
139
- color: `${lightThemeColors.neutral.outlinedColor} !important`,
140
- },
141
- "&.Mui-selected:hover": {
142
- bgcolor: `${lightThemeColors.neutral.plainActiveBg} !important`,
143
- color: `${lightThemeColors.neutral.outlinedColor} !important`,
144
- },
145
- };
146
- const fullNameLabel = t("leads.form.fullName");
147
- const fullNamePlaceholder = t("leads.form.fullNamePlaceholder");
148
- const firstNameLabel = t("leads.form.firstName");
149
- const firstNamePlaceholder = t("leads.form.firstNamePlaceholder");
150
- const lastNameLabel = t("leads.form.lastName");
151
- const lastNamePlaceholder = t("leads.form.lastNamePlaceholder");
152
- const emailLabel = t("leads.form.email");
153
- const genderLabel = t("leads.form.gender");
154
- const genderPlaceholder = t("leads.form.genderPlaceholder");
155
- const countryLabel = t("leads.form.country");
156
- const countryPlaceholder = t("leads.form.countryPlaceholder");
157
- const phoneNumberLabel = t("leads.form.phone");
158
- const phoneNumberPlaceholder = t("leads.form.phonePlaceholder");
159
- const submitButtonLabel = submitButtonCta ?? t("leads.buttons.submit");
160
- const startButtonLabel = t("classicQuiz.buttons.start");
161
- const handleInputChange = (field) => (e) => {
162
- setFormData((prev) => ({
163
- ...prev,
164
- [field]: e.target.value,
165
- }));
166
- };
167
- const handlePhoneCountryChange = (_event, newValue) => {
168
- setFormData((prev) => ({
169
- ...prev,
170
- phoneCountryCode: newValue,
171
- }));
172
- };
173
- const handleCountryChange = (_event, newValue) => {
174
- setFormData((prev) => ({
175
- ...prev,
176
- country: newValue || "",
177
- }));
178
- };
179
- const handleGenderChange = (_event, newValue) => {
180
- setFormData((prev) => ({
181
- ...prev,
182
- gender: newValue || "",
183
- }));
184
- };
185
- const handleSubmit = async (e) => {
186
- e.preventDefault();
187
- setError("");
188
- const payload = {
189
- firstName: formData.firstName,
190
- lastName: formData.lastName,
191
- fullName: formData.fullName,
192
- email: formData.email,
193
- gender: formData.gender,
194
- country: formData.country,
195
- phoneCountryCode: "+" + formData.phoneCountryCode?.phone,
196
- phoneNumber: formData.phoneNumber,
197
- campaignId,
198
- campaignName,
199
- contentType,
200
- contentId,
201
- contentName,
202
- customFields,
203
- };
204
- // Only filter user input fields, keep campaign and content data
205
- const userInputFields = [
206
- "firstName",
207
- "lastName",
208
- "fullName",
209
- "email",
210
- "gender",
211
- "country",
212
- "phoneCountryCode",
213
- "phoneNumber",
214
- ];
215
- const filteredPayload = Object.fromEntries(Object.entries(payload).map(([key, value]) => {
216
- // If it's a user input field, only include if it's in the fields array
217
- if (userInputFields.includes(key)) {
218
- if (fields.includes(key) && value !== "" && value !== null) {
219
- return [key, value];
220
- }
221
- return [key, null];
222
- }
223
- // Always include non-user input fields (campaign, content, custom fields)
224
- return [key, value];
225
- }));
226
- setIsLoading(true);
227
- try {
228
- await sdk.profile.collectLead(filteredPayload);
229
- setIsSuccess(true);
230
- }
231
- catch (error) {
232
- setError(t("leads.form.error"));
233
- }
234
- finally {
235
- setIsLoading(false);
236
- }
237
- };
238
- return (_jsx("form", { onSubmit: handleSubmit, children: _jsxs(Stack, { spacing: 2, sx: { fontFamily: primaryFont }, children: [fields.includes("fullName") && (_jsxs(FormControl, { required: true, disabled: isSuccess, children: [_jsx(FormLabel, { sx: labelStyles, children: fullNameLabel }), _jsx(Input, { value: formData.fullName, onChange: handleInputChange("fullName"), placeholder: fullNamePlaceholder, sx: inputStyles })] })), fields.includes("firstName") && (_jsxs(FormControl, { required: true, disabled: isSuccess, children: [_jsx(FormLabel, { sx: labelStyles, children: firstNameLabel }), _jsx(Input, { value: formData.firstName, onChange: handleInputChange("firstName"), placeholder: firstNamePlaceholder, sx: inputStyles })] })), fields.includes("lastName") && (_jsxs(FormControl, { required: true, disabled: isSuccess, children: [_jsx(FormLabel, { sx: labelStyles, children: lastNameLabel }), _jsx(Input, { value: formData.lastName, onChange: handleInputChange("lastName"), placeholder: lastNamePlaceholder, sx: inputStyles })] })), fields.includes("email") && (_jsxs(FormControl, { required: true, disabled: isSuccess, children: [_jsx(FormLabel, { sx: labelStyles, children: emailLabel }), _jsx(Input, { type: "email", value: formData.email, onChange: handleInputChange("email"), placeholder: "your.email@example.com", sx: inputStyles })] })), fields.includes("gender") && (_jsxs(FormControl, { disabled: isSuccess, children: [_jsx(FormLabel, { sx: labelStyles, children: genderLabel }), _jsx(Select, { value: formData.gender, onChange: handleGenderChange, placeholder: genderPlaceholder, slotProps: selectStyles, children: genderOptions.map((option) => (_jsx(Option, { value: option.value, sx: optionStyles, children: option.label }, option.value))) })] })), fields.includes("country") && (_jsxs(FormControl, { required: true, disabled: isSuccess, children: [_jsx(FormLabel, { sx: labelStyles, children: countryLabel }), _jsx(Select, { value: formData.country, onChange: handleCountryChange, placeholder: countryPlaceholder, slotProps: selectStyles, children: countries.map((country) => (_jsx(Option, { value: country.code, sx: optionStyles, children: country.label }, `${country.code}-${country.label}`))) })] })), (fields.includes("phoneCountryCode") ||
239
- fields.includes("phoneNumber")) && (_jsxs(FormControl, { required: true, disabled: isSuccess, children: [_jsx(FormLabel, { sx: labelStyles, children: phoneNumberLabel }), _jsxs(Box, { sx: formStyles.phoneContainer, children: [fields.includes("phoneCountryCode") && (_jsx(Autocomplete, { value: formData.phoneCountryCode, onChange: handlePhoneCountryChange, slotProps: {
240
- input: {
241
- autoComplete: "new-phone-country-code",
242
- },
243
- listbox: selectStyles.listbox,
244
- root: selectStyles.root,
245
- clearIndicator: {
246
- sx: {
247
- "&:hover": {
248
- bgcolor: lightThemeColors.neutral.plainHoverBg,
249
- color: lightThemeColors.neutral.plainHoverColor,
250
- },
251
- },
252
- },
253
- popupIndicator: {
254
- sx: {
255
- "&:hover": {
256
- bgcolor: lightThemeColors.neutral.plainHoverBg,
257
- color: lightThemeColors.neutral.plainHoverColor,
258
- },
259
- },
260
- },
261
- }, sx: formStyles.countrySelect, options: countries, autoHighlight: true, getOptionLabel: (option) => `+${option.phone}`, renderOption: (props, option) => (_createElement(AutocompleteOption, { ...props, key: `autocomplete-${option.code}-${option.label}`, sx: {
262
- ...optionStyles,
263
- "&[aria-selected='true']": {
264
- bgcolor: lightThemeColors.neutral.plainActiveBg,
265
- },
266
- } },
267
- _jsx(ListItemDecorator, { children: _jsx("img", { loading: "lazy", width: "20", srcSet: `https://flagcdn.com/w40/${option.code.toLowerCase()}.png 2x`, src: `https://flagcdn.com/w20/${option.code.toLowerCase()}.png`, alt: "" }) }),
268
- _jsxs(ListItemContent, { sx: formStyles.listItemContent, children: [option.label, _jsxs(Typography, { level: "body-xs", children: ["+", option.phone] })] }))) })), fields.includes("phoneNumber") && (_jsx(Input, { value: formData.phoneNumber, onChange: handleInputChange("phoneNumber"), placeholder: phoneNumberPlaceholder, sx: {
269
- ...formStyles.phoneInput,
270
- ...inputStyles,
271
- } }))] })] })), _jsx(LeadAgreementCheckbox, { primaryColor: primaryColor, brandingUrls: brandingUrls, isDisabled: isSuccess }), error && _jsx(AlertMessage, { variant: "error", message: error }), isSuccess ? (_jsxs(_Fragment, { children: [_jsx(AlertMessage, { variant: "success", title: leadSuccessTitle ?? t("leads.success.title"), description: leadSuccessDescription ?? t("leads.success.description") }), startGame ? (_jsx(Button, { size: "lg", sx: {
272
- ...formStyles.submitButton,
273
- bgcolor: primaryColor,
274
- color: onPrimaryColor,
275
- ":hover": {
276
- bgcolor: primaryContainer,
277
- color: onPrimaryColor,
278
- },
279
- }, onClick: startGame, children: startButtonLabel })) : (_jsx(_Fragment, {}))] })) : (_jsx(Button, { type: "submit", loading: isLoading, size: "lg", sx: {
280
- ...formStyles.submitButton,
281
- bgcolor: primaryColor,
282
- color: onPrimaryColor,
283
- ":hover": {
284
- bgcolor: primaryContainer,
285
- color: onPrimaryColor,
286
- },
287
- }, children: submitButtonLabel }))] }) }));
288
- };
289
- export default LeadForm;
@@ -1,37 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { useCornerRadius, useFontFamily, useInternalTheme, } from "@fansunited/common/functions/theme";
3
- import CheckCircleIcon from "@mui/icons-material/CheckCircle";
4
- import InfoIcon from "@mui/icons-material/Info";
5
- import WarningIcon from "@mui/icons-material/Warning";
6
- import { Alert, Stack, Typography } from "@mui/joy";
7
- const getAlertIcon = (variant, warningColor) => {
8
- switch (variant) {
9
- case "success":
10
- return _jsx(CheckCircleIcon, {});
11
- case "error":
12
- return _jsx(WarningIcon, { sx: { color: warningColor } });
13
- case "info":
14
- return _jsx(InfoIcon, {});
15
- }
16
- };
17
- const getAlertColor = (variant) => {
18
- switch (variant) {
19
- case "success":
20
- return "success";
21
- case "error":
22
- return "danger";
23
- case "info":
24
- return "primary";
25
- }
26
- };
27
- const AlertMessage = ({ variant, title, message, description, }) => {
28
- const theme = useInternalTheme();
29
- const borderRadius = useCornerRadius();
30
- const secondaryFontFamily = useFontFamily().secondary;
31
- const alertColor = getAlertColor(variant);
32
- return (_jsx(Alert, { variant: "soft", color: alertColor, startDecorator: getAlertIcon(variant, theme.colorSchemes.light.palette.danger.plainColor), sx: {
33
- gap: 1,
34
- borderRadius: borderRadius.sm,
35
- }, children: _jsxs(Stack, { children: [title && (_jsx(Typography, { level: "title-md", color: alertColor, fontWeight: "bold", sx: { fontFamily: secondaryFontFamily }, children: title })), _jsx(Typography, { level: "body-sm", sx: { fontFamily: secondaryFontFamily }, children: message }), description && (_jsx(Typography, { level: "body-xs", sx: { fontFamily: secondaryFontFamily }, children: description }))] }) }));
36
- };
37
- export default AlertMessage;
@@ -1,31 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { Box } from "@mui/joy";
3
- import Option from "./Option";
4
- const Answers = (props) => {
5
- // Two options per row layout
6
- if (props.twoByTwo) {
7
- // Group options into pairs (two per row)
8
- const rows = [];
9
- for (let i = 0; i < props.options.length; i += 2) {
10
- // For each pair, create a new row
11
- // If there's an odd number of options, the last row will have just one option
12
- const row = props.options.slice(i, i + 2);
13
- rows.push(row);
14
- }
15
- return (_jsx(Box, { sx: { py: 2, display: "flex", flexDirection: "column", gap: 2 }, children: rows.map((row, rowIndex) => (_jsx(Box, { sx: {
16
- display: "flex",
17
- flexDirection: {
18
- xs: "column",
19
- md: "row",
20
- },
21
- gap: 2,
22
- }, children: row.map((option) => (_jsx(Option, { option: option, showAnswer: props.showAnswer, questionImage: props.questionImage, selectedOption: props.selectedOption, answerQuestion: props.answerQuestion, brandingColors: props.brandingColors }, option.optionId))) }, `row-${rowIndex}`))) }));
23
- }
24
- return (_jsx(Box, { sx: {
25
- py: 2,
26
- display: "flex",
27
- flexDirection: { xs: "column", md: "row" },
28
- gap: 2,
29
- }, children: props.options.map((option) => (_jsx(Option, { option: option, showAnswer: props.showAnswer, selectedOption: props.selectedOption, questionImage: props.questionImage, answerQuestion: props.answerQuestion, brandingColors: props.brandingColors }, option.optionId))) }));
30
- };
31
- export default Answers;
@@ -1,118 +0,0 @@
1
- import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { AspectRatio, Box, Typography } from "@mui/joy";
3
- import { useBorderSize, useColors, useCornerRadius, useFontFamily, useSpacingScale, } from "@fansunited/common/functions/theme";
4
- import { useInternalTheme, useImageUrl } from "@fansunited/common";
5
- const Option = (props) => {
6
- const theme = useInternalTheme();
7
- const colors = useColors();
8
- const borderRadius = useCornerRadius().sm;
9
- const fontFamilyPrimary = useFontFamily().primary;
10
- const xsBorderRadius = useCornerRadius().xs;
11
- const borderSize = useBorderSize().size;
12
- const spacingScale = useSpacingScale();
13
- const optionImage = props.questionImage
14
- ? null
15
- : useImageUrl(props.option.images);
16
- const primaryColor = props.brandingColors?.primaryColor || colors.palette.primary.plainColor;
17
- const successColor = colors.palette.success.plainColor;
18
- const dangerColor = colors.palette.danger.plainColor;
19
- const onPrimaryColor = colors.palette.primary.onPrimary;
20
- const lightTextColor = theme.colorSchemes.light.textColor;
21
- const getOptionStyle = (option) => {
22
- if (!props.showAnswer) {
23
- // Not showing correct answer e.g. default styling
24
- return props.selectedOption === option.optionId
25
- ? {
26
- bgcolor: primaryColor,
27
- boxShadow: `inset 0 0 0 ${borderSize} ${primaryColor}`,
28
- color: onPrimaryColor,
29
- }
30
- : {
31
- bgcolor: "#FFFFFF",
32
- color: lightTextColor,
33
- boxShadow: "none",
34
- };
35
- }
36
- if (option.correct) {
37
- // Correct option
38
- return {
39
- bgcolor: successColor,
40
- color: "#fff",
41
- boxShadow: "none",
42
- };
43
- }
44
- if (props.selectedOption === option.optionId && !option.correct) {
45
- // Wrong option
46
- return {
47
- bgcolor: dangerColor,
48
- color: "#fff",
49
- boxShadow: "none",
50
- };
51
- }
52
- return {
53
- bgcolor: "#FFFFFF",
54
- color: lightTextColor,
55
- opacity: props.showAnswer ? 0.6 : 1,
56
- boxShadow: "none",
57
- };
58
- };
59
- const onClick = () => {
60
- if (!props.showAnswer) {
61
- props.answerQuestion(props.option.optionId);
62
- }
63
- };
64
- const { bgcolor, color, opacity, boxShadow } = getOptionStyle(props.option);
65
- return (_jsx(Box, { sx: {
66
- borderRadius,
67
- flex: 1, // Take equal space within the row
68
- p: spacingScale.xs,
69
- gap: spacingScale.xs,
70
- bgcolor,
71
- cursor: props.showAnswer ? "default" : "pointer",
72
- transition: "all 300ms cubic-bezier(0.2, 0, 0, 1)",
73
- transform: "scale(1)",
74
- boxShadow,
75
- // Using boxShadow instead of border to prevent layout shifts
76
- "&:hover": {
77
- transform: props.showAnswer ? "scale(1)" : "scale(1.02)",
78
- // boxShadow: !props.showAnswer
79
- // ? `inset 0 0 0 ${borderSize} ${primaryColor}`
80
- // : boxShadow,
81
- },
82
- "&:active": {
83
- transform: props.showAnswer ? "scale(1)" : "scale(0.98)",
84
- },
85
- // Make the overall container have consistent height
86
- display: "flex",
87
- flexDirection: "column",
88
- opacity: opacity,
89
- }, onClick: onClick, children: optionImage ? (_jsxs(_Fragment, { children: [_jsx(Box, { sx: {
90
- borderRadius: xsBorderRadius,
91
- overflow: "hidden",
92
- flexGrow: 1,
93
- }, children: _jsx(AspectRatio, { ratio: "16/9", sx: { borderRadius: xsBorderRadius }, children: _jsx("img", { src: optionImage, alt: "Option illustration", style: {
94
- width: "100%",
95
- height: "100%",
96
- objectFit: "cover",
97
- } }) }) }), _jsx(Typography, { level: "body-md", sx: {
98
- fontFamily: fontFamilyPrimary,
99
- fontWeight: 500,
100
- fontSize: "0.935rem",
101
- lineHeight: "24px",
102
- letterSpacing: "0.46px",
103
- textAlign: "center",
104
- color,
105
- px: spacingScale["2xs"],
106
- }, children: props.option.option })] })) : (_jsx(Typography, { level: "body-md", sx: {
107
- fontFamily: fontFamilyPrimary,
108
- fontWeight: 500,
109
- fontSize: "0.935rem",
110
- lineHeight: "24px",
111
- letterSpacing: "0.46px",
112
- textAlign: "center",
113
- color,
114
- px: spacingScale["2xs"],
115
- my: "auto",
116
- }, children: props.option.option })) }, props.option.optionId));
117
- };
118
- export default Option;
@@ -1,43 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { Button as JoyButton, Typography } from "@mui/joy";
3
- import { useCornerRadius, useFontFamily, } from "@fansunited/common/functions/theme";
4
- const Button = (props) => {
5
- const fontFamilyPrimary = useFontFamily().primary;
6
- const buttonRadius = useCornerRadius().xl;
7
- return (_jsx(JoyButton, { variant: "soft", disabled: props.selectedOption === null || props.showAnswer, sx: {
8
- borderRadius: buttonRadius,
9
- py: "10px",
10
- pr: "12px",
11
- pl: "16px",
12
- bgcolor: props.buttonColor,
13
- color: "#FFFFFF",
14
- transition: "all 300ms cubic-bezier(0.2, 0, 0, 1)",
15
- transform: "scale(1)",
16
- alignSelf: "center",
17
- "&:hover": {
18
- bgcolor: props.buttonColor,
19
- transform: "scale(1.02)",
20
- },
21
- "&:active": {
22
- color: "#FFFFFF",
23
- transform: "scale(0.98)",
24
- },
25
- "&:disabled": {
26
- bgcolor: "#000000",
27
- color: "#FFFFFF",
28
- opacity: "12%",
29
- },
30
- }, endDecorator: props.endDecorator, onClick: props.onClick, children: _jsx(Typography, { sx: {
31
- fontFamily: fontFamilyPrimary,
32
- fontWeight: 500,
33
- fontSize: "0.9375rem",
34
- lineHeight: "24px",
35
- letterSpacing: "0.46px",
36
- textTransform: "uppercase",
37
- color: "#FFFFFF",
38
- gap: "8px",
39
- display: "flex",
40
- alignItems: "center",
41
- }, children: props.label }) }));
42
- };
43
- export default Button;
@@ -1,24 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { Box } from "@mui/joy";
3
- import { useBorderSize, useColors, useCornerRadius, } from "@fansunited/common/functions/theme";
4
- /**
5
- * MainCard component is a styled container that serves as a main card layout for STANDARD and SPLIT variants.
6
- */
7
- const MainCard = ({ children, brandingBorderColor, }) => {
8
- const mdBorderRadius = useCornerRadius().md;
9
- const borderColor = brandingBorderColor || useColors().secondaryContainer;
10
- const borderSize = useBorderSize().size;
11
- const border = borderSize + " solid " + borderColor;
12
- return (_jsx(Box, { sx: {
13
- display: "flex",
14
- flexDirection: { xs: "column", md: "row" },
15
- width: "100%",
16
- borderRadius: mdBorderRadius,
17
- boxShadow: "md",
18
- border,
19
- overflow: "hidden",
20
- background: useColors().surface,
21
- minHeight: "250px",
22
- }, children: children }));
23
- };
24
- export default MainCard;
@@ -1,118 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { Box, Typography } from "@mui/joy";
3
- import { useInternalTheme } from "@fansunited/common";
4
- import CheckIcon from "@mui/icons-material/Check";
5
- import CloseIcon from "@mui/icons-material/Close";
6
- const Pagination = (props) => {
7
- const renderSteps = () => {
8
- const theme = useInternalTheme();
9
- const borderRadius = theme.customRadius.light.full;
10
- const fontFamilySecondary = theme.customFontFamily.light.secondary;
11
- const totalQuestions = props.classicQuiz.questionsCount;
12
- // Create an array of step indicators
13
- return Array.from({ length: totalQuestions }, (_, index) => {
14
- const questionNumber = index + 1;
15
- // Determine the background, border colors and textColor based on question status
16
- let backgroundColor, borderColor;
17
- let textColor = "#FFFFFF";
18
- if (questionNumber < props.currentQuestion) {
19
- // This question has been answered
20
- const questionParticipation = props.userParticipation.find((p) => p.questionId === props.classicQuiz.questions[index].questionId);
21
- if (questionParticipation) {
22
- // Find if the selected option was correct
23
- const question = props.classicQuiz.questions[index];
24
- const selectedOption = question.options.find((option) => option.optionId === questionParticipation.optionId);
25
- if (selectedOption?.correct) {
26
- // Correct answer
27
- backgroundColor =
28
- theme.colorSchemes.light.palette.success.plainColor;
29
- borderColor =
30
- theme.colorSchemes.light.palette.success.outlinedBorder;
31
- }
32
- else {
33
- // Incorrect answer
34
- backgroundColor =
35
- theme.colorSchemes.light.palette.danger.plainColor;
36
- borderColor =
37
- theme.colorSchemes.light.palette.danger.outlinedBorder;
38
- }
39
- }
40
- else {
41
- // Fallback if participation data is missing
42
- backgroundColor = theme.colorSchemes.light.secondaryContainer;
43
- borderColor = theme.colorSchemes.light.secondaryContainer;
44
- }
45
- }
46
- else if (questionNumber === props.currentQuestion) {
47
- // Current question - use primary color
48
- backgroundColor = theme.colorSchemes.light.palette.primary.plainColor;
49
- borderColor = theme.colorSchemes.light.palette.primary.outlinedBorder;
50
- }
51
- else {
52
- // Future questions - use neutral/secondary color
53
- // backgroundColor = theme.colorSchemes?.light?.secondaryContainer;
54
- // borderColor = theme.colorSchemes?.light?.outlineEnabledBorder;
55
- backgroundColor = "transparent";
56
- borderColor = "transparent";
57
- textColor =
58
- theme.colorSchemes.light.palette.primary.plainColor || "#1A77D2";
59
- }
60
- // Determine what to display inside the circle
61
- let content;
62
- if (questionNumber < props.currentQuestion) {
63
- const questionParticipation = props.userParticipation.find((p) => p.questionId === props.classicQuiz.questions[index].questionId);
64
- if (questionParticipation) {
65
- const question = props.classicQuiz.questions[index];
66
- const selectedOption = question.options.find((option) => option.optionId === questionParticipation.optionId);
67
- if (selectedOption?.correct) {
68
- // Show checkmark for correct answer
69
- content = (_jsx(CheckIcon, { sx: {
70
- color: "#FAFAFA",
71
- fontSize: "1rem",
72
- } }));
73
- }
74
- else {
75
- // Show X for incorrect answer
76
- content = (_jsx(CloseIcon, { sx: {
77
- color: "#FAFAFA",
78
- fontSize: "1rem",
79
- } }));
80
- }
81
- }
82
- else {
83
- // Fallback
84
- content = questionNumber;
85
- }
86
- }
87
- else {
88
- // For current and future questions, show the question number
89
- content = questionNumber;
90
- }
91
- return (_jsx(Box, { sx: {
92
- maxWidth: "40px",
93
- width: "100%",
94
- height: "40px",
95
- borderRadius,
96
- backgroundColor,
97
- border: `1px solid ${borderColor}`,
98
- transition: "background-color 0.3s ease",
99
- display: "flex",
100
- alignItems: "center",
101
- justifyContent: "center",
102
- fontFamily: fontFamilySecondary,
103
- }, children: typeof content === "number" ? (_jsx(Typography, { level: "body-md", sx: {
104
- fontWeight: 400,
105
- lineHeight: "150%",
106
- letterSpacing: "0.15px",
107
- fontSize: "1rem",
108
- color: textColor,
109
- }, children: content })) : (content) }, `step-${questionNumber}`));
110
- });
111
- };
112
- return (_jsx(Box, { sx: {
113
- display: "flex",
114
- justifyContent: "center",
115
- gap: "8px",
116
- }, children: renderSteps() }));
117
- };
118
- export default Pagination;