Skip to content

Commit

Permalink
Merge pull request #79 from blahkheart/dev
Browse files Browse the repository at this point in the history
Projects and lists Pagination
  • Loading branch information
escottalexander authored Sep 25, 2023
2 parents ce990fa + 9df813c commit 3f6749a
Show file tree
Hide file tree
Showing 8 changed files with 208 additions and 113 deletions.
87 changes: 59 additions & 28 deletions packages/nextjs/components/lists/AllLists.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import React, { useState } from "react";
import React, { useEffect, useState } from "react";
import { Spinner } from "../Spinner";
import Pagination from "./Pagination";
import useSWR from "swr";
import { useSignMessage } from "wagmi";
import { useAccount } from "wagmi";
import Card from "~~/components/lists/Card";
import ListHeader from "~~/components/lists/ListHeader";
import Pagination from "~~/components/lists/Pagination";
import YourBallot from "~~/components/op/projects/YourBallot";
import Sidebar from "~~/components/shared/Sidebar";
import { ListDocument } from "~~/models/List";
import VerifyOptions from "~~/types/verifyOptions";
import { fetcher } from "~~/utils/fetcher";
Expand All @@ -18,7 +21,15 @@ const AllLists: React.FC = () => {
const [selectedCategory, setSelectedCategory] = useState("all");
const [isLoading, setIsLoading] = useState(false);
const [loadingListId, setLoadingListId] = useState<string>("");
const { data: lists, mutate } = useSWR<ListDocument[]>(`/api/list`, fetcher);
const {
data: listsData,
isLoading: isLoadingList,
mutate,
} = useSWR(`/api/list?pageQuery=${currentPage}&limit=12`, fetcher);
const [totalPages, setTotalPages] = useState(1);
const [lists, setLists] = useState<ListDocument[] | undefined>([]);
const { isDisconnected } = useAccount();
const [wallet, setWallet] = useState<boolean | false>(false);

const { signMessageAsync } = useSignMessage({
onSettled(data, error) {
Expand All @@ -28,7 +39,6 @@ const AllLists: React.FC = () => {
});

const { address } = useAccount();
const totalPages = 5;

const handlePageChange = (pageNumber: any) => {
setCurrentPage(pageNumber);
Expand All @@ -43,17 +53,15 @@ const AllLists: React.FC = () => {
return await signMessageAsync({ message: messageToSign });
};

// const sendLikeRequest = async (address: string | undefined, signature: string, listId: string) => {
// const payload = { address, signature, listId };
useEffect(() => {
setWallet(isDisconnected);
}, [isDisconnected]);

// const response = await fetch("/api/list/like", {
// method: "POST",
// headers: { "content-type": "application/json" },
// body: JSON.stringify(payload),
// });

// return response.json();
// };
useEffect(() => {
if (!listsData) return;
setTotalPages(listsData.totalPages);
setLists(listsData.lists);
}, [listsData]);

const handleLike = async (list: any) => {
try {
Expand Down Expand Up @@ -83,27 +91,50 @@ const AllLists: React.FC = () => {
const filteredProjects =
selectedCategory === "all" ? lists : lists?.filter(list => list?.tags?.includes(selectedCategory));

if (lists && lists?.length < 1)
if (lists && lists.length === 0 && isLoadingList) {
return (
<div className="flex mt-8 pt-8 justify-center">
<Spinner />
</div>
);
}

if (lists && lists.length === 0)
return (
<div className="text-center font-bold text-2xl pt-8">
<h1>No list available...</h1>
</div>
);

return (
<div className="w-full">
<ListHeader displayList={displayList} titleHeader="Lists" display={display} onCategoryChange={onCategoryChange} />
<div
className={`px-4 w-full grid pt-8 gap-4 ${
display === "grids" ? "list__container-card_display " : "grid-rows-1 w-full"
} `}
>
{filteredProjects?.map(list => (
<div key={list._id} className={`${display === "grids" && "w-fit"}`}>
<Card list={list} isLoading={isLoading} loadingList={loadingListId} onLike={() => handleLike(list)} />
<div className="mx-auto px-12 mt-12 grid lg:grid-cols-[350px,1fr] gap-4">
{!wallet ? <YourBallot /> : <Sidebar />}
{isLoadingList ? (
<div className="flex mt-8 pt-8 justify-center">
<Spinner />
</div>
) : (
<div className="w-full pb-10 mb-5">
<ListHeader
displayList={displayList}
titleHeader="Lists"
display={display}
onCategoryChange={onCategoryChange}
/>
<div
className={`px-4 w-full grid pt-8 gap-4 ${
display === "grids" ? "list__container-card_display " : "grid-rows-1 w-full"
} `}
>
{filteredProjects?.map(list => (
<div key={list._id} className={`${display === "grids" && "w-fit"}`}>
<Card list={list} isLoading={isLoading} loadingList={loadingListId} onLike={() => handleLike(list)} />
</div>
))}
</div>
))}
</div>
<Pagination currentPage={currentPage} totalPages={totalPages} onPageChange={handlePageChange} />
<Pagination currentPage={currentPage} totalPages={totalPages} onPageChange={handlePageChange} />
</div>
)}
</div>
);
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import React from "react";

const Pagination = ({ currentPage, totalPages, onPageChange }) => {
const range = (from, to) => {
interface IPagination {
currentPage: number;
totalPages: number;
onPageChange: (page: number) => void;
}

const Pagination: React.FC<IPagination> = ({ currentPage, totalPages, onPageChange }) => {
const range = (from: number, to: number) => {
return Array.from({ length: to - from + 1 }, (_, i) => from + i);
};

Expand Down Expand Up @@ -36,10 +42,15 @@ const Pagination = ({ currentPage, totalPages, onPageChange }) => {
</button>
))}

{nextPage && (
{totalPages > 1 && (
<button
className="px-4 py-2 rounded-md font-normal text-base leading-6 font-inter border border-gray-300 bg-white text-lightBlack hover:bg-customWhite"
onClick={() => onPageChange(nextPage)}
disabled={!nextPage}
className={`px-4 py-2 rounded-md font-normal text-base leading-6 font-inter border border-gray-300 ${
!nextPage
? "bg-gray-300 text-gray-500 cursor-not-allowed hover:bg-gray-300 hover:text-gray-500"
: "bg-white text-lightBlack hover:bg-customWhite"
}`}
onClick={() => onPageChange(nextPage ? nextPage : 1)}
>
Next
</button>
Expand Down
1 change: 0 additions & 1 deletion packages/nextjs/components/project/ProjectHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ const ProjectHeader = ({ project }: { project: ProjectDocument }) => {
const [isSuccess, setIsSuccess] = useState(false);
const [loadingMessage, setLoadingMessage] = useState("");
const [successMessage, setSuccessMessage] = useState("");
// const userData = { totalOP: 100000 };
const [isAdded, setIsAdded] = useState(false);
const { state, dispatch } = useBallot();

Expand Down
103 changes: 70 additions & 33 deletions packages/nextjs/components/projects/AllProjects.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,25 @@
import React, { useEffect, useState } from "react";
import { Spinner } from "../Spinner";
import Pagination from "../lists/Pagination";
import useSWR from "swr";
import { useAccount } from "wagmi";
import ListHeader from "~~/components/lists/ListHeader";
import Pagination from "~~/components/lists/Pagination";
import YourBallot from "~~/components/op/projects/YourBallot";
import Card from "~~/components/projects/Card";
import Sidebar from "~~/components/shared/Sidebar";
import { ProjectDocument } from "~~/models/Project";
import { fetcher } from "~~/utils/fetcher";

interface Props {
projects: ProjectDocument[];
}

const AllProjects: React.FC<Props> = ({ projects }) => {
const AllProjects = () => {
const { isDisconnected } = useAccount();
const [wallet, setWallet] = useState<boolean | false>(false);
const [display, setDisplay] = useState("grids");
const [currentPage, setCurrentPage] = useState(1);
const { data: projectsData, isLoading } = useSWR(`/api/projects?pageQuery=${currentPage}&limit=12`, fetcher);
const [selectedCategory, setSelectedCategory] = useState("all");
const [allProjects, setAllProjects] = useState<ProjectDocument[]>(projects);
const [filteredProjects, setFilteredProjects] = useState<ProjectDocument[]>(projects);
const [shuffledProjects, setShuffledProjects] = useState<ProjectDocument[]>(projects);
const totalPages = 5;
const [allProjects, setAllProjects] = useState<ProjectDocument[] | undefined>([]);
const [filteredProjects, setFilteredProjects] = useState<ProjectDocument[] | undefined>([]);
const [totalPages, setTotalPages] = useState(1);

const handlePageChange = (pageNumber: any) => {
setCurrentPage(pageNumber);
Expand All @@ -25,42 +29,75 @@ const AllProjects: React.FC<Props> = ({ projects }) => {
setDisplay(option);
};

useEffect(() => {
setWallet(isDisconnected);
}, [isDisconnected]);

useEffect(() => {
function filterProjects() {
const _filteredProjects =
selectedCategory === "all" ? allProjects : allProjects.filter(project => project.category === selectedCategory);
selectedCategory === "all"
? allProjects
: allProjects?.filter(project => project.category === selectedCategory);
setFilteredProjects(_filteredProjects);
}
filterProjects();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [selectedCategory, allProjects]);

useEffect(() => {
setAllProjects(shuffledProjects);
}, [shuffledProjects]);
if (!projectsData) return;
setTotalPages(projectsData.totalPages);
setAllProjects(projectsData.projects);
}, [projectsData]);

if (allProjects && allProjects.length === 0 && isLoading) {
return (
<div className="flex mt-8 pt-8 justify-center">
<Spinner />
</div>
);
}

if (allProjects && allProjects.length === 0) {
return (
<div className="text-center font-bold text-2xl pt-8">
<h1>No projects available...</h1>
</div>
);
}

return (
<div className="w-full">
<div className="container mx-auto">
<ListHeader
displayList={displayList}
titleHeader="Projects"
display={display}
onCategoryChange={setSelectedCategory}
projects={allProjects}
onShuffleProjects={setShuffledProjects}
/>
<div
className={`px-4 grid pt-8 gap-4 ${
display == "grids" ? "lg:grid-cols-3 md:grid-cols-2 sm:grid-cols-1" : "grid-rows-1 w-full"
} `}
>
{filteredProjects.map(project => (
<Card key={project._id} project={project} display={display} />
))}
</div>
<div className="mx-auto px-12 mt-12 grid lg:grid-cols-[350px,1fr] gap-4">
{!wallet ? <YourBallot /> : <Sidebar />}
<div>
{isLoading ? (
<div className="flex justify-center">
<Spinner />
</div>
) : (
<div className="container mx-auto">
<ListHeader
displayList={displayList}
titleHeader="Projects"
display={display}
onCategoryChange={setSelectedCategory}
projects={allProjects}
onShuffleProjects={setAllProjects}
/>
<div
className={`px-4 grid pt-8 gap-4 ${
display == "grids" ? "lg:grid-cols-3 md:grid-cols-2 sm:grid-cols-1" : "grid-rows-1 w-full"
} `}
>
{filteredProjects?.map(project => (
<Card key={project._id} project={project} display={display} />
))}
</div>

<Pagination currentPage={currentPage} totalPages={totalPages} onPageChange={handlePageChange} />
<Pagination currentPage={currentPage} totalPages={totalPages} onPageChange={handlePageChange} />
</div>
)}
</div>
</div>
);
Expand Down
28 changes: 26 additions & 2 deletions packages/nextjs/pages/api/list/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,32 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
// Connect to the database
await dbConnect();
if (req.method === "GET") {
const lists: ListDocument[] = await List.find({});
return res.status(200).json(lists);
const { pageQuery } = req.query;
const { limit } = req.query;
if (pageQuery) {
const page = parseInt(Array.isArray(pageQuery) ? pageQuery[0] : pageQuery, 10);
const pagesLimit = limit && parseInt(Array.isArray(limit) ? limit[0] : limit, 10);
// Pagination variables
const pageSize: any = pagesLimit ?? 9;
const totalProjects = await List.countDocuments();
const totalPages = Math.ceil(totalProjects / pageSize);
if (page > totalPages) {
return res.status(404).json({ message: "Page not found" });
}

// Determine the number of documents to skip based on the current page
const skip = (page - 1) * pageSize;

// Fetch the projects for the current page
const lists: ListDocument[] = await List.find().skip(skip).limit(pageSize).exec();

console.log(`API GET /api/list?pageQuery=${page}`);

return res.status(200).json({ lists, totalPages });
} else {
const lists: ListDocument[] = await List.find({});
return res.status(200).json(lists);
}
}

if (req.method !== "POST") {
Expand Down
34 changes: 31 additions & 3 deletions packages/nextjs/pages/api/projects/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,35 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
return res.status(405).json({ message: "Method not allowed." });
}
await dbConnect();
const projects: ProjectDocument[] = await Project.find({});
console.log("API GET /api/projects");
return res.status(200).json(projects);
const { pageQuery } = req.query;
const { limit } = req.query;
if (pageQuery) {
const page = parseInt(Array.isArray(pageQuery) ? pageQuery[0] : pageQuery, 10);
const pagesLimit = limit && parseInt(Array.isArray(limit) ? limit[0] : limit, 10);
// Pagination variables
const pageSize: any = pagesLimit ?? 9;
const totalProjects = await Project.countDocuments();
const totalPages = Math.ceil(totalProjects / pageSize);

if (page > totalPages) {
return res.status(404).json({ message: "Page not found" });
}

// Determine the number of documents to skip based on the current page
const skip = (page - 1) * pageSize;

// Fetch the projects for the current page
const projects: ProjectDocument[] = await Project.find().skip(skip).limit(pageSize).exec();

console.log(`API GET /api/projects?pageQuery=${page}`);

return res.status(200).json({ projects, totalPages });
} else {
// Fetch all projects if pageQuery isn't provided
const projects: ProjectDocument[] = await Project.find({});

console.log("API GET /api/projects");

return res.status(200).json(projects);
}
}
Loading

0 comments on commit 3f6749a

Please sign in to comment.