From ce3198a90e29353913507fb38bc0b6bd61e67b4e Mon Sep 17 00:00:00 2001 From: veganbeef Date: Mon, 7 Oct 2024 12:07:12 -0700 Subject: [PATCH] WIP: useGap hook in apply flow --- packages/builder/package.json | 3 +- .../src/components/application/Form.tsx | 321 +++++ packages/gap/.eslintrc.js | 3 + packages/gap/package.json | 28 + packages/gap/react-app-env.d.ts | 5 + packages/gap/src/hooks.ts | 451 +++++++ packages/gap/src/index.ts | 2 + packages/gap/tsconfig.build.json | 15 + packages/gap/tsconfig.json | 11 + packages/gap/tsconfig.tsbuildinfo | 1 + packages/gap/webpack.config.js | 34 + pnpm-lock.yaml | 1169 ++++++++++++++++- pnpm-workspace.yaml | 1 + 13 files changed, 1999 insertions(+), 45 deletions(-) create mode 100644 packages/gap/.eslintrc.js create mode 100644 packages/gap/package.json create mode 100644 packages/gap/react-app-env.d.ts create mode 100644 packages/gap/src/hooks.ts create mode 100644 packages/gap/src/index.ts create mode 100644 packages/gap/tsconfig.build.json create mode 100644 packages/gap/tsconfig.json create mode 100644 packages/gap/tsconfig.tsbuildinfo create mode 100644 packages/gap/webpack.config.js diff --git a/packages/builder/package.json b/packages/builder/package.json index 851b738af..04b836e53 100644 --- a/packages/builder/package.json +++ b/packages/builder/package.json @@ -2,7 +2,7 @@ "name": "builder", "version": "0.1.0", "private": true, - "engines": { + "engines": { "npm": ">=8.5.5", "node": ">=20.1.0" }, @@ -16,6 +16,7 @@ "@datadog/browser-rum": "^4.16.0", "@ethersproject/address": "^5.7.0", "@ethersproject/providers": "^5.7.2", + "gap": "file:../gap", "@gitcoinco/passport-sdk-types": "^0.2.0", "@headlessui/react": "^1.6.5", "@heroicons/react": "^2.0.11", diff --git a/packages/builder/src/components/application/Form.tsx b/packages/builder/src/components/application/Form.tsx index 5c2875f96..f9e0f9252 100644 --- a/packages/builder/src/components/application/Form.tsx +++ b/packages/builder/src/components/application/Form.tsx @@ -1,3 +1,4 @@ +// Form.tsx import { Stack } from "@chakra-ui/react"; import { datadogRum } from "@datadog/browser-rum"; import { getConfig } from "common/src/config"; @@ -16,6 +17,7 @@ import { RoundApplicationMetadata, } from "data-layer/dist/roundApplication.types"; import { getChainById, useValidateCredential } from "common"; +import { useGap } from "gap"; import { Fragment, useEffect, useState } from "react"; import { shallowEqual, useDispatch, useSelector } from "react-redux"; import { Link } from "react-router-dom"; @@ -373,6 +375,136 @@ export default function Form({ const needsProject = !schema.questions.find((q) => q.type === "project"); const now = new Date().getTime() / 1000; + const { + getProjectById, + createProject, + createGrant, + createMilestone, + project, + milestones, + isGapLoading, + error, + } = useGap(process.env.REACT_APP_KARMA_GAP_INDEXER_URL!); + + const [newProjectData, setNewProjectData] = useState<{ + title: string; + description: string; + imageURL: string; + links?: { type: string; url: string }[]; + tags?: { name: string }[]; + members?: `0x${string}`[]; + }>({ + title: "", + description: "", + imageURL: "", + links: [], + tags: [], + members: [], + }); + + const [newGrantData, setNewGrantData] = useState<{ + communityUID: string; + title: string; + proposalURL: string; + description?: string; + cycle?: string; + season?: string; + milestones?: Array<{ + title: string; + description: string; + endsAt: number; + }>; + }>({ + communityUID: "", + title: "", + proposalURL: "", + description: "", + cycle: "", + season: "", + milestones: [], + }); + + const [newMilestoneData, setNewMilestoneData] = useState<{ + title: string; + description: string; + endsAt: number; + }>({ + title: "", + description: "", + endsAt: Date.now(), + }); + + const handleNewProjectInputChange = (e: ChangeHandlers) => { + const { name, value } = e.target; + setNewProjectData((prevData) => ({ + ...prevData, + [name]: value, + })); + }; + + const handleNewGrantInputChange = (e: ChangeHandlers) => { + const { name, value } = e.target; + setNewGrantData((prevData) => ({ + ...prevData, + [name]: value, + })); + }; + + const handleNewMilestoneInputChange = ( + e: React.ChangeEvent< + HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement + > + ) => { + const { name, value } = e.target; + let updatedValue: string | number = value; + + if (name === "endsAt") { + updatedValue = new Date(value).getTime(); + } + + setNewMilestoneData((prevData) => ({ + ...prevData, + [name]: updatedValue, + })); + }; + + const handleCreateMilestone = async () => { + try { + setIsLoading(true); + + // Step 1: Create Project + const projectResult = await createProject(newProjectData); + + // Step 2: Create Grant + const grantResult = await createGrant( + newGrantData, + projectResult.projectUID + ); + + // Step 3: Create Milestone + await createMilestone(newMilestoneData, grantResult.grantUID); + + // After creating everything, refresh the project data + getProjectById(projectResult.projectUID); + setIsLoading(false); + } catch (err) { + console.error("Error creating milestone:", err); + setIsLoading(false); + } + }; + + useEffect(() => { + if (isValidProjectSelected && selectedProjectID) { + getProjectById(selectedProjectID); + } + }, [isValidProjectSelected, selectedProjectID, getProjectById]); + + useEffect(() => { + if (project) { + console.log("Project found:", project); + } + }, [project]); + return ( <> {preview && selectedProjectMetadata && ( @@ -455,6 +587,195 @@ export default function Form({ ); } + if (input.title === "Milestones") { + const renderMilestoneContent = () => { + if (isGapLoading) { + return

Loading project information...

; + } + if (project) { + return ( +
+

Project Title: {project.title}

+ {/* Display existing milestones if any */} + {milestones && milestones.length > 0 ? ( +
+

Existing Milestones:

+
    + {milestones.map((milestone) => ( +
  • + {milestone.title}: + {milestone.description} +
  • + ))} +
+
+ ) : ( +

No milestones found for this project.

+ )} + {/* Form to create a new milestone */} +

Create a New Milestone

+ +