Dwayne Harris 5 years ago
parent
commit
802d4319ef
  1. 13
      src/actions/registration.ts
  2. 1
      src/components/app/app.scss
  3. 5
      src/components/app/index.ts
  4. 30
      src/components/create-group-form/create-group-form.tsx
  5. 21
      src/components/create-group-form/index.ts
  6. 4
      src/components/create-user-form/create-user-form.tsx
  7. 7
      src/components/create-user-form/index.ts
  8. 4
      src/components/pages/directory/index.ts
  9. 2
      src/components/pages/register-group/index.ts
  10. 13
      src/components/pages/register/index.ts
  11. 72
      src/components/pages/register/register.tsx
  12. 2
      src/components/text-field/index.ts
  13. 2
      src/components/user-info/index.ts
  14. 22
      src/reducers/registration.ts
  15. 3
      src/selectors/authentication.ts
  16. 15
      src/selectors/directory.ts
  17. 10
      src/selectors/entities.ts
  18. 13
      src/selectors/forms.ts
  19. 36
      src/selectors/index.ts
  20. 3
      src/selectors/menu.ts
  21. 3
      src/selectors/registration.ts
  22. 2
      src/store/index.ts
  23. 1
      src/types/index.ts
  24. 5
      src/types/store.ts

13
src/actions/registration.ts

@ -0,0 +1,13 @@
import { Action } from 'redux'
export interface SetPageAction extends Action {
type: 'REGISTRATION_SET_PAGE'
payload: number
}
export type RegistrationActions = SetPageAction
export const setPage = (page: number): SetPageAction => ({
type: 'REGISTRATION_SET_PAGE',
payload: page,
})

1
src/components/app/app.scss

@ -20,6 +20,7 @@ $title-weight: 400;
@import "../../../node_modules/bulma/sass/base/_all.sass";
@import "../../../node_modules/bulma/sass/form/_all.sass";
@import "../../../node_modules/bulma/sass/grid/columns.sass";
// @import "../../../node_modules/bulma/sass/grid/tiles.sass";
@import "../../../node_modules/bulma/sass/elements/button.sass";
@import "../../../node_modules/bulma/sass/elements/notification.sass";
@import "../../../node_modules/bulma/sass/elements/other.sass";

5
src/components/app/index.ts

@ -1,12 +1,13 @@
import { connect } from 'react-redux'
import { getMenuCollapsed, getFetching } from 'src/selectors'
import { getFetching } from 'src/selectors'
import { getCollapsed } from 'src/selectors/menu'
import { AppState } from 'src/types'
import App from './app'
const mapStateToProps = (state: AppState) => ({
collapsed: getMenuCollapsed(state),
collapsed: getCollapsed(state),
fetching: getFetching(state),
})

30
src/components/create-group-form/create-group-form.tsx

@ -0,0 +1,30 @@
import React, { FC, useEffect } from 'react'
import TextField from '../text-field'
interface Props {
initForm: () => void
}
const CreateGroupForm: FC<Props> = ({ initForm }) => {
useEffect(() => {
initForm()
}, [])
return (
<div className="container">
<TextField name="name" label="Community Name" />
<div className="field">
<label className="label">Registration Type</label>
<div className="select is-small">
<select>
<option>Anyone can join</option>
<option>Invite only</option>
</select>
</div>
</div>
</div>
)
}
export default CreateGroupForm

21
src/components/create-group-form/index.ts

@ -0,0 +1,21 @@
import { Dispatch } from 'redux'
import { connect } from 'react-redux'
import { initField } from 'src/actions/forms'
import { AppState } from 'src/types'
import CreateGroupForm from './create-group-form'
const mapStateToProps = (state: AppState) => ({
})
const mapDispatchToProps = (dispatch: Dispatch) => ({
initForm: () => {
dispatch(initField('name'))
}
})
export default connect(
mapStateToProps,
mapDispatchToProps
)(CreateGroupForm)

4
src/components/register-form/register-form.tsx → src/components/create-user-form/create-user-form.tsx

