diff --git a/package-lock.json b/package-lock.json index a4e331c..67144b2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "0.0.0", "dependencies": { "classnames": "^2.5.1", + "lodash": "4.17.21", "react": "^18.2.0", "react-dom": "^18.2.0" }, @@ -16,6 +17,7 @@ "@testing-library/jest-dom": "^6.4.2", "@testing-library/react": "^15.0.2", "@testing-library/user-event": "^14.5.2", + "@types/lodash": "^4.17.0", "@types/react": "^18.2.66", "@types/react-dom": "^18.2.22", "@typescript-eslint/eslint-plugin": "^7.2.0", @@ -1627,6 +1629,12 @@ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, + "node_modules/@types/lodash": { + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.0.tgz", + "integrity": "sha512-t7dhREVv6dbNj0q17X12j7yDG4bD/DHYX7o5/DbDxobP0HnGPgpRz2Ej77aL7TZT3DSw13fqUTj8J4mMnqa7WA==", + "dev": true + }, "node_modules/@types/node": { "version": "20.12.7", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.7.tgz", @@ -3678,8 +3686,7 @@ "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, "node_modules/lodash.merge": { "version": "4.6.2", diff --git a/package.json b/package.json index 5a2393f..f3e136c 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ }, "dependencies": { "classnames": "^2.5.1", + "lodash": "4.17.21", "react": "^18.2.0", "react-dom": "^18.2.0" }, @@ -19,6 +20,7 @@ "@testing-library/jest-dom": "^6.4.2", "@testing-library/react": "^15.0.2", "@testing-library/user-event": "^14.5.2", + "@types/lodash": "^4.17.0", "@types/react": "^18.2.66", "@types/react-dom": "^18.2.22", "@typescript-eslint/eslint-plugin": "^7.2.0", diff --git a/src/App.tsx b/src/App.tsx index 6ac0078..dd627c2 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -4,6 +4,7 @@ import { useState } from "react"; import ModeToggle from "@components/ModeToggle/ModeToggle"; import Review from "@components/Modes/Review/Review"; +import Challenge from "@components/Modes/Challenge/Challenge"; import { Mode } from "@types"; @@ -17,7 +18,7 @@ function App() { Music Theory Practice - {activeMode === Mode.review ? :
foo
} + {activeMode === Mode.review ? : } ); diff --git a/src/components/Modes/Challenge/Challenge.tsx b/src/components/Modes/Challenge/Challenge.tsx new file mode 100644 index 0000000..623162c --- /dev/null +++ b/src/components/Modes/Challenge/Challenge.tsx @@ -0,0 +1,49 @@ +import { useState } from "react"; +import { shuffle } from "lodash"; + +import { Note, Scale } from "@types"; +import data from "@data"; + +export default function Challenge() { + const { notes, scales } = data; + // this stuff will need to be refs or go in an effect as we will lose it on renders... + const shuffledNotes: Note[] = shuffle(notes); + const randomScale: Scale = shuffle(scales).pop() || scales[0]; + const notesInScale: number[] = [...randomScale.notes]; + + // on click, if id is in notes left, turn tile a color and remove said id from array + const [notesLeft, setNotesLeft] = useState(notesInScale); + // think about what the default state should be. On load, it's in progress + const [inProgress, setInprogress] = useState(true); + + const notesLeftCount = notesLeft.length; + + function handleClick(id: number): void { + const index = notesLeft.indexOf(id); + if (index > -1) { + // match. Remove note + const updated = [...notesLeft.splice(index, 1)]; + setNotesLeft(updated); + } + } + return ( + <> +

Remaining Notes: {notesLeftCount}

+

Scale: {randomScale.name}

+
+ {shuffledNotes.map((note) => { + return ( + + ); + })} +
+ + ); +}