Building out the Purchase Detail Component
Hey there, welcome back to the course. In this video we are going to further develop the purchase detail component.
Guide Tasks
  • Read Tutorial
  • Watch Guide Video
Video locked
This video is viewable to users with a Bottega Bootcamp license

Let's get rid of this text in the purchase detail component, and let's go to chrome and see what we need. All right, so we need an order number and an order date, let's start with that and a shipping address.

So div, className is purchase-detail__order-number. All right now let's just copy this a few times, so we've got order date and shipping address. Okay, in each of these we need a label and let's do this, let's make this a component by going up here and saying constant or we'll just make it a function and we'll say purchaseDetailLabel and this is going to take in an object, a title, and a value.

And then in here we're just going to make it a function. So function purchaseDetailLabel and we're just going to return a div, we're also going to pass in a className I guess, so className, then down here say className is equal to brace's className and then we'll say purchase-detail-label.

All right, now what we can do is put those in here, we can say label, we can say class name is purchase-detail-label_label and then we will put the title in there. And then we'll make a div, and will say className is purchase-detail-label_value and then we'll put the value in there. So what I want to do is rename this one to title and then make this a div as well not a label.

purchaseDetail.js

function PurchaseDetailLabel({className, title, value}) {
    return (
        <div className={'${className} purchase-detail-label'}>
            <div className='purchase-detail-label__title'>{title}</div>
            <div className='purchase-detail-label__value'>{value}</div>
        </div>
    )
}

Let's go ahead and capitalize PurchaseDetailLabel, and let's get ahead and get rid of these divs in the PurchaseDetail and say and we'll pass in a className of purchase-detail__order-number. Let's put these all on a separate line, then we've got title is Order Number, and then we've got value is, well let's take in a prop called orderNumber.

purchaseDetail.js

class PurchaseDetail extends Component {
    render() {
        const { className } = this.props;

        return (
            <div className={'${className} purchase-detail'}>
                <PurchaseDetailLabel
                className='purchase-detail__order-number'
                title='Order Number'
                value={orderNumber}/>
            </div>
        )
    }
}

export default PurchaseDetail;

Okay, let's check our model though, okay so let's go into user.js so we've got order name and order number so we just want these properties here so I'm going to copy one of these objects and get rid of this file or close it.

large

And I'm just going to paste it in here just to have a reference, I'm going to comment it out. You don't have to do this, I'm just doing it so I know what to type in feel free to do it if you want. All right, orderNumber, that's good. Now we need the orderDate, so copy this and let's put order-date, and we'll call it Order Date, and we'll pass in the order Date.

Okay, now what we need to do is get the shipping, remember the shipping address which contains a name and the address so basically the whole user object. So let's put another one in here, let's change the class to shipping, let's change the title to shipping address and let's change the value to shipping, we're going to have two values.

So we're going to put string interpolation in here. All right, string literal, and we'll say name and then we'll say \n so we'll put it on a new line, and then we'll put in the address okay, so the shipping address.

purchaseDetail.js

class PurchaseDetail extends Component {
    render() {
        const { className } = this.props;

        return (
            <div className={'${className} purchase-detail'}>
                <PurchaseDetailLabel
                className='purchase-detail__order-number'
                title='Order Number'
                value={orderNumber}/>
                <PurchaseDetailLabel
                className='purchase-detail__order-date'
                title='Order Date'
                value={orderDate}/>
                <PurchaseDetailLabel
                className='purchase-detail__order-shipping'
                title='Shipping Address'
                value={'${name}\n${shippingAddress}'}/>
            </div>
        )
    }
}

Because you'll notice that in here it has the name then on a new line it has the address.

large

So let's go ahead and let's try this out and see what's going on. It's going to crash initially because we don't have values for these. So let's get those out of props, we've got the order number, we got the order date, and then we got the user, and then we need to take something out of the user. We need to say name and we need a shipping address from the user.

purchaseDetail.js

