Skip to content

Commit

Permalink
feat: add empty state, pagination and more styles
Browse files Browse the repository at this point in the history
  • Loading branch information
andyesp committed Sep 20, 2023
1 parent 8775de7 commit 1209d17
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 17 deletions.
13 changes: 13 additions & 0 deletions src/components/Icon/PeaceCircle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
function PeaceCircle() {
return (
<svg xmlns="http://www.w3.org/2000/svg" width="124" height="124" fill="none" viewBox="0 0 124 124">
<rect width="124" height="124" fill="#F3F2F5" rx="62"></rect>
<path
fill="#736E7D"
d="M58 30c2.212 0 4 1.788 4 4v26h-8V34c0-2.212 1.787-4 4-4zm12 20c2.212 0 4 1.788 4 4v8c0 2.213-1.788 4-4 4-2.213 0-4-1.787-4-4v-8c0-2.212 1.787-4 4-4zm8 8c0-2.212 1.787-4 4-4 2.212 0 4 1.788 4 4v8c0 2.213-1.788 4-4 4-2.213 0-4-1.787-4-4v-8zM41.662 36.4L51.987 60h-8.725l-8.925-20.4a3.992 3.992 0 012.063-5.263 3.988 3.988 0 015.262 2.063zm3.375 27.663L45.012 64H57c2.762 0 5 2.237 5 5s-2.238 5-5 5h-7c-1.1 0-2 .9-2 2s.9 2 2 2h7c4.975 0 9-4.025 9-9v-.075A8.005 8.005 0 0070 70c1.65 0 3.175-.5 4.45-1.35A8.003 8.003 0 0082 74a7.879 7.879 0 004-1.075V74c0 11.05-8.95 20-20 20h-7.713c-5.3 0-10.387-2.112-14.137-5.862l-1.45-1.45A15.97 15.97 0 0138 75.374V72c0-4.088 3.075-7.463 7.037-7.938z"
></path>
</svg>
)
}

export default PeaceCircle
24 changes: 20 additions & 4 deletions src/components/NotificationFeed.css
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,13 @@
min-width: 346px;
min-height: 370px;
max-height: 385px;
height: 100;
padding-bottom: 16px;
overflow-y: auto;
pointer-events: none;
opacity: 0;
display: flex;
flex-direction: column;
position: absolute;
top: 60px;
right: -15px;
Expand Down Expand Up @@ -58,13 +62,25 @@
cursor: pointer;
}

