Dwayne Harris 5 years ago
parent
commit
adf4a966c8
  1. 4
      src/actions/directory.ts
  2. 4
      src/actions/entities.ts
  3. 2
      src/components/app/app.tsx
  4. 49
      src/components/group-info/index.tsx
  5. 32
      src/components/group-list/group-list-item/index.tsx
  6. 63
      src/components/pages/group/group.tsx
  7. 26
      src/components/pages/group/index.ts
  8. 2
      src/components/pages/login/login.tsx
  9. 6
      src/components/pages/self/self.tsx

4
src/actions/directory.ts

@ -7,7 +7,7 @@ import { startRequest, finishRequest } from 'src/actions/requests'
import { groupSchema } from 'src/store/schemas'
import { objectToQuerystring } from 'src/utils'
import { AppThunkAction, Entity, RequestKey } from 'src/types'
import { AppThunkAction, Entity, RequestKey, EntityType } from 'src/types'
export interface SetGroupsAction extends Action {
type: 'DIRECTORY_SET_GROUPS'
@ -50,7 +50,7 @@ export const fetchGroup = (id: string): AppThunkAction => {
path: `/api/group/${id}`
})
dispatch(setEntity('group', group))
dispatch(setEntity(EntityType.Group, group))
dispatch(finishRequest(RequestKey.FetchGroup, true))
} catch (err) {
dispatch(finishRequest(RequestKey.FetchGroup, false))

4
src/actions/entities.ts

@ -1,5 +1,5 @@
import { Action } from 'redux'
import { Entity, EntityStore } from '../types'
import { Entity, EntityStore, EntityType } from '../types'
export interface SetEntityAction extends Action {
type: 'ENTITIES_SET_ENTITY'
@ -18,7 +18,7 @@ export interface SetEntitiesAction extends Action {
export type EntitiesActions = SetEntityAction | SetEntitiesAction
export const setEntity = (type: string, entity: Entity): SetEntityAction => ({
export const setEntity = (type: EntityType, entity: Entity): SetEntityAction => ({
type: 'ENTITIES_SET_ENTITY',
payload: {
type,

2
src/components/app/app.tsx

@ -12,6 +12,7 @@ import UserInfo from '../user-info'
import About from '../pages/about'
import Developers from '../pages/developers'
import Directory from '../pages/directory'
import Group from '../pages/group'
import Home from '../pages/home'
import Login from '../pages/login'
import Register from '../pages/register'
@ -59,6 +60,7 @@ const App: FC<Props> = ({ collapsed, fetching, fetchSelf, setChecked }) => {
<Route exact path="/" component={Home} />
<Route path="/login" component={Login} />
<Route path="/register" component={Register} />
<Route path="/c/:id" component={Group} />
<Route path="/c/:id/register" component={RegisterGroup} />
<Route path="/communities" component={Directory} />
<Route path="/self" component={Self} />

49
src/components/group-info/index.tsx

@ -0,0 +1,49 @@
import React, { FC } from 'react'
import moment from 'moment'
import { Group } from 'src/types'
interface Props {
group: Group
}
const GroupInfo: FC<Props> = ({ group }) => (
<nav className="level">
<div className="level-item has-text-centered">
<div>
<p className="heading">Members</p>
<p className="title">{group.members}</p>
</div>
</div>
<div className="level-item has-text-centered">
<div>
<p className="heading">Posts</p>
<p className="title">{group.posts}</p>
</div>
</div>
<div className="level-item has-text-centered">
<div>
<p className="heading has-text-success">Awards</p>
<p className="title">{group.posts}</p>
</div>
</div>
<div className="level-item has-text-centered">
<div>
<p className="heading">Points</p>
<p className="title">{group.points}</p>
</div>
</div>
<div className="level-item has-text-centered">
<div>
<p className="heading">Created</p>
<p className="title is-size-5">{moment(group.created).format('MMMM Do, YYYY')}</p>
</div>
</div>
</nav>
)
export default GroupInfo

32
src/components/group-list/group-list-item/index.tsx

@ -3,6 +3,8 @@ import { Link } from 'react-router-dom'
import { Group } from 'src/types'
import GroupInfo from 'src/components/group-info'
interface Props {
group: Group
}
@ -14,35 +16,7 @@ const GroupListItem: FC<Props> = ({ group }) => (
{group.about && <p>{group.about}</p>}
<br /><br />
<nav className="level">
<div className="level-item has-text-centered">
<div>
<p className="heading">Members</p>
<p className="title">{group.members}</p>
</div>
</div>
<div className="level-item has-text-centered">
<div>
<p className="heading">Posts</p>
<p className="title">{group.posts}</p>
</div>
</div>
<div className="level-item has-text-centered">
<div>
<p className="heading has-text-success">Awards</p>
<p className="title">{group.posts}</p>
</div>
</div>
<div className="level-item has-text-centered">
<div>
<p className="heading">Points</p>
<p className="title">{group.points}</p>
</div>
</div>
</nav>
<GroupInfo group={group} />
</div>
)

63
src/components/pages/group/group.tsx

@ -0,0 +1,63 @@
import React, { FC, useEffect } from 'react'
import { RouteComponentProps } from 'react-router-dom'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { faEdit } from '@fortawesome/free-solid-svg-icons'
import { setTitle } from 'src/utils'
import { Group } from 'src/types'
import PageHeader from 'src/components/page-header'
import GroupInfo from 'src/components/group-info'
interface Params {
id: string
}
export interface Props extends RouteComponentProps<Params> {
group?: Group
fetchGroup: () => void
}
const Self: FC<Props> = ({ group, fetchGroup }) => {
useEffect(() => {
fetchGroup()
}, [])
useEffect(() => {
if (group) setTitle(group.name)
}, [group])
if (!group) {
return (
<div>
<PageHeader title="Group" />
<div className="main-content"></div>
</div>
)
}
return (
<div>
<PageHeader title={group.name} />
<div className="main-content">
<GroupInfo group={group} />
<br /><br />
{group.membership === 'admin' &&
<div>
<button className="button is-warning">
<span className="icon is-small">
<FontAwesomeIcon icon={faEdit} />
</span>
<span>Edit {group.name}</span>
</button>
</div>
}
</div>
</div>
)
}
export default Self

26
src/components/pages/group/index.ts

@ -0,0 +1,26 @@
import { connect } from 'react-redux'
import { handleApiError } from 'src/api/errors'
import { fetchGroup } from 'src/actions/directory'
import { getEntity } from 'src/selectors/entities'
import { AppState, EntityType, Group, AppThunkDispatch } from 'src/types'
import GroupPage, { Props } from './group'
const mapStateToProps = (state: AppState, ownProps: Props) => ({
group: getEntity<Group>(state, EntityType.Group, ownProps.match.params.id),
})
const mapDispatchToProps = (dispatch: AppThunkDispatch, ownProps: Props) => ({
fetchGroup: () => {
try {
dispatch(fetchGroup(ownProps.match.params.id))
} catch (err) {
handleApiError(err, dispatch, ownProps.history)
}
}
})
export default connect(
mapStateToProps,
mapDispatchToProps
)(GroupPage)

2
src/components/pages/login/login.tsx

@ -61,7 +61,7 @@ const Login: FC<Props> = ({
<PasswordField placeholder="Your password" showStrength={false} />
<br />
<button className={classNames(buttonClassDictionary)} onClick={() => authenticate(name, password)}>Log In</button>
<button className={classNames(buttonClassDictionary)} onClick={() => authenticate(name, password)} disabled={authenticating}>Log In</button>
</div>
</div>
</div>

6
src/components/pages/self/self.tsx

@ -4,14 +4,14 @@ import moment from 'moment'
import { useAuthenticationCheck } from 'src/hooks'
import { setTitle } from 'src/utils'
import { Entity } from 'src/types'
import { User } from 'src/types'
import PageHeader from 'src/components/page-header'
export interface Props extends RouteComponentProps {
checked: boolean
authenticated: boolean
user?: Entity
user?: User
logout: () => void
}
@ -33,7 +33,7 @@ const Self: FC<Props> = ({ checked, authenticated, user, logout, history }) => {
return (
<div>
<PageHeader title={user.name as string || user.id as string} subtitle={`@${user.id}`} />
<PageHeader title={user.name || user.id} subtitle={`@${user.id}`} />
<div className="main-content">
<nav className="level">

Loading…
Cancel
Save