diff --git a/components/NotificationsTable.js b/components/NotificationsTable.js index f6883c82b..a267e23ee 100644 --- a/components/NotificationsTable.js +++ b/components/NotificationsTable.js @@ -1,7 +1,8 @@ /* globals DOMPurify, marked: false */ -import { useState, useEffect } from 'react' +import { useState, useEffect, useCallback } from 'react' import upperFirst from 'lodash/upperFirst' +import { debounce } from 'lodash' import Table from './Table' import Collapse from './Collapse' import { formatDateTime, prettyId } from '../lib/utils' @@ -11,12 +12,37 @@ export default function NotificationsTable({ numUnviewed, markViewed, markAllViewed, + setSearchTerm, + searchTerm, }) { + const [immediateSearchTerm, setImmediateSearchTerm] = useState(null) + + const delaySearch = useCallback( + debounce((term) => setSearchTerm(term), 300), + [] + ) + + useEffect(() => { + if (searchTerm !== null) return + setImmediateSearchTerm(null) + }, [searchTerm]) + if (!messages) return null const headingContent = ( - <> - Message Details +
+
+ + { + setImmediateSearchTerm(e.target.value) + delaySearch(e.target.value) + }} + /> +
) return ( diff --git a/pages/notifications.js b/pages/notifications.js index 494eb13e6..e79986559 100644 --- a/pages/notifications.js +++ b/pages/notifications.js @@ -25,6 +25,7 @@ export default function Notifications({ appContext }) { const [page, setPage] = useState(1) const [error, setError] = useState(null) const [shouldRefresh, setShouldRefresh] = useState(false) + const [searchTerm, setSearchTerm] = useState(null) const router = useRouter() const { setUnreadNotificationCount, decrementNotificationCount } = useContext(UserContext) const { setBannerHidden } = appContext @@ -93,6 +94,7 @@ export default function Notifications({ appContext }) { setToEmail(router.query.email || user.profile.preferredEmail || user.profile.emails[0]) setPage(1) + setSearchTerm(null) }, [user?.id, router.isReady, router.query.email]) useEffect(() => { @@ -147,11 +149,13 @@ export default function Notifications({ appContext }) { if (!accessToken || !toEmail) return setError(null) + const cleanSearchTerm = searchTerm?.trim() api .get( '/messages', { + ...(cleanSearchTerm?.length && { subject: `${cleanSearchTerm}.*` }), to: toEmail, limit: pageSize, offset: pageSize * (page - 1), @@ -168,6 +172,34 @@ export default function Notifications({ appContext }) { }) }, [accessToken, toEmail, page, shouldRefresh]) + useEffect(() => { + const cleanSearchTerm = searchTerm?.trim() + if (!cleanSearchTerm?.length) { + if (searchTerm === '') { + // search term cleared + setPage(1) + setShouldRefresh((refresh) => !refresh) + } + return + } + api + .get( + '/messages', + { subject: `${cleanSearchTerm}.*`, to: toEmail, limit: pageSize }, + + { accessToken } + ) + .then((apiRes) => { + setMessages(apiRes.messages ?? []) + setCount(apiRes.count ?? 0) + setPage(1) + }) + .catch((apiError) => { + setError(apiError) + setMessages(null) + }) + }, [searchTerm]) + return (
@@ -231,6 +263,8 @@ export default function Notifications({ appContext }) { numUnviewed={unviewedCounts?.[toEmail] ?? 0} markViewed={markViewed} markAllViewed={markAllViewed} + setSearchTerm={setSearchTerm} + searchTerm={searchTerm} />