Skip to content

Commit

Permalink
notifications
Browse files Browse the repository at this point in the history
  • Loading branch information
xkopenreview committed Dec 23, 2024
1 parent 6064f3f commit 2357d46
Show file tree
Hide file tree
Showing 12 changed files with 534 additions and 17 deletions.
31 changes: 15 additions & 16 deletions app/(Home)/NavNotificationCount.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,28 +36,27 @@
// }
//#endregion

import { Suspense } from 'react'
import api from '../../lib/api-client'
import serverAuth from '../auth'
import serverAuth, { isSuperUser } from '../auth'
import NotificationCount from './NotificationCount'

export const dynamic = 'force-dynamic'

export default async function NavNotificationCount() {
const { user, token } = await serverAuth()
let count = 0
if (!user) {
if (!user || isSuperUser(user)) {
return null
}
try {
const result = await api.get(
'/messages',
{ to: user.profile.emails[0], viewed: false, transitiveMembers: true },
{ accessToken: token }
)
count = result.count
} catch (error) {
console.log('error is', error)
}

if (count === 0) return null
return <span className="badge">{count}</span>
const notificationCountP = api.get(
'/messages',
{ to: user.profile.emails[0], viewed: false, transitiveMembers: true },
{ accessToken: token }
)

return (
<Suspense fallback={null}>
<NotificationCount notificationCountP={notificationCountP} />
</Suspense>
)
}
23 changes: 23 additions & 0 deletions app/(Home)/NotificationCount.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
'use client'

import { use, useEffect, useState } from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { setNotificationCount } from '../../notificationSlice'

export default function NotificationCount({ notificationCountP }) {
const { count: initialCount } = use(notificationCountP)
const { count: storeCount } = useSelector((state) => state.notification)
const [count, setCount] = useState(initialCount)
const dispatch = useDispatch()

useEffect(() => {
if (storeCount === null) {
dispatch(setNotificationCount(initialCount))
return
}
setCount(storeCount)
}, [storeCount])

if (!count) return null
return <span className="badge">{count}</span>
}
104 changes: 104 additions & 0 deletions app/notifications/Notifications.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
'use client'

import { use, useState } from 'react'
import Table from '../../components/Table'
import NotificationsTable from './NotificationsTable'
import { useDispatch, useSelector } from 'react-redux'
import api from '../../lib/api-client'
import { decrementNotificationCount } from '../../notificationSlice'

export default function Notifications({
unviewedMessagesCountsP,
confirmedEmails,
defaultToEmail,
}) {
const [toEmail, setToEmail] = useState(defaultToEmail)
const initialUnviewedCounts = use(unviewedMessagesCountsP)
const [unviewedCounts, setUnviewedCounts] = useState(initialUnviewedCounts)
const { token } = useSelector((state) => state.root)
const dispatch = useDispatch()

const markAllViewed = async () => {
try {
const apiRes = await api.get(
'/messages',
{ to: toEmail, viewed: false },
{ accessToken: token }
)
if (!apiRes.messages?.length) return

const unreadMessageIds = apiRes.messages.map((m) => m.id)
await api.post(
'/messages/viewed',
{ ids: unreadMessageIds, vdate: Date.now() },
{ accessToken: token }
)

setUnviewedCounts({
...unviewedCounts,
[toEmail]: unviewedCounts[toEmail] - unreadMessageIds.length,
})
dispatch(decrementNotificationCount(unreadMessageIds.length))
} catch (apiError) {
promptError(apiError.message)
}
}
const markViewed = async (messageId) => {
const now = Date.now()
try {
await api.post(
'/messages/viewed',
{ ids: [messageId], vdate: now },
{ accessToken: token }
)
setUnviewedCounts({
...unviewedCounts,
[toEmail]: unviewedCounts[toEmail] - 1,
})
dispatch(decrementNotificationCount(1))
} catch (apiError) {
promptError(apiError.message)
}
}

return (
<div className="row">
<div className="filters-col">
<Table
className="filters-table"
headings={[{ id: 'filters', content: <span>Inboxes</span> }]}
>
<tr>
<td>
<ul className="nav nav-pills nav-stacked">
{confirmedEmails.map((email) => (
<li
key={email}
role="presentation"
className={toEmail === email ? 'active' : null}
onClick={(e) => {
setToEmail(email)
}}
>
<a>{email}</a>
{unviewedCounts?.[email] > 0 && (
<span className="badge badge-light">{unviewedCounts[email]}</span>
)}
</li>
))}
</ul>
</td>
</tr>
</Table>
</div>
<div className="messages-col">
<NotificationsTable
toEmail={toEmail}
numUnviewed={unviewedCounts?.[toEmail] ?? 0}
markViewed={markViewed}
markAllViewed={markAllViewed}
/>
</div>
</div>
)
}
126 changes: 126 additions & 0 deletions app/notifications/Notifications.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
@use '../../styles/utils/constants';
@use '../../styles/utils/mixins';

.notifications :global {
header h1 {
margin-bottom: 1.5rem;
}

.filters-col {
margin-left: 15px;
margin-right: 15px;
}
.messages-col {
margin-left: 15px;
margin-right: 15px;
}
@media #{constants.$desktop} {
.filters-col {
float: left;
width: 245px;
margin-right: 0.5rem;
}
.messages-col {
float: left;
width: calc(100% - 245px - 30px - 1rem);
margin-left: 0.5rem;
}
}

.table > thead > tr > th {
padding: 0.375rem 0.5rem;
}
table.messages-table {
border-bottom: 0;

th > span.pull-left {
line-height: 26px;
}
td.viewed {
opacity: 0.6;
background-color: #eee;
&:hover {
opacity: 0.8;
}
.collapse-widget > div {
border-left: 3px solid #fff;
padding-top: 0.5rem;
padding-right: 0.5rem;
padding-bottom: 0.5rem;
background-color: constants.$backgroundWhite;
}
}
.email-title h4 {
font-size: 1rem;
line-height: normal;
color: constants.$darkBlue;
cursor: pointer;
margin: 0;
}
.collapse-widget > div {
margin-top: 0.375rem;
border-left: 3px solid #eee;
padding-left: 0.875rem;
}
}
.markdown-rendered {
@include mixins.markdown-content-styles;
p:last-child {
margin-bottom: 0;
}
}
.filters-table {
th > span {
line-height: 26px;
}
tbody > tr > td {
padding: 0;
padding-top: 0.75rem;
}
}
.nav-stacked {
& > li {
display: flex;
justify-content: space-between;
border-radius: 4px;
padding: 12px 10px;
cursor: pointer;

&:hover {
background-color: constants.$borderGray;
}
&.active {
background-color: constants.$mediumDarkBlue;
& > a {
background-color: transparent;
}
& > .badge {
background-color: constants.$backgroundWhite;
color: constants.$mediumDarkBlue;
}
}

& > a {
padding: 0;
font-weight: bold;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
&:hover {
background-color: transparent;
}
}
}
& > li + li {
margin-top: 6px;
}
.badge {
background-color: constants.$mediumDarkBlue;
padding: 0px 6px;
min-width: 20px;
line-height: 20px;
margin-left: 4px;
flex-shrink: 0;
}
}
}
Loading

0 comments on commit 2357d46

Please sign in to comment.