diff --git a/packages/nextjs/app/_components/ApplyEligibilityLink.tsx b/packages/nextjs/app/_components/ApplyEligibilityLink.tsx new file mode 100644 index 0000000..fc9979c --- /dev/null +++ b/packages/nextjs/app/_components/ApplyEligibilityLink.tsx @@ -0,0 +1,86 @@ +"use client"; + +import Link from "next/link"; +import { useConnectModal } from "@rainbow-me/rainbowkit"; +import { useAccount } from "wagmi"; +import { LockClosedIcon, LockOpenIcon } from "@heroicons/react/24/outline"; +import { useBGBuilderData } from "~~/hooks/useBGBuilderData"; + +type BuilderStatus = "notConnected" | "notMember" | "eligible"; + +const FeedbackMessage = ({ builderStatus }: { builderStatus: BuilderStatus }) => { + if (builderStatus === "notConnected") { + return ( +
+

+ 🔎 Connect your wallet to verify eligibility. +

+
+ ); + } + if (builderStatus === "notMember") { + return ( +
+

+ ❌ Not a BuidlGuidl member. +

+

+ Join by completing challenges at{" "} + + speedrunethereum.com + +

+
+ ); + } + // builderStatus is "eligible" + return ( +
+

+ ✅ You are eligible to apply! +

+

Participate in the grants program as a member.

+
+ ); +}; + +export const ApplyEligibilityLink = () => { + const { isConnected, address: connectedAddress } = useAccount(); + const { isBuilderPresent, isLoading: isFetchingBuilderData } = useBGBuilderData(connectedAddress); + const { openConnectModal } = useConnectModal(); + + const builderStatus: BuilderStatus = + !isConnected || isFetchingBuilderData ? "notConnected" : !isBuilderPresent ? "notMember" : "eligible"; + + return ( +
+

Do you qualify?

+ + {builderStatus === "eligible" ? ( + + + APPLY FOR A GRANT + + ) : ( + + )} +
+ ); +}; diff --git a/packages/nextjs/app/_components/CommunityGrant.tsx b/packages/nextjs/app/_components/CommunityGrant.tsx index 7c35b16..997ba99 100644 --- a/packages/nextjs/app/_components/CommunityGrant.tsx +++ b/packages/nextjs/app/_components/CommunityGrant.tsx @@ -1,12 +1,12 @@ import Image from "next/image"; -import Link from "next/link"; +import { ApplyEligibilityLink } from "./ApplyEligibilityLink"; export const CommunityGrant = () => { return (
{/* Left section(Title, desc and btn) */} -
+
{/* Title */}

@@ -31,12 +31,7 @@ export const CommunityGrant = () => { Are you a BG member eager to make an impact in the ecosystem? At BuidlGuidl, we're excited to support your builds. We offer sponsorships of up to 1 ETH for projects that drive the community forward.

- - Apply for a grant - +

{/* Right section (Who, process, payment, etc) */} diff --git a/packages/nextjs/app/api/grants/new/route.ts b/packages/nextjs/app/api/grants/new/route.ts index 3cdd18f..9cf4dfc 100644 --- a/packages/nextjs/app/api/grants/new/route.ts +++ b/packages/nextjs/app/api/grants/new/route.ts @@ -19,14 +19,14 @@ export async function POST(req: Request) { try { const { title, description, signature, signer } = (await req.json()) as ReqBody; - if (!title || !description || !signature || !signer) { - return NextResponse.json({ error: "Invalid form details submited" }, { status: 400 }); + if (!title || !description || !signature || !signer || description.length > 750 || title.length > 75) { + return NextResponse.json({ error: "Invalid form details submitted" }, { status: 400 }); } // Verif if the builder is present const builder = await findUserByAddress(signer); if (!builder.exists) { - return NextResponse.json({ error: "Only buidlguild builders can submit for grants" }, { status: 401 }); + return NextResponse.json({ error: "Only Buidlguidl builders can submit for grants" }, { status: 401 }); } const recoveredAddress = await recoverTypedDataAddress({ diff --git a/packages/nextjs/app/apply/_component/Form.tsx b/packages/nextjs/app/apply/_component/Form.tsx index 2205abf..0ac9c4d 100644 --- a/packages/nextjs/app/apply/_component/Form.tsx +++ b/packages/nextjs/app/apply/_component/Form.tsx @@ -1,5 +1,6 @@ "use client"; +import React, { useState } from "react"; import { useRouter } from "next/navigation"; import SubmitButton from "./SubmitButton"; import useSWRMutation from "swr/mutation"; @@ -16,8 +17,11 @@ type ReqBody = { signer?: string; }; +const MAX_DESCRIPTION_LENGTH = 750; + const Form = () => { const { address: connectedAddress } = useAccount(); + const [descriptionLength, setDescriptionLength] = useState(0); const { signTypedDataAsync } = useSignTypedData(); const router = useRouter(); const { trigger: postNewGrant } = useSWRMutation("/api/grants/new", postMutationFetcher); @@ -60,7 +64,7 @@ const Form = () => { }; return ( -
+

Submit Proposal

@@ -68,22 +72,28 @@ const Form = () => {

Description

-
+