Skip to content

Commit

Permalink
12 add custom timer to generate noteschords automatically (#16)
Browse files Browse the repository at this point in the history
* Add AutoSkipper component

* Add autoskipper on chords

* Fix indent
  • Loading branch information
cyrilgourgouillon committed Nov 25, 2023
1 parent fe84a12 commit 6211d41
Show file tree
Hide file tree
Showing 11 changed files with 153 additions and 27 deletions.
65 changes: 65 additions & 0 deletions src/components/AutoSkipper.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { ButtonGroup, Button, IconButton, useToast } from "@chakra-ui/react";
import { useEffect, useState } from "react";
import { Speed, speeds } from "../config";
import { getSpeedColor, getSpeedIcon } from "../services";

export const AutoSkipper = ({ onSkip }: { onSkip: () => void }) => {
const toast = useToast();
const [speed, setSpeed] = useState<Speed | undefined>(undefined);
const [intervalId, setIntervalId] = useState<number | undefined>();

useEffect(() => {
if (speed) {
const skipInterval = setInterval(() => {
onSkip();
}, speed);

setIntervalId(skipInterval);

return () => clearInterval(skipInterval);
}
}, [onSkip, speed]);

const handleStopAutoSkipper = () => {
clearInterval(intervalId);
setSpeed(undefined);
};

const triggerToast = (skipDuration: Speed) => {
toast({
title: `Auto-skip every ${skipDuration / 1000} seconds`,
status: "info",
duration: 1000,
});
};

return (
<>
<ButtonGroup size="sm" isAttached>
<Button
className={`w-full ${speed === undefined ? "cursor-default" : ""}`}
variant="outline"
onClick={handleStopAutoSkipper}
disabled={speed === undefined}
colorScheme={speed === undefined ? "grey" : "blue"}
>
{speed === undefined ? "Auto-skipper" : "Stop"}
</Button>
{speeds.map((s, i) => (
<IconButton
key={i}
aria-label="minus"
icon={getSpeedIcon(s)}
variant="outline"
onClick={() => {
triggerToast(s);
setSpeed(s);
}}
isActive={speed === s}
colorScheme={speed === s ? getSpeedColor(s) : ""}
/>
))}
</ButtonGroup>
</>
);
};
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Chord } from "../../config";
import { chordToString } from "../../services/chordService";
import { Chord } from "../config";
import { chordToString } from "../services/chordService";

export const ChordsList = ({
chords,
Expand Down
1 change: 0 additions & 1 deletion src/components/ChordsList/index.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Note } from "../../config";
import { Note } from "../config";

export const NotesList = ({
notes,
Expand Down
1 change: 0 additions & 1 deletion src/components/NotesList/index.ts

This file was deleted.

15 changes: 15 additions & 0 deletions src/config/Speed.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export enum Speed {
walk = 15000,
run = 10000,
drive = 5000,
fly = 3000,
rush = 1000,
}

export const speeds = [
Speed.walk,
Speed.run,
Speed.drive,
Speed.fly,
Speed.rush,
];
1 change: 1 addition & 0 deletions src/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ export * from "./GuitarStrings";
export * from "./Chords";
export * from "./AppPages";
export * from "./Caged";
export * from "./Speed";
17 changes: 8 additions & 9 deletions src/pages/ChordsPage.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useState } from "react";
import { Button, IconButton } from "@chakra-ui/react";
import { Button, ButtonGroup, IconButton } from "@chakra-ui/react";

import { FaPlus, FaMinus } from "react-icons/fa";

Expand All @@ -17,6 +17,7 @@ import {
} from "../config/constants";
import { CagedType } from "../config";
import { MdBuild } from "react-icons/md";
import { AutoSkipper } from "../components/AutoSkipper";

export const ChordsPage = () => {
const [chords, setChords] = useState(
Expand All @@ -35,7 +36,7 @@ export const ChordsPage = () => {
setIsShapeVisible((prevState: boolean) => !prevState);
};

const handleGetRandomChordOnClick = () => {
const handleGetRandomChordsOnClick = () => {
setChords(getListOfRandomChords(numberOfChordDisplayed));
setCagedPosition(getRandomNoteFromCaged());
};
Expand All @@ -58,37 +59,35 @@ export const ChordsPage = () => {

return (
<div className="h-full flex flex-col items-center justify-center">
<div className="text-lg font-semibold mb-10">RANDOM CHORDS GENERATOR</div>
<div className="w-screen flex items-center justify-center">
<div className="flex flex-col items-center">
<ChordsList chords={chords} ShapeDecorator={ShapeDecorator} />
<div className="flex flex-col gap-1">
<div className="flex gap-1">
<ButtonGroup isAttached>
<IconButton
aria-label="minus"
icon={<FaMinus />}
variant="outline"
onClick={() => handleChangeNumberOfChordDisplayed(-1)}
disabled={numberOfChordDisplayed === CHORDS_LIST_MIN}
/>
<Button variant="outline" onClick={handleGetRandomChordOnClick}>
<Button onClick={handleGetRandomChordsOnClick}>
Generate list of {numberOfChordDisplayed} chords
</Button>
<IconButton
aria-label="plus"
icon={<FaPlus />}
variant="outline"
onClick={() => handleChangeNumberOfChordDisplayed(1)}
disabled={numberOfChordDisplayed === CHORDS_LIST_MAX}
/>
</div>
</ButtonGroup>
<Button
leftIcon={<MdBuild />}
variant="outline"
size="xs"
onClick={toggleCagedVisible}
>
Toggle shape complexity
</Button>
<AutoSkipper onSkip={handleGetRandomChordsOnClick} />
</div>
</div>
</div>
Expand Down
35 changes: 22 additions & 13 deletions src/pages/NotesPage.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,28 @@
import { useState } from "react";
import { Button, IconButton } from "@chakra-ui/react";
import { Button, ButtonGroup, IconButton } from "@chakra-ui/react";

import { MdBuild } from "react-icons/md";
import { FaPlus, FaMinus } from "react-icons/fa";

import { GuitarString, Note } from "../config";
import { NotesList } from "../components";

import { getListOfRandomNotes, getRandomString, isValidNoteCountList } from "../services";
import { DEFAULT_NUMBER_OF_NOTE, NOTES_LIST_MAX, NOTES_LIST_MIN } from "../config/constants";
import {
getListOfRandomNotes,
getRandomString,
isValidNoteCountList,
} from "../services";
import {
DEFAULT_NUMBER_OF_NOTE,
NOTES_LIST_MAX,
NOTES_LIST_MIN,
} from "../config/constants";
import { AutoSkipper } from "../components/AutoSkipper";

export const NotesPage = () => {
const [notes, setNotes] = useState<Note[]>(getListOfRandomNotes(DEFAULT_NUMBER_OF_NOTE));
const [notes, setNotes] = useState<Note[]>(
getListOfRandomNotes(DEFAULT_NUMBER_OF_NOTE)
);
const [isStringVisible, setIsStringVisible] = useState(false);
const [guitarString, setGuitarString] = useState<GuitarString>(
getRandomString()
Expand All @@ -20,7 +31,7 @@ export const NotesPage = () => {
DEFAULT_NUMBER_OF_NOTE
);

const handleGetRandomNoteOnClick = () => {
const handleGetRandomNotesOnClick = () => {
setNotes(getListOfRandomNotes(numberOfNoteDisplayed));
setGuitarString(getRandomString());
};
Expand All @@ -47,40 +58,38 @@ export const NotesPage = () => {

return (
<div className="h-full flex flex-col items-center justify-center">
<div className="text-lg font-semibold mb-10">RANDOM NOTES GENERATOR</div>
<div className="w-screen flex items-center justify-center">
<div className="flex flex-col items-center">
<NotesList
notes={notes}
GuitarStringDecorator={GuitarStringDecorator}
/>
<div className="flex flex-col gap-1">
<div className="flex gap-1">
<div className="flex flex-col gap-1 items-stretch">
<ButtonGroup isAttached>
<IconButton
aria-label="minus"
icon={<FaMinus />}
variant="outline"
onClick={() => handleChangeNumberOfNoteDisplayed(-1)}
disabled={numberOfNoteDisplayed === NOTES_LIST_MIN}
/>
<Button variant="outline" onClick={handleGetRandomNoteOnClick}>
<Button onClick={handleGetRandomNotesOnClick}>
Generate list of {numberOfNoteDisplayed} notes
</Button>
<IconButton
aria-label="plus"
icon={<FaPlus />}
variant="outline"
onClick={() => handleChangeNumberOfNoteDisplayed(1)}
disabled={numberOfNoteDisplayed === NOTES_LIST_MAX}
/>
</div>
</ButtonGroup>
<Button
leftIcon={<MdBuild />}
variant="outline"
size="xs"
onClick={toggleStringVisible}
>
Toggle string complexity
</Button>
<AutoSkipper onSkip={handleGetRandomNotesOnClick} />
</div>
</div>
</div>
Expand Down
1 change: 1 addition & 0 deletions src/services/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from "./noteService";
export * from "./stringService";
export * from "./chordService";
export * from "./speedService";
38 changes: 38 additions & 0 deletions src/services/speedService.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import {
FaCarSide,
FaPlane,
FaRocket,
FaRunning,
FaWalking,
} from "react-icons/fa";
import { Speed } from "../config";

export const getSpeedIcon = (speed: Speed) => {
switch (speed) {
case Speed.walk:
return <FaWalking />;
case Speed.run:
return <FaRunning />;
case Speed.drive:
return <FaCarSide />;
case Speed.fly:
return <FaPlane />;
case Speed.rush:
return <FaRocket />;
}
};

export const getSpeedColor = (speed: Speed) => {
switch (speed) {
case Speed.walk:
return "yellow";
case Speed.run:
return "orange";
case Speed.drive:
return "red";
case Speed.fly:
return "pink";
case Speed.rush:
return "purple";
}
};

0 comments on commit 6211d41

Please sign in to comment.