Simple page de modification de profil

This commit is contained in:
2020-07-16 20:21:58 +02:00
parent 05dd505d6b
commit 758c166f27
14 changed files with 284 additions and 29 deletions

View File

@ -3,6 +3,7 @@ import { BrowserRouter, Route, Redirect, Switch } from "react-router-dom";
import { HomePage } from './HomePage/HomePage';
import { store } from '../store/store';
import { Provider } from 'react-redux';
import { ProfilePage } from './ProfilePage/ProfilePage';
export class App extends React.Component {
render() {
@ -11,6 +12,7 @@ export class App extends React.Component {
<BrowserRouter>
<Switch>
<Route path="/" exact component={HomePage} />
<Route path="/profile" exact component={ProfilePage} />
<Route component={() => <Redirect to="/" />} />
</Switch>
</BrowserRouter>

View File

@ -7,7 +7,7 @@ export function HomePage() {
const currentUser = useSelector((state: RootState) => state.auth.currentUser);
return (
<Page title="Daddy - Accueil">
<Page title="Accueil">
<div className="container is-fluid">
<section className="section">
<div className="columns">
@ -15,7 +15,7 @@ export function HomePage() {
<div className="box">
{
currentUser && currentUser.email ?
<p>Bonjour <span className="has-text-weight-bold">{currentUser.email}</span> !</p> :
<p>Bonjour <span className="has-text-weight-bold">{currentUser.name ? currentUser.name : currentUser.email}</span> !</p> :
<p>Veuillez vous authentifier.</p>
}
</div>

View File

@ -1,44 +1,62 @@
import React from 'react';
import React, { Fragment, useState } from 'react';
import logo from '../resources/logo.svg';
import { useSelector } from 'react-redux';
import { RootState } from '../store/reducers/root';
import { Config } from '../config';
import { Link } from 'react-router-dom';
export function Navbar() {
const isAuthenticated = useSelector<RootState>(state => state.auth.isAuthenticated);
const [ isActive, setActive ] = useState(false);
const toggleMenu = () => {
setActive(active => !active);
};
return (
<nav className="navbar" role="navigation" aria-label="main navigation">
<div className="container is-fluid">
<div className="navbar-brand">
<a className="navbar-item" href="#/">
<Link className="navbar-item" to="/">
<img src={logo} style={{marginRight:'5px',width:'28px',height:'28px'}} />
<h1 className="is-size-4">Daddy</h1>
</a>
<a role="button" className="navbar-burger" aria-label="menu" aria-expanded="false">
</Link>
<a role="button"
className={`navbar-burger ${isActive ? 'is-active' : ''}`}
onClick={toggleMenu}
aria-label="menu"
aria-expanded="false">
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
</a>
</div>
<div className="navbar-menu">
<div className={`navbar-menu ${isActive ? 'is-active' : ''}`}>
<div className="navbar-end">
<div className="navbar-item">
<div className="buttons">
{
isAuthenticated ?
<a className="button is-small" href={Config.logoutURL}>
<span className="icon">
<i className="fas fa-sign-out-alt"></i>
</span>
<span>Se déconnecter</span>
</a> :
<a className="button is-small" href={Config.loginURL}>
<Fragment>
<Link to="/profile" className="button">
<span className="icon">
<i className="fas fa-user"></i>
</span>
</Link>
<a className="button" href={Config.logoutURL}>
<span className="icon">
<i className="fas fa-sign-out-alt"></i>
</span>
</a>
</Fragment> :
<a className="button" href={Config.loginURL}>
<span className="icon">
<i className="fas fa-sign-in-alt"></i>
</span>
<span>Se connecter</span>
</a>
}
</div>
</div>
</div>
</div>

View File

@ -25,6 +25,6 @@ export class Page extends React.PureComponent<PageProps> {
updateTitle() {
const { title } = this.props;
if (title !== undefined) window.document.title = title;
if (title !== undefined) window.document.title = title + ' - Daddy';
}
}

View File

@ -0,0 +1,38 @@
import React, { useEffect } from 'react';
import { Page } from '../Page';
import { useSelector, useDispatch } from 'react-redux';
import { RootState } from '../../store/reducers/root';
import { UserForm } from '../UserForm';
import { Loader } from '../Loader';
import { User } from '../../types/user';
import { updateProfile } from '../../store/actions/profile';
export function ProfilePage() {
const currentUser = useSelector((state: RootState) => state.auth.currentUser);
const dispatch = useDispatch();
const onUserChange = (user: User) => {
if (currentUser.name !== user.name) {
dispatch(updateProfile({ name: user.name }))
}
};
return (
<Page title="Mon profil">
<div className="container is-fluid">
<section className="section">
<div className="columns">
<div className="column is-6 is-offset-3">
<h2 className="is-size-2 subtitle">Mon profil</h2>
{
currentUser ?
<UserForm onChange={onUserChange} user={currentUser} /> :
<Loader />
}
</div>
</div>
</section>
</div>
</Page>
);
}

View File

@ -0,0 +1,80 @@
import React, { useState, ChangeEvent, useEffect } from 'react';
import { User } from '../types/user';
export interface UserFormProps {
user: User
onChange?: (user: User) => void
}
export function UserForm({ user, onChange }: UserFormProps) {
const [ state, setState ] = useState({
changed: false,
user: {
name: '',
email: '',
createdAt: null,
connectedAt: null,
...user,
}
});
const onSaveClick = () => {
if (!state.changed) return;
if (typeof onChange !== 'function') return;
onChange(state.user);
setState(state => {
return {
...state,
changed: false,
};
})
};
const onUserAttrChange = function(attrName: string, evt: ChangeEvent<HTMLInputElement>) {
const value = evt.currentTarget.value;
setState(state => {
return {
...state,
changed: true,
user: {
...state.user,
[attrName]: value,
}
};
});
};
return (
<div className="form">
<div className="field">
<label className="label">Nom d'utilisateur</label>
<div className="control">
<input type="text" className="input" value={state.user.name}
onChange={onUserAttrChange.bind(null, "name")} />
</div>
</div>
<div className="field">
<label className="label">Adresse courriel</label>
<div className="control">
<p className="input is-static">{state.user.email}</p>
</div>
</div>
<div className="field">
<label className="label">Date de dernière connexion</label>
<div className="control">
<p className="input is-static">{state.user.connectedAt}</p>
</div>
</div>
<div className="field">
<label className="label">Date de création</label>
<div className="control">
<p className="input is-static">{state.user.createdAt}</p>
</div>
</div>
<div className="buttons is-right">
<button disabled={!state.changed}
className="button is-primary" onClick={onSaveClick}>Enregistrer</button>
</div>
</div>
);
}