Skip to content

Commit

Permalink
feature: Auth SignIn/SignOut
Browse files Browse the repository at this point in the history
  • Loading branch information
w-arantes committed Mar 26, 2020
1 parent 161e7ad commit df3f89a
Show file tree
Hide file tree
Showing 13 changed files with 319 additions and 25 deletions.
25 changes: 16 additions & 9 deletions src/components/Header/index.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,38 @@
import React from 'react';
import { useSelector } from 'react-redux';
import { Link } from 'react-router-dom';

import Notifications from '~/components/Notifications';

import logo from '~/assets/logo-purple.svg';
import { Container, Content, Profile } from './styles';

import Notifications from '../Notifications';

export default function Header() {
const profile = useSelector(state => state.user.profile);

return (
<Container>
<Content>
<nav>
<img src={logo} alt="Gobarber" />
<Link to="/dashboard">DASHBOARD</Link>
<h1>
<img src={logo} alt="GoBarber" />
</h1>
<Link to="/dashboard">Dashboard</Link>
</nav>

<aside>
<Notifications />

<Profile>
<div>
<strong>Wellington Arantes</strong>
<Link to="/profile">Meu Perfil</Link>
<strong>{profile.name}</strong>
<Link to="/profile">My Profile</Link>
</div>
<img
src="https://api.adorable.io/avatars/50/[email protected]"
alt="Wellington Arantes"
src={
(profile.avatar && profile.avatar.url) ||
`https://ui-avatars.com/api/?background=7159c1&color=fff&name=${profile.name}`
}
alt={profile.name}
/>
</Profile>
</aside>
Expand Down
1 change: 1 addition & 0 deletions src/components/Header/styles.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ export const Profile = styled.div`
}
}
img {
width: 32px;
height: 32px;
border-radius: 50%;
}
Expand Down
2 changes: 1 addition & 1 deletion src/components/Notifications/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export default function Notifications() {

setNotifications(
notifications.map(notification =>
notification._id == id ? { ...notification, read: true } : notification
notification._id === id ? { ...notification, read: true } : notification
)
);
}
Expand Down
59 changes: 59 additions & 0 deletions src/pages/Profile/AvatarInput/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import React, { useState, useRef, useEffect } from 'react';
import { useField } from '@rocketseat/unform';
import api from '~/services/api';

import { Container } from './styles';

export default function AvatarInput() {
const { defaultValue, registerField } = useField('avatar');

const [file, setFile] = useState(defaultValue && defaultValue.id);
const [preview, setPreview] = useState(defaultValue && defaultValue.url);

const ref = useRef();

useEffect(() => {
if (ref.current) {
registerField({
name: 'avatar_id',
ref: ref.current,
path: 'dataset.file',
});
}
}, [ref, registerField]);

async function handleChange(e) {
const data = new FormData();

data.append('file', e.target.files[0]);

const response = await api.post('files', data);

const { id, url } = response.data;

setFile(id);
setPreview(url);
}

return (
<Container>
<label htmlFor="avatar">
<img
src={
preview || 'https://api.adorable.io/avatars/50/[email protected]'
}
alt=""
/>

<input
type="file"
id="avatar"
accept="image/*"
data-file={file}
onChange={handleChange}
ref={ref}
/>
</label>
</Container>
);
}
26 changes: 26 additions & 0 deletions src/pages/Profile/AvatarInput/styles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import styled from 'styled-components';

export const Container = styled.div`
align-self: center;
margin-bottom: 30px;
label {
cursor: pointer;
&:hover {
opacity: 0.7;
}
img {
height: 120px;
width: 120px;
border-radius: 50%;
border: 3px solid rgba(255, 255, 255, 0.3);
background: #eee;
}
input {
display: none;
}
}
`;
50 changes: 48 additions & 2 deletions src/pages/Profile/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,53 @@
import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { Form, Input } from '@rocketseat/unform';

// import { Container } from './styles';
import { signOut } from '~/store/modules/auth/actions';
import { updateProfileRequest } from '~/store/modules/user/actions';

import AvatarInput from './AvatarInput';

import { Container } from './styles';

export default function Profile() {
return <div />;
const dispatch = useDispatch();
const profile = useSelector(state => state.user.profile);

function handleSubmit(data) {
dispatch(updateProfileRequest(data));
}

function handleSignOut() {
dispatch(signOut());
}

return (
<Container>
<Form initialData={profile} onSubmit={handleSubmit}>
<AvatarInput name="avatar_id" />
<Input name="name" placeholder="Nome completo" />
<Input name="email" placeholder="Seu endereço de e-mail" />

<hr />

<Input
type="password"
name="oldPassword"
placeholder="Sua senha atual"
/>
<Input type="password" name="password" placeholder="Nova senha" />
<Input
type="password"
name="confirmPassword"
placeholder="Confirmação de senha"
/>

<button type="submit">Atualizar perfil</button>
</Form>

<button type="submit" onClick={handleSignOut}>
Sair do GoBarber
</button>
</Container>
);
}
87 changes: 87 additions & 0 deletions src/pages/Profile/styles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import styled from 'styled-components';
import { darken } from 'polished';

export const Container = styled.div`
max-width: 600px;
margin: 50px auto;
form {
display: flex;
flex-direction: column;
margin-top: 30px;
input {
background: rgba(0, 0, 0, 0.1);
border: 0;
border-radius: 4px;
height: 44px;
padding: 0 15px;
color: #fff;
margin: 0 0 10px;
&::placeholder {
color: rgba(255, 255, 255, 0.7);
}
}
span {
color: #fb6f91;
align-self: flex-start;
margin: 0 0 10px;
font-weight: bold;
}
hr {
border: 0;
height: 1px;
background: rgba(255, 255, 255, 0.2);
margin: 10px 0 20px;
}
button {
margin: 5px 0 0;
height: 44px;
background: #3b9eff;
font-weight: bold;
color: #fff;
border: 0;
border-radius: 4px;
font-size: 16px;
transition: background 0.2s;
&:hover {
background: ${darken(0.03, '#3b9eff')};
}
}
a {
color: #fff;
margin-top: 15px;
font-size: 16px;
opacity: 0.8;
&:hover {
opacity: 1;
}
}
}
> button {
width: 100%;
margin: 10px 0 0;
height: 44px;
background: #fb6f91;
font-weight: bold;
color: #fff;
border: 0;
border-radius: 4px;
font-size: 16px;
transition: background 0.2s;
&:hover {
background: ${darken(0.08, '#fb6f91')};
}
}
`;

// export const Input = styled.div``;
6 changes: 6 additions & 0 deletions src/store/modules/auth/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,9 @@ export function signFailure() {
type: '@auth/SIGN_FAILURE',
};
}

export function signOut() {
return {
type: '@auth/SIGN_OUT',
};
}
10 changes: 7 additions & 3 deletions src/store/modules/auth/reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ const INITIAL_STATE = {
export default function auth(state = INITIAL_STATE, action) {
return produce(state, draft => {
switch (action.type) {
case '@auth/SIGN_IN_REQUEST': {
case '@auth/LOG_IN_REQUEST': {
draft.loading = true;
break;
}
case '@auth/SIGN_IN_SUCCESS': {
case '@auth/LOG_IN_SUCCESS': {
draft.token = action.payload.token;
draft.signed = true;
draft.loading = false;
Expand All @@ -23,8 +23,12 @@ export default function auth(state = INITIAL_STATE, action) {
draft.loading = false;
break;
}
case '@auth/LOG_OUT': {
draft.token = null;
draft.signed = false;
break;
}
default:
return state;
}
});
}
7 changes: 6 additions & 1 deletion src/store/modules/auth/sagas.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { toast } from 'react-toastify';
import api from '~/services/api';
import history from '~/services/history';

import { signInSuccess, signFailure } from './actions';
import { signInSuccess, signFailure, signOut } from './actions';

export function* signIn({ payload }) {
try {
Expand Down Expand Up @@ -62,8 +62,13 @@ export function setToken({ payload }) {
}
}

export function signOut() {
history.push('/');
}

export default all([
takeLatest('persist/REHYDRATE', setToken),
takeLatest('@auth/SIGN_IN_REQUEST', signIn),
takeLatest('@auth/SIGN_UP_REQUEST', signUp),
takeLatest('@auth/SIGN_OUT', signOut),
]);
19 changes: 19 additions & 0 deletions src/store/modules/user/actions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
export function updateProfileRequest(data) {
return {
type: '@user/UPDATE_PROFILE_REQUEST',
payload: { data },
};
}

export function updateProfileSuccess(data, profile) {
return {
type: '@user/UPDATE_PROFILE_SUCCESS',
payload: { profile },
};
}

export function updateProfileFailure() {
return {
type: '@user/UPDATE_PROFILE_FAILURE',
};
}
Loading

0 comments on commit df3f89a

Please sign in to comment.