dictionary-modal-content.tsx 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. import { useCallback } 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 { isError, runAsync } = useAsync()
  19. const handleRemove = useCallback(
  20. word => {
  21. ignoredWords.remove(word)
  22. runAsync(
  23. postJSON('/spelling/unlearn', {
  24. body: {
  25. word,
  26. },
  27. })
  28. ).catch(debugConsole.error)
  29. },
  30. [runAsync]
  31. )
  32. return (
  33. <>
  34. <Modal.Header closeButton>
  35. <Modal.Title>{t('edit_dictionary')}</Modal.Title>
  36. </Modal.Header>
  37. <Modal.Body>
  38. {isError ? (
  39. <Alert bsStyle="danger">{t('generic_something_went_wrong')}</Alert>
  40. ) : null}
  41. {ignoredWords.learnedWords?.size > 0 ? (
  42. <ul className="list-unstyled dictionary-entries-list">
  43. {[...ignoredWords.learnedWords]
  44. .sort(wordsSortFunction)
  45. .map(learnedWord => (
  46. <li key={learnedWord} className="dictionary-entry">
  47. <span className="dictionary-entry-name">{learnedWord}</span>
  48. <Tooltip
  49. id={`tooltip-remove-learned-word-${learnedWord}`}
  50. description={t('edit_dictionary_remove')}
  51. overlayProps={{ delay: 0 }}
  52. >
  53. <Button
  54. bsStyle="danger"
  55. bsSize="xs"
  56. onClick={() => handleRemove(learnedWord)}
  57. >
  58. <Icon
  59. type="trash-o"
  60. accessibilityLabel={t('edit_dictionary_remove')}
  61. />
  62. </Button>
  63. </Tooltip>
  64. </li>
  65. ))}
  66. </ul>
  67. ) : (
  68. <p className="dictionary-empty-body text-center">
  69. <i>{t('edit_dictionary_empty')}</i>
  70. </p>
  71. )}
  72. </Modal.Body>
  73. <Modal.Footer>
  74. <Button bsStyle={null} className="btn-secondary" onClick={handleHide}>
  75. {t('done')}
  76. </Button>
  77. </Modal.Footer>
  78. </>
  79. )
  80. }