From fd7e7fed84437f55923b27a30c12ba228b3b3493 Mon Sep 17 00:00:00 2001 From: Danilo Verde Date: Fri, 15 Jul 2022 18:15:27 -0300 Subject: [PATCH 1/2] :sparkles: feature: shuffle questions order --- src/components/common/shuffle.ts | 20 +++++++++++++++++++ .../practices/information-panel.tsx | 12 ++++++++++- src/components/practices/practices.hook.ts | 7 ++++++- src/components/practices/practices.spec.tsx | 3 +++ src/components/practices/practices.tsx | 4 +++- .../github-practices/github-practices.tsx | 2 ++ 6 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 src/components/common/shuffle.ts diff --git a/src/components/common/shuffle.ts b/src/components/common/shuffle.ts new file mode 100644 index 0000000..f5f6bbb --- /dev/null +++ b/src/components/common/shuffle.ts @@ -0,0 +1,20 @@ +/** + * Fisher-Yates shuffle + * Shuffles an array in place. ES6 version + * @see https://stackoverflow.com/a/6274381 + * @see https://bost.ocks.org/mike/shuffle/ + * @param questions object to shuffle + * @returns {any[]} shuffled object + */ +const Shuffle = (questions: any): any => { + for (let i = Object.keys(questions).length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + // eslint-disable-next-line no-param-reassign + [questions[i], questions[j]] = [questions[j], questions[i]]; + } + // eslint-disable-next-line no-console + console.log('questions: ', questions); + return questions; +}; + +export default Shuffle; diff --git a/src/components/practices/information-panel.tsx b/src/components/practices/information-panel.tsx index 55b19d0..4d862da 100644 --- a/src/components/practices/information-panel.tsx +++ b/src/components/practices/information-panel.tsx @@ -16,14 +16,21 @@ const RefreshSVG: React.FC = () => ( ); +const ShuffleSVG: React.FC = () => ( + + + +); + interface InformationPanelProps { data: PracticesData onNavigatePractice: (id: number) =>void onResetPractices?: () => void + onShuffleQuestions?: () => void } const InformationPanel: React.FC = ({ - data, onNavigatePractice, onResetPractices, + data, onNavigatePractice, onResetPractices, onShuffleQuestions, }) => { const navigate = useNavigate(); const practiceItems = Object.values(data); @@ -59,6 +66,9 @@ const InformationPanel: React.FC = ({ ) : null} +
diff --git a/src/components/practices/practices.hook.ts b/src/components/practices/practices.hook.ts index c9b65ac..554b381 100644 --- a/src/components/practices/practices.hook.ts +++ b/src/components/practices/practices.hook.ts @@ -2,6 +2,7 @@ import { useCallback, useEffect, useReducer } from 'react'; import { useLocalStorageState } from '../common/local-storage.hook'; import { OptionStatus, PracticeStatus, SelectionOption } from '../practice/practice'; import { PracticesData } from './practices'; +import Shuffle from '../common/shuffle'; const arrSame = (arrA: any[], arrB: any[]) => { const intersection = arrA.filter((x) => arrB.includes(x)); @@ -140,8 +141,12 @@ export const usePracticesWithLocalStorage = (id: string, initPractices: Practice setPractices({}); }; + const shuffleHandler = () => { + setStorage(Shuffle(practices)); + }; + return [practices, { - handleSubmit, handleSelectionChange, setPractices, resetStorage, + handleSubmit, handleSelectionChange, setPractices, resetStorage, shuffleHandler, }] as const; }; diff --git a/src/components/practices/practices.spec.tsx b/src/components/practices/practices.spec.tsx index 710e77d..1a42c57 100644 --- a/src/components/practices/practices.spec.tsx +++ b/src/components/practices/practices.spec.tsx @@ -106,16 +106,19 @@ describe('Practices Component', () => { it('should reset practice if reset button is clicked', async () => { const resetHandler = jest.fn(); + const shuffleHandler = jest.fn(); renderWithRouterProvider(); const actionButton = screen.getByTestId('action-button'); await userEvent.click(actionButton); await userEvent.click(screen.getByTestId('reset-button')); expect(resetHandler).toBeCalled(); + expect(shuffleHandler).toBeCalled(); // Test home button is working await userEvent.click(screen.getByTestId('homepage-button')); }); diff --git a/src/components/practices/practices.tsx b/src/components/practices/practices.tsx index 32a6a0e..5aaa4ea 100644 --- a/src/components/practices/practices.tsx +++ b/src/components/practices/practices.tsx @@ -33,11 +33,12 @@ interface PracticesProps { onSubmit: (id: number, selection: SelectionOption[]) => void; onSelectionChange: (id: number, selection: SelectionOption[]) => void; onResetPractices?: () => void; + onShuffleQuestions?: () => void; } export const Practices: React.FC = ( { - data, baseImageURL, onSubmit, onSelectionChange, onResetPractices, + data, baseImageURL, onSubmit, onSelectionChange, onResetPractices, onShuffleQuestions, }, ) => { const [isOpen, setIsOpen] = useState(false); @@ -92,6 +93,7 @@ export const Practices: React.FC = ( data={data} onNavigatePractice={handleNavigatePractice} onResetPractices={onResetPractices} + onShuffleQuestions={onShuffleQuestions} /> {/*
*/} diff --git a/src/pages/github-practices/github-practices.tsx b/src/pages/github-practices/github-practices.tsx index 565a65d..4afff88 100644 --- a/src/pages/github-practices/github-practices.tsx +++ b/src/pages/github-practices/github-practices.tsx @@ -24,6 +24,7 @@ const GithubPractices: React.FC = ({ githubLink }) => { handleSelectionChange, setPractices, resetStorage, + shuffleHandler, }] = usePracticesWithLocalStorage(link, {}); useEffect(() => { @@ -41,6 +42,7 @@ const GithubPractices: React.FC = ({ githubLink }) => { onSelectionChange={handleSelectionChange} baseImageURL={link} onResetPractices={resetStorage} + onShuffleQuestions={shuffleHandler} /> ); }; From ff24b7d76dbf80ae31cc6fcb500c736d7867903a Mon Sep 17 00:00:00 2001 From: Danilo Verde Date: Sat, 16 Jul 2022 09:53:31 -0300 Subject: [PATCH 2/2] Update shuffle.ts Typo on JSDOC --- src/components/common/shuffle.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/common/shuffle.ts b/src/components/common/shuffle.ts index f5f6bbb..9a0bf27 100644 --- a/src/components/common/shuffle.ts +++ b/src/components/common/shuffle.ts @@ -1,6 +1,6 @@ /** * Fisher-Yates shuffle - * Shuffles an array in place. ES6 version + * Shuffles an object in place. ES6 version * @see https://stackoverflow.com/a/6274381 * @see https://bost.ocks.org/mike/shuffle/ * @param questions object to shuffle