@ -5,7 +5,7 @@ interface Props {
initForm: () => void
}
const RegisterForm: FC<Props> = ({ initForm }) => {
const CreateUserForm: FC<Props> = ({ initForm }) => {
useEffect(() => {
initForm()
}, [])
@ -19,4 +19,4 @@ const RegisterForm: FC<Props> = ({ initForm }) => {
)
}
export default RegisterForm
export default CreateUserForm

7
src/components/register-form/index.ts → src/components/create-user-form/index.ts

@ -1,17 +1,16 @@
import { Dispatch } from 'redux'
import { connect } from 'react-redux'
import { initForm, initField } from 'src/actions/forms'
import { initField } from 'src/actions/forms'
import { AppState } from 'src/types'
import RegisterForm from './register-form'
import CreateUserForm from './create-user-form'
const mapStateToProps = (state: AppState) => ({
})
const mapDispatchToProps = (dispatch: Dispatch) => ({
initForm: () => {
// dispatch(initForm())
dispatch(initField('username'))
dispatch(initField('name'))
dispatch(initField('email'))
@ -21,4 +20,4 @@ const mapDispatchToProps = (dispatch: Dispatch) => ({
export default connect(
mapStateToProps,
mapDispatchToProps
)(RegisterForm)
)(CreateUserForm)

4
src/components/pages/directory/index.ts

@ -1,13 +1,13 @@
import { connect } from 'react-redux'
import { fetchGroups } from 'src/actions/directory'
import { getDirectoryGroups } from 'src/selectors'
import { getGroups } from 'src/selectors/directory'
import { AppState, AppThunkDispatch } from 'src/types'
import Directory from './directory'
const mapStateToProps = (state: AppState) => ({
groups: getDirectoryGroups(state),
groups: getGroups(state),
})
const mapDispatchToProps = (dispatch: AppThunkDispatch) => ({

2
src/components/pages/register-group/index.ts

@ -2,7 +2,7 @@ import { connect } from 'react-redux'
import { handleApiError } from 'src/api/errors'
import { fetchGroup } from 'src/actions/directory'
import { getEntity } from 'src/selectors'
import { getEntity } from 'src/selectors/entities'
import { AppState, AppThunkDispatch } from 'src/types'
import RegisterGroup, { Props } from './register-group'

13
src/components/pages/register/index.ts

@ -1,10 +1,19 @@
import { connect } from 'react-redux'
import { getPage } from 'src/selectors/registration'
import { setPage } from 'src/actions/registration'
import { AppState, AppThunkDispatch } from 'src/types'
import Register from './register'
const mapStateToProps = (state: AppState) => ({})
const mapDispatchToProps = (dispatch: AppThunkDispatch) => ({})
const mapStateToProps = (state: AppState) => ({
page: getPage(state),
})
const mapDispatchToProps = (dispatch: AppThunkDispatch) => ({
setPage: (page: number) => {
dispatch(setPage(page))
}
})
export default connect(
mapStateToProps,

72
src/components/pages/register/register.tsx

@ -1,30 +1,70 @@
import React, { FC } from 'react'
import TextField from '../../text-field'
import RegisterForm from '../../register-form'
import CreateGroupForm from '../../create-group-form'
import CreateUserForm from '../../create-user-form'
export interface Props {
interface PageProps {
setPage: (page: number) => void
}
const Register: FC<Props> = () => {
return (
<div className="main-content">
<h1 className="title">Create a new Community and Account</h1>
<div className="columns">
<div className="column">
<h1 className="subtitle has-text-primary">Community</h1>
interface Page {
title: string
component: FC<PageProps>
}
<div>
<TextField name="group-name" label="Name" placeholder="Community Name" />
const pages: Page[] = [
{
title: 'Create a Community',
component: ({ setPage }) => {
return (
<div className="columns">
<div className="column is-10 is-offset-1">
<CreateGroupForm />
<br />
<button className="button is-pulled-right is-primary" onClick={() => setPage(1)}>Next: Your Account</button>
</div>
</div>
)
},
},
{
title: 'Create an Account',
component: ({ setPage }) => {
return (
<div className="columns">
<div className="column is-10 is-offset-1">
<CreateUserForm />
<br />
<button className="button is-pulled-left is-warning" onClick={() => setPage(0)}>Back: Community</button>
<button className="button is-pulled-right is-primary">Finish</button>
</div>
</div>
)
},
},
]
<div className="column">
<h1 className="subtitle has-text-primary">You</h1>
export interface Props {
page: number
setPage: (page: number) => void
}
const Register: FC<Props> = ({ page: index, setPage }) => {
const page = pages[index]
const Component = page.component
<RegisterForm />
return (
<div>
<section className="hero is-dark is-bold">
<div className="hero-body">
<div className="container">
<h1 className="title">{page.title}</h1>
</div>
</div>
</section>
<div className="main-content">
<Component setPage={setPage} />
</div>
</div>
)

2
src/components/text-field/index.ts

@ -1,6 +1,6 @@
import { connect } from 'react-redux'
import { getFieldValue, getFieldNotification } from 'src/selectors'
import { getFieldValue, getFieldNotification } from 'src/selectors/forms'
import { AppState } from 'src/types'
import TextField, { Props } from './text-field'

2
src/components/user-info/index.ts

@ -1,6 +1,6 @@
import { connect } from 'react-redux'
import { getAuthenticated } from 'src/selectors'
import { getAuthenticated } from 'src/selectors/authentication'
import { AppState } from 'src/types'
import UserInfo from './user-info'

22
src/reducers/registration.ts

@ -0,0 +1,22 @@
import { Reducer } from 'redux'
import { RegistrationActions } from '../actions/registration'
import { RegistrationState } from '../types'
const initialState: RegistrationState = {
page: 0,
}
const reducer: Reducer<RegistrationState, RegistrationActions> = (state = initialState, action) => {
switch (action.type) {
case 'REGISTRATION_SET_PAGE':
return {
...state,
page: action.payload,
}
default:
return state
}
}
export default reducer

3
src/selectors/authentication.ts

@ -0,0 +1,3 @@
import { AppState } from '../types'
export const getAuthenticated = (state: AppState) => state.authentication.authenticated

15
src/selectors/directory.ts

@ -0,0 +1,15 @@
import { denormalize } from 'normalizr'
import { createSelector } from 'reselect'
import { groupSchema } from '../store/schemas'
import { getEntityStore } from './entities'
import { AppState, Entity } from '../types'
export const getGroupIds = (state: AppState) => state.directory.groups
export const getGroups = createSelector(
[getEntityStore, getGroupIds],
(store, groups) => {
return denormalize(groups, [groupSchema], store) as Entity[]
}
)

10
src/selectors/entities.ts

@ -0,0 +1,10 @@
import { AppState } from '../types'
export const getEntityStore = (state: AppState) => state.entities
export const getEntity = (state: AppState, type: string, id: string) => {
const store = getEntityStore(state)
const collection = store[type]
return collection ? collection[id] : undefined
}

13
src/selectors/forms.ts

@ -0,0 +1,13 @@
import { AppState } from '../types'
export const getForm = (state: AppState) => state.forms.form
export const getFieldValue = (state: AppState, name: string) => {
const field = getForm(state)[name]
return field ? field.value : undefined
}
export const getFieldNotification = (state: AppState, name: string) => {
const field = getForm(state)[name]
return field ? field.notification : undefined
}

36
src/selectors/index.ts

@ -1,45 +1,11 @@
import { denormalize } from 'normalizr'
import { createSelector } from 'reselect'
import values from 'lodash/values'
import { groupSchema } from '../store/schemas'
import { AppState, Entity } from '../types'
import { AppState } from '../types'
export const getEntityStore = (state: AppState) => state.entities
export const getEntity = (state: AppState, type: string, id: string) => {
const store = getEntityStore(state)
const collection = store[type]
return collection ? collection[id] : undefined
}
export const getForm = (state: AppState) => state.forms.form
export const getFieldValue = (state: AppState, name: string) => {
const field = getForm(state)[name]
return field ? field.value : undefined
}
export const getFieldNotification = (state: AppState, name: string) => {
const field = getForm(state)[name]
return field ? field.notification : undefined
}
export const getMenuCollapsed = (state: AppState) => state.menu.collapsed
export const getAuthenticated = (state: AppState) => state.authentication.authenticated
export const getNotifications = (state: AppState) => state.notifications
export const getRequests = (state: AppState) => state.requests
export const getFetching = createSelector(getRequests, requests => {
return values(requests).reduce((fetching, request) => fetching || request.fetching, false)
})
export const getDirectoryGroupIds = (state: AppState) => state.directory.groups
export const getDirectoryGroups = createSelector(
[getEntityStore, getDirectoryGroupIds],
(store, groups) => {
return denormalize(groups, [groupSchema], store) as Entity[]
}
)

3
src/selectors/menu.ts

@ -0,0 +1,3 @@
import { AppState } from '../types'
export const getCollapsed = (state: AppState) => state.menu.collapsed

3
src/selectors/registration.ts

@ -0,0 +1,3 @@
import { AppState } from 'src/types'
export const getPage = (state: AppState) => state.registration.page

2
src/store/index.ts

@ -7,6 +7,7 @@ import entities from '../reducers/entities'
import forms from '../reducers/forms'
import menu from '../reducers/menu'
import notifications from '../reducers/notifications'
import registration from '../reducers/registration'
import requests from '../reducers/requests'
import logger from 'redux-logger'
@ -20,6 +21,7 @@ const store = createStore(
forms,
menu,
notifications,
registration,
requests,
}),
applyMiddleware(thunk, logger)

1
src/types/index.ts

@ -34,6 +34,7 @@ export {
RequestsState,
NotificationsState,
EntitiesState,
RegistrationState,
AppState,
} from './store'

5
src/types/store.ts

@ -56,6 +56,10 @@ export interface DirectoryState {
continuation?: string
}
export interface RegistrationState {
page: number
}
export type RequestsState = APIRequestCollection
export type NotificationsState = Notification[]
export type EntitiesState = EntityStore
@ -67,5 +71,6 @@ export interface AppState {
forms: FormsState
menu: MenuState
notifications: NotificationsState
registration: RegistrationState
requests: RequestsState
}
Loading…
Cancel
Save