BasicInfoSettings.tsx 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  1. import React, { type JSX } from 'react';
  2. import { useAtomValue } from 'jotai';
  3. import { useTranslation, i18n } from 'next-i18next';
  4. import { i18n as i18nConfig } from '^/config/next-i18next.config';
  5. import { toastSuccess, toastError } from '~/client/util/toastr';
  6. import { registrationWhitelistAtom } from '~/states/server-configurations';
  7. import { usePersonalSettings } from '~/stores/personal-settings';
  8. export const BasicInfoSettings = (): JSX.Element => {
  9. const { t } = useTranslation();
  10. const registrationWhitelist = useAtomValue(registrationWhitelistAtom);
  11. const {
  12. data: personalSettingsInfo, mutate: mutatePersonalSettings, sync, updateBasicInfo, error,
  13. } = usePersonalSettings();
  14. const submitHandler = async() => {
  15. try {
  16. await updateBasicInfo();
  17. sync();
  18. toastSuccess(t('toaster.update_successed', { target: t('Basic Info'), ns: 'commons' }));
  19. }
  20. catch (errs) {
  21. const err = errs[0];
  22. const message = err.message;
  23. const code = err.code;
  24. if (code === 'email-is-already-in-use') {
  25. toastError(t('alert.email_is_already_in_use', { ns: 'commons' }));
  26. }
  27. else {
  28. toastError(message);
  29. }
  30. }
  31. };
  32. const changePersonalSettingsHandler = (updateData) => {
  33. if (personalSettingsInfo == null) {
  34. return;
  35. }
  36. mutatePersonalSettings({ ...personalSettingsInfo, ...updateData });
  37. };
  38. return (
  39. <>
  40. <div className="row mt-3 mt-md-4">
  41. <label htmlFor="userForm[name]" className="text-start text-md-end col-md-3 col-form-label">{t('Name')}</label>
  42. <div className="col-md-6">
  43. <input
  44. className="form-control"
  45. type="text"
  46. name="userForm[name]"
  47. defaultValue={personalSettingsInfo?.name || ''}
  48. onChange={e => changePersonalSettingsHandler({ name: e.target.value })}
  49. />
  50. </div>
  51. </div>
  52. <div className="row mt-3">
  53. <label htmlFor="userForm[email]" className="text-start text-md-end col-md-3 col-form-label">{t('Email')}</label>
  54. <div className="col-md-6">
  55. <input
  56. className="form-control"
  57. type="text"
  58. name="userForm[email]"
  59. defaultValue={personalSettingsInfo?.email || ''}
  60. onChange={e => changePersonalSettingsHandler({ email: e.target.value })}
  61. />
  62. {registrationWhitelist != null && registrationWhitelist.length !== 0 && (
  63. <div className="form-text text-muted">
  64. {t('page_register.form_help.email')}
  65. <ul>
  66. {registrationWhitelist.map(data => <li key={data}><code>{data}</code></li>)}
  67. </ul>
  68. </div>
  69. )}
  70. </div>
  71. </div>
  72. <div className="row mt-3">
  73. <label className="text-start text-md-end col-md-3 col-form-label">{t('Disclose E-mail')}</label>
  74. <div className="col-md-6 my-auto">
  75. <div className="form-check form-check-inline me-4">
  76. <input
  77. type="radio"
  78. id="radioEmailShow"
  79. className="form-check-input"
  80. name="userForm[isEmailPublished]"
  81. checked={personalSettingsInfo?.isEmailPublished === true}
  82. onChange={() => changePersonalSettingsHandler({ isEmailPublished: true })}
  83. />
  84. <label className="form-label form-check-label mb-0" htmlFor="radioEmailShow">{t('Show')}</label>
  85. </div>
  86. <div className="form-check form-check-inline">
  87. <input
  88. type="radio"
  89. id="radioEmailHide"
  90. className="form-check-input"
  91. name="userForm[isEmailPublished]"
  92. checked={personalSettingsInfo?.isEmailPublished === false}
  93. onChange={() => changePersonalSettingsHandler({ isEmailPublished: false })}
  94. />
  95. <label className="form-label form-check-label mb-0" htmlFor="radioEmailHide">{t('Hide')}</label>
  96. </div>
  97. </div>
  98. </div>
  99. <div className="row mt-3">
  100. <label className="text-start text-md-end col-md-3 col-form-label">{t('Language')}</label>
  101. <div className="col-md-6 my-auto">
  102. {
  103. i18nConfig.locales.map((locale) => {
  104. if (i18n == null) { return }
  105. const fixedT = i18n.getFixedT(locale);
  106. return (
  107. <div key={locale} className="form-check form-check-inline me-4">
  108. <input
  109. type="radio"
  110. id={`radioLang${locale}`}
  111. className="form-check-input"
  112. name="userForm[lang]"
  113. checked={personalSettingsInfo?.lang === locale}
  114. onChange={() => changePersonalSettingsHandler({ lang: locale })}
  115. />
  116. <label className="form-label form-check-label mb-0" htmlFor={`radioLang${locale}`}>{fixedT('meta.display_name') as string}</label>
  117. </div>
  118. );
  119. })
  120. }
  121. </div>
  122. </div>
  123. <div className="row mt-3">
  124. <label htmlFor="userForm[slackMemberId]" className="text-start text-md-end col-md-3 col-form-label">{t('Slack Member ID')}</label>
  125. <div className="col-md-6">
  126. <input
  127. className="form-control"
  128. type="text"
  129. key="slackMemberId"
  130. name="userForm[slackMemberId]"
  131. defaultValue={personalSettingsInfo?.slackMemberId || ''}
  132. onChange={e => changePersonalSettingsHandler({ slackMemberId: e.target.value })}
  133. />
  134. </div>
  135. </div>
  136. <div className="row mt-4">
  137. <div className="offset-4 col-5">
  138. <button
  139. data-testid="grw-besic-info-settings-update-button"
  140. type="button"
  141. className="btn btn-primary"
  142. onClick={submitHandler}
  143. disabled={error != null}
  144. >
  145. {t('Update')}
  146. </button>
  147. </div>
  148. </div>
  149. </>
  150. );
  151. };