From 28b96288f6ec8797eea9a795175ac536fe71481b Mon Sep 17 00:00:00 2001 From: Pablo Pettinari Date: Tue, 26 Dec 2023 15:13:35 +0100 Subject: [PATCH 1/6] create initial community events page --- src/components/layout/ApplicantsLayout.tsx | 11 + src/constants.ts | 17 +- .../applicants/community-events/index.tsx | 378 ++++++++++++++++++ 3 files changed, 404 insertions(+), 2 deletions(-) create mode 100644 src/pages/applicants/community-events/index.tsx diff --git a/src/components/layout/ApplicantsLayout.tsx b/src/components/layout/ApplicantsLayout.tsx index f128842d..014153f5 100644 --- a/src/components/layout/ApplicantsLayout.tsx +++ b/src/components/layout/ApplicantsLayout.tsx @@ -10,6 +10,7 @@ import { APPLICANTS_TABS, APPLICANTS_TABS_MAP, APPLICANTS_URL, + COMMUNITY_EVENTS_URL, GRANTEE_FINANCE_URL, OFFICE_HOURS_URL, PROJECT_GRANTS_URL, @@ -64,6 +65,16 @@ export const ApplicantsLayout: FC = ({ children }) => { ); break; + case 4: + router.push( + { + pathname: COMMUNITY_EVENTS_URL + }, + undefined, + { scroll: false } + ); + break; + default: break; } diff --git a/src/constants.ts b/src/constants.ts index 9ad37dc3..2fb89890 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -62,6 +62,8 @@ export const SIDEBAR_SMALL_GRANTS_LINKS: SidebarLink[] = [ { text: 'Apply', href: `${SMALL_GRANTS_URL}/#apply` } ]; +export const COMMUNITY_EVENTS_URL = '/applicants/community-events'; + export const ACADEMIC_GRANTS_2022_URL = '/academic-grants-2022'; export const SIDEBAR_ACADEMIC_GRANTS_2022_LINKS: SidebarLink[] = [ { text: 'Summary', href: `${ACADEMIC_GRANTS_2022_URL}/#description` }, @@ -192,6 +194,7 @@ export const SIDEBAR_DATA_COLLECTION_GRANTS_LINKS: SidebarLink[] = [ export const PROJECT_GRANTS_APPLY_URL = '/applicants/project-grants/apply'; export const OFFICE_HOURS_APPLY_URL = '/applicants/office-hours/apply'; export const SMALL_GRANTS_APPLY_URL = '/applicants/small-grants/apply'; +export const COMMUNITY_EVENTS_APPLY_URL = '/applicants/community-events/apply'; export const ACADEMIC_GRANTS_APPLY_URL = '/academic-grants/apply'; export const DEVCON_GRANTS_APPLY_URL = '/devcon-grants/apply'; export const ECODEV_GRANTS_APPLY_URL = '/ecodev-grants/apply'; @@ -205,6 +208,7 @@ export const GRANTEE_FINANCE_URL = '/applicants/grantee-finance'; export const PROJECT_GRANTS_THANK_YOU_PAGE_URL = '/applicants/project-grants/thank-you'; export const OFFICE_HOURS_THANK_YOU_PAGE_URL = '/applicants/office-hours/thank-you'; export const SMALL_GRANTS_THANK_YOU_PAGE_URL = '/applicants/small-grants/thank-you'; +export const COMMUNITY_EVENTS_THANK_YOU_PAGE_URL = '/applicants/community-events/thank-you'; export const GRANTEE_FINANCE_THANK_YOU_PAGE_URL = '/applicants/grantee-finance/thank-you'; export const ACADEMIC_GRANTS_THANK_YOU_PAGE_URL = '/academic-grants/thank-you'; export const DEVCON_GRANTS_THANK_YOU_PAGE_URL = '/devcon-grants/thank-you'; @@ -243,18 +247,27 @@ export const ACCOUNT_ABSTRACTION_GRANTS_EMAIL_ADDRESS = 'account-abstraction@eth export const GRANTS_EMAIL_ADDRESS = 'grant-rounds@ethereum.org'; // applicants tabs -export const APPLICANTS_TABS = ['Overview', 'Office Hours', 'Small Grants', 'Project Grants']; +export const APPLICANTS_TABS = [ + 'Overview', + 'Office Hours', + 'Small Grants', + 'Project Grants', + 'Community Events' +]; export const APPLICANTS_TABS_MAP: TabsMap = { [APPLICANTS_URL]: 0, [OFFICE_HOURS_URL]: 1, [SMALL_GRANTS_URL]: 2, [PROJECT_GRANTS_URL]: 3, + [COMMUNITY_EVENTS_URL]: 4, [OFFICE_HOURS_APPLY_URL]: 1, [OFFICE_HOURS_THANK_YOU_PAGE_URL]: 1, [SMALL_GRANTS_APPLY_URL]: 2, [SMALL_GRANTS_THANK_YOU_PAGE_URL]: 2, [PROJECT_GRANTS_APPLY_URL]: 3, - [PROJECT_GRANTS_THANK_YOU_PAGE_URL]: 3 + [PROJECT_GRANTS_THANK_YOU_PAGE_URL]: 3, + [COMMUNITY_EVENTS_APPLY_URL]: 4, + [COMMUNITY_EVENTS_THANK_YOU_PAGE_URL]: 4 }; // about tabs diff --git a/src/pages/applicants/community-events/index.tsx b/src/pages/applicants/community-events/index.tsx new file mode 100644 index 00000000..978976cc --- /dev/null +++ b/src/pages/applicants/community-events/index.tsx @@ -0,0 +1,378 @@ +import { Accordion, Box, Flex, Link, ListItem, Stack } from '@chakra-ui/react'; +import { useInView } from 'react-intersection-observer'; +import type { NextPage } from 'next'; + +import { + ApplicantsSidebar, + ApplicationAttentionMsg, + FAQItem, + List, + PageMetadata, + PageSection, + PageSubheading, + PageText, + ProcessStep, + ReadyToApply +} from '../../../components/UI'; + +import { + ETHEREUM_COMMUNITY_URL, + ETHEREUM_GRANTS_URL, + ETHRESEARCH_URL, + SIDEBAR_SMALL_GRANTS_LINKS, + SMALL_GRANTS_APPLY_URL +} from '../../../constants'; + +const CommunityEventsGrants: NextPage = () => { + // `threshold` option allows us to control the % of visibility required before triggering the Intersection Observer + // https://react-intersection-observer.vercel.app/?path=/story/introduction--page#options + const [ref, inView] = useInView({ threshold: 0.5 }); + const [ref2, inView2] = useInView({ threshold: 0.5, initialInView: false }); + const [ref3, inView3] = useInView({ threshold: 0.5, initialInView: false }); + const [ref4, inView4] = useInView({ threshold: 0.5, initialInView: false }); + const [ref5, inView5] = useInView({ threshold: 0.5, initialInView: false }); + const [ref6, inView6] = useInView({ threshold: 0.5, initialInView: false }); + const [ref7, inView7] = useInView({ threshold: 0.5, initialInView: false }); + const [ref8, inView8] = useInView({ threshold: 0, initialInView: false }); + + return ( + <> + + + + + + + + +
+ Community Events + + + Small grants, capped at $30,000, have a streamlined application + and evaluation process to deliver a decision around two weeks after submission. + + + + A small grants application might be a good fit if any of the + following apply to your project: + + + + + + In early stage: you've started work but are still testing assumptions or + working toward a proof of concept. + + + Experimental: you have an idea that's a little “out there” but + potentially impactful - and the only way to find out is to try it. + + Time sensitive: you need a decision within a few weeks. + Smaller in scope: funding request comes in under $30,000. + + Community event related: sponsorship requests for events focused on + Ethereum's technology and community can also be submitted via the small + grants pipeline. + + + +
+
+ + +
+ +
+
+ + +
+ Process + + + + Just fill out the online form! Make sure you have read and understood our scope + and criteria below. After submitting, you'll receive a confirmation email + within two business days. + + + + Every submission is read and considered by the ESP team. You most likely + won't hear from us during the evaluation process for a small grant + application, but you're always welcome to get in touch - just reply to the + confirmation email if you have questions or think of anything else we should + know. + + + + Unless we reach out to clarify anything on your application, you can expect to + hear back from us with a final decision around two weeks after you submit it. + + + + We sign a grant agreement, complete KYC and send funds in fiat, ETH or DAI - and + you get to work! + + + + Once you've completed work on your grant, you'll share the results in + a report, blog post or video. + + +
+ +
+ Requirements + + + We're flexible in many ways, but we do have some hard rules for the projects + we fund: + + + + + Work funded by ESP grants must benefit Ethereum in a way that aligns with + ESP's mission and scope. + + + Any output must be open source or otherwise freely available; for-profit + companies are welcome to apply but the specific grant funded work must be + non-commercial. + + +
+ +
+ Eligibility + + + We are happy to hear from all kinds of contributors who are working within our + scope: + + + + Individuals, teams or organizations. + + Newcomers to Ethereum, established projects, past grantees or applicants. + + + Any area of expertise - we work with developers, researchers, academics, + designers, educators, communicators, community organizers, and more. + + + Projects at any point in the development process: just an idea, early stages, + proof of concept, or with significant progress already made. However, we do not + fund past work. + + Builders of any age, origin, identity or background. + +
+ +
+ What is NOT eligible + + + + Anything that is not legal within the jurisdiction where the work is taking + place. + + + Financial products (trading, investment products, lending, betting, etc). + + Projects with a planned token launch or public funding round. + + Art projects or charities that don't fit within our scope. + + Token or investment focused events. + +
+ +
+ Tips for submitting a great application + + + The information you submit here is what we'll use to make a final decision + about your grant application, so take the time to understand what we're + looking for and answer the form questions thoughtfully. + + + + When evaluating your application, we look for much more than just an explanation + of the proposed work. In order to determine the potential impact on the ecosystem, + we need a deeper understanding of both the “why” and the “how” of the project. + Some things to keep in mind: + + + + + Be specific: we want you to share your grand vision - but you + also need to tell us, concretely, how you plan to achieve your goals. + + + Be thorough: the more information you can provide in a grant + application, the better. We encourage you to provide any supporting documents + such as whitepapers, research papers, or slides from presentations you've + given about your project. + + + Show your work: we expect you to have made a meaningful effort + to validate and refine your approach and researched what other solutions are + being developed, and to be able to articulate how yours is different. + + + Dig deeper: we want to know what problem you're trying to + solve, but also why you think it's important to solve that specific + problem, how solving it will benefit Ethereum and how it fits within our + mission. + + + Think broader: how does your project connect to, complement and + enable the work of others? How can you make sure your work stays relevant and + has a sustained impact? + + + Identify output (what is produced) as well as outcome (what is + accomplished): what will be the tangible result of your work - a research paper, + a code repo, a community event, a working prototype? Who will use it, and how + will they access it? + + + Be realistic: we'll consider the funding amount you + request in relation to the proposed scope of work, so go with a number that + reflects what you think you'll need for the specific work in your proposal. + Remember that being awarded a grant now doesn't mean you can't apply + for additional funding later! + + +
+ +
+ FAQ + + + + + Applications are not shared with the public. However, any information you + provide may be shared with advisors in the review process, so let us know in + your application if there's something you want us to keep confidential! + + + + + + Mostly, yes. We are legally required to perform KYC before transferring funds + to you, and will need to know your real identity to complete that process. + However, we are happy to keep that information confidential outside of the few + members of the EF team involved in KYC processing, and use a pseudonym or omit + your name entirely in any communications that will be visible to anyone else. + + + + + We can provide payment in ETH, DAI, or Fiat currency. + + + + + Ethereum's ecosystem is unique in the way it embraces both + entrepreneurship and collaboration, and we want to keep it that way. We + believe that builders can and should be able to build a business while + continuing to contribute to FOSS and public goods. + + + + Although we do not fund work that is intended to be monetized, we are happy to + hear from for-profit entities that are building public goods. We regularly + fund components or areas of work carried out by for-profit companies, as long + as the specific funded work fits within our scope and remains free and open to + anyone. + + + + + + Yes! The team meets weekly to review every submission we receive, and give + careful consideration to whether the project is eligible and what we can do to + support. We love learning about the amazing work people are doing in the + ecosystem, even when that work is outside of our scope. + + + + + + Small grants have a hard limit of $30,000, but if you anticipate needing more + to get to the finish line, you have options. You can apply for Project Grants, + which have no funding cap. If your project is otherwise a better fit for a + small grant, e.g. it's more experimental or in early stages, consider + applying for a small grant for a specific component or phase of work, and we + can revisit the possibility of funding additional work as you approach the + finish line on your initial grant. + + + + + + Don't be discouraged! We have a finite scope and sometimes it's just + not a fit, or not the right time - that doesn't mean the work you're + doing isn't important. Consider continuing to develop your idea at a + hackathon or by posting to forums like{' '} + + ethresear.ch + + , looking into{' '} + + other funding sources + + , or participating in{' '} + + community groups or events + {' '} + for new perspectives and possibilities within the vast and vibrant Ethereum + ecosystem. + + + + You can also reapply in the future if you feel that something has changed. If + you're considering reapplying, we recommend signing up for office hours + first before restarting the application process. + + + +
+ +
+ + + +
+
+
+
+
+ + ); +}; + +export default CommunityEventsGrants; From 8032b2e592e5b947560b8d38f306e5f2e3318f7d Mon Sep 17 00:00:00 2001 From: Pablo Pettinari Date: Tue, 26 Dec 2023 15:39:05 +0100 Subject: [PATCH 2/6] create community event form --- src/components/forms/CommunityEventsForm.tsx | 1216 +++++++++++++++++ src/components/forms/Forms.tsx | 9 +- src/components/forms/api.ts | 27 +- src/components/forms/index.ts | 1 + src/constants.ts | 14 + .../applicants/community-events/apply.tsx | 42 + .../applicants/community-events/index.tsx | 8 +- src/types.ts | 33 + 8 files changed, 1340 insertions(+), 10 deletions(-) create mode 100644 src/components/forms/CommunityEventsForm.tsx create mode 100644 src/pages/applicants/community-events/apply.tsx diff --git a/src/components/forms/CommunityEventsForm.tsx b/src/components/forms/CommunityEventsForm.tsx new file mode 100644 index 00000000..c753ece3 --- /dev/null +++ b/src/components/forms/CommunityEventsForm.tsx @@ -0,0 +1,1216 @@ +import { + Box, + Center, + Fade, + Flex, + FormControl, + FormLabel, + Input, + Radio, + RadioGroup, + Stack, + Textarea, + useToast +} from '@chakra-ui/react'; +import { Select } from 'chakra-react-select'; +import { FC, useState } from 'react'; +import { Controller, FormProvider, useForm } from 'react-hook-form'; +import { useRouter } from 'next/router'; + +import { DropdownIndicator, PageText } from '../UI'; +import { SubmitButton } from '../SubmitButton'; +import { Captcha } from '.'; + +import { api } from './api'; + +import { chakraStyles } from './selectStyles'; + +import { + COUNTRY_OPTIONS, + HOW_DID_YOU_HEAR_ABOUT_ESP_OPTIONS, + INDIVIDUAL, + EVENT_FORMAT_OPTIONS, + EVENT_TYPE_OPTIONS, + TEAM +} from './constants'; +import { COMMUNITY_EVENTS_THANK_YOU_PAGE_URL, TOAST_OPTIONS } from '../../constants'; + +import { IndividualOrTeam, CommunityEventsFormData } from '../../types'; +import { containURL } from '../../utils'; + +export const CommunityEventsForm: FC = () => { + const router = useRouter(); + const toast = useToast(); + const [individualOrTeam, setIndividualOrTeam] = useState(INDIVIDUAL); + + const methods = useForm({ + mode: 'onBlur' + }); + const { + handleSubmit, + register, + control, + formState: { errors, isValid, isSubmitting }, + reset + } = methods; + + const onSubmit = async (data: CommunityEventsFormData) => { + return api.communityGrants + .submit(data) + .then(res => { + if (res.ok) { + reset(); + router.push(COMMUNITY_EVENTS_THANK_YOU_PAGE_URL); + } else { + toast({ + ...TOAST_OPTIONS, + title: 'Something went wrong while submitting, please try again.', + status: 'error' + }); + + throw new Error('Network response was not OK'); + } + }) + .catch(err => console.error('There has been a problem with your operation: ', err.message)); + }; + + return ( + + +
+ + + + + First name + + + !containURL(value) + })} + /> + + {errors?.firstName?.type === 'required' && ( + + + First name is required. + + + )} + {errors?.firstName?.type === 'maxLength' && ( + + + First name cannot exceed 40 characters. + + + )} + {errors?.firstName?.type === 'validate' && ( + + + First name cannot contain a URL. + + + )} + + + + + + Last name + + + !containURL(value) + })} + /> + + {errors?.lastName?.type === 'required' && ( + + + Last name is required. + + + )} + {errors?.lastName?.type === 'maxLength' && ( + + + Last name cannot exceed 80 characters. + + + )} + {errors?.lastName?.type === 'validate' && ( + + + Last name cannot contain a URL. + + + )} + + + + + + + Email + + + + + {errors?.email?.type === 'required' && ( + + + Email is required. + + + )} + + + {/* If the component doesn't expose input's ref, we should use the Controller component, */} + {/* which will take care of the registration process (https://react-hook-form.com/get-started#IntegratingwithUIlibraries) */} + ( + + + + Are you submitting on behalf of a team, or as an individual? + + + + { + onChange(value); + setIndividualOrTeam(value); + }} + value={value} + fontSize='input' + colorScheme='white' + > + + + Individual + + + + Team + + + + + )} + /> + + + + + + + Name of organization or entity + + + !containURL(value) + })} + /> + + {errors?.company?.type === 'required' && ( + + + Organization name is required. + + + )} + {errors?.company?.type === 'maxLength' && ( + + + Organization name cannot exceed 255 characters. + + + )} + {errors?.company?.type === 'validate' && ( + + + Organization name cannot contain a URL. + + + )} + + + + + + + + Individual or team summary + + + + + Tell us about yourself, your experience, and your motivations. Feel free to link to + any biography pages, LinkedIn pages, etc. + + +