Skip to content

Commit

Permalink
feat: add unread notifications indicator
Browse files Browse the repository at this point in the history
  • Loading branch information
Ni-2 committed Oct 2, 2024
1 parent fca8bf9 commit 550d03e
Show file tree
Hide file tree
Showing 6 changed files with 395 additions and 262 deletions.
11 changes: 4 additions & 7 deletions libs/shared-components/src/mini-overlay/OverlayWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import React, { FC, useRef } from 'react'
import styled from 'styled-components'
import { Drawer, Space, Button } from 'antd'
import { Typography } from 'antd'
import { NotificationProvider } from '@mweb/engine'
import NotificationFeed from '../notifications/NotificationFeed'
import CloseIcon from './assets/icons/Close'
const { Title } = Typography
Expand Down Expand Up @@ -180,12 +179,10 @@ const OverlayWrapper: FC<IOverlayWrapperProps> = ({
data-testid="overlay-notify"
children={
<Body ref={overlayRef}>
<NotificationProvider recipientId={loggedInAccountId}>
<NotificationFeed
connectWallet={connectWallet}
loggedInAccountId={loggedInAccountId}
/>
</NotificationProvider>
<NotificationFeed
connectWallet={connectWallet}
loggedInAccountId={loggedInAccountId}
/>
</Body>
}
></Drawer>
Expand Down
335 changes: 335 additions & 0 deletions libs/shared-components/src/mini-overlay/SidePanel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,335 @@
import React, { useEffect, useRef, useState } from 'react'
import styled from 'styled-components'
import { Button } from 'antd'
import { AppWithSettings, MutationDto, useNotifications } from '@mweb/engine'
import { Image } from '../common/Image'
import Profile, { IWalletConnect } from './Profile'
import { MutationFallbackIcon, ArrowIcon, BellIcon, BellWithCircle } from './assets/icons'

const SidePanelWrapper = styled.div<{ $isApps: boolean }>`
position: absolute;
z-index: 6000;
display: flex;
width: 58px;
top: 55px;
user-select: none;
flex-direction: column;
justify-content: center;
align-items: center;
border-radius: 4px 0px 0px 4px;
background: ${(props) => (props.$isApps ? '#EEEFF5' : '#F8F9FF')};
box-shadow: 0 4px 20px 0 rgba(11, 87, 111, 0.15);
font-family: sans-serif;
box-sizing: border-box;
`

const TopBlock = styled.div<{ $open?: boolean; $noMutations: boolean }>`
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding: 6px;
background: ${(props) => (props.$open ? '#fff' : 'transparent')};
border-width: 1px 0 1px 1px;
border-style: solid;
border-color: #e2e2e5;
border-radius: ${(props) => (props.$noMutations ? '4px 0 0 4px' : '4px 0 0 0')};
position: relative;
gap: 6px;
`

const ButtonWrapper = styled.div`
display: flex;
flex-direction: column;
box-sizing: content-box !important;
overflow: hidden;
justify-content: center;
align-items: center;
width: 46px;
margin-top: -7px;
padding: 0 5px 5px;
`

const AppsWrapper = styled.div`
display: flex;
flex-direction: column;
padding: 5px 6px;
gap: 10px;
`

const ButtonOpenWrapper = styled.div<{ $open?: boolean }>`
display: flex;
box-sizing: border-box;
justify-content: center;
align-items: center;
overflow: hidden;
width: 100%;
height: 32px;
background: ${(props) => (props.$open ? '#fff' : 'transparent')};
padding-left: 6px;
padding-right: 6px;
border-width: 1px 0 1px 1px;
border-style: solid;
border-color: #e2e2e5;
border-radius: 0 0 0 4px;
.svgTransform {
svg {
transform: rotate(180deg);
}
}
`

const ButtonOpen = styled.button<{ $open?: boolean }>`
display: flex;
box-sizing: border-box;
overflow: hidden;
justify-content: center;
align-items: center;
width: 100%;
height: 22px;
outline: none;
background: transparent;
border-radius: 4px;
border: ${(props) => (props.$open ? 'none' : '1px solid #e2e2e5')};
padding: 0;
path {
stroke: #7a818b;
}
&:hover {
background: #fff;
path {
stroke: #384bff;
}
}
&:active {
background: #384bff;
path {
stroke: #fff;
}
}
`

const MutationIconWrapper = styled.button<{ $isStopped?: boolean; $isButton: boolean }>`
display: flex;
box-sizing: border-box;
justify-content: center;
align-items: center;
width: 46px;
height: 46px;
outline: none;
border: none;
background: #fff;
padding: 0;
border-radius: 50%;
transition: all 0.15s ease-in-out;
position: relative;
box-shadow: 0 4px 5px 0 rgba(45, 52, 60, 0.2);
cursor: ${(props) => (props.$isButton ? 'pointer' : 'default !important')};
.labelAppCenter {
opacity: 0;
}
img {
box-sizing: border-box;
object-fit: cover;
width: 100%;
height: 100%;
border-radius: 50%;
filter: ${(props) => (props.$isStopped ? 'grayscale(1)' : 'grayscale(0)')};
transition: all 0.15s ease-in-out;
}
&:hover {
box-shadow: ${(props) =>
props.$isButton ? '0px 4px 20px 0px #0b576f26, 0px 4px 5px 0px #2d343c1a' : 'initial'};
img {
filter: ${(props) => (props.$isButton ? 'brightness(115%)' : 'none')};
}
}
&:active {
box-shadow: ${(props) =>
props.$isButton ? '0px 4px 20px 0px #0b576f26, 0px 4px 5px 0px #2d343c1a' : 'initial'};
img {
filter: ${(props) => (props.$isButton ? 'brightness(125%)' : 'none')};
}
}
&:hover .labelAppTop {
opacity: ${(props) => (props.$isStopped ? '0' : '1')};
}
&:hover .labelAppCenter {
opacity: 1;
}
`

const BellButton = styled(Button)<{ type?: string }>`
width: 44px !important;
height: 22px;
padding: 0 0 0 15px;
display: flex;
justify-content: flex-start;
svg > circle {
transition: all 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);
stroke: ${(props) => (props.type === 'primary' ? '#1677ff' : 'white')};
}
&:hover svg > circle {
stroke: ${(props) => (props.type === 'primary' ? '#4096ff' : 'white')};
}
&:active svg > circle {
stroke: ${(props) => (props.type === 'primary' ? '#0958d9' : 'white')};
}
`

interface ISidePanelProps extends Partial<IWalletConnect> {
children: React.ReactNode
baseMutation: MutationDto | null
mutationApps: AppWithSettings[]
loggedInAccountId?: string | null
overlayRef: React.RefObject<HTMLDivElement>
trackingRefs?: Set<React.RefObject<HTMLDivElement>>
open: boolean
setOpen: React.Dispatch<React.SetStateAction<boolean>>
}

const SidePanel: React.FC<ISidePanelProps> = ({
children,
nearNetwork,
connectWallet,
disconnectWallet,
loggedInAccountId,
baseMutation,
mutationApps,
overlayRef,
trackingRefs = new Set(),
open, // ToDo: change name
setOpen, // ToDo: change name
}) => {
const { notifications } = useNotifications()
const [haveUnreadNotifications, setHaveUnreadNotifications] = useState<boolean>(
!!notifications.filter((not) => not.status === 'new').length
)
const [isOpen, setIsOpen] = useState(false) // ToDo: change name
const [isProfileOpen, setProfileOpen] = useState(false)

const rootRef = useRef<HTMLDivElement>(null)
const openCloseWalletPopupRef = useRef<HTMLButtonElement>(null)

trackingRefs.add(rootRef)
trackingRefs.add(overlayRef)

useEffect(() => {
setHaveUnreadNotifications(!!notifications.filter((not) => not.status === 'new').length)
}, [notifications])

const showDrawer = () => setOpen((val) => !val)

const handleMutationIconClick = () => {
setProfileOpen((val) => !val)
}

const isMutationIconButton = !!connectWallet && !!disconnectWallet && !!nearNetwork

return (
<SidePanelWrapper
ref={rootRef}
$isApps={mutationApps.length > 0}
data-mweb-context-type="mweb-overlay"
data-mweb-context-parsed={JSON.stringify({ id: 'mweb-overlay' })}
data-mweb-context-level="system"
>
<TopBlock $open={isOpen || mutationApps.length > 0} $noMutations={!mutationApps.length}>
<MutationIconWrapper
$isButton={isMutationIconButton}
title={baseMutation?.metadata.name}
onClick={handleMutationIconClick}
ref={openCloseWalletPopupRef}
data-mweb-context-type="mweb-overlay"
data-mweb-context-parsed={JSON.stringify({
id: isMutationIconButton ? 'mutation-button' : 'mutation-icon',
})}
data-mweb-context-level="system"
>
{baseMutation?.metadata.image ? (
<Image image={baseMutation?.metadata.image} />
) : (
<MutationFallbackIcon />
)}
<div data-mweb-insertion-point="mutation-icon" style={{ display: 'none' }} />
</MutationIconWrapper>
{open ? (
<BellButton block type="primary" onClick={showDrawer}>
{haveUnreadNotifications ? (
<BellWithCircle isPrimary={true} />
) : (
<BellIcon color="white" />
)}
</BellButton>
) : (
<BellButton block onClick={showDrawer}>
{haveUnreadNotifications ? (
<BellWithCircle isPrimary={false} />
) : (
<BellIcon color="#7A818B" />
)}
</BellButton>
)}
</TopBlock>
{isOpen || !mutationApps.length ? null : (
<ButtonWrapper
data-mweb-insertion-point="mweb-actions-panel"
data-mweb-layout-manager="vertical"
/>
)}
{isOpen ? <AppsWrapper>{children}</AppsWrapper> : null}
{mutationApps.length > 0 ? (
<ButtonOpenWrapper
$open={isOpen || mutationApps.length > 0}
data-mweb-context-type="mweb-overlay"
data-mweb-context-parsed={JSON.stringify({ id: 'open-apps-button' })}
data-mweb-context-level="system"
>
<ButtonOpen
$open={isOpen}
className={isOpen ? 'svgTransform' : ''}
onClick={() => {
setOpen(false)
setIsOpen(!isOpen)
}}
>
<ArrowIcon />
</ButtonOpen>
<div data-mweb-insertion-point="open-apps-button" style={{ display: 'none' }} />
</ButtonOpenWrapper>
) : null}
{isProfileOpen && isMutationIconButton ? (
<Profile
accountId={loggedInAccountId ?? null}
closeProfile={() => {
setProfileOpen(false)
}}
connectWallet={connectWallet}
disconnectWallet={disconnectWallet}
nearNetwork={nearNetwork}
trackingRefs={trackingRefs}
openCloseWalletPopupRef={openCloseWalletPopupRef}
/>
) : null}
</SidePanelWrapper>
)
}

export default SidePanel
8 changes: 4 additions & 4 deletions libs/shared-components/src/mini-overlay/assets/icons/Bell.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import React from 'react'

const Bell = (p: string, s: string) => {
const Bell = ({ color }: { color: string }) => {
return (
<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12" fill="none">
<path
d="M9.4375 3.81817C9.4375 2.95019 9.08982 2.11776 8.47095 1.504C7.85208 0.890245 7.01271 0.545441 6.1375 0.545441C5.26229 0.545441 4.42292 0.890245 3.80405 1.504C3.18518 2.11776 2.8375 2.95019 2.8375 3.81817C2.8375 7.63635 1.1875 8.72726 1.1875 8.72726H11.0875C11.0875 8.72726 9.4375 7.63635 9.4375 3.81817Z"
fill={p}
stroke={s}
fill={color}
stroke={color}
strokeLinecap="round"
strokeLinejoin="round"
/>
<path
d="M7.08855 10.9091C6.99185 11.0744 6.85306 11.2116 6.68607 11.307C6.51908 11.4024 6.32976 11.4526 6.13705 11.4526C5.94434 11.4526 5.75501 11.4024 5.58802 11.307C5.42103 11.2116 5.28224 11.0744 5.18555 10.9091"
stroke={s}
stroke={color}
strokeLinecap="round"
strokeLinejoin="round"
/>
Expand Down
Loading

0 comments on commit 550d03e

Please sign in to comment.