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

Minor UI tweaks and feedback modals after user grant applications #11

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .cursorrules
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
You are an expert AI programming assistant that primarily focuses on producing clear, readable Typescript code.

You always use th elatest stable version of React and Typescript, and you are familiar with the latest features and best practices.

You also use the latest versions of Tailwind, DaisyUI, Wagmi, Viem and NodeJS.

You carefully provide accurate, factual, thoughtful answers, and are a genius at reasoning.

- FOllow the user's requirements carefully & to the letter.
- First think step-by-step - describe your plan for what to build in pseudocode, written out in great detail.
- Confirm, then write code!
- Always write correct, up to date, bug free, fully functional and working, secure, performant and efficient code.
- Focus on readability over being perfomant.
- Fully implement all requested functionality.
- Leave NO todo's, placeholders or missing pieces.
- If you think there might not be a correct answer, you say so. If you do not know the anser, say so instead of guessing.
38 changes: 36 additions & 2 deletions packages/nextjs/app/apply/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client";

import { useEffect } from "react";
import { useEffect, useRef } from "react";
import Link from "next/link";
import { useRouter } from "next/navigation";
import { CreateNewGrantReqBody } from "../api/grants/new/route";
Expand Down Expand Up @@ -29,6 +29,8 @@ const Apply: NextPage = () => {
const { openConnectModal } = useConnectModal();
const { isAuthenticated } = useAuthSession();

const feedbackModalRef = useRef<HTMLDialogElement>(null);

useEffect(() => {
if (isAuthenticated) {
router.refresh();
Expand All @@ -47,16 +49,48 @@ const Apply: NextPage = () => {
...fieldValues,
});
notification.success(`The grant proposal has been created`);
router.push("/my-grants");
feedbackModalRef.current?.showModal();
} catch (error) {
const errorMessage = getParsedError(error);
notification.error(errorMessage);
}
};

const handleModalClose = () => {
feedbackModalRef.current?.close();
router.push("/my-grants");
};

return (
<div className="flex flex-col w-full items-center justify-center p-6 sm:p-10">
<h2 className="text-2xl sm:text-3xl font-extrabold !mb-0">Apply for a grant</h2>
<p className="text-center text-lg text-base-content/80 mt-4 max-w-2xl">
Open to all public goods projects. ENS-specific projects should apply through the ENS Ecosystem Grants program
instead.
</p>

<dialog ref={feedbackModalRef} className="modal">
<div className="modal-box flex flex-col space-y-3">
<form method="dialog" className="bg-secondary -mx-6 -mt-6 px-6 py-4">
<div className="flex items-center">
<p className="font-bold text-xl m-0 text-center w-full">Application Submitted Successfully!</p>
</div>
</form>

<div className="text-center">
<p>
Grant applications are reviewed at a regular cadence, you will receive information if we need more info,
if the application was rejected and why, or approved and for what amount, based on the info submitted.
</p>
<div className="mt-6 flex justify-center">
<Button onClick={handleModalClose}>Accept</Button>
</div>
</div>
</div>
<form method="dialog" className="modal-backdrop">
<button onClick={handleModalClose}>close</button>
</form>
</dialog>

<FormProvider {...formMethods}>
<div className="mt-6 sm:mt-10 card card-compact rounded-xl w-full max-w-4xl bg-secondary shadow-lg mb-8 sm:mb-12 p-4 sm:p-6">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { forwardRef } from "react";
import { forwardRef, useRef } from "react";
import { useRouter } from "next/navigation";
import { NewStageModalFormValues, newStageModalFormSchema } from "./schema";
import { useMutation } from "@tanstack/react-query";
Expand Down Expand Up @@ -27,6 +27,7 @@ export const NewStageModal = forwardRef<HTMLDialogElement, NewStageModalProps>(
schema: newStageModalFormSchema,
});
const { handleSubmit } = formMethods;
const feedbackModalRef = useRef<HTMLDialogElement>(null);

const onSubmit = async (fieldValues: NewStageModalFormValues) => {
try {
Expand All @@ -44,12 +45,13 @@ export const NewStageModal = forwardRef<HTMLDialogElement, NewStageModalProps>(

await postNewStage({ milestone, signature, grantId });
closeModal();
router.refresh();
feedbackModalRef.current?.showModal();
} catch (error) {
const errorMessage = getParsedError(error);
notification.error(errorMessage);
}
};

const { signTypedDataAsync, isPending: isSigning } = useSignTypedData();
const router = useRouter();

Expand All @@ -58,33 +60,63 @@ export const NewStageModal = forwardRef<HTMLDialogElement, NewStageModalProps>(
postMutationFetcher("/api/stages/new", { body: newStageBody }),
});

const handleFeedbackModalClose = () => {
feedbackModalRef.current?.close();
router.refresh();
};

return (
<dialog id="action_modal" className="modal" ref={ref}>
<div className="modal-box flex flex-col space-y-3">
<form method="dialog" className="bg-secondary -mx-6 -mt-6 px-6 py-4 flex items-center justify-between">
<div className="flex justify-between items-center">
<p className="font-bold text-xl m-0">Stage {previousStage.stageNumber + 1} application</p>
<>
<dialog id="action_modal" className="modal" ref={ref}>
<div className="modal-box flex flex-col space-y-3">
<form method="dialog" className="bg-secondary -mx-6 -mt-6 px-6 py-4 flex items-center justify-between">
<div className="flex justify-between items-center">
<p className="font-bold text-xl m-0">Stage {previousStage.stageNumber + 1} application</p>
</div>
{/* if there is a button in form, it will close the modal */}
<button className="btn btn-sm btn-circle btn-ghost text-xl h-auto">✕</button>
</form>
<FormProvider {...formMethods}>
<form onSubmit={handleSubmit(onSubmit)} className="w-full flex flex-col">
<FormTextarea label="Stage milestones" showMessageLength {...getCommonOptions("milestone")} />
<Button
variant="green"
type="submit"
disabled={isPostingNewStage || isSigning}
className="self-center mt-4"
>
{(isPostingNewStage || isSigning) && <span className="loading loading-spinner"></span>}
Apply for a grant
</Button>
</form>
</FormProvider>
</div>
</dialog>

<dialog ref={feedbackModalRef} className="modal">
<div className="modal-box flex flex-col space-y-3">
<form method="dialog" className="bg-secondary -mx-6 -mt-6 px-6 py-4">
<div className="flex items-center">
<p className="font-bold text-xl m-0 text-center w-full">Stage Application Submitted!</p>
</div>
</form>

<div className="text-center">
<p>
Your stage application will be reviewed. You will receive information if we need more details, if the
application was rejected and why, or when it is approved and for what amount.
</p>
<div className="mt-6 flex justify-center">
<Button onClick={handleFeedbackModalClose}>Accept</Button>
</div>
</div>
{/* if there is a button in form, it will close the modal */}
<button className="btn btn-sm btn-circle btn-ghost text-xl h-auto">✕</button>
</div>
<form method="dialog" className="modal-backdrop">
<button onClick={handleFeedbackModalClose}>close</button>
</form>
<FormProvider {...formMethods}>
<form onSubmit={handleSubmit(onSubmit)} className="w-full flex flex-col">
<FormTextarea label="Stage milestones" showMessageLength {...getCommonOptions("milestone")} />
<Button
variant="green"
type="submit"
disabled={isPostingNewStage || isSigning}
className="self-center mt-4"
>
{(isPostingNewStage || isSigning) && <span className="loading loading-spinner"></span>}
Apply for a grant
</Button>
</form>
</FormProvider>
</div>
</dialog>
<Toaster />
</dialog>
</>
);
},
);
Expand Down
7 changes: 3 additions & 4 deletions packages/nextjs/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,17 +34,16 @@ const Home: NextPage = () => {
<div className="flex items-center flex-col flex-grow">
<div className="max-w-4xl text-center px-4 py-8 sm:py-16">
<h1 className="text-3xl font-extrabold !mb-0">ENS PG Builder Grants</h1>
<div className="mt-4 text-gray-400 max-w-2xl mx-auto space-y-4">
<div className="mt-4 max-w-2xl mx-auto space-y-4">
<p>
The ENS PG Builder Grants program is designed to support foundational public goods in the Ethereum and Web3
PG Builder Grants program is designed to support foundational public goods in the Ethereum and Web3
ecosystems. The program aims to empower projects that have demonstrated exceptional usefulness and impact
for developers and users alike.
</p>
<p>
By providing significant financial support, we help projects continue to drive innovation and growth within
the ecosystem. Whether you&apos;re building infrastructure, developing tools, or creating educational
resources, the ENS PG Builder Grants offer a pathway to secure the funding you need to make a lasting
difference.
resources, PG Builder Grants offer a pathway to secure the funding you need to make a lasting difference.
</p>
</div>
<Stats />
Expand Down
Loading