diff --git a/packages/nextjs/app/_components/ActiveGrants.tsx b/packages/nextjs/app/_components/ActiveGrants.tsx new file mode 100644 index 0000000..83902f5 --- /dev/null +++ b/packages/nextjs/app/_components/ActiveGrants.tsx @@ -0,0 +1,54 @@ +import Image from "next/image"; +import { Address } from "~~/components/scaffold-eth"; +import { getAllActiveGrants } from "~~/services/database/grants"; +import { GrantData } from "~~/services/database/schema"; +import { formatDateFromNow } from "~~/utils/grants"; + +const ActiveGrantRow = ({ title, askAmount, builder, approvedAt }: GrantData) => { + return ( + + {title} + {askAmount} ETH + +
+ + {approvedAt ? formatDateFromNow(approvedAt) : "-"} + + ); +}; + +export const ActiveGrants = async () => { + const activeGrants = await getAllActiveGrants(); + + if (!activeGrants.length) { + return null; + } + + return ( +
+
+

WIP grants

+ sparkle +
+
+
+ + + + + + + + + + + {activeGrants.map(grant => ( + + ))} + +
TitleFundingBuilderDate
+
+
+
+ ); +}; diff --git a/packages/nextjs/app/page.tsx b/packages/nextjs/app/page.tsx index c9be180..9835252 100644 --- a/packages/nextjs/app/page.tsx +++ b/packages/nextjs/app/page.tsx @@ -1,3 +1,4 @@ +import { ActiveGrants } from "./_components/ActiveGrants"; import { CommunityGrant } from "./_components/CommunityGrant"; import { CompletedGrants } from "./_components/CompletedGrants"; import { EcosystemGrants } from "./_components/EcosystemGrants"; @@ -12,6 +13,7 @@ const Home = () => { + ); }; diff --git a/packages/nextjs/services/database/grants.ts b/packages/nextjs/services/database/grants.ts index bced581..e8a1df1 100644 --- a/packages/nextjs/services/database/grants.ts +++ b/packages/nextjs/services/database/grants.ts @@ -92,6 +92,20 @@ export const getAllCompletedGrants = async () => { } }; +export const getAllActiveGrants = async () => { + try { + const grantsSnapshot = await grantsCollection.where("status", "==", PROPOSAL_STATUS.APPROVED).get(); + const grants: GrantData[] = []; + grantsSnapshot.forEach(doc => { + grants.push({ id: doc.id, ...doc.data() } as GrantData); + }); + return grants; + } catch (error) { + console.error("Error getting all active grants:", error); + throw error; + } +}; + export const reviewGrant = async (grantId: string, action: ProposalStatusType) => { try { const validActions = Object.values(PROPOSAL_STATUS); diff --git a/packages/nextjs/utils/grants.ts b/packages/nextjs/utils/grants.ts index 758dbda..bbe06de 100644 --- a/packages/nextjs/utils/grants.ts +++ b/packages/nextjs/utils/grants.ts @@ -7,3 +7,25 @@ export const PROPOSAL_STATUS = { } as const; export type ProposalStatusType = (typeof PROPOSAL_STATUS)[keyof typeof PROPOSAL_STATUS]; + +export function formatDateFromNow(input: string | number | Date) { + const date = input instanceof Date ? input : new Date(input); + const formatter = new Intl.RelativeTimeFormat("en"); + const ranges = [ + ["years", 3600 * 24 * 365], + ["months", 3600 * 24 * 30], + ["weeks", 3600 * 24 * 7], + ["days", 3600 * 24], + ["hours", 3600], + ["minutes", 60], + ["seconds", 1], + ] as const; + const secondsElapsed = (date.getTime() - Date.now()) / 1000; + + for (const [rangeType, rangeVal] of ranges) { + if (rangeVal < Math.abs(secondsElapsed)) { + const delta = secondsElapsed / rangeVal; + return formatter.format(Math.round(delta), rangeType); + } + } +}