Skip to content

Commit

Permalink
load more and group notifications instead of pagination
Browse files Browse the repository at this point in the history
  • Loading branch information
GraemeFulton committed Jun 30, 2024
1 parent 29a1dfe commit be97689
Show file tree
Hide file tree
Showing 5 changed files with 150 additions and 55 deletions.
30 changes: 30 additions & 0 deletions components/LoadMoreButton.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import React from 'react';
import Button from './Primitives/Button';

const LoadMoreButton = ({
total,
pageSize,
currentCount,
onLoadMore,
loading
}) => {
const hasMore = currentCount < total;

if (!hasMore) return null;

return (
<div className="flex justify-center mt-2 pb-12 md:pb-4">
<Button
onClick={onLoadMore}
disabled={loading}
className={`!rounded-full ${
loading ? 'opacity-50 cursor-not-allowed' : ''
}`}
>
{loading ? 'Loading...' : 'Load more'}
</Button>
</div>
);
};

export default LoadMoreButton;
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,13 @@ const GroupedLikeNotification = ({ notification }) => {
})}
</p>
</div>
{(notification.read === false || notification.read === "false") && (
{(notification.read === false || notification.read === "false") ? (
<div className="flex-shrink-0 my-auto">
<div className="rounded-full flex-none bg-blue-500 h-[9px] w-[9px] my-auto mr-2"></div>
</div>
)}
): <div className="flex-shrink-0 my-auto">
<div className="rounded-full flex-none bg-white h-[9px] w-[9px] my-auto mr-2"></div>
</div>}
</div>
);
};
Expand Down
86 changes: 49 additions & 37 deletions components/Notifications/NotificationsList.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import NotificationEmptyState from "./EmptyState";
import axios from "axios";
import { useRouter } from "next/navigation";
import GroupedLikeNotification from "./NotificationCard/GroupedLikeNotification";
import LoadMoreButton from "../LoadMoreButton";

