@constructor-io/constructorio-ui-quizzes 1.8.3 → 1.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/constructorio-ui-quizzes-bundled.js +14 -14
- package/lib/cjs/package.json +1 -1
- package/lib/cjs/src/components/CioQuiz/actions.js +1 -0
- package/lib/cjs/src/components/CioQuiz/index.js +2 -1
- package/lib/cjs/src/components/CioQuiz/quizLocalReducer.js +21 -0
- package/lib/cjs/src/components/ControlBar/ControlBar.js +5 -2
- package/lib/cjs/src/components/ResultFavoritesButton/ResultFavoritesButton.js +2 -2
- package/lib/cjs/src/components/SkipButton/SkipButton.js +13 -0
- package/lib/cjs/src/constants.js +10 -1
- package/lib/cjs/src/hooks/usePropsGetters/index.js +10 -7
- package/lib/cjs/src/hooks/usePropsGetters/useAddToFavoritesButtonProps.js +10 -18
- package/lib/cjs/src/hooks/usePropsGetters/useSkipQuestionButtonProps.js +21 -0
- package/lib/cjs/src/hooks/useQuiz.js +2 -2
- package/lib/cjs/src/hooks/useQuizEvents/index.js +3 -0
- package/lib/cjs/src/hooks/useQuizEvents/useQuizSkipClick.js +31 -0
- package/lib/cjs/src/stories/Quiz/tests/mocks.js +1 -0
- package/lib/cjs/src/utils.js +10 -1
- package/lib/mjs/package.json +1 -1
- package/lib/mjs/src/components/CioQuiz/actions.js +1 -0
- package/lib/mjs/src/components/CioQuiz/index.js +2 -1
- package/lib/mjs/src/components/CioQuiz/quizLocalReducer.js +25 -0
- package/lib/mjs/src/components/ControlBar/ControlBar.js +5 -2
- package/lib/mjs/src/components/ResultFavoritesButton/ResultFavoritesButton.js +2 -2
- package/lib/mjs/src/components/SkipButton/SkipButton.js +10 -0
- package/lib/mjs/src/constants.js +9 -0
- package/lib/mjs/src/hooks/usePropsGetters/index.js +10 -7
- package/lib/mjs/src/hooks/usePropsGetters/useAddToFavoritesButtonProps.js +6 -10
- package/lib/mjs/src/hooks/usePropsGetters/useSkipQuestionButtonProps.js +17 -0
- package/lib/mjs/src/hooks/useQuiz.js +2 -2
- package/lib/mjs/src/hooks/useQuizEvents/index.js +3 -0
- package/lib/mjs/src/hooks/useQuizEvents/useQuizSkipClick.js +31 -0
- package/lib/mjs/src/stories/Quiz/tests/mocks.js +4 -0
- package/lib/mjs/src/utils.js +10 -1
- package/lib/styles.css +47 -3
- package/lib/types/src/components/CioQuiz/actions.d.ts +2 -1
- package/lib/types/src/components/CioQuiz/context.d.ts +2 -1
- package/lib/types/src/components/SkipButton/SkipButton.d.ts +6 -0
- package/lib/types/src/constants.d.ts +3 -2
- package/lib/types/src/hooks/usePropsGetters/index.d.ts +3 -2
- package/lib/types/src/hooks/usePropsGetters/useAddToFavoritesButtonProps.d.ts +1 -1
- package/lib/types/src/hooks/usePropsGetters/useSkipQuestionButtonProps.d.ts +3 -0
- package/lib/types/src/hooks/useQuizEvents/useQuizSkipClick.d.ts +6 -0
- package/lib/types/src/stories/Quiz/tests/mocks.d.ts +2 -2
- package/lib/types/src/types.d.ts +17 -4
- package/lib/types/src/utils.d.ts +1 -0
- package/package.json +1 -1
package/lib/cjs/package.json
CHANGED
|
@@ -9,6 +9,7 @@ var QuestionTypes;
|
|
|
9
9
|
QuestionTypes["SingleSelect"] = "single";
|
|
10
10
|
QuestionTypes["MultipleSelect"] = "multiple";
|
|
11
11
|
QuestionTypes["Next"] = "next";
|
|
12
|
+
QuestionTypes["Skip"] = "skip";
|
|
12
13
|
QuestionTypes["Back"] = "back";
|
|
13
14
|
QuestionTypes["Reset"] = "reset";
|
|
14
15
|
QuestionTypes["Hydrate"] = "hydrate";
|
|
@@ -14,7 +14,7 @@ const utils_1 = require("../../utils");
|
|
|
14
14
|
const ProgressBar_1 = tslib_1.__importDefault(require("../ProgressBar/ProgressBar"));
|
|
15
15
|
function CioQuiz(props) {
|
|
16
16
|
var _a;
|
|
17
|
-
const { cioClient, state, events: { hydrateQuiz, resetSessionStorageState }, getAddToCartButtonProps, getAddToFavoritesButtonProps, getCoverQuestionProps, getHydrateQuizButtonProps, getNextQuestionButtonProps, getOpenTextInputProps, getPreviousQuestionButtonProps, getQuizImageProps, getQuizResultButtonProps, getQuizResultLinkProps, getResetQuizButtonProps, getSelectInputProps, primaryColorStyles, } = (0, useQuiz_1.default)(props);
|
|
17
|
+
const { cioClient, state, events: { hydrateQuiz, resetSessionStorageState }, getAddToCartButtonProps, getAddToFavoritesButtonProps, getCoverQuestionProps, getHydrateQuizButtonProps, getNextQuestionButtonProps, getSkipQuestionButtonProps, getOpenTextInputProps, getPreviousQuestionButtonProps, getQuizImageProps, getQuizResultButtonProps, getQuizResultLinkProps, getResetQuizButtonProps, getSelectInputProps, primaryColorStyles, } = (0, useQuiz_1.default)(props);
|
|
18
18
|
const [showSessionPrompt, setShowSessionPrompt] = (0, react_1.useState)(false);
|
|
19
19
|
const { resultsPageOptions, sessionStateOptions } = props;
|
|
20
20
|
const { quizSessionStorageState: { hasSessionStorageState, skipToResults }, } = state;
|
|
@@ -36,6 +36,7 @@ function CioQuiz(props) {
|
|
|
36
36
|
getCoverQuestionProps,
|
|
37
37
|
getHydrateQuizButtonProps,
|
|
38
38
|
getNextQuestionButtonProps,
|
|
39
|
+
getSkipQuestionButtonProps,
|
|
39
40
|
getOpenTextInputProps,
|
|
40
41
|
getPreviousQuestionButtonProps,
|
|
41
42
|
getQuizImageProps,
|
|
@@ -51,6 +51,27 @@ function quizLocalReducer(state, action) {
|
|
|
51
51
|
// We now commit current answers to prevAnswerInputs
|
|
52
52
|
prevAnswerInputs: answerInputs, answers: newAnswers, isQuizCompleted: false });
|
|
53
53
|
}
|
|
54
|
+
case actions_1.QuestionTypes.Skip: {
|
|
55
|
+
const { answers, answerInputs } = state;
|
|
56
|
+
const newAnswers = [...answers];
|
|
57
|
+
const lastAnswerInputIndex = answers.length;
|
|
58
|
+
const currentAnswerInput = Object.values(state.answerInputs)[lastAnswerInputIndex];
|
|
59
|
+
switch (currentAnswerInput.type) {
|
|
60
|
+
case actions_1.QuestionTypes.OpenText:
|
|
61
|
+
newAnswers.push(['false']);
|
|
62
|
+
break;
|
|
63
|
+
case actions_1.QuestionTypes.Cover:
|
|
64
|
+
newAnswers.push(['seen']);
|
|
65
|
+
break;
|
|
66
|
+
case actions_1.QuestionTypes.SingleSelect:
|
|
67
|
+
case actions_1.QuestionTypes.MultipleSelect:
|
|
68
|
+
default:
|
|
69
|
+
newAnswers.push([]);
|
|
70
|
+
}
|
|
71
|
+
return Object.assign(Object.assign({}, state), {
|
|
72
|
+
// We now commit current answers to prevAnswerInputs
|
|
73
|
+
prevAnswerInputs: answerInputs, answers: newAnswers, isQuizCompleted: false });
|
|
74
|
+
}
|
|
54
75
|
case actions_1.QuestionTypes.Back: {
|
|
55
76
|
const prevAnswerInputs = Object.assign({}, state.prevAnswerInputs);
|
|
56
77
|
return Object.assign(Object.assign({}, state), { answerInputs: prevAnswerInputs, answers: [...state.answers.slice(0, -1)], isLastAnswer: false, isQuizCompleted: false });
|
|
@@ -4,12 +4,15 @@ const tslib_1 = require("tslib");
|
|
|
4
4
|
const react_1 = tslib_1.__importStar(require("react"));
|
|
5
5
|
const BackButton_1 = tslib_1.__importDefault(require("../BackButton/BackButton"));
|
|
6
6
|
const CTAButton_1 = tslib_1.__importDefault(require("../CTAButton/CTAButton"));
|
|
7
|
+
const SkipButton_1 = tslib_1.__importDefault(require("../SkipButton/SkipButton"));
|
|
7
8
|
const context_1 = tslib_1.__importDefault(require("../CioQuiz/context"));
|
|
8
9
|
function ControlBar(props) {
|
|
9
10
|
const { ctaButtonText } = props;
|
|
10
|
-
const { getNextQuestionButtonProps } = (0, react_1.useContext)(context_1.default);
|
|
11
|
+
const { getNextQuestionButtonProps, getSkipQuestionButtonProps } = (0, react_1.useContext)(context_1.default);
|
|
11
12
|
return (react_1.default.createElement("div", { className: 'cio-question-buttons-container' },
|
|
12
13
|
react_1.default.createElement(BackButton_1.default, null),
|
|
13
|
-
react_1.default.createElement(
|
|
14
|
+
react_1.default.createElement("div", { className: 'cio-question-buttons-group' },
|
|
15
|
+
react_1.default.createElement(SkipButton_1.default, { propsGetters: getSkipQuestionButtonProps }),
|
|
16
|
+
react_1.default.createElement(CTAButton_1.default, { ctaText: ctaButtonText, propsGetters: getNextQuestionButtonProps }))));
|
|
14
17
|
}
|
|
15
18
|
exports.default = ControlBar;
|
|
@@ -10,8 +10,8 @@ function ResultFavoritesButton(props) {
|
|
|
10
10
|
return (
|
|
11
11
|
// eslint-disable-next-line react/button-has-type
|
|
12
12
|
react_1.default.createElement("button", Object.assign({}, getAddToFavoritesButtonProps(item, price)),
|
|
13
|
-
react_1.default.createElement("svg", {
|
|
14
|
-
react_1.default.createElement("path", { d: '
|
|
13
|
+
react_1.default.createElement("svg", { width: '21', height: '21', viewBox: '0 0 24 24', strokeWidth: '2', strokeLinecap: 'round', strokeLinejoin: 'round' },
|
|
14
|
+
react_1.default.createElement("path", { d: 'M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z' }))));
|
|
15
15
|
}
|
|
16
16
|
return null;
|
|
17
17
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
const react_1 = tslib_1.__importDefault(require("react"));
|
|
5
|
+
function SkipButton(props) {
|
|
6
|
+
const { propsGetters, className = 'cio-button-container' } = props, rest = tslib_1.__rest(props, ["propsGetters", "className"]);
|
|
7
|
+
return (react_1.default.createElement("div", { className: `${className || ''}` }, propsGetters && (
|
|
8
|
+
// eslint-disable-next-line react/button-has-type
|
|
9
|
+
react_1.default.createElement("button", Object.assign({}, rest, propsGetters()),
|
|
10
|
+
"Skip",
|
|
11
|
+
react_1.default.createElement("span", null, " question")))));
|
|
12
|
+
}
|
|
13
|
+
exports.default = SkipButton;
|
package/lib/cjs/src/constants.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.RequestStates = exports.callbacksDescription = exports.changePrimaryColorDescription = exports.smallContainerDescription = exports.cioJsClientDescription = exports.basicDescription = exports.hookDescription = exports.componentDescription = exports.quizSessionStateKey = exports.quizId = exports.apiKey = void 0;
|
|
3
|
+
exports.RequestStates = exports.favoritesDescription = exports.callbacksDescription = exports.changePrimaryColorDescription = exports.smallContainerDescription = exports.cioJsClientDescription = exports.basicDescription = exports.hookDescription = exports.componentDescription = exports.quizSessionStateKey = exports.quizId = exports.apiKey = void 0;
|
|
4
4
|
// Autocomplete key index
|
|
5
5
|
exports.apiKey = 'key_wJSdZSiesX5hiVLt';
|
|
6
6
|
exports.quizId = 'coffee-quiz';
|
|
@@ -25,6 +25,7 @@ exports.componentDescription = `- import \`CioQuiz\` to render in your JSX.
|
|
|
25
25
|
- \`numResultsToDisplay\` is an optional parameter that determines how many results should be displayed on results page
|
|
26
26
|
- \`callbacks\` lets you pass callback functions that will be called on certain actions
|
|
27
27
|
- \`onQuizNextQuestion\` is an optional callback function that will be called when user moves to the next question
|
|
28
|
+
- \`onQuizSkipQuestion\` is an optional callback function that will be called when user skips a question
|
|
28
29
|
- \`sessionStateOptions\` lets you configure the session modal behavior
|
|
29
30
|
- \`showSessionModal\` is a boolean used to decide whether to show the session modal. The default behavior is to show the session modal
|
|
30
31
|
- \`showSessionModalOnResults\` is a boolean to decide whether to show the session modal after reaching the results page. The default behavior is to not show the session modal
|
|
@@ -57,6 +58,7 @@ const {
|
|
|
57
58
|
getCoverQuestionProps: () => ({...})), // prop getter for jsx quiz cover question,
|
|
58
59
|
getHydrateQuizButtonProps: () => ({...})), // prop getter for jsx hydrate quiz button,
|
|
59
60
|
getNextQuestionButtonProps: () => ({...})), // prop getter for jsx next button to traverse the quiz,
|
|
61
|
+
getSkipQuestionButtonProps: () => ({...})), // prop getter for jsx skip button to traverse the quiz,
|
|
60
62
|
getPreviousQuestionButtonProps: () => ({...})), // prop getter for jsx back button to traverse the quiz,
|
|
61
63
|
getOpenTextInputProps: () => ({...})), // prop getter for jsx open text input,
|
|
62
64
|
getSelectInputProps: () => ({...})), // prop getter for jsx select input for select type questions,
|
|
@@ -90,6 +92,13 @@ In the example below, the \`primaryColor\` prop has been used to override this c
|
|
|
90
92
|
> Advanced Option: Instead of passing a primaryColor prop, you can also override \`--primary-color-h\`, \`--primary-color-s\`, and \`--primary-color-l\` CSS variables within a \`.cio-quiz\` container element. If explicitly given a value in your CSS, then the values of these variables will be used as the HSL values for your quiz.
|
|
91
93
|
`;
|
|
92
94
|
exports.callbacksDescription = `Pass an \`apiKey\`, a \`quizId\`, and \`callbacks\``;
|
|
95
|
+
exports.favoritesDescription = `
|
|
96
|
+
Add \`const [favorites, setFavorites] = useState([]);\` or equivalent to manage the favorite items' state.
|
|
97
|
+
|
|
98
|
+
Pass favorites as an array to \`favoriteItems\` in \`resultsPageOptions\` as a prop to CioQuiz.
|
|
99
|
+
|
|
100
|
+
Pass a callback function to \`onAddToFavoritesClick\` in \`resultsPageOptions\` as a prop to CioQuiz to handle favorites state changes to update \`favorites\` array.
|
|
101
|
+
`;
|
|
93
102
|
var RequestStates;
|
|
94
103
|
(function (RequestStates) {
|
|
95
104
|
RequestStates["Stale"] = "STALE";
|
|
@@ -8,13 +8,15 @@ const useOpenTextInputProps_1 = tslib_1.__importDefault(require("./useOpenTextIn
|
|
|
8
8
|
const useNextQuestionButtonProps_1 = tslib_1.__importDefault(require("./useNextQuestionButtonProps"));
|
|
9
9
|
const usePreviousQuestionButtonProps_1 = tslib_1.__importDefault(require("./usePreviousQuestionButtonProps"));
|
|
10
10
|
const useAddToFavoritesButtonProps_1 = tslib_1.__importDefault(require("./useAddToFavoritesButtonProps"));
|
|
11
|
-
const
|
|
11
|
+
const useSkipQuestionButtonProps_1 = tslib_1.__importDefault(require("./useSkipQuestionButtonProps"));
|
|
12
|
+
const usePropsGetters = (quizEvents, quizApiState, quizLocalState, favoriteItems) => {
|
|
12
13
|
var _a, _b, _c;
|
|
13
|
-
const { quizAnswerChanged, nextQuestion, previousQuestion, resetQuiz, hydrateQuiz, addToCart, addToFavorites, resultClick, } = quizEvents;
|
|
14
|
+
const { quizAnswerChanged, nextQuestion, skipQuestion, previousQuestion, resetQuiz, hydrateQuiz, addToCart, addToFavorites, resultClick, } = quizEvents;
|
|
14
15
|
const getOpenTextInputProps = (0, useOpenTextInputProps_1.default)(quizAnswerChanged, nextQuestion, (_a = quizApiState.quizCurrentQuestion) === null || _a === void 0 ? void 0 : _a.next_question, quizLocalState.answerInputs);
|
|
15
16
|
const getCoverQuestionProps = (0, useCoverQuestionProps_1.default)(quizAnswerChanged, (_b = quizApiState.quizCurrentQuestion) === null || _b === void 0 ? void 0 : _b.next_question);
|
|
16
17
|
const getSelectInputProps = (0, useSelectInputProps_1.default)(quizAnswerChanged, nextQuestion, (_c = quizApiState.quizCurrentQuestion) === null || _c === void 0 ? void 0 : _c.next_question, quizLocalState.answerInputs);
|
|
17
18
|
const getNextQuestionButtonProps = (0, useNextQuestionButtonProps_1.default)(nextQuestion, quizApiState, quizLocalState);
|
|
19
|
+
const getSkipQuestionButtonProps = (0, useSkipQuestionButtonProps_1.default)(skipQuestion, quizApiState);
|
|
18
20
|
const getPreviousQuestionButtonProps = (0, usePreviousQuestionButtonProps_1.default)(quizApiState, previousQuestion);
|
|
19
21
|
const getResetQuizButtonProps = (0, react_1.useCallback)((stylesType = 'primary') => ({
|
|
20
22
|
className: stylesType === 'primary' ? 'cio-question-cta-button' : 'cio-question-redo-button',
|
|
@@ -31,7 +33,7 @@ const usePropsGetters = (quizEvents, quizApiState, quizLocalState) => {
|
|
|
31
33
|
type: 'button',
|
|
32
34
|
onClick: (e) => addToCart(e, result, price),
|
|
33
35
|
}), [addToCart]);
|
|
34
|
-
const getAddToFavoritesButtonProps = (0, useAddToFavoritesButtonProps_1.default)(addToFavorites);
|
|
36
|
+
const getAddToFavoritesButtonProps = (0, useAddToFavoritesButtonProps_1.default)(addToFavorites, favoriteItems);
|
|
35
37
|
const quizResultClickDown = (0, react_1.useCallback)((event, result, position) => {
|
|
36
38
|
if ((event === null || event === void 0 ? void 0 : event.key) === ' ' || (event === null || event === void 0 ? void 0 : event.key) === 'Enter') {
|
|
37
39
|
if (resultClick) {
|
|
@@ -57,16 +59,16 @@ const usePropsGetters = (quizEvents, quizApiState, quizLocalState) => {
|
|
|
57
59
|
const getQuizImageProps = (0, react_1.useCallback)(() => {
|
|
58
60
|
var _a, _b, _c, _d, _e, _f;
|
|
59
61
|
return ({
|
|
60
|
-
src: (_c = (_b = (_a = quizApiState.quizCurrentQuestion) === null || _a === void 0 ? void 0 : _a.next_question) === null || _b === void 0 ? void 0 : _b.images) === null || _c === void 0 ? void 0 : _c.primary_url,
|
|
61
|
-
alt: (_f = (_e = (_d = quizApiState.quizCurrentQuestion) === null || _d === void 0 ? void 0 : _d.next_question) === null || _e === void 0 ? void 0 : _e.images) === null || _f === void 0 ? void 0 : _f.primary_alt,
|
|
62
|
+
src: ((_c = (_b = (_a = quizApiState.quizCurrentQuestion) === null || _a === void 0 ? void 0 : _a.next_question) === null || _b === void 0 ? void 0 : _b.images) === null || _c === void 0 ? void 0 : _c.primary_url) || undefined,
|
|
63
|
+
alt: ((_f = (_e = (_d = quizApiState.quizCurrentQuestion) === null || _d === void 0 ? void 0 : _d.next_question) === null || _e === void 0 ? void 0 : _e.images) === null || _f === void 0 ? void 0 : _f.primary_alt) || undefined,
|
|
62
64
|
});
|
|
63
65
|
}, [quizApiState.quizCurrentQuestion]);
|
|
64
66
|
const getSelectQuestionImageProps = (0, react_1.useCallback)((option) => {
|
|
65
67
|
var _a, _b;
|
|
66
68
|
return ({
|
|
67
69
|
className: 'cio-question-option-image',
|
|
68
|
-
src: (_a = option === null || option === void 0 ? void 0 : option.images) === null || _a === void 0 ? void 0 : _a.primary_url,
|
|
69
|
-
alt: (_b = option === null || option === void 0 ? void 0 : option.images) === null || _b === void 0 ? void 0 : _b.primary_alt,
|
|
70
|
+
src: ((_a = option === null || option === void 0 ? void 0 : option.images) === null || _a === void 0 ? void 0 : _a.primary_url) || undefined,
|
|
71
|
+
alt: ((_b = option === null || option === void 0 ? void 0 : option.images) === null || _b === void 0 ? void 0 : _b.primary_alt) || undefined,
|
|
70
72
|
});
|
|
71
73
|
}, []);
|
|
72
74
|
return {
|
|
@@ -83,6 +85,7 @@ const usePropsGetters = (quizEvents, quizApiState, quizLocalState) => {
|
|
|
83
85
|
getAddToFavoritesButtonProps,
|
|
84
86
|
getQuizResultButtonProps,
|
|
85
87
|
getQuizResultLinkProps,
|
|
88
|
+
getSkipQuestionButtonProps,
|
|
86
89
|
};
|
|
87
90
|
};
|
|
88
91
|
exports.default = usePropsGetters;
|
|
@@ -1,25 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const react_1 = require("react");
|
|
4
|
-
function useAddToFavoritesButtonProps(addToFavorites) {
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
onClick: (e) => {
|
|
14
|
-
var _a, _b;
|
|
15
|
-
addToFavorites(e, result, price, !(favorited === null || favorited === void 0 ? void 0 : favorited[((_a = result === null || result === void 0 ? void 0 : result.data) === null || _a === void 0 ? void 0 : _a.id) || '0']));
|
|
16
|
-
toggleIdFavorited(((_b = result === null || result === void 0 ? void 0 : result.data) === null || _b === void 0 ? void 0 : _b.id) || '0');
|
|
17
|
-
},
|
|
18
|
-
type: 'button',
|
|
19
|
-
});
|
|
20
|
-
},
|
|
4
|
+
function useAddToFavoritesButtonProps(addToFavorites, favoriteItems) {
|
|
5
|
+
const isResultFavorited = (result) => { var _a, _b; return ((_a = result === null || result === void 0 ? void 0 : result.data) === null || _a === void 0 ? void 0 : _a.id) && (favoriteItems === null || favoriteItems === void 0 ? void 0 : favoriteItems.includes((_b = result === null || result === void 0 ? void 0 : result.data) === null || _b === void 0 ? void 0 : _b.id)); };
|
|
6
|
+
const getAddToFavoritesButtonProps = (0, react_1.useCallback)((result, price) => ({
|
|
7
|
+
className: `${'cio-result-card-favorites-button'} ${isResultFavorited(result) ? 'favorited' : ''}`,
|
|
8
|
+
onClick: (e) => {
|
|
9
|
+
addToFavorites(e, result, price, !isResultFavorited(result));
|
|
10
|
+
},
|
|
11
|
+
type: 'button',
|
|
12
|
+
}),
|
|
21
13
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
22
|
-
[
|
|
14
|
+
[addToFavorites]);
|
|
23
15
|
return getAddToFavoritesButtonProps;
|
|
24
16
|
}
|
|
25
17
|
exports.default = useAddToFavoritesButtonProps;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const react_1 = require("react");
|
|
4
|
+
function useSkipQuestionButtonProps(skipQuestion, quizApiState) {
|
|
5
|
+
const getSkipQuestionButtonProps = (0, react_1.useCallback)(() => {
|
|
6
|
+
var _a, _b, _c, _d;
|
|
7
|
+
const currentQuestionId = (_b = (_a = quizApiState.quizCurrentQuestion) === null || _a === void 0 ? void 0 : _a.next_question) === null || _b === void 0 ? void 0 : _b.id;
|
|
8
|
+
const isHidden = currentQuestionId &&
|
|
9
|
+
(((_c = quizApiState.quizCurrentQuestion) === null || _c === void 0 ? void 0 : _c.isCoverQuestion) ||
|
|
10
|
+
!((_d = quizApiState.quizCurrentQuestion) === null || _d === void 0 ? void 0 : _d.next_question.is_skippable));
|
|
11
|
+
return {
|
|
12
|
+
className: isHidden ? 'cio-question-skip-button hide' : 'cio-question-skip-button',
|
|
13
|
+
type: 'button',
|
|
14
|
+
onClick: () => {
|
|
15
|
+
skipQuestion();
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
}, [quizApiState.quizCurrentQuestion, skipQuestion]);
|
|
19
|
+
return getSkipQuestionButtonProps;
|
|
20
|
+
}
|
|
21
|
+
exports.default = useSkipQuestionButtonProps;
|
|
@@ -9,7 +9,7 @@ const usePrimaryColorStyles_1 = tslib_1.__importDefault(require("./usePrimaryCol
|
|
|
9
9
|
const useQuizEvents_1 = tslib_1.__importDefault(require("./useQuizEvents"));
|
|
10
10
|
const useQuizState_1 = tslib_1.__importDefault(require("./useQuizState"));
|
|
11
11
|
const useQuiz = (quizOptions) => {
|
|
12
|
-
const { apiKey, cioJsClient, primaryColor } = quizOptions;
|
|
12
|
+
const { apiKey, cioJsClient, primaryColor, resultsPageOptions: { favoriteItems }, } = quizOptions;
|
|
13
13
|
// Log console errors for required parameters quizId and resultsPageOptions
|
|
14
14
|
(0, useConsoleErrors_1.default)(quizOptions);
|
|
15
15
|
// Quiz Cio Client
|
|
@@ -21,7 +21,7 @@ const useQuiz = (quizOptions) => {
|
|
|
21
21
|
// Props getters
|
|
22
22
|
const { quizApiState, quizLocalState, quizSessionStorageState } = quizState;
|
|
23
23
|
const { skipToResults } = quizSessionStorageState;
|
|
24
|
-
const propGetters = (0, usePropsGetters_1.default)(quizEvents, quizApiState, quizLocalState);
|
|
24
|
+
const propGetters = (0, usePropsGetters_1.default)(quizEvents, quizApiState, quizLocalState, favoriteItems);
|
|
25
25
|
const primaryColorStyles = (0, usePrimaryColorStyles_1.default)(primaryColor);
|
|
26
26
|
(0, react_1.useEffect)(() => {
|
|
27
27
|
if (skipToResults)
|
|
@@ -11,6 +11,7 @@ const useQuizResetClick_1 = tslib_1.__importDefault(require("./useQuizResetClick
|
|
|
11
11
|
const useHydrateQuizLocalState_1 = tslib_1.__importDefault(require("./useHydrateQuizLocalState"));
|
|
12
12
|
const utils_1 = require("../../utils");
|
|
13
13
|
const useQuizAddToFavorites_1 = tslib_1.__importDefault(require("./useQuizAddToFavorites"));
|
|
14
|
+
const useQuizSkipClick_1 = tslib_1.__importDefault(require("./useQuizSkipClick"));
|
|
14
15
|
const useQuizEvents = (quizOptions, cioClient, quizState) => {
|
|
15
16
|
const { quizApiState, dispatchLocalState, dispatchApiState, quizLocalState, quizSessionStorageState, } = quizState;
|
|
16
17
|
const { resultsPageOptions, callbacks } = quizOptions;
|
|
@@ -19,6 +20,7 @@ const useQuizEvents = (quizOptions, cioClient, quizState) => {
|
|
|
19
20
|
const quizAnswerChanged = (0, useQuizAnswerChangeHandler_1.default)(quizApiState, dispatchLocalState);
|
|
20
21
|
// Quiz Next button click callback
|
|
21
22
|
const nextQuestion = (0, useQuizNextClick_1.default)(quizApiState, quizLocalState, dispatchLocalState, callbacks === null || callbacks === void 0 ? void 0 : callbacks.onQuizNextQuestion);
|
|
23
|
+
const skipQuestion = (0, useQuizSkipClick_1.default)(quizApiState, quizLocalState, dispatchLocalState, callbacks === null || callbacks === void 0 ? void 0 : callbacks.onQuizSkipQuestion);
|
|
22
24
|
// Quiz Back button click callback
|
|
23
25
|
const previousQuestion = (0, useQuizBackClick_1.default)(quizApiState, dispatchLocalState);
|
|
24
26
|
// Quiz result add to cart callback
|
|
@@ -39,6 +41,7 @@ const useQuizEvents = (quizOptions, cioClient, quizState) => {
|
|
|
39
41
|
quizAnswerChanged,
|
|
40
42
|
previousQuestion,
|
|
41
43
|
nextQuestion,
|
|
44
|
+
skipQuestion,
|
|
42
45
|
resetQuiz,
|
|
43
46
|
hydrateQuiz: hydrateQuizLocalState,
|
|
44
47
|
resetSessionStorageState: (0, utils_1.resetQuizSessionStorageState)(quizSessionStorageState.key),
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const react_1 = require("react");
|
|
4
|
+
const actions_1 = require("../../components/CioQuiz/actions");
|
|
5
|
+
const utils_1 = require("../../utils");
|
|
6
|
+
const useQuizSkipClick = (quizApiState, quizLocalState, dispatchLocalState, onQuizSkipQuestion) => {
|
|
7
|
+
const quizSkipClickHandler = (0, react_1.useCallback)(() => {
|
|
8
|
+
var _a;
|
|
9
|
+
const currentQuestion = (_a = quizApiState.quizCurrentQuestion) === null || _a === void 0 ? void 0 : _a.next_question;
|
|
10
|
+
const currentQuestionId = currentQuestion === null || currentQuestion === void 0 ? void 0 : currentQuestion.id;
|
|
11
|
+
if (dispatchLocalState && currentQuestionId) {
|
|
12
|
+
if (!((currentQuestion === null || currentQuestion === void 0 ? void 0 : currentQuestion.type) === 'cover')) {
|
|
13
|
+
dispatchLocalState({
|
|
14
|
+
type: actions_1.QuestionTypes.Skip,
|
|
15
|
+
payload: quizApiState.quizCurrentQuestion,
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
const currentAnswerInput = Object.assign(Object.assign({}, quizLocalState.answerInputs[currentQuestionId]), { value: (currentQuestion === null || currentQuestion === void 0 ? void 0 : currentQuestion.type) === 'open' ? 'false' : null });
|
|
19
|
+
if (currentQuestion && (0, utils_1.isFunction)(onQuizSkipQuestion)) {
|
|
20
|
+
onQuizSkipQuestion(Object.assign(Object.assign({}, currentQuestion), { answer: currentAnswerInput }));
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}, [
|
|
24
|
+
dispatchLocalState,
|
|
25
|
+
onQuizSkipQuestion,
|
|
26
|
+
quizApiState.quizCurrentQuestion,
|
|
27
|
+
quizLocalState.answerInputs,
|
|
28
|
+
]);
|
|
29
|
+
return quizSkipClickHandler;
|
|
30
|
+
};
|
|
31
|
+
exports.default = useQuizSkipClick;
|
|
@@ -153,6 +153,7 @@ const useMockContextValue = (question) => {
|
|
|
153
153
|
getAddToFavoritesButtonProps: () => (Object.assign(Object.assign({}, mockElementProps), { className: 'cio-result-card-favorites-button' })),
|
|
154
154
|
getHydrateQuizButtonProps: () => (Object.assign(Object.assign({}, mockElementProps), { className: 'cio-question-cta-button' })),
|
|
155
155
|
getNextQuestionButtonProps: () => (Object.assign(Object.assign({}, mockElementProps), { className: 'cio-question-cta-button' })),
|
|
156
|
+
getSkipQuestionButtonProps: () => (Object.assign(Object.assign({}, mockElementProps), { className: 'cio-question-skip-button' })),
|
|
156
157
|
getPreviousQuestionButtonProps: () => (Object.assign(Object.assign({}, mockElementProps), { className: 'cio-question-back-button' })),
|
|
157
158
|
getQuizImageProps: () => mockElementProps,
|
|
158
159
|
getQuizResultButtonProps: () => mockElementProps,
|
package/lib/cjs/src/utils.js
CHANGED
|
@@ -45,9 +45,18 @@ exports.getStoryParams = getStoryParams;
|
|
|
45
45
|
exports.functionStrings = {
|
|
46
46
|
onAddToCartClick: `(item) => console.dir(item)`,
|
|
47
47
|
onQuizResultClick: `(result, position) => console.dir(result, position)`,
|
|
48
|
-
onAddToFavoritesClick: `(
|
|
48
|
+
onAddToFavoritesClick: `(result) => {
|
|
49
|
+
if (result.data) {
|
|
50
|
+
if (!favorites.includes(result.data.id)) {
|
|
51
|
+
setFavorites([...favorites, result.data.id]);
|
|
52
|
+
} else {
|
|
53
|
+
setFavorites(favorites.filter((id) => id !== result.data?.id));
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}`,
|
|
49
57
|
onQuizResultsLoaded: `(results) => console.dir(results)`,
|
|
50
58
|
onQuizNextQuestion: `(question) => console.dir(question)`,
|
|
59
|
+
onQuizSkipQuestion: `(question) => console.dir(question)`,
|
|
51
60
|
cioJsClient: `cioJsClient`,
|
|
52
61
|
};
|
|
53
62
|
const stringifyWithDefaults = (obj) => {
|
package/lib/mjs/package.json
CHANGED
|
@@ -6,6 +6,7 @@ export var QuestionTypes;
|
|
|
6
6
|
QuestionTypes["SingleSelect"] = "single";
|
|
7
7
|
QuestionTypes["MultipleSelect"] = "multiple";
|
|
8
8
|
QuestionTypes["Next"] = "next";
|
|
9
|
+
QuestionTypes["Skip"] = "skip";
|
|
9
10
|
QuestionTypes["Back"] = "back";
|
|
10
11
|
QuestionTypes["Reset"] = "reset";
|
|
11
12
|
QuestionTypes["Hydrate"] = "hydrate";
|
|
@@ -10,7 +10,7 @@ import SessionPromptModal from '../SessionPromptModal/SessionPromptModal';
|
|
|
10
10
|
import { convertPrimaryColorsToString, renderImages } from '../../utils';
|
|
11
11
|
import ProgressBar from '../ProgressBar/ProgressBar';
|
|
12
12
|
export default function CioQuiz(props) {
|
|
13
|
-
const { cioClient, state, events: { hydrateQuiz, resetSessionStorageState }, getAddToCartButtonProps, getAddToFavoritesButtonProps, getCoverQuestionProps, getHydrateQuizButtonProps, getNextQuestionButtonProps, getOpenTextInputProps, getPreviousQuestionButtonProps, getQuizImageProps, getQuizResultButtonProps, getQuizResultLinkProps, getResetQuizButtonProps, getSelectInputProps, primaryColorStyles, } = useQuiz(props);
|
|
13
|
+
const { cioClient, state, events: { hydrateQuiz, resetSessionStorageState }, getAddToCartButtonProps, getAddToFavoritesButtonProps, getCoverQuestionProps, getHydrateQuizButtonProps, getNextQuestionButtonProps, getSkipQuestionButtonProps, getOpenTextInputProps, getPreviousQuestionButtonProps, getQuizImageProps, getQuizResultButtonProps, getQuizResultLinkProps, getResetQuizButtonProps, getSelectInputProps, primaryColorStyles, } = useQuiz(props);
|
|
14
14
|
const [showSessionPrompt, setShowSessionPrompt] = useState(false);
|
|
15
15
|
const { resultsPageOptions, sessionStateOptions } = props;
|
|
16
16
|
const { quizSessionStorageState: { hasSessionStorageState, skipToResults }, } = state;
|
|
@@ -32,6 +32,7 @@ export default function CioQuiz(props) {
|
|
|
32
32
|
getCoverQuestionProps,
|
|
33
33
|
getHydrateQuizButtonProps,
|
|
34
34
|
getNextQuestionButtonProps,
|
|
35
|
+
getSkipQuestionButtonProps,
|
|
35
36
|
getOpenTextInputProps,
|
|
36
37
|
getPreviousQuestionButtonProps,
|
|
37
38
|
getQuizImageProps,
|
|
@@ -74,6 +74,31 @@ export default function quizLocalReducer(state, action) {
|
|
|
74
74
|
isQuizCompleted: false,
|
|
75
75
|
};
|
|
76
76
|
}
|
|
77
|
+
case QuestionTypes.Skip: {
|
|
78
|
+
const { answers, answerInputs } = state;
|
|
79
|
+
const newAnswers = [...answers];
|
|
80
|
+
const lastAnswerInputIndex = answers.length;
|
|
81
|
+
const currentAnswerInput = Object.values(state.answerInputs)[lastAnswerInputIndex];
|
|
82
|
+
switch (currentAnswerInput.type) {
|
|
83
|
+
case QuestionTypes.OpenText:
|
|
84
|
+
newAnswers.push(['false']);
|
|
85
|
+
break;
|
|
86
|
+
case QuestionTypes.Cover:
|
|
87
|
+
newAnswers.push(['seen']);
|
|
88
|
+
break;
|
|
89
|
+
case QuestionTypes.SingleSelect:
|
|
90
|
+
case QuestionTypes.MultipleSelect:
|
|
91
|
+
default:
|
|
92
|
+
newAnswers.push([]);
|
|
93
|
+
}
|
|
94
|
+
return {
|
|
95
|
+
...state,
|
|
96
|
+
// We now commit current answers to prevAnswerInputs
|
|
97
|
+
prevAnswerInputs: answerInputs,
|
|
98
|
+
answers: newAnswers,
|
|
99
|
+
isQuizCompleted: false,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
77
102
|
case QuestionTypes.Back: {
|
|
78
103
|
const prevAnswerInputs = { ...state.prevAnswerInputs };
|
|
79
104
|
return {
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import React, { useContext } from 'react';
|
|
2
2
|
import BackButton from '../BackButton/BackButton';
|
|
3
3
|
import CTAButton from '../CTAButton/CTAButton';
|
|
4
|
+
import SkipButton from '../SkipButton/SkipButton';
|
|
4
5
|
import QuizContext from '../CioQuiz/context';
|
|
5
6
|
function ControlBar(props) {
|
|
6
7
|
const { ctaButtonText } = props;
|
|
7
|
-
const { getNextQuestionButtonProps } = useContext(QuizContext);
|
|
8
|
+
const { getNextQuestionButtonProps, getSkipQuestionButtonProps } = useContext(QuizContext);
|
|
8
9
|
return (React.createElement("div", { className: 'cio-question-buttons-container' },
|
|
9
10
|
React.createElement(BackButton, null),
|
|
10
|
-
React.createElement(
|
|
11
|
+
React.createElement("div", { className: 'cio-question-buttons-group' },
|
|
12
|
+
React.createElement(SkipButton, { propsGetters: getSkipQuestionButtonProps }),
|
|
13
|
+
React.createElement(CTAButton, { ctaText: ctaButtonText, propsGetters: getNextQuestionButtonProps }))));
|
|
11
14
|
}
|
|
12
15
|
export default ControlBar;
|
|
@@ -7,8 +7,8 @@ export default function ResultFavoritesButton(props) {
|
|
|
7
7
|
return (
|
|
8
8
|
// eslint-disable-next-line react/button-has-type
|
|
9
9
|
React.createElement("button", { ...getAddToFavoritesButtonProps(item, price) },
|
|
10
|
-
React.createElement("svg", {
|
|
11
|
-
React.createElement("path", { d: '
|
|
10
|
+
React.createElement("svg", { width: '21', height: '21', viewBox: '0 0 24 24', strokeWidth: '2', strokeLinecap: 'round', strokeLinejoin: 'round' },
|
|
11
|
+
React.createElement("path", { d: 'M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z' }))));
|
|
12
12
|
}
|
|
13
13
|
return null;
|
|
14
14
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
function SkipButton(props) {
|
|
3
|
+
const { propsGetters, className = 'cio-button-container', ...rest } = props;
|
|
4
|
+
return (React.createElement("div", { className: `${className || ''}` }, propsGetters && (
|
|
5
|
+
// eslint-disable-next-line react/button-has-type
|
|
6
|
+
React.createElement("button", { ...rest, ...propsGetters() },
|
|
7
|
+
"Skip",
|
|
8
|
+
React.createElement("span", null, " question")))));
|
|
9
|
+
}
|
|
10
|
+
export default SkipButton;
|
package/lib/mjs/src/constants.js
CHANGED
|
@@ -22,6 +22,7 @@ export const componentDescription = `- import \`CioQuiz\` to render in your JSX.
|
|
|
22
22
|
- \`numResultsToDisplay\` is an optional parameter that determines how many results should be displayed on results page
|
|
23
23
|
- \`callbacks\` lets you pass callback functions that will be called on certain actions
|
|
24
24
|
- \`onQuizNextQuestion\` is an optional callback function that will be called when user moves to the next question
|
|
25
|
+
- \`onQuizSkipQuestion\` is an optional callback function that will be called when user skips a question
|
|
25
26
|
- \`sessionStateOptions\` lets you configure the session modal behavior
|
|
26
27
|
- \`showSessionModal\` is a boolean used to decide whether to show the session modal. The default behavior is to show the session modal
|
|
27
28
|
- \`showSessionModalOnResults\` is a boolean to decide whether to show the session modal after reaching the results page. The default behavior is to not show the session modal
|
|
@@ -54,6 +55,7 @@ const {
|
|
|
54
55
|
getCoverQuestionProps: () => ({...})), // prop getter for jsx quiz cover question,
|
|
55
56
|
getHydrateQuizButtonProps: () => ({...})), // prop getter for jsx hydrate quiz button,
|
|
56
57
|
getNextQuestionButtonProps: () => ({...})), // prop getter for jsx next button to traverse the quiz,
|
|
58
|
+
getSkipQuestionButtonProps: () => ({...})), // prop getter for jsx skip button to traverse the quiz,
|
|
57
59
|
getPreviousQuestionButtonProps: () => ({...})), // prop getter for jsx back button to traverse the quiz,
|
|
58
60
|
getOpenTextInputProps: () => ({...})), // prop getter for jsx open text input,
|
|
59
61
|
getSelectInputProps: () => ({...})), // prop getter for jsx select input for select type questions,
|
|
@@ -87,6 +89,13 @@ In the example below, the \`primaryColor\` prop has been used to override this c
|
|
|
87
89
|
> Advanced Option: Instead of passing a primaryColor prop, you can also override \`--primary-color-h\`, \`--primary-color-s\`, and \`--primary-color-l\` CSS variables within a \`.cio-quiz\` container element. If explicitly given a value in your CSS, then the values of these variables will be used as the HSL values for your quiz.
|
|
88
90
|
`;
|
|
89
91
|
export const callbacksDescription = `Pass an \`apiKey\`, a \`quizId\`, and \`callbacks\``;
|
|
92
|
+
export const favoritesDescription = `
|
|
93
|
+
Add \`const [favorites, setFavorites] = useState([]);\` or equivalent to manage the favorite items' state.
|
|
94
|
+
|
|
95
|
+
Pass favorites as an array to \`favoriteItems\` in \`resultsPageOptions\` as a prop to CioQuiz.
|
|
96
|
+
|
|
97
|
+
Pass a callback function to \`onAddToFavoritesClick\` in \`resultsPageOptions\` as a prop to CioQuiz to handle favorites state changes to update \`favorites\` array.
|
|
98
|
+
`;
|
|
90
99
|
export var RequestStates;
|
|
91
100
|
(function (RequestStates) {
|
|
92
101
|
RequestStates["Stale"] = "STALE";
|
|
@@ -5,12 +5,14 @@ import useOpenTextInputProps from './useOpenTextInputProps';
|
|
|
5
5
|
import useNextQuestionButtonProps from './useNextQuestionButtonProps';
|
|
6
6
|
import usePreviousQuestionButtonProps from './usePreviousQuestionButtonProps';
|
|
7
7
|
import useAddToFavoritesButtonProps from './useAddToFavoritesButtonProps';
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
import useSkipQuestionButtonProps from './useSkipQuestionButtonProps';
|
|
9
|
+
const usePropsGetters = (quizEvents, quizApiState, quizLocalState, favoriteItems) => {
|
|
10
|
+
const { quizAnswerChanged, nextQuestion, skipQuestion, previousQuestion, resetQuiz, hydrateQuiz, addToCart, addToFavorites, resultClick, } = quizEvents;
|
|
10
11
|
const getOpenTextInputProps = useOpenTextInputProps(quizAnswerChanged, nextQuestion, quizApiState.quizCurrentQuestion?.next_question, quizLocalState.answerInputs);
|
|
11
12
|
const getCoverQuestionProps = useCoverQuestionProps(quizAnswerChanged, quizApiState.quizCurrentQuestion?.next_question);
|
|
12
13
|
const getSelectInputProps = useSelectInputProps(quizAnswerChanged, nextQuestion, quizApiState.quizCurrentQuestion?.next_question, quizLocalState.answerInputs);
|
|
13
14
|
const getNextQuestionButtonProps = useNextQuestionButtonProps(nextQuestion, quizApiState, quizLocalState);
|
|
15
|
+
const getSkipQuestionButtonProps = useSkipQuestionButtonProps(skipQuestion, quizApiState);
|
|
14
16
|
const getPreviousQuestionButtonProps = usePreviousQuestionButtonProps(quizApiState, previousQuestion);
|
|
15
17
|
const getResetQuizButtonProps = useCallback((stylesType = 'primary') => ({
|
|
16
18
|
className: stylesType === 'primary' ? 'cio-question-cta-button' : 'cio-question-redo-button',
|
|
@@ -27,7 +29,7 @@ const usePropsGetters = (quizEvents, quizApiState, quizLocalState) => {
|
|
|
27
29
|
type: 'button',
|
|
28
30
|
onClick: (e) => addToCart(e, result, price),
|
|
29
31
|
}), [addToCart]);
|
|
30
|
-
const getAddToFavoritesButtonProps = useAddToFavoritesButtonProps(addToFavorites);
|
|
32
|
+
const getAddToFavoritesButtonProps = useAddToFavoritesButtonProps(addToFavorites, favoriteItems);
|
|
31
33
|
const quizResultClickDown = useCallback((event, result, position) => {
|
|
32
34
|
if (event?.key === ' ' || event?.key === 'Enter') {
|
|
33
35
|
if (resultClick) {
|
|
@@ -48,13 +50,13 @@ const usePropsGetters = (quizEvents, quizApiState, quizLocalState) => {
|
|
|
48
50
|
onKeyDown: (event) => quizResultClickDown(event, result, position),
|
|
49
51
|
}), [quizResultClickDown, resultClick]);
|
|
50
52
|
const getQuizImageProps = useCallback(() => ({
|
|
51
|
-
src: quizApiState.quizCurrentQuestion?.next_question?.images?.primary_url,
|
|
52
|
-
alt: quizApiState.quizCurrentQuestion?.next_question?.images?.primary_alt,
|
|
53
|
+
src: quizApiState.quizCurrentQuestion?.next_question?.images?.primary_url || undefined,
|
|
54
|
+
alt: quizApiState.quizCurrentQuestion?.next_question?.images?.primary_alt || undefined,
|
|
53
55
|
}), [quizApiState.quizCurrentQuestion]);
|
|
54
56
|
const getSelectQuestionImageProps = useCallback((option) => ({
|
|
55
57
|
className: 'cio-question-option-image',
|
|
56
|
-
src: option?.images?.primary_url,
|
|
57
|
-
alt: option?.images?.primary_alt,
|
|
58
|
+
src: option?.images?.primary_url || undefined,
|
|
59
|
+
alt: option?.images?.primary_alt || undefined,
|
|
58
60
|
}), []);
|
|
59
61
|
return {
|
|
60
62
|
getOpenTextInputProps,
|
|
@@ -70,6 +72,7 @@ const usePropsGetters = (quizEvents, quizApiState, quizLocalState) => {
|
|
|
70
72
|
getAddToFavoritesButtonProps,
|
|
71
73
|
getQuizResultButtonProps,
|
|
72
74
|
getQuizResultLinkProps,
|
|
75
|
+
getSkipQuestionButtonProps,
|
|
73
76
|
};
|
|
74
77
|
};
|
|
75
78
|
export default usePropsGetters;
|
|
@@ -1,18 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export default function useAddToFavoritesButtonProps(addToFavorites) {
|
|
3
|
-
const
|
|
4
|
-
const toggleIdFavorited = useCallback((id) => {
|
|
5
|
-
setFavorited({ ...favorited, [id]: !favorited?.[id] });
|
|
6
|
-
}, [favorited]);
|
|
1
|
+
import { useCallback } from 'react';
|
|
2
|
+
export default function useAddToFavoritesButtonProps(addToFavorites, favoriteItems) {
|
|
3
|
+
const isResultFavorited = (result) => result?.data?.id && favoriteItems?.includes(result?.data?.id);
|
|
7
4
|
const getAddToFavoritesButtonProps = useCallback((result, price) => ({
|
|
8
|
-
className: `${'cio-result-card-favorites-button'} ${
|
|
5
|
+
className: `${'cio-result-card-favorites-button'} ${isResultFavorited(result) ? 'favorited' : ''}`,
|
|
9
6
|
onClick: (e) => {
|
|
10
|
-
addToFavorites(e, result, price, !
|
|
11
|
-
toggleIdFavorited(result?.data?.id || '0');
|
|
7
|
+
addToFavorites(e, result, price, !isResultFavorited(result));
|
|
12
8
|
},
|
|
13
9
|
type: 'button',
|
|
14
10
|
}),
|
|
15
11
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
16
|
-
[
|
|
12
|
+
[addToFavorites]);
|
|
17
13
|
return getAddToFavoritesButtonProps;
|
|
18
14
|
}
|