[ABANDONED] React/Redux front end for the Flexor social network.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

139 lines
5.5 KiB

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
  1. import React, { FC } from 'react'
  2. import { useSelector, useDispatch } from 'react-redux'
  3. import { useHistory } from 'react-router-dom'
  4. import { faDoorOpen, faCheckCircle, faIdCard, faEnvelope, faUserShield, faUserCircle } from '@fortawesome/free-solid-svg-icons'
  5. import { unauthenticate, updateSelf } from '../../actions/authentication'
  6. import { initForm, initField } from '../../actions/forms'
  7. import { getAuthenticatedUser } from '../../selectors/authentication'
  8. import { getForm } from '../../selectors/forms'
  9. import { handleApiError } from '../../api/errors'
  10. import { PRIVACY_OPTIONS } from '../../constants'
  11. import { useAuthenticationCheck, useDeepCompareEffect } from '../../hooks'
  12. import { setTitle, valueFromForm } from '../../utils'
  13. import Title from '../../components/title'
  14. import Subtitle from '../../components/subtitle'
  15. import Section from '../../components/section'
  16. import HorizontalRule from '../../components/horizontal-rule'
  17. import PrimaryButton from '../../components/controls/primary-button'
  18. import SecondaryButton from '../../components/controls/secondary-button'
  19. import Loading from '../../components/pages/loading'
  20. import TextField from '../../components/controls/text-field'
  21. import TextareaField from '../../components/controls/textarea-field'
  22. import SelectField from '../../components/controls/select-field'
  23. import CheckboxField from '../../components/controls/checkbox-field'
  24. import ImageField from '../../components/controls/image-field'
  25. import CoverImageField from '../../components/controls/cover-image-field'
  26. import ThemeField from '../../components/controls/theme-field'
  27. import StaticField from '../../components/controls/static-field'
  28. const Self: FC = () => {
  29. const dispatch = useDispatch()
  30. const history = useHistory()
  31. const user = useSelector(getAuthenticatedUser)
  32. const form = useSelector(getForm)
  33. useAuthenticationCheck()
  34. const handleLogout = () => {
  35. localStorage.clear()
  36. dispatch(unauthenticate())
  37. window.location.href = '/'
  38. }
  39. const handleUpdate = () => {
  40. if (!user) return
  41. const settings = user.settings ?? {}
  42. const name = valueFromForm<string>(form, 'name', '')
  43. const about = valueFromForm<string>(form, 'about', '')
  44. const requiresApproval = valueFromForm<boolean>(form, 'requiresApproval', true)
  45. const privacy = valueFromForm<string>(form, 'privacy', 'public')
  46. const imageUrl = valueFromForm<string>(form, 'image', '')
  47. const coverImageUrl = valueFromForm<string>(form, 'coverImage', '')
  48. const theme = valueFromForm<string>(form, 'theme', '')
  49. const allowThemeChange = valueFromForm<boolean>(form, 'allowThemeChange', true)
  50. try {
  51. dispatch(updateSelf({
  52. name,
  53. about,
  54. requiresApproval,
  55. privacy,
  56. imageUrl,
  57. coverImageUrl,
  58. theme,
  59. settings: {
  60. ...settings,
  61. allowThemeChange,
  62. }
  63. }))
  64. } catch (err) {
  65. handleApiError(err, dispatch, history)
  66. }
  67. }
  68. useDeepCompareEffect(() => {
  69. if (user) {
  70. setTitle(`${user.name} @${user.id}`)
  71. dispatch(initForm())
  72. dispatch(initField('name', user.name))
  73. dispatch(initField('about', user.about ?? ''))
  74. dispatch(initField('requiresApproval', user.requiresApproval))
  75. dispatch(initField('privacy', user.privacy))
  76. dispatch(initField('image', user.imageUrl ?? ''))
  77. dispatch(initField('coverImage', user.coverImageUrl ?? ''))
  78. dispatch(initField('theme', user.theme))
  79. dispatch(initField('allowThemeChange', user.settings.allowThemeChange))
  80. }
  81. }, [user])
  82. if (!user) return <Loading />
  83. return (
  84. <div>
  85. <Section>
  86. <Title>{user.name ?? user.id}</Title>
  87. <Subtitle>@{user.id}</Subtitle>
  88. <HorizontalRule />
  89. <PrimaryButton text="Your Page" icon={faUserCircle} onClick={() => history.push(`/u/${user.id}`)} />
  90. <StaticField label="ID" icon={faIdCard} value={user.id} />
  91. <StaticField label="ID" icon={faEnvelope} value={user.email} />
  92. <TextField name="name" label="Name" placeholder="Your Display Name" />
  93. <TextareaField name="about" label="About" placeholder="Your Bio" />
  94. <ThemeField name="theme" label="Color" />
  95. <SelectField name="privacy" label="Privacy" options={PRIVACY_OPTIONS} icon={faUserShield} />
  96. <ImageField name="image" label="Avatar" />
  97. <CoverImageField name="coverImage" />
  98. <CheckboxField name="requiresApproval">
  99. Approve each Subscription request from other users.
  100. </CheckboxField>
  101. <br />
  102. <CheckboxField name="allowThemeChange">
  103. Allow theme changes on User and Community pages.
  104. </CheckboxField>
  105. <HorizontalRule />
  106. <nav className="level">
  107. <div>
  108. <PrimaryButton text="Save" icon={faCheckCircle} onClick={() => handleUpdate()} />
  109. </div>
  110. <div>
  111. <SecondaryButton text="Log Out" icon={faDoorOpen} onClick={() => handleLogout()} />
  112. </div>
  113. </nav>
  114. </Section>
  115. </div>
  116. )
  117. }
  118. export default Self