junior-dev-struggle-bus / juniordevstrugglebus

Website for the Junior Dev Struggle Bus Meetup
https://www.juniordevstrugglebus.com
MIT License
9 stars 18 forks source link

Internal form page added for new resource submission #45

Closed Xoadra closed 4 years ago

Xoadra commented 4 years ago

This is a bit of a monster PR, but with it comes some really cool stuff, including the new way that visitors will be able to submit resources to the website! One step closer to putting #30 to rest!

I've added a new page that's a subroute to the Resources page accessed by the add resources tab on that page that previously would send users to a Google form. The page is pretty much one big form with fields identical to the ones from the Google form. What's different is this form will submit new resource entries to a Netlify function that, pending @nspilman's FaunaDB integration, will allow us to add and house all of our resources in-house instead of through a Google sheet.

Bear in mind that I'm bringing in a pretty significant chunk of code. That's probably why this PR can't be automatically merged. In it, I've had to make a bit of adjustments to the routing of the site as well as the Netlify function itself.

What's most significant though is the new <Form/> component that manages the add resource form and posts new resources and the <Message/> component that displays submission feedback and initializes page redirection on successful posts. it makes extensive use of state via hooks, and the useEffect hook in <Message/> to handle redirection. All in all, there are a lot of moving parts and state changes going on, so be warned that this new form adds a fair amount of complexity.

The most important thing to note is how state is managed for form fields. in order for the form to scale well to future changes, I've coupled required field constraints and form labeling into state as objects instead of just saving field input in state as a string. I've also added two variables at the top, universal and preset for initializing state in a more modularized and maintainable way. As you can probably guess, universal includes properties that all fields share and are initialized to the same value. This is then added to the preset object via the spread operator which formulates the initial state of each form field. This way, future changes only have to be made in one place to change the behavior of the form. In turn, this will make the form much easier to maintain with far future bugs as the site gradually evolves.

I added quite a bit of cool functionality to the form as well, such as state-dependent style changes that lock the form and prevent any further submissions after a successful submission has been made. Another of these behaviors is some very basic validation added to the form that is shown to users via the <Message/> component. Right now, the only validation that is done is to enforce the required field ruleset. In this case, that just means that each field must have something in it, even if its just one character. Future form validation messages should be passed to <Message/> component since it is meant to handle all validation messages as well as page redirection itself.

Feel free to pick my brain if you have any questions! This PR here also offers some great examples of using React hooks so if anyone in the community is trying to learn hooks and needs some real-life examples and use cases, just have them look at the add resources form page that's in this PR!

Let me know if there are any other questions or concerns you have. I hope you enjoy this contribution as much (or better yet, more) as I enjoyed putting all of this complex logic together for everyone. 🙂

nspilman commented 4 years ago

This looks great. I'm thinking a future item will be creating a Metadata class in Faunadb and storing all this information there, which we can then programmatically render on the page. In the meantime, this is what we need.

The Universal preset that's the spread into the UseState calls is a very cool.

nspilman commented 4 years ago

Fixed merge conflicts in AddResource.js and and functions/resources.js. Merging