Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add /api/projects endpoints #34

Closed
wants to merge 12 commits into from
31,039 changes: 17,370 additions & 13,669 deletions packages/firebase/seed.sample.json

Large diffs are not rendered by default.

8 changes: 3 additions & 5 deletions packages/nextjs/app/project/[id]/page.tsx
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file won't display for me due to lines 43-56 where [...data?.github, ...data?.packages]. If the project doesn't have github or packages properties then the spread operator is trying to act upon undefined causing this error:
Error: (intermediate value) is not iterable.

We should check for the existence of github and packages before using the spread operator.

Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,9 @@ import { ProjectTotalsComponent } from "~~/components/onchain-impact-dashboard/p
import { ProjectService } from "~~/services/onchainImpactDashboardApi/projectService";

export async function generateStaticParams() {
const { getPaginatedProjects } = ProjectService();
const data = await getPaginatedProjects();
return data.map(item => ({
id: item.id,
}));
const { getProjectIds } = ProjectService();
const projectIds = await getProjectIds();
return projectIds.map(id => ({ id }));
}

const ProjectDetail: NextPage<{ params: { id: string } }> = async ({ params }) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ export const LeaderBoardComponent = () => {
const [startDate, setStartDate] = useState("");
const [endDate, setEndDate] = useState("");
const { getPaginatedGlobalScores } = GlobalScoreService();
const { getPaginatedProjects } = ProjectService();
const { getAllProjects } = ProjectService();

const getProjects = async () => {
const data = await getPaginatedProjects();
const data = await getAllProjects();
setProjects(data);
};
useEffect(() => {
Expand Down
19 changes: 19 additions & 0 deletions packages/nextjs/pages/api/projects/detail/[id].ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { convertProjectToDto } from "..";
import type { NextApiRequest, NextApiResponse } from "next";
import { getProjectById } from "~~/services/database/projects";

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method !== "GET") {
return res.status(405).json({ message: "Method not allowed." });
}
const id = req.query.id as string | undefined;
if (!id) return res.status(400).json({ message: "Must include project ID" });
try {
const projectDetail = await getProjectById(id);
const projectDetailDto = convertProjectToDto(projectDetail);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The request from the project page needs more than the dto version. It needs the whole Project.

res.status(200).json(projectDetailDto);
} catch (error) {
console.error(error);
res.status(500).json({ message: "Internal Server Error" });
}
}
15 changes: 15 additions & 0 deletions packages/nextjs/pages/api/projects/ids.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import type { NextApiRequest, NextApiResponse } from "next";
import { getProjectIds } from "~~/services/database/projects";

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method !== "GET") {
return res.status(405).json({ message: "Method not allowed." });
}
try {
const ids = await getProjectIds();
res.status(200).json(ids);
} catch (error) {
console.error(error);
res.status(500).json({ message: "Internal Server Error" });
}
}
38 changes: 38 additions & 0 deletions packages/nextjs/pages/api/projects/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import type { NextApiRequest, NextApiResponse } from "next";
import { Project } from "~~/app/types/data";
import { getProjects } from "~~/services/database/projects";

type ProjectDto = Pick<
Project,
"id" | "name" | "profileAvatarUrl" | "description" | "socialLinks" | "proejctCoverImageUrl"
>;

export const convertProjectToDto = ({
id,
proejctCoverImageUrl,
name,
profileAvatarUrl,
description,
socialLinks,
}: Project): ProjectDto => ({
id,
proejctCoverImageUrl,
name,
profileAvatarUrl,
description,
socialLinks,
});

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
if (req.method !== "GET") {
return res.status(405).json({ message: "Method not allowed." });
}
try {
const projects = await getProjects();
const projectDtos = projects.map(convertProjectToDto);
res.status(200).json(projectDtos);
} catch (error) {
console.error(error);
res.status(500).json({ message: "Internal Server Error" });
}
}
18 changes: 17 additions & 1 deletion packages/nextjs/services/database/projects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,21 @@ import { Project } from "./schema";
const firestoreDB = getFirestoreConnector();
const collectionName = "projects";
const getProjectDoc = (id: string) => firestoreDB.collection(collectionName).doc(id);
export const getProjectById = (id: string) => getProjectDoc(id).get();
const getProjectsSnapshot = () => firestoreDB.collection(collectionName).get();
export const addProjectDoc = (project: Project) => addDocumentToCollection(collectionName, project);

export const getProjectIds = async () => {
const snapshot = await firestoreDB.collection(collectionName).get();
const ids = snapshot.docs.map(doc => doc.id);
return ids;
};

export const getProjectById = async (id: string) => {
const snapshot = await getProjectDoc(id).get();
return { id: snapshot.id, ...snapshot.data() } as Project;
};

export const getProjects = async () => {
const snapshot = await getProjectsSnapshot();
return snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() } as Project));
};
Original file line number Diff line number Diff line change
@@ -1,21 +1,29 @@
import { Project } from "../database/schema";

export const ProjectService = () => {
const baseURL = `${process.env.NEXT_PUBLIC_API_URL}/stub/projects`;
const getPaginatedProjects = async () => {
const response = await fetch(`${baseURL}?limit=100`);
const data = await response.json();
return data.data as Project[];
const baseURL = process.env.NEXT_PUBLIC_API_URL;

const getAllProjects = async () => {
const response = await fetch(`${baseURL}/projects`);
const allProjects = await response.json();
return allProjects as Project[];
};

const getProjectById = async (id: string) => {
const response = await fetch(`${baseURL}?id=${id}`);
const { data }: { data: Project } = await response.json();
const response = await fetch(`${baseURL}/projects/detail/${id}`);
const project: Project = await response.json();
return project;
};

const getProjectIds = async () => {
const response = await fetch(`${baseURL}/projects/ids`);
const data: string[] = await response.json();
return data;
};

return {
getPaginatedProjects,
getAllProjects,
getProjectById,
getProjectIds,
};
};
Loading