Finishing the Sign Up Form
All right let's go ahead and finish off this form here by basically fixing up our grid and placing them where they belong and then making this go back and couple other small things okay.
Guide Tasks
  • Read Tutorial
  • Watch Guide Video
Video locked
This video is viewable to users with a Bottega Bootcamp license

So we have our e-mail and password and we have the name and confirm password okay. In here, we have name, email, password, and confirm password. So let's go define where these belong on the grid, and let's check how big this is okay, it's about 50 pixels. Okay so we'll wing that a bit, it doesn't matter if it's 100 percent accurate. Okay, we also have password requirements.

All right so let's go fix the grid by closing the terminal and going into signup.js. Well first let's check in our signupForm.js, looks like we've got, okay so these are all named correctly. Let's call this confirmed password confirm, okay so we have name, email, password, and confirm. Okay, let's go into signup.scss and scroll down to .sign-up-form, and let's say an e-mail, okay, we've got an e-mail and password.

Okay we need a couple more in here, I'm going to copy e-mail and password, and let's rename the top one to name, then we've got e-mail then we've got password and then we've got confirm. Now let's change all these grid rows accordingly, so we've got name, we've got e-mail, we've got a password, and we've got confirm. Okay, let's get rid of these margins.

signup.scss

.sign-up-form {
    & > * {
        grid-column: 1/-1;
    }
    &__name {
        grid-row: name-s/name-e;
    }
    &__email {
        grid-row: email-s/email-e;
    }
    &__password {
        grid-row: password-s/password-e;
    }
    &__confirm {
        grid-row: confirm-s/confirm-e;
    }

    &__line {
        grid-row: line-s/line-e;
        border-top: 1px solid #ccc;
        margin-bottom: 24px;
    }
    &__login {
        grid-row: buttons-s/buttons-e;
        grid-column: create-s/create-e;
    }
    &__back {
        grid-row: buttons-s/buttons-e;
        grid-column: back-s/back-e;
    }
    &__details {
        grid-row: 1/-1;
        justify-self: end;
        align-self: start;
    }

Now, this isn't going to work right away because we don't really have the rows named correctly. So the first one needs to be named so up here in form say name start to name end then we've got e-mail start to e-mail end. Now what we need to do is provide two additional columns for password and confirm, so let's just copy these and paste them.

Okay, now that's going to be a little confusing here because that was a big line so just pay attention closely, we want to cut these two brackets out, we should be good. Now, this is even a bit confusing for me right now just because there's so many. Okay, so we've got name, e-mail, that we got password so these two are going to be password and then the next two are going to be confirm. These two are going to be confirm, okay and we got that big space so we're probably going to have to change this but let's see what this looks like for now.

signup.scss

&__form {
    display: grid;
    grid-template-rows: [name-s] 64px [name-e email-s] 64px [email-e] [password-s] 64px [password-e confirm-s] 64px [confirm-e] minmax(20px, 289px) [line-s] 2px [line-e login-s] 38px [login-e];
    grid-template-columns: 1fr;
}

Okay, let's go into our application. All right, it looks good to me.

large

So what we need to do is give these all a little gap of 15 pixels. So what we want to do is just say since there's so many what we'll do is we'll just apply a grid-gap with the grid row gap is 15 pixels.

grid-row-gap: 15px;

Let's see what that looks like. Okay, it looks good to me.

large

Now what we want to do is put in more space in between the email and the password because if you remember in the design the email and password have 50 pixels. So what we need to do is say okay 50 minus 15 is 35. So what we can do is we can say on password the margin-top is 35 pixels right.

&__password {
    grid-row: password-s/password-e;
}

Looks good to me, let's go try our app, all right looks a little messy.

large

So what we need to do is, we need to either apply that to the confirm as well or better yet we can just get rid of that grid-row and we can go up into grid rows and in between the email and password first password we can just put 35 pixels and then mark it as space end and space start.

grid-template-rows: [name-s] 64px [name-e email-s] 64px [email-e space-s] 35px [space-e password-s] 64px [password-e confirm-s] 64px [confirm-e] minmax(20px, 289px) [line-s] 2px [line-e login-s] 38px [login-e];

Alright and that looks really good.

large

Now, this is way too far down these buttons. So what we need to do is remove or change that 289 pixels to something like 96 pixels minus 15 pixels per our gap, so 193. So let's say 193 pixels, what was the logic there. No, I meant it in 96 minus 15 for 81 pixels, make that 81 pixels and then see what that looks like.

grid-template-rows: [name-s] 64px [name-e email-s] 64px [email-e space-s] 35px [space-e password-s] 64px [password-e confirm-s] 64px [confirm-e] minmax(20px, 81px) [line-s] 2px [line-e login-s] 38px [login-e];

Looks good to me.

large

Now we're going to have to remove 15 pixels from the buttons margin-top because we have that gap now. So let's go in here and basically what we want to do is we want to remove 15 pixels alright so 24 pixels.

signup.scss

&__login {
    margin-top: 24px;
    grid-row: login-s/login-e;
}

Okay cool, let's go try this out now. Looks good to me.

large

Now, all we need to do is specify where the back button belongs and the login button and then fix up the content in the quick links. So let's go do that right now, what we need to do is we need to introduce some columns right. So we want there to be 1fr still put that on the right. But then we also want the button which was 137 pixels if I remember, and then we want the login button.

Now what I'm going to do is I'm not going to specify the width of the login button because we don't need to if we have the width of this because it doesn't matter if the button is going to be however long the button is we just need to specify that it belongs 137 pixels to the right, plus the margin.

Okay so let's go check the margin in the design which is about 40 pixels so what we need to do is put in 40 pixels here, okay and this will be a space so we'll say space start to space end and then this will be login start to login end or I guess this button is going to be called create account. So we'll say create start to create end. And then right here we'll say back start and back end, no pun intended, this is front-end but still.

signup.scss

&__form {
    display: grid;
    grid-template-rows: [name-s] 64px [name-e email-s] 64px [email-e space-s] 35px [space-e password-s] 64px [password-e confirm-s] 64px [confirm-e] minmax(20px, 81px) [line-s] 2px [line-e login-s] 38px [login-e];
    grid-template-columns: [back-s] 137px [back-e space-s] 40px [space-e create-s] 1fr [create-e] 1fr;
    grid-row-gap: 15px;
}

Okay so now what we need to do is we need to actually specify where things belong. Okay, now everything's going to stretch across except for we want to override login and back to not do that. Okay, so we've got login, and we've got back, so this is going to say grid column is back start to back end, okay now this is going to be grid column from create start to create end. Now let's change these logins because we want these to say create now okay, at least on this side so grid row will be create.

signup.scss

&__login {
    margin-top: 24px;
    grid-row: create-s/create-e;
    grid-column: create-s/create-e;
}
&__back {
    grid-column: back-s/back-e;
}

Then we'll go up here to our rows and we'll rename login to create or better yet we can just rename them to buttons and then what we can do is we can go down here and we can change grid row to buttons and that way we can apply it to the back button and have it not look weird, it doesn't say create on the back button and then we don't have to change login to create.

signup.scss

&__form {
    display: grid;
    grid-template-rows: [name-s] 64px [name-e email-s] 64px [email-e space-s] 35px [space-e password-s] 64px [password-e confirm-s] 64px [confirm-e] minmax(20px, 81px) [line-s] 2px [line-e buttons-s] 38px [buttons-e];
    grid-template-columns: [back-s] 137px [back-e space-s] 40px [space-e create-s] 1fr [create-e] 1fr;
    grid-row-gap: 15px;
}
&__login {
    margin-top: 24px;
    grid-row: buttons-s/buttons-e;
    grid-column: create-s/create-e;
}
&__back {
    grid-row: buttons-s/buttons-e;
    grid-column: back-s/back-e;
}

Anyway, that looks good, let's go try it out now. It looks a little a little bit good, it looks a little off though.

large

The reason it's off is because we're applying this margin-top only to the login, so instead of doing it to the login, let's get rid of this and let's go to the line and let's see margin-bottom. Now I believe this didn't work before and the reason it didn't work before is because, let's see, let's comment this out. Yeah, that's the 15px gap you're seeing there.

The reason it didn't work before or at all still is because of the line is only 2 pixels. So let's add in 24 pixels here, so let's say 26 pixels, now it will work.

signup.scss

&__form {
    display: grid;
    grid-template-rows: [name-s] 64px [name-e email-s] 64px [email-e space-s] 35px [space-e password-s] 64px [password-e confirm-s] 64px [confirm-e] minmax(20px, 81px) [line-s] 26px [line-e buttons-s] 38px [buttons-e];
    grid-template-columns: [back-s] 137px [back-e space-s] 40px [space-e create-s] 1fr [create-e] 1fr;
    grid-row-gap: 15px;
}
&__line {
    grid-row: line-s/line-e;
    border-top: 1px solid #ccc;
    margin-bottom: 24px;
}

Okay, see it looks great.

large

Now let's just change these quick links and be done with this form, so we can move on to the actual application. Well, I guess this is the actual application but the bulk of the application. Okay, so in the design, these aren't links and it says password requirements. So I'm just going to drag this over here, let's see not like that, I'll drag this over here, all right cool. So what we need to do is basically go into our signupForm and we need to go to our details, our links here, and we need to change these titles to what it says in the design.

So at least six characters, and then we got, at least one number, now we have at least one symbol. Okay, now what I want to do is get rid of these onClicks and then I want to rename links to info, and then what we'll do is we will copy that info array around here and in details instead of saying links will say info and then pass in info. Okay and then will change the title real quick to Password Requirements.

signupForm.js

class SignUpForm extends Component {
    render() {
        const { className, handleSubmit } = this.props;
        const info = [
            {
                _id: 0,
                title: 'At least 6 characters'
            },
            {
                _id: 1,
                title: 'At least one number'
            },
            {
                _id: 2,
                title: 'At least one symbol'
            }
        ]
<Details className='sign-up-form__details' title='Password Requirements' info={info}/>

Okay, now let's go into details.js, and what we need to do is we need to, this will crash now if we go to signin or signup right because it's trying to map over links but they don't even exist. Okay, it's now info so what we need to do is pass in info here, and we need to take it out of props and then what we'll do is we will cut this links map and we'll cut this well we'll say right here this.renderChildren(); and then what we'll do is we'll take info and links out of this, and we'll write a function above render called render children is equal to an arrow function and then in here we'll say constant links and infos is equal to this.props.

details.js

import React, { Component } from 'react';

class Details extends Component {

    renderChildren = () => {
        const { links, infos } = this.props;
    }

    render() {
        const {className, title } = this.props;
        return (
            <div calssName={'${className} details'}>
                <div className='details__title'>{title}</div>
                <div className='details__links'>
                    {
                        this.renderChildren()
                    }
                </div>
            </div>
        )
    }
}

export default Details;

Now what we can do is say if links else if infos and then we can basically make a let here, we'll say let children is equal to an empty array and then what we can do is we can say children is equal to our map statement that we had earlier. Okay, so children is equal to links.map link and this is in the if link's scenario okay and then opposed to that if it's infos that's there, we can say children is equal to infos.map and I'll say info here info.id and then we obviously have no onClick and we'll keep it as an a tag just because we have styles on it, we can probably change it to a div and it wouldn't matter, let's try that.

details.js

import React, { Component } from 'react';

class Details extends Component {

    renderChildren = () => {
        const { links, info } = this.props;
        let children = [];
        if(links) {
            children = links.map(link => {
                return <a key={link._id} onClick={link.onClick} className='details__link'>{link.title}</a>
            })
        } else if(info) {
            children = info.map(info => {
                return <a key={info._id} className='details__link'>{info.title}</a>
            })
        }
    }

    render() {
        const {className, title } = this.props;
        return (
            <div calssName={'${className} details'}>
                <div className='details__title'>{title}</div>
                <div className='details__links'>
                    {
                        this.renderChildren()
                    }
                </div>
            </div>
        )
    }
}

export default Details;

Okay, let's see what this looks like actually.

large

See Password Requirements, looks like we have an error but we don't call it infos that's why we called it info. And then what say item instead of info.

details.js

} else if(info) {
    children = info.map(item => {
        return <a key={item._id} className='details__link'>{item.title}</a>
    })
}

Okay cool, that looks good to me. Let's go ahead and call this a div now, save it and then what we need to do. This didn't work either because we need to return it, we're not doing anything with children we need to go down here and say return children.

details.js

import React, { Component } from 'react';

class Details extends Component {

    renderChildren = () => {
        const { links, info } = this.props;
        let children = [];
        if(links) {
            children = links.map(link => {
                return <a key={link._id} onClick={link.onClick} className='details__link'>{link.title}</a>
            })
        } else if(info) {
            children = info.map(item => {
                return <div key={item._id} className='details__link'>{item.title}</div>
            })
        }
        return children
    }

So in the case that nothing is passed in links or info, it's still going to just return an empty children array. So that's going to look good. All right sweet, so let's go ahead and apply some inline styles to this div so it doesn't get these underlines. So we need a say after class we need to just say style is equal to an object in braces so two sets of brackets, and we'll say, well we wont do that, we'll just apply another class name. We'll say details and instead of link we'll say item.

 return <div key={item._id} className='details__item'>{item.title}</div>

And then what we can do is we can go into details.scss and we can just say .details__item and we can say text declaration line is none and that will overwrite it.

details.scss

.details__item {
    text-decoration-line: none;
}

See, it's all gone.

large

Okay, so a bit long of a video. A lot covered but we got everything done in this form, so that's good, we got all this done. We need to add in this back button now okay, so let's add this in and then end the video.

So let's go into our signupForm.js and on back all we're going to do is just say history.push, and we'll push it to the signup.

signupForm.js

<Field className='sign-up-form__back'
onClick={() => history.push('/signin')}
type='button'
title='Back'
name='back'
short={true}
component={FormButton}/>
<Details className='sign-up-form__details' title='Password Requirements' info={info}/>

Now what we need to do is import history so let's go to the top here, it looks like we're already importing it, so we're good there. So let's go to our app here and let's hit back. Looks like it doesn't push us, let's reload the page. Okay, it's because we're pushing us to signup I bet, yeah, we need to push us to sign in. Okay, reload the page hit back, we're brought to sign in and it fills it out.

large

Let's go to not registered, looks good to me, and yeah that looks really clean.

large

All we need to do now is push login to the shop right. Let's go to bootstrap and see with that route is, looks like we don't have a shop route yet. So what we need to do in the next video is basically handle this shop route, we need to create a shop component and a shop route so we can actually get to the shop when we hit login here.

So let's go ahead and commit our code after we change the not registered to create account. We really need to change that in this video. So let's go to signinForm.js and just change this login title to create account, and then we'll just do it now and we'll push the user to shop straight from here.

signupForm.js

<div className='sign-up-form__line'></div>
<Field className='sign-up-form__login'
onClick={() => history.push('/shop')}
type='submit'
title='Create Account'
name='login'
component={FormButton}/>

So we're pushing them to shop when they hit create account and then we're going to do the same when they login. So let's go to signinForm.js and instead of saying trying to submit we'll just say history.push shop.

signinForm.js

<div className='sign-in-form__line'></div>
<Field className='sign-in-form__login'
onClick={() => history.push('/shop')}
type='submit'
title='Login'
name='login'
component={FormButton}/>

So now what will happen is when we hit create it will take us to shop and when we hit back it takes us to signin, and when you hit login it takes us to shop. Okay cool, so that's really the next case is create account, you're brought, I guess you're brought here to purchase History but we want to basically get on with the shop, we don't want to handle this account information stuff yet.

So what we need to do is hit login, login, and I guess it takes a straight to purchase history, so maybe we should handle this first. We'll handle the purchase history and account information first, so we need a change these routes real quick instead of shop to account okay, can change them to account in signinForm

signinForm.js

<div className='sign-in-form__line'></div>
<Field className='sign-in-form__login'
onClick={() => history.push('/account')}
type='submit'
title='Login'
name='login'
component={FormButton}/>

and in signupForm.js will change it to account.

signupForm.js

<div className='sign-up-form__line'></div>
<Field className='sign-up-form__login'
onClick={() => history.push('/account')}
type='submit'
title='Create Account'
name='login'
component={FormButton}/>

So we're going to handle the purchase history and account information. They belong in the same one that's why I'm calling it account. So let's go ahead and commit our code and I'll see you in the next video.

Terminal

git status
git add .
git commit -m "finished signup form and grid"

I'll see you in the next video

Resources

Source code