const NotificationsList = () => {
const { user } = useUser({
Expand All @@ -23,7 +24,7 @@ const NotificationsList = () => {

const router = useRouter();

const { notifications, loading, refetch, total, pageSize } =
const { notifications, loading, refetch, total, pageSize, fetchMore,hasMoreNotifications } =
useFetchNotifications(user);

const [currentPage, setCurrentPage] = useState(1);
Expand All @@ -32,23 +33,26 @@ const NotificationsList = () => {
refetch(1);
}, [user]);

const changePage = offset => {
setCurrentPage(offset);
refetch(offset);
// const changePage = offset => {
// setCurrentPage(offset);
// refetch(offset);
// };
const loadMore = () => {
const nextPage = currentPage + 1;
setCurrentPage(nextPage);
fetchMore(nextPage);
};

const [showMarkAllAsRead, setShowMarkAllAsRead] = useState(false);
useEffect(() => {
for(let i = 0; i < notifications?.length; i++) {
if (notifications[i].read == 'false') {
for (let i = 0; i < notifications?.length; i++) {
if (notifications[i].read == "false") {
setShowMarkAllAsRead(true);
break;
}
}

}, [notifications]);


const clearNotifications = async id => {
var data = JSON.stringify({
id: id ? id : "*",
Expand All @@ -74,46 +78,54 @@ const NotificationsList = () => {
.catch(function (error) {
console.log(error);
});

location.reload()
};

location.reload();
};

return (
<div className="flex flex-col">
{/* <header className="bg-gray-900 text-white py-4 px-6">
<h1 className="text-2xl font-bold">Notifications</h1>
</header> */}
<main className="flex-1 my-6">
<div className="grid gap-4">
{loading ? (
[1, 2, 3, 4, 5, 6].map(i => <Skeleton key={i} />)
) : notifications?.length ? (
notifications.map(notification => (
<NotificationItem
key={notification.id}
notification={notification}
/>
))
) : (
<NotificationEmptyState />
)}
</div>
</main>
<div>
{showMarkAllAsRead ? (
<footer className="py-4 flex justify-end">
<Button onClick={() => clearNotifications("*")}>
Mark All as Read
<footer className="py-4 flex justify-end -mt-[64px]">
<Button variant={'ghostSmallBlue'} className="!rounded-full" onClick={() => clearNotifications("*")}>
Mark all as read
</Button>
</footer>
) : null}

<NewPagination
<div className="flex flex-col">
{/* <header className="bg-gray-900 text-white py-4 px-6">
<h1 className="text-2xl font-bold">Notifications</h1>
</header> */}
<main className="flex-1 my-6">
<div className="grid gap-4">
{loading ? (
[1, 2, 3, 4, 5, 6].map(i => <Skeleton key={i} />)
) : notifications?.length ? (
notifications.map(notification => (
<NotificationItem
key={notification.id}
notification={notification}
/>
))
) : (
<NotificationEmptyState />
)}
</div>
</main>

{/* <NewPagination
total={total}
pageSize={pageSize}
currentPage={currentPage}
onPageNumChange={changePage}
/>
/> */}
{hasMoreNotifications?<LoadMoreButton
total={total}
pageSize={pageSize}
currentCount={notifications?.length}
onLoadMore={loadMore}
loading={loading}
/>:null}
</div>
</div>
);
};
Expand Down
79 changes: 65 additions & 14 deletions components/Notifications/useFetchNotifications.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,31 @@
"use client";
import { useEffect, useState } from "react";
import { getUserNotifications } from "@/lib/api";
import { groupNotifications } from "@/lib/notifications/groupNotifications";

const PAGE_SIZE = 9;
const PAGE_SIZE = 8;

const ungroupNotifications = (groupedNotifications) => {
return groupedNotifications.flatMap(notification =>
notification.groupInfo ? notification.groupInfo.notifications : notification
);
};

const useFetchNotifications = user => {
const [total, setTotal] = useState(null);
const [notifications, setNotifications] = useState(null);
const [notifications, setNotifications] = useState([]);
const [loading, setLoading] = useState(true);
const [currentPage, setCurrentPage] = useState(1);
const [hasMoreNotifications, setHasMoreNotifications] = useState(true);

useEffect(() => {
refetch(1);
refetch();
}, []);

const refetch = async offset => {
const refetch = async () => {
setLoading(true);

let pageOffset = (offset - 1) * PAGE_SIZE;
if (!pageOffset) {
pageOffset = 0;
}
setCurrentPage(1);
setHasMoreNotifications(true);

if (!user) {
return false;
Expand All @@ -28,18 +34,63 @@ const useFetchNotifications = user => {
const data = await getUserNotifications({
user,
pageSize: PAGE_SIZE,
offset: pageOffset,
offset: 0,
});

const notificationsForUser = data.userNotifications?.notifications;
const notificationsForUser = data.userNotifications?.notifications || [];
const groupedNotifications = groupNotifications(notificationsForUser);

setNotifications(notificationsForUser);
setNotifications(groupedNotifications);
setTotal(data.userNotifications?.count);
setHasMoreNotifications(groupedNotifications.length < data.userNotifications?.count);

setLoading(false);
};

return { loading, notifications, total, pageSize: PAGE_SIZE, refetch };
const fetchMore = async () => {
if (loading || !hasMoreNotifications) {
return;
}

setLoading(true);

const nextPage = currentPage + 1;
const pageOffset = (nextPage - 1) * PAGE_SIZE;

const data = await getUserNotifications({
user,
pageSize: PAGE_SIZE,
offset: pageOffset,
});

const newNotifications = data.userNotifications?.notifications || [];

if (newNotifications.length === 0) {
setHasMoreNotifications(false);
setLoading(false);
return;
}

const ungroupedExistingNotifications = ungroupNotifications(notifications);
const combinedNotifications = [...ungroupedExistingNotifications, ...newNotifications];
const regroupedNotifications = groupNotifications(combinedNotifications);

setNotifications(regroupedNotifications);
setCurrentPage(nextPage);
setHasMoreNotifications(regroupedNotifications.length < total);

setLoading(false);
};

return {
loading,
notifications,
total,
pageSize: PAGE_SIZE,
refetch,
fetchMore,
hasMoreNotifications
};
};

export default useFetchNotifications;
export default useFetchNotifications;
4 changes: 2 additions & 2 deletions lib/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ import creatorArticlesQuery from "./queries/creatorArticlesQuery";
import getUserRelatedPostsFromPostId from "./queries/getUserRelatedPostsFromPostId";
import likeCountQuery from "./queries/likeCountQuery";
import notificationCountQuery from "./queries/notificationCountQuery";
import { groupNotifications } from "./notifications/groupNotifications";
// import { groupNotifications } from "./notifications/groupNotifications";
/**
* main fetch
* @param {*} query
Expand Down Expand Up @@ -722,7 +722,7 @@ export async function getUserNotifications({ user, pageSize, offset }) {
});
if(data.userNotifications.notifications.length === 0) return data;
//group the notifications
data.userNotifications.notifications = groupNotifications(data.userNotifications?.notifications);
// data.userNotifications.notifications = groupNotifications(data.userNotifications?.notifications);
return data;
}

Expand Down

0 comments on commit be97689

Please sign in to comment.