dictionary-modal-content.tsx 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. import { useCallback, useState } from 'react'
  2. import { useTranslation } from 'react-i18next'
  3. import { Alert, Button, Modal } from 'react-bootstrap'
  4. import Icon from '../../../shared/components/icon'
  5. import Tooltip from '../../../shared/components/tooltip'
  6. import useAsync from '../../../shared/hooks/use-async'
  7. import { postJSON } from '../../../infrastructure/fetch-json'
  8. import ignoredWords from '../ignored-words'
  9. import { debugConsole } from '@/utils/debugging'
  10. type DictionaryModalContentProps = {
  11. handleHide: () => void
  12. }
  13. const wordsSortFunction = (a: string, b: string) => a.localeCompare(b)
  14. export default function DictionaryModalContent({
  15. handleHide,
  16. }: DictionaryModalContentProps) {
  17. const { t } = useTranslation()
  18. const [learnedWords, setLearnedWords] = useState(ignoredWords.learnedWords)
  19. const { isError, runAsync } = useAsync()
  20. const handleRemove = useCallback(
  21. word => {
  22. runAsync(
  23. postJSON('/spelling/unlearn', {
  24. body: {
  25. word,
  26. },
  27. })
  28. )
  29. .then(() => {
  30. ignoredWords.remove(word)
  31. setLearnedWords(new Set(ignoredWords.learnedWords))
  32. })
  33. .catch(debugConsole.error)
  34. },
  35. [runAsync]
  36. )
  37. return (
  38. <>
  39. <Modal.Header closeButton>
  40. <Modal.Title>{t('edit_dictionary')}</Modal.Title>
  41. </Modal.Header>
  42. <Modal.Body>
  43. {isError ? (
  44. <Alert bsStyle="danger">{t('generic_something_went_wrong')}</Alert>
  45. ) : null}
  46. {learnedWords?.size > 0 ? (
  47. <ul className="list-unstyled dictionary-entries-list">
  48. {[...learnedWords].sort(wordsSortFunction).map(learnedWord => (
  49. <li key={learnedWord} className="dictionary-entry">
  50. <span className="dictionary-entry-name">{learnedWord}</span>
  51. <Tooltip
  52. id={`tooltip-remove-learned-word-${learnedWord}`}
  53. description={t('edit_dictionary_remove')}
  54. overlayProps={{ delay: 0 }}
  55. >
  56. <Button
  57. bsStyle="danger"
  58. bsSize="xs"
  59. onClick={() => handleRemove(learnedWord)}
  60. >
  61. <Icon
  62. type="trash-o"
  63. accessibilityLabel={t('edit_dictionary_remove')}
  64. />
  65. </Button>
  66. </Tooltip>
  67. </li>
  68. ))}
  69. </ul>
  70. ) : (
  71. <p className="dictionary-empty-body text-center">
  72. <i>{t('edit_dictionary_empty')}</i>
  73. </p>
  74. )}
  75. </Modal.Body>
  76. <Modal.Footer>
  77. <Button bsStyle={null} className="btn-secondary" onClick={handleHide}>
  78. {t('close')}
  79. </Button>
  80. </Modal.Footer>
  81. </>
  82. )
  83. }