[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.

145 lines
5.0 KiB

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
4 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
  1. // view-group.tsx
  2. // Copyright (C) 2020 Dwayne Harris
  3. // This program is free software: you can redistribute it and/or modify
  4. // it under the terms of the GNU General Public License as published by
  5. // the Free Software Foundation, either version 3 of the License, or
  6. // (at your option) any later version.
  7. // This program is distributed in the hope that it will be useful,
  8. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. // GNU General Public License for more details.
  11. // You should have received a copy of the GNU General Public License
  12. // along with this program. If not, see <https://www.gnu.org/licenses/>.
  13. import React, { FC, useEffect, useState } from 'react'
  14. import { useSelector, useDispatch } from 'react-redux'
  15. import { useParams, useHistory } from 'react-router-dom'
  16. import { faEdit, faUserCheck, faBan } from '@fortawesome/free-solid-svg-icons'
  17. import moment from 'moment'
  18. import { handleApiError } from '../../api/errors'
  19. import { setTheme } from '../../actions/theme'
  20. import { fetchGroup } from '../../actions/groups'
  21. import { getAuthenticated } from '../../selectors/authentication'
  22. import { getEntity } from '../../selectors/entities'
  23. import { getThemeName } from '../../selectors/theme'
  24. import { useDeepCompareEffect, useTheme, useSetting } from '../../hooks'
  25. import { setTitle } from '../../utils'
  26. import { AppState, EntityType, Group, GroupMembershipType, AppThunkDispatch, LevelItem } from '../../types'
  27. import Title from '../../components/title'
  28. import Level from '../../components/level'
  29. import Section from '../../components/section'
  30. import PrimaryButton from '../../components/controls/primary-button'
  31. import Button from '../../components/controls/button'
  32. import Loading from '../../components/pages/loading'
  33. import HorizontalRule from '../../components/horizontal-rule'
  34. interface Params {
  35. id: string
  36. }
  37. const ViewGroup: FC = () => {
  38. const { id } = useParams<Params>()
  39. const theme = useTheme()
  40. const themeName = useSelector(getThemeName)
  41. const [selectedThemeName] = useState(themeName)
  42. const group = useSelector<AppState, Group | undefined>(state => getEntity<Group>(state, EntityType.Group, id))
  43. const authenticated = useSelector(getAuthenticated)
  44. const dispatch = useDispatch<AppThunkDispatch>()
  45. const history = useHistory()
  46. const allowThemeChange = useSetting<boolean>('allowThemeChange', true)
  47. useEffect(() => {
  48. try {
  49. dispatch(fetchGroup(id))
  50. } catch (err) {
  51. handleApiError(err, dispatch, history)
  52. }
  53. }, [])
  54. useDeepCompareEffect(() => {
  55. if (group) {
  56. setTitle(group.name)
  57. if (allowThemeChange) dispatch(setTheme(group.theme))
  58. }
  59. return () => {
  60. if (allowThemeChange) dispatch(setTheme(selectedThemeName))
  61. }
  62. }, [group])
  63. if (!group) return <Loading />
  64. const isAdmin = group.membership === GroupMembershipType.Admin
  65. const isMember = !!group.membership
  66. const items: LevelItem[] = []
  67. items.push({
  68. label: 'Members',
  69. content: group.members,
  70. })
  71. items.push({
  72. label: 'Posts',
  73. content: group.posts,
  74. })
  75. items.push({
  76. label: 'Awards',
  77. content: group.awards,
  78. })
  79. items.push({
  80. label: 'Points',
  81. content: group.points,
  82. })
  83. items.push({
  84. label: 'Created',
  85. content: moment(group.updated).format('MMMM Do, YYYY'),
  86. })
  87. return (
  88. <div>
  89. <Section>
  90. {group.coverImageUrl &&
  91. <div className="cover-image">
  92. <img src={group.coverImageUrl} />
  93. </div>
  94. }
  95. <div className="header">
  96. {group.imageUrl &&
  97. <div className="image">
  98. <img src={group.imageUrl} />
  99. </div>
  100. }
  101. <div>
  102. <Title>{group.name}</Title>
  103. <p style={{ color: theme.text }}>{group.about}</p>
  104. </div>
  105. </div>
  106. <Level items={items} />
  107. <HorizontalRule />
  108. <div className="buttons">
  109. {!authenticated &&
  110. <PrimaryButton text="Create an Account" icon={faUserCheck} onClick={() => history.push(`/c/${group.id}/register`)} />
  111. }
  112. {!isMember &&
  113. <Button text="Block" icon={faBan} onClick={() => history.push(`/c/${group.id}/register`)} color={theme.backgroundPrimary} backgroundColor={theme.red} />
  114. }
  115. {isAdmin &&
  116. <PrimaryButton text={`Edit ${group.name}`} icon={faEdit} onClick={() => history.push(`/c/${group.id}/admin/`)} />
  117. }
  118. </div>
  119. </Section>
  120. </div>
  121. )
  122. }
  123. export default ViewGroup