.NotificationFeed__UnsubscribedView {
padding: 0 16px;
text-align: center;
.NotificationFeed__EmptyView {
gap: 16px;
}

.NotificationFeed__Item {
.NotificationFeed__List {
display: flex;
flex-direction: column;
gap: 10px;
}

.NotificationFeed__EmptyView,
.NotificationFeed__UnsubscribedView {
display: flex;
flex-direction: column;
padding: 0 16px;
align-items: center;
justify-content: center;
text-align: center;
height: 100%;
}

.NotificationFeed__LoadMoreButtonContainer {
Expand Down
58 changes: 45 additions & 13 deletions src/components/NotificationFeed.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useMemo, useState } from 'react'
import { useEffect, useMemo, useState } from 'react'

import { Web3Provider } from '@ethersproject/providers'
import * as PushAPI from '@pushprotocol/restapi'
Expand All @@ -9,21 +9,27 @@ import { Button } from 'decentraland-ui/dist/components/Button/Button'
import { Loader } from 'decentraland-ui/dist/components/Loader/Loader'

import { Governance } from '../clients/Governance'
import { isSameAddress } from '../entities/Snapshot/utils'
import { DEFAULT_QUERY_STALE_TIME } from '../hooks/constants'
import { useClickOutside } from '../hooks/useClickOutside'
import { CHAIN_ID, CHANNEL_ADDRESS, ENV, getCaipAddress } from '../utils/notifications'
import { CHAIN_ID, CHANNEL_ADDRESS, ENV, Notification, getCaipAddress } from '../utils/notifications'

import FullWidthButton from './Common/FullWidthButton'
import Heading from './Common/Typography/Heading'
import Text from './Common/Typography/Text'
import NotificationBellActive from './Icon/NotificationBellActive'
import NotificationBellInactive from './Icon/NotificationBellInactive'
import PeaceCircle from './Icon/PeaceCircle'
import NotificationItem from './Notifications/NotificationItem'

import './NotificationFeed.css'

const NOTIFICATIONS_PER_PAGE = 5

export default function NotificationFeed() {
const [isOpen, setOpen] = useState(false)
const [user, userState] = useAuthContext()
const [filteredNotifications, setFilteredNotifications] = useState<Notification[]>([])

useClickOutside('.NotificationFeed__Content', isOpen, () => setOpen(false))

Expand All @@ -40,9 +46,8 @@ export default function NotificationFeed() {
staleTime: DEFAULT_QUERY_STALE_TIME,
})

// TODO: Type subscriptions query
const isSubscribed = useMemo(
() => !!subscriptions?.find((item: any) => item.channel === CHANNEL_ADDRESS),
() => !!subscriptions?.find((item: { channel: string }) => isSameAddress(item.channel, CHANNEL_ADDRESS)),
[subscriptions]
)
const {
Expand Down Expand Up @@ -90,6 +95,24 @@ export default function NotificationFeed() {
})
}

const handleLoadMoreClick = () => {
const notifications = userNotifications?.slice(
0,
filteredNotifications.length + NOTIFICATIONS_PER_PAGE
) as unknown as Notification[]
setFilteredNotifications(notifications)
}

useEffect(() => {
if (filteredNotifications.length === 0 && userNotifications && userNotifications?.length > 0) {
const notifications = userNotifications.slice(0, NOTIFICATIONS_PER_PAGE) as unknown as Notification[]
setFilteredNotifications(notifications)
}
}, [userNotifications, filteredNotifications.length])

const hasNotifications = filteredNotifications && filteredNotifications.length > 0
const showLoadMoreButton = isSubscribed && !isLoadingNotifications && hasNotifications

return (
<>
<button
Expand Down Expand Up @@ -120,17 +143,26 @@ export default function NotificationFeed() {
</Button>
</div>
)}
{!isLoadingNotifications && isSubscribed && userNotifications && (
{isSubscribed && !isLoadingNotifications && !hasNotifications && (
<div className="NotificationFeed__EmptyView">
<PeaceCircle />
<Text color="secondary" weight="medium">
No notifications at this time
</Text>
</div>
)}
{showLoadMoreButton && (
<div>
{userNotifications?.map((notification) => (
<div key={notification.payload_id} className="NotificationFeed__Item">
<Text>{notification.payload.data.asub}</Text>
<Text>{notification.payload.data.amsg}</Text>
</div>
))}
<div className="NotificationFeed__LoadMoreButtonContainer">
<FullWidthButton>Load more</FullWidthButton>
<div className="NotificationFeed__List">
{filteredNotifications?.map((notification) => (
<NotificationItem key={notification.payload_id} notification={notification} />
))}
</div>
{filteredNotifications.length !== userNotifications?.length && (
<div className="NotificationFeed__LoadMoreButtonContainer">
<FullWidthButton onClick={handleLoadMoreClick}>Load more</FullWidthButton>
</div>
)}
</div>
)}
{(isLoadingSubscriptions ||
Expand Down
11 changes: 11 additions & 0 deletions src/components/Notifications/NotificationItem.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
.NotificationItem {
padding: 0 16px;
}

.NotificationItem__Text {
margin-bottom: 0;
}

.NotificationItem__Date {
text-transform: uppercase;
}
26 changes: 26 additions & 0 deletions src/components/Notifications/NotificationItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import Time from '../../utils/date/Time'
import type { Notification } from '../../utils/notifications'
import Link from '../Common/Typography/Link'
import Text from '../Common/Typography/Text'

import './NotificationItem.css'

interface Props {
notification: Notification
}

export default function NotificationItem({ notification }: Props) {
const hasLink = !!notification.payload.data.acta
const Component = hasLink ? Link : 'div'

return (
<Component className="NotificationItem" href={notification.payload.data.acta}>
<Text className="NotificationItem__Text" size="sm">
{notification.payload.data.amsg}
</Text>
<Text className="NotificationItem__Date" color="secondary" size="xs">
{Time(notification.epoch).fromNow()}
</Text>
</Component>
)
}
2 changes: 2 additions & 0 deletions src/utils/notifications.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
// TODO: Move to notification types file
export type Notification = {
payload_id: number
epoch: string
payload: {
data: {
acta: string
asub: string
amsg: string
}
Expand Down

0 comments on commit 1209d17

Please sign in to comment.