institution-and-role.tsx 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. import { useState, useEffect } from 'react'
  2. import { useTranslation } from 'react-i18next'
  3. import { UserEmailData } from '../../../../../../types/user-email'
  4. import { Button } from 'react-bootstrap'
  5. import { isChangingAffiliation } from '../../utils/selectors'
  6. import { useUserEmailsContext } from '../../context/user-email-context'
  7. import DownshiftInput from './downshift-input'
  8. import Icon from '../../../../shared/components/icon'
  9. import useAsync from '../../../../shared/hooks/use-async'
  10. import { postJSON } from '../../../../infrastructure/fetch-json'
  11. import { defaults as roles } from '../../roles'
  12. import { defaults as departments } from '../../departments'
  13. type InstitutionAndRoleProps = {
  14. userEmailData: UserEmailData
  15. }
  16. function InstitutionAndRole({ userEmailData }: InstitutionAndRoleProps) {
  17. const { t } = useTranslation()
  18. const { isLoading, isError, runAsync } = useAsync()
  19. const { affiliation } = userEmailData
  20. const {
  21. state,
  22. setLoading: setUserEmailsContextLoading,
  23. setEmailAffiliationBeingEdited,
  24. updateAffiliation,
  25. } = useUserEmailsContext()
  26. const [role, setRole] = useState(affiliation?.role || '')
  27. const [department, setDepartment] = useState(affiliation?.department || '')
  28. useEffect(() => {
  29. setUserEmailsContextLoading(isLoading)
  30. }, [setUserEmailsContextLoading, isLoading])
  31. const handleChangeAffiliation = () => {
  32. setEmailAffiliationBeingEdited(userEmailData.email)
  33. }
  34. const handleCancelAffiliationChange = () => {
  35. setEmailAffiliationBeingEdited(null)
  36. setRole(affiliation?.role || '')
  37. setDepartment(affiliation?.department || '')
  38. }
  39. const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
  40. event.preventDefault()
  41. runAsync(
  42. postJSON('/user/emails/endorse', {
  43. body: {
  44. email: userEmailData.email,
  45. role,
  46. department,
  47. },
  48. })
  49. )
  50. .then(() => {
  51. updateAffiliation(userEmailData.email, role, department)
  52. })
  53. .catch(() => {})
  54. }
  55. if (!affiliation?.institution) {
  56. return null
  57. }
  58. return (
  59. <>
  60. <div>{affiliation.institution.name}</div>
  61. {!isChangingAffiliation(state, userEmailData.email) ? (
  62. <div className="small">
  63. {(affiliation.role || affiliation.department) && (
  64. <>
  65. {[affiliation.role, affiliation.department]
  66. .filter(Boolean)
  67. .join(', ')}
  68. <br />
  69. </>
  70. )}
  71. <Button className="btn-inline-link" onClick={handleChangeAffiliation}>
  72. {!affiliation.department && !affiliation.role
  73. ? t('add_role_and_department')
  74. : t('change')}
  75. </Button>
  76. </div>
  77. ) : (
  78. <div className="affiliation-change-container small">
  79. <form onSubmit={handleSubmit}>
  80. <DownshiftInput
  81. items={roles}
  82. inputValue={role}
  83. placeholder={t('role')}
  84. setValue={setRole}
  85. />
  86. <DownshiftInput
  87. items={departments}
  88. inputValue={department}
  89. placeholder={t('department')}
  90. setValue={setDepartment}
  91. />
  92. <Button
  93. bsSize="sm"
  94. bsStyle="success"
  95. type="submit"
  96. disabled={!role || !department || isLoading || state.isLoading}
  97. >
  98. {isLoading ? <>{t('saving')}…</> : t('save_or_cancel-save')}
  99. </Button>
  100. {!isLoading && (
  101. <>
  102. <span className="mx-2">{t('save_or_cancel-or')}</span>
  103. <Button
  104. className="btn-inline-link"
  105. onClick={handleCancelAffiliationChange}
  106. >
  107. {t('save_or_cancel-cancel')}
  108. </Button>
  109. </>
  110. )}
  111. </form>
  112. </div>
  113. )}
  114. {isError && (
  115. <span className="text-danger small">
  116. <Icon type="exclamation-triangle" fw />{' '}
  117. {t('error_performing_request')}
  118. </span>
  119. )}
  120. </>
  121. )
  122. }
  123. export default InstitutionAndRole