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
+
+
+
+
+
+
+
+ Title |
+ Funding |
+ Builder |
+ Date |
+
+
+
+ {activeGrants.map(grant => (
+
+ ))}
+
+
+
+
+
+ );
+};
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);
+ }
+ }
+}