class PurchaseDetail extends Component {
    render() {
        const { className, orderNumber, orderDate, user } = this.props;
        const { name, shippingAddress } = user;

        return (
            <div className={'${className} purchase-detail'}>
                <PurchaseDetailLabel
                className='purchase-detail__order-number'
                title='Order Number'
                value={orderNumber}/>

Now you actually need to provide these details for it to work okay, those are the two we need left the total and the credit card, I'll leave those comments. Okay, so we need to provide the user the order date and the order number.

So in order for this to work we basically just need to get this from mapStateToProps because we already have it in the detail if you remember. We actually don't even need mapStateToProps we just need connect, so import { connect } from 'react-redux';. Now down here at the bottom we just need to say PurchaseDetail is equal to connect and then we'll pass in mapStateToProps and we'll bind it, no actions required.

purchaseDetail.js

import { connect } from 'react-redux';
PurchaseDetail = connect(mapStateToProps)(PurchaseDetail);

export default PurchaseDetail;

Okay, let's type out our mapStateToProps function and in here we just want to return the purchase detail selected okay. So say purchaseDetail and then let's say constant purchaseDetail is equal to state.user alright that should work. We've got to extract it though so let's put some spaces around it or some braces.

purchaseDetail.js

function mapStateToProps(state) {
    const { purchaseDetail } = state.user;
    return {
        purchaseDetail
    }
}

PurchaseDetail = connect(mapStateToProps)(PurchaseDetail);

export default PurchaseDetail;

Okay, so get this all in here. Make sure you understand what's going on with this component. We're going to have to style it, but we just want to see if the data is going over properly. So let's go to Google Chrome and we have some errors, pretty expected, okay so mapStateToProps is not defined, yeah it is, function mapStateToProps is not defined, okay, name is undefined.

Okay, let's check our initial state, that's the problem here. We need to go into the userReducer.js and on purchaseDetail we need to provide a user and we need to say that it has a name of nothing and then address nothing will also provide the other fields right.

So we need to provide all these other things okay so I'm going to copy this. Put it in our initial state, we'll just make this an empty string, we'll leave this as a new date. we'll make this an empty string and we will make this zero and this can be -1.

large

Okay cool, now lets try this out, that might be the problem, okay, it still has this problem. Let's leave this here, let's go into purchaseDetail.js, so mapStateToProps PurchaseDetail, I'm going to go to localhost 3000 and sign in and see what happens.

large

Cannot read property, name of undefined line 21. Okay, we need to check line 21, let's go up here to line 21. For some reason it's not pulling it out correctly, probably, it just doesn't make sense, it should be there. Shipping addresses is not defined, well no duh. Okay, I'm going to cut this out and comment it right there. Okay think you, click on an item and it doesn't feel anything up.

It should but it's not and that's because we're not passing anything to this, well, yeah we are, because we're using mapStateToProps. Okay here's the problem, it's that, I'm going to put this back in and get rid of this. The problem is that we're just putting it in here, it would work if we set this.props.purchaseDetail.

So we could do it this way and it will work, or not. Okay, purchaseDetail and let's just say this.props and then let's say purchaseDetail and let's use the spreader operator on it, okay, let's try that out. Okay, that didn't work, let's go to the front and let's log in and it doesn't work. It's probably because we're using a Date object.

Okay so let's go into our userReducer and instead of a new date let's just say null, let's save it and let's go back to our app and it's working, and now it's not working. So what we need to do is, we need to not use date objects okay, it's freaking out because we're using date objects. So what we need to do is say, I still want to use a date object so we can parse it, but it has to be a string, okay, so we have to say new Date().toDateString().

So I'm going to copy just the .toDateString, and then I'm actually going to get rid of it and then that way we can put it at the very top one and then we can just copy this entire thing and then we can select the new date here and hit command + d through all of these and then just paste it without over writing the top one.

Okay, so just make sure these are all to date strings, it still might not work but whatever, let's try it out. Okay, it works, I'm very happy now. Okay, it works fine, everything's well. Let's reload the page and see what happens, and no errors, okay excellent.

Let's go into our code and let's go back to purchaseDetail and let me show you what I was thinking, we can do this way, or we can return it as purchaseDetail and it still wont work right, we'll get the errors we're getting before. But we can say this.props.purchaseDetail. Now, I'd like to do it the other way by using the spread operator because the only thing, it's a detail, so we want to just have that as the props it shouldn't have anything other than the purchaseDetail on the class.

All right let's try. Looks good to me, it's got our properties. Now we need to put in the total and the credit card. Okay, so let's just do that really quickly, it should be quick, let's go into the PurchaseDetail and let's copy this a couple times and let's say instead of shipping we obviously want the total, all right. And the title needs to be total and what needs to go in here is the total okay, we need to take that out of props and then same with the credit card.

Now let's see, did we call it credit card or card, yeah we called it credit card, okay so card in total. Now what we need to do is we need to change this one to credit-card and we need to change our title to Credit Card and then we need to replace the content in here with credit card, okay so that should be working, let's go ahead and try it out.

All right fills out the information, looks good to me, switching up, I guess it's not switching but whatever. Click that, it doesn't change your data again for whatever reason, do they all have the same id? I don't know.

So in the next video what we need to do is we need to lay these all out on a grid and we need to style them so they look like the design and then we'll add in the track shipment, and print receipt buttons which do absolutely nothing in this design, so they're going to do absolutely nothing in our application. Okay, so let's commit our code, and then hop into the styles and get rid of the purchaseDetails component.

Terminal

git status
git add .
git commit -m "purchase detail component"

I'll see you in the next video.

Resources

Source code