API & Client: Profile update

This commit is contained in:
SamR1
2018-01-01 16:59:46 +01:00
parent cac4f368bf
commit 2c4f3c4462
16 changed files with 524 additions and 76 deletions

View File

@ -1,5 +1,7 @@
import keyIndex from 'react-key-index'
import mpwoApi from '../mpwoApi'
import { history } from '../index'
function AuthError(message) {
return { type: 'AUTH_ERROR', message }
@ -17,25 +19,21 @@ function ProfileError(message) {
return { type: 'PROFILE_ERROR', message }
}
const updateFormDataEmail = value => ({
type: 'UPDATE_FORMDATA_EMAIL',
email: value,
export const handleFormChange = (target, value) => ({
type: 'UPDATE_USER_FORMDATA',
target,
value,
})
const updateFormDataUsername = value => ({
type: 'UPDATE_FORMDATA_USERNAME',
username: value,
export const updateProfileFormData = (target, value) => ({
type: 'UPDATE_PROFILE_FORMDATA',
target,
value,
})
const updateFormDataPassword = value => ({
type: 'UPDATE_FORMDATA_PASSWORD',
password: value,
})
const updateFormDataPasswordConf = value => ({
type: 'UPDATE_FORMDATA_PASSWORD_CONF',
passwordConf: value,
})
function initProfileFormData(user) {
return { type: 'INIT_PROFILE_FORM', user }
}
export function getProfile(dispatch) {
return mpwoApi
@ -43,7 +41,6 @@ export function getProfile(dispatch) {
.then(ret => {
if (ret.status === 'success') {
dispatch(ProfileSuccess(ret))
// window.location.href = '/'
} else {
dispatch(ProfileError(ret.message))
}
@ -139,15 +136,29 @@ export function handleUserFormSubmit(event, formType) {
}
}
export const handleFormChange = event => dispatch => {
switch (event.target.name) {
case 'email':
return dispatch(updateFormDataEmail(event.target.value))
case 'username':
return dispatch(updateFormDataUsername(event.target.value))
case 'password':
return dispatch(updateFormDataPassword(event.target.value))
default: // case 'password-conf':
return dispatch(updateFormDataPasswordConf(event.target.value))
export function initProfileForm () {
return (dispatch, getState) => {
const state = getState()
dispatch(initProfileFormData(state.user))
}
}
export function handleProfileFormSubmit(event) {
event.preventDefault()
return (dispatch, getState) => {
const state = getState()
return mpwoApi
.updateProfile(state.formProfile.formProfile)
.then(ret => {
if (ret.status === 'success') {
getProfile(dispatch)
history.push('/profile')
} else {
dispatch(AuthError(ret.message))
}
})
.catch(error => {
throw error
})
}
}

View File

@ -31,6 +31,14 @@
text-align: left;
}
label {
width: 100%;
}
input, textarea {
width: 100%;
}
.page-title {
font-size: 2em;
margin: 1em;

View File

@ -7,6 +7,7 @@ import Logout from './User/Logout'
import NavBar from './NavBar'
import NotFound from './NotFound'
import Profile from './User/Profile'
import ProfileEdit from './User/ProfileEdit'
import UserForm from './User/UserForm'
import { isLoggedIn } from '../utils'
@ -57,6 +58,18 @@ export default class App extends React.Component {
)}
/>
<Route exact path="/logout" component={Logout} />
<Route
exact path="/profile/edit"
render={() => (
isLoggedIn() ? (
<ProfileEdit />
) : (
<UserForm
formType={'Login'}
/>
)
)}
/>
<Route
exact path="/profile"
render={() => (

View File

@ -51,10 +51,10 @@ export default function Form (props) {
{props.formType === 'Register' &&
<div className="form-group">
<input
name="password-conf"
name="passwordConf"
className="form-control input-lg"
type="password"
placeholder="Enter password confirmation"
placeholder="Enter the password confirmation"
required
onChange={props.onHandleFormChange}
/>

View File

@ -28,7 +28,12 @@ function Profile ({ user }) {
<div className="row">
<div className="col-md-8">
<p>Email : {user.email}</p>
<p>Registration date : {user.createdAt}</p>
<p>Registration Date : {user.createdAt}</p>
<p>First Name : {user.firstName}</p>
<p>Last Name : {user.lastName}</p>
<p>Birth Date : {user.birthDate}</p>
<p>Location : {user.location}</p>
<p>Bio : {user.bio}</p>
</div>
</div>
</div>

View File

@ -0,0 +1,162 @@
import React from 'react'
import { Helmet } from 'react-helmet'
import { connect } from 'react-redux'
import {
initProfileForm,
updateProfileFormData,
handleProfileFormSubmit
} from '../../actions'
class ProfileEdit extends React.Component {
componentDidMount() {
this.props.initForm(this.props.user)
}
render () {
const { formProfile,
onHandleFormChange,
onHandleProfileFormSubmit,
user
} = this.props
return (
<div>
<Helmet>
<title>mpwo - {user.username} - Edit Profile</title>
</Helmet>
<div className="container">
<h1 className="page-title">Profile Edition</h1>
<div className="row">
<div className="col-md-2" />
<div className="col-md-8">
<div className="card">
<div className="card-header">
{user.username}
</div>
<div className="card-body">
<div className="row">
<div className="col-md-12">
<form onSubmit={event =>
onHandleProfileFormSubmit(event)}
>
<div className="form-group">
<label>Email:
<input
name="email"
className="form-control input-lg"
type="text"
value={user.email}
readOnly
/>
</label>
</div>
<div className="form-group">
<label>
Registration Date:
<input
name="createdAt"
className="form-control input-lg"
type="text"
value={user.createdAt}
readOnly
/>
</label>
</div>
<div className="form-group">
<label>
First Name:
<input
name="firstName"
className="form-control input-lg"
type="text"
value={formProfile.firstName}
onChange={onHandleFormChange}
/>
</label>
</div>
<div className="form-group">
<label>
Last Name:
<input
name="lastName"
className="form-control input-lg"
type="text"
value={formProfile.lastName}
onChange={onHandleFormChange}
/>
</label>
</div>
<div className="form-group">
<label>
Birth Date
<input
name="birthDate"
className="form-control input-lg"
type="text"
value={formProfile.birthDate}
onChange={onHandleFormChange}
/>
</label>
</div>
<div className="form-group">
<label>
Location:
<input
name="location"
className="form-control input-lg"
type="text"
value={formProfile.location}
onChange={onHandleFormChange}
/>
</label>
</div>
<div className="form-group">
<label>
Bio:
<textarea
name="bio"
className="form-control input-lg"
maxLength="200"
type="text"
value={formProfile.bio}
onChange={onHandleFormChange}
/>
</label>
</div>
<input
type="submit"
className="btn btn-primary btn-lg btn-block"
value="Submit"
/>
</form>
</div>
</div>
</div>
</div>
</div>
<div className="col-md-2" />
</div>
</div>
</div>
)
}
}
export default connect(
state => ({
formProfile: state.formProfile.formProfile,
user: state.user,
}),
dispatch => ({
initForm: () => {
dispatch(initProfileForm())
},
onHandleFormChange: event => {
dispatch(updateProfileFormData(event.target.name, event.target.value))
},
onHandleProfileFormSubmit: event => {
dispatch(handleProfileFormSubmit(event))
},
})
)(ProfileEdit)

View File

@ -47,7 +47,7 @@ export default connect(
}),
dispatch => ({
onHandleFormChange: event => {
dispatch(handleFormChange(event))
dispatch(handleFormChange(event.target.name, event.target.value))
},
onHandleUserFormSubmit: (event, formType) => {
dispatch(handleUserFormSubmit(event, formType))

View File

@ -46,4 +46,23 @@ export default class MpwoApi {
.then(response => response.json())
.catch(error => error)
}
static updateProfile(form) {
const request = new Request(`${apiUrl}auth/profile/edit`, {
method: 'POST',
headers: new Headers({
'Content-Type': 'application/json',
Authorization: `Bearer ${window.localStorage.getItem('authToken')}`,
}),
body: JSON.stringify({
first_name: form.firstName,
last_name: form.lastName,
bio: form.bio,
location: form.location,
birth_date: form.birthdate,
}),
})
return fetch(request)
.then(response => response.json())
.catch(error => error)
}
}

View File

@ -4,32 +4,11 @@ import initial from './initial'
const formData = (state = initial.formData, action) => {
switch (action.type) {
case 'UPDATE_FORMDATA_EMAIL':
case 'UPDATE_USER_FORMDATA':
return {
formData: {
...state.formData,
email: action.email
},
}
case 'UPDATE_FORMDATA_USERNAME':
return {
formData: {
...state.formData,
username: action.username
},
}
case 'UPDATE_FORMDATA_PASSWORD':
return {
formData: {
...state.formData,
password: action.password
},
}
case 'UPDATE_FORMDATA_PASSWORD_CONF':
return {
formData: {
...state.formData,
passwordConf: action.passwordConf
[action.target]: action.value
},
}
case 'PROFILE_SUCCESS':
@ -39,6 +18,33 @@ const formData = (state = initial.formData, action) => {
}
}
const formProfile = (state = initial.formProfile, action) => {
switch (action.type) {
case 'UPDATE_PROFILE_FORMDATA':
return {
formProfile: {
...state.formProfile,
[action.target]: action.value
},
}
case 'INIT_PROFILE_FORM':
return {
formProfile: {
...state.formProfile,
firstName: action.user.firstName,
lastName: action.user.lastName,
birthDate: action.user.birthDate,
location: action.user.location,
bio: action.user.bio,
},
}
case 'PROFILE_SUCCESS':
return initial.formProfile
default:
return state
}
}
const message = (state = initial.message, action) => {
switch (action.type) {
case 'AUTH_ERROR':
@ -73,14 +79,29 @@ const user = (state = initial.user, action) => {
case 'LOGOUT':
window.localStorage.removeItem('authToken')
return initial.user
case 'PROFILE_SUCCESS':
case 'PROFILE_SUCCESS':
return {
id: action.message.data.id,
username: action.message.data.username,
email: action.message.data.email,
isAdmin: action.message.data.admin,
createdAt: action.message.data.created_at,
isAuthenticated: true
isAuthenticated: true,
firstName: action.message.data.first_name
? action.message.data.first_name
: '',
lastName: action.message.data.last_name
? action.message.data.last_name
: '',
bio: action.message.data.bio
? action.message.data.bio
: '',
location: action.message.data.location
? action.message.data.location
: '',
birthDate: action.message.data.birth_date
? action.message.data.birth_date
: '',
}
default:
return state
@ -89,6 +110,7 @@ const user = (state = initial.user, action) => {
const reducers = combineReducers({
formData,
formProfile,
message,
messages,
user,

View File

@ -8,13 +8,27 @@ export default {
createdAt: '',
isAdmin: false,
isAuthenticated: false,
firstName: '',
lastName: '',
bio: '',
location: '',
birthDate: ''
},
formData: {
formData: {
username: '',
email: '',
password: '',
passwordConf: '',
username: '',
email: '',
password: '',
passwordConf: '',
}
},
formProfile: {
formProfile: {
firstName: '',
lastName: '',
bio: '',
location: '',
birthDate: ''
}
},
}