-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
320 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import React from 'react'; | ||
import { Link } from 'react-router-dom'; | ||
|
||
import Notifications from '~/components/Notifications'; | ||
|
||
import logo from '~/assets/logo-purple.svg'; | ||
import { Container, Content, Profile } from './styles'; | ||
|
||
export default function Header() { | ||
return ( | ||
<Container> | ||
<Content> | ||
<nav> | ||
<img src={logo} alt="Gobarber" /> | ||
<Link to="/dashboard">DASHBOARD</Link> | ||
</nav> | ||
|
||
<aside> | ||
<Notifications /> | ||
|
||
<Profile> | ||
<div> | ||
<strong>Wellington Arantes</strong> | ||
<Link to="/profile">Meu Perfil</Link> | ||
</div> | ||
<img | ||
src="https://api.adorable.io/avatars/50/[email protected]" | ||
alt="Wellington Arantes" | ||
/> | ||
</Profile> | ||
</aside> | ||
</Content> | ||
</Container> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
import styled from 'styled-components'; | ||
|
||
export const Container = styled.div` | ||
background: #fff; | ||
padding: 0 30px; | ||
`; | ||
|
||
export const Content = styled.div` | ||
display: flex; | ||
justify-content: space-between; | ||
align-items: center; | ||
height: 64px; | ||
max-width: 900px; | ||
margin: 0 auto; | ||
nav { | ||
display: flex; | ||
align-items: center; | ||
img { | ||
margin-right: 20px; | ||
padding-right: 20px; | ||
border-right: 1px solid #eee; | ||
} | ||
a { | ||
font-weight: bold; | ||
color: #7159c1; | ||
} | ||
} | ||
aside { | ||
display: flex; | ||
align-items: center; | ||
} | ||
`; | ||
|
||
export const Profile = styled.div` | ||
display: flex; | ||
margin-left: 20px; | ||
padding-left: 20px; | ||
border-left: 1px solid #eee; | ||
div { | ||
text-align: right; | ||
margin-right: 10px; | ||
strong { | ||
display: block; | ||
color: #333; | ||
} | ||
a { | ||
display: block; | ||
margin-top: 2px; | ||
font-size: 12px; | ||
color: #999; | ||
} | ||
} | ||
img { | ||
height: 32px; | ||
border-radius: 50%; | ||
} | ||
`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
import React, { useState, useEffect, useMemo } from 'react'; | ||
import { MdNotifications } from 'react-icons/md'; | ||
import { parseISO, formatDistance } from 'date-fns'; | ||
import pt from 'date-fns/locale/pt'; | ||
|
||
import api from '~/services/api'; | ||
|
||
import { | ||
Container, | ||
Badge, | ||
NotificationList, | ||
Scroll, | ||
Notification, | ||
} from './styles'; | ||
|
||
export default function Notifications() { | ||
const [visible, setVisible] = useState(false); | ||
const [notifications, setNotifications] = useState([]); | ||
|
||
const hasUnread = useMemo( | ||
() => !!notifications.find(notification => notification.read === false), | ||
[notifications] | ||
); | ||
|
||
useEffect(() => { | ||
async function loadNotifications() { | ||
const response = await api.get('notifications'); | ||
|
||
const data = response.data.map(notification => ({ | ||
...notification, | ||
timeDistance: formatDistance( | ||
parseISO(notification.createdAt), | ||
new Date(), | ||
{ addSuffix: true, locale: pt } | ||
), | ||
})); | ||
|
||
setNotifications(data); | ||
} | ||
|
||
loadNotifications(); | ||
}, []); | ||
|
||
function handleToggleVisible() { | ||
setVisible(!visible); | ||
} | ||
|
||
async function handleMarkAsRead(id) { | ||
await api.put(`notifications/${id}`); | ||
|
||
setNotifications( | ||
notifications.map(notification => | ||
notification._id == id ? { ...notification, read: true } : notification | ||
) | ||
); | ||
} | ||
|
||
return ( | ||
<Container> | ||
<Badge onClick={handleToggleVisible} hasUnread={hasUnread}> | ||
<MdNotifications color="#7159c1" size={20} /> | ||
</Badge> | ||
|
||
<NotificationList visible={visible}> | ||
<Scroll> | ||
{notifications.map(notification => ( | ||
<Notification key={notification._id} unread={!notification.read}> | ||
<p>{notification.content}</p> | ||
<time>{notification.timeDistance}</time> | ||
{!notification.read && ( | ||
<button | ||
type="button" | ||
onClick={() => handleMarkAsRead(notification._id)} | ||
> | ||
Marcar como lida | ||
</button> | ||
)} | ||
</Notification> | ||
))} | ||
</Scroll> | ||
</NotificationList> | ||
</Container> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
import styled, { css } from 'styled-components'; | ||
import PerfectScrollbar from 'react-perfect-scrollbar'; | ||
import { lighten } from 'polished'; | ||
|
||
export const Container = styled.div` | ||
position: relative; | ||
`; | ||
|
||
export const Badge = styled.button` | ||
background: none; | ||
border: 0; | ||
position: relative; | ||
${props => | ||
props.hasUnread && | ||
css` | ||
&::after { | ||
position: absolute; | ||
right: 0; | ||
top: 0; | ||
width: 8px; | ||
height: 8px; | ||
background: #ff892e; | ||
content: ''; | ||
border-radius: 50%; | ||
} | ||
`} | ||
`; | ||
|
||
export const NotificationList = styled.div` | ||
position: absolute; | ||
width: 260px; | ||
left: calc(50% - 130px); | ||
top: calc(100% + 30px); | ||
background: rgba(0, 0, 0, 0.6); | ||
border-radius: 4px; | ||
padding: 15px 5px; | ||
display: ${props => (props.visible ? 'block' : 'none')}; | ||
&::before { | ||
content: ''; | ||
position: absolute; | ||
left: calc(50% - 20px); | ||
top: -20px; | ||
width: 0; | ||
height: 0; | ||
border-left: 20px solid transparent; | ||
border-right: 20px solid transparent; | ||
border-bottom: 20px solid rgba(0, 0, 0, 0.6); | ||
} | ||
`; | ||
|
||
export const Scroll = styled(PerfectScrollbar)` | ||
max-height: 260px; | ||
padding: 5px 15px; | ||
`; | ||
|
||
export const Notification = styled.div` | ||
color: #fff; | ||
& + div { | ||
margin-top: 15px; | ||
padding-top: 15px; | ||
border-top: 1px solid rgba(255, 255, 255, 0.1); | ||
} | ||
p { | ||
font-size: 13px; | ||
line-height: 18px; | ||
} | ||
time { | ||
font-size: 12px; | ||
opacity: 0.6; | ||
margin-bottom: 5px; | ||
} | ||
button { | ||
font-size: 12px; | ||
border: 0; | ||
background: none; | ||
color: ${lighten(0.2, '#7159c1')}; | ||
} | ||
${props => | ||
props.unread && | ||
css` | ||
&::after { | ||
content: ''; | ||
display: inline-block; | ||
width: 8px; | ||
height: 8px; | ||
background: #ff892e; | ||
border-radius: 50%; | ||
margin-left: 10px; | ||
} | ||
`} | ||
`; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.