ChordForm.tsx 1.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. import React, {
  2. useState,
  3. useEffect,
  4. ReactElement,
  5. FormEvent,
  6. ChangeEvent,
  7. } from 'react';
  8. import { chord2fingering, chords, notes, accidentals } from './chords';
  9. const availableChords = Object.keys(chords);
  10. const availableNotes = Object.keys(notes);
  11. const availableAccidentals = Object.keys(accidentals);
  12. const ChordForm = ({
  13. onSubmit,
  14. }: {
  15. onSubmit: (chord: string) => void;
  16. }): ReactElement => {
  17. const [chord, setChord] = useState('');
  18. const [error, setError] = useState('');
  19. useEffect(() => {
  20. try {
  21. chord2fingering(chord);
  22. setError('');
  23. } catch (e) {
  24. setError(e.message);
  25. }
  26. }, [chord]);
  27. const handleSubmit = (e: FormEvent) => {
  28. e.preventDefault();
  29. setChord('');
  30. onSubmit(chord);
  31. };
  32. const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
  33. const value = e.target.value;
  34. setChord(value);
  35. };
  36. return (
  37. <form onSubmit={handleSubmit}>
  38. {chord && error && <div>{error}</div>}
  39. <input value={chord} onChange={handleChange} />
  40. <input type="submit" value="submit" disabled={!chord || !!error} />
  41. <div>
  42. {availableNotes.map(note => (
  43. <a onClick={() => setChord(note)} key={note}>
  44. {note}
  45. </a>
  46. ))}
  47. </div>
  48. <div>
  49. {availableAccidentals.map(acc => (
  50. <a onClick={() => setChord(value => value + acc)} key={acc}>
  51. {acc}
  52. </a>
  53. ))}
  54. </div>
  55. <div>
  56. {availableChords.map(chord => (
  57. <a onClick={() => setChord(value => value + chord)} key={chord}>
  58. {chord}
  59. </a>
  60. ))}
  61. </div>
  62. </form>
  63. );
  64. };
  65. export default ChordForm;