‫All right, this is part two
‫of Building the Tour Page Detail Page.
‫And we left off the last video
‫after building this Quick Facts part here
‫using some mixins, right?
‫And so next up it's time to build
‫this part here of the guides.
‫Now we don't know beforehand how many tour guides
‫there actually are on each tour.
‫And so just like on the overview page,
‫here we need to have another loop
‫to basically loop through all the guides
‫that are associated with a certain tour.
‫So, let's do that.
‫And right now we actually have these three elements.
‫So these three box, one for each guide.
‫But as we just said, that's not how we want it to work.
‫So let's get rid of these two and then create a loop here,
‫which in each iteration will create a box,
‫so an element like this.
‫And that should be fairly easy.
‫So again, we use each
‫and then the name of the variable in the current iteration,
‫in, and then the array that we want to loop through.
‫And so that's tour.guides.
‫Right?
‫So,
‫where is that?
‫Yeah, so here is our array of guides.
‫Which of course, in the database will then be populated
‫with the corresponding users and not just the IDs, right?
‫So now we need to indent all of this here.
‫And so each of these guides here
‫will basically be a user document.
‫So let's quickly check that out in Compass
‫because we don't have that kind of data in our JSON document
‫because, of course, the population only happens
‫behind the scenes using Mongos, right?
‫So each of the guides is a user.
‫And so what we want is the name and the photo.
‫So here we want the photo, of course.
‫Which is, in this page,
‫at images/users and then the name of the user photo.
‫So guide.photo.
‫Which is here, again, the variable name
‫in the current iteration.
‫Then here I don't know why it says Lead guide,
‫but let's actually put the name of the person here.
‫So guide.name.
‫Then here we want the guide's name again,
‫.name.
‫And then we also want the label.
‫And so basically that will be
‫Lead guide when it's lead guide
‫and simply tour guide when it's a regular guide.
‫Now let me show you what happens
‫when we just put the role here.
‫So remember that role is the property
‫where we say if a user is a guide
‫or a lead guide or even an admin.
‫Okay?
‫So, again, let's for now see what happens
‫when we just put it like this.
‫And with that we should be ready to actually test it.
‫Let's give it a save.
‫And here we go.
‫So we have the three photos, the names,
‫but then here the guide role
‫doesn't really look good, right?
‫So remember how, in fact, we want to say lead guide
‫and tour guide.
‫Okay, and so now it's time to use a conditional.
‫Now pug actually has conditionals built in,
‫but they are really simple and we can't
‫do a lot of stuff with them.
‫For example, they don't even allow us
‫to test for equality, for example.
‫But, the good thing is that we can
‫actually still use JavaScript for that.
‫And so again, we use some unbuffered code for that.
‫So with the dash syntax and then we can
‫use a regular JavaScript if here.
‫So again, as if we were just writing JavaScript.
‫And so guide.role and now we can test and say
‫if it's a lead-guide.
‫Well then here we want to say
‫Lead guide, okay?
‫And let's put another one here
‫and say if the role is just guide,
‫well, then we want Tour guide.
‫And so this is how we use a JavaScript if write inside
‫of pug and then combine it with a pug output like this.
‫All right?
‫So, let's see.
‫And indeed, that is much nicer.
‫Okay.
‫Let's get rid of this empty space here
‫and move on to the next one,
‫which is the description box.
‫So first up here in the heading
‫we actually also have the name of the tour.
‫So this here is the name of the tour,
‫and so let's create a template string,
‫and in there let's put tour.name.
‫I thought that would work.
‫But it doesn't.
‫This only works in JavaScript.
‫Okay, and actually I just remembered
‫that we also want to have the tour right in the main title.
‫So, right here actually.
‫Okay, so let's do that.
‫Okay.
‫But anyway, let's move down here
‫and create these paragraphs.
‫Now as you see we actually have
‫two paragraphs here for this text.
‫So let's just take a look at how we have it here
‫in the description.
‫And as you see, we of course only have one big string.
‫But we have it in the middle divided
‫with these new line characters.
‫All right?
‫And so what we're gonna do is to split the string
‫by the new line character.
‫Okay?
‫So that's easy, right?
‫So, unbuffered code to write JavaScript.
‫Paragraphs equals tour.description.split
‫by the new line character.
‫And so this will now create an array.
‫So paragraphs is an array,
‫where each of the element is basically one paragraph.
‫Okay?
‫And so now all we need to do is to loop
‫through all of these paragraphs and print their content.
‫So each p, let's say,
‫in paragraphs will be p.description_text
‫equal to the current paragraph, which is p.
‫So, simple right?
‫Let's check that out.
‫And we cannot really see if it's different
‫because I just used this blind text here.
‫But I can tell you that this here
‫should be the correct text.
‫And if we go to the forest hiker tour,
‫actually here in Compass,
‫so where is that?
‫Right here.
‫So if we go here to the description
‫and try to edit that,
‫so let's just add another new line character here.
‫Then let's update and then we should see a new paragraph
‫popping up somewhere here.
‫Let's change that.
‫And that didn't go so well.
‫I'm not sure why.
‫I never tried to do it,
‫so what I just did was the first time that I tried it.
‫So I'm not sure what went wrong here.
‫Maybe we really just need to create a new line
‫by hitting enter,
‫but that didn't really work out either.
‫So let's see if we actually have
‫the new line character here.
‫And maybe it's this one here.
‫Well, but never mind, just trust me on this.
‫And now our new line is still there,
‫what's happening?
‫All right, here we go, let's update it.
‫All right, now our other new line that we had here before
‫also kind of disappeared, but never mind.
‫I guess I just shouldn't have used
‫Compass in order to edit this text here.
‫Okay?
‫Anyway, let's now move on to the images.
‫And right now we don't see them here,
‫but this is how it's supposed to look like, okay?
‫So we have three images here
‫displaying side-by-side like this.
‫And so these are actually the images that are
‫somewhere here.
‫So yeah, in the images field
‫we have this array of these three images.
‫So once more we're going to use a loop
‫in order to loop through them.
‫So, simple enough.
‫So, each image in tour.images.
‫And so for each of them we want to create this.
‫So here the source.
‫And that's image/tours, actually.
‫And then the name of the current image,
‫which is image of course.
‫And then here in the alt text we have
‫actually the number of the tour,
‫and more importantly also here in the CSS class name.
‫And so you see that the next one
‫has that image two and image three.
‫Okay?
‫So how are we going to do that?
‫Well, in a pug loop we can
‫actually define a second variable.
‫And that second variable is then going to be the index.
‫So let's call that i, very simply.
‫And so that is a zero-based index,
‫which is going to be zero for the first element
‫and one and two for the other two elements.
‫And so let's first start by putting that there.
‫So that is i, which is the index, plus 1,
‫because we want this to be 1 and not zero.
‫And now this part here is a bit trickier,
‫because we cannot use this syntax,
‫and we can also not use the other interpolation syntax
‫right here in the class name.
‫And so instead what we're going to do is to copy this,
‫and actually define it as a class attribute.
‫Okay, and so that is exactly the same.
‫But here we can then use a template string
‫in order to then fill that one here.
‫So i + 1.
‫All right, let's get rid of this.
‫And let's test it.
‫Whoa, something's not right here.
‫So, we have our images, but they do not look correct.
‫But the class name is actually right.
‫And also you see it here applied.
‫But for some reason it didn't find these images.
‫Or actually it did.
‫Down here it says that it didn't.
‫Ah, but these are actually other images.
‫But these are some other ones that are a bit further down.
‫Anyway, what I guess is not correct here
‫is that this image should be inside of this picture box,
‫and so I guess something in our indentation here is wrong.
‫And yeah, indeed that is.
‫So you see this image is at the same level
‫as this div element.
‫So of course, there is a missing indentation.
‫All right.
‫And so that should now be fixed.
‫And here we go.
‫All right.
‫So that, just to see that this was the problem.
‫Now indeed the picture is inside of the picture box.
‫So great.
‫Next up is the map.
‫Which remember, I'm going to leave for the next lecture,
‫so that for now we can worry about
‫putting the tour reviews here in this element.
‫Okay.
‫And so, again, we're now moving on to this part here.
‫Now where are these reviews actually coming from.
‫Well, remember how here
‫in the viewController we did populate
‫the reviews field with the actual review data.
‫And so right now we have tours.reviews,
‫which is an array of all the reviews.
‫And so as you can probably guess,
‫we are now going to create yet another loop
‫right here inside this review element.
‫So, each review in tour.reviews.
‫And then in each of them we will have this review card.
‫All right.
‫Now this here is a lot of code,
‫which is kind of distracting us here from our main content.
‫And so let's again, actually create a mixin here.
‫All right.
‫So,
‫let's put it here at the top.
‫And you'll see why in a second.
‫So reviewCard.
‫And in here we pass the review itself.
‫All right.
‫And now we actually need to fix these indentations.
‫And instead of doing it manually,
‫remember, I'm going to use
‫that VS Code package that we have.
‫And so command shift p or control shift p on Windows
‫and then Beautify pug.
‫And so that fixes it.
‫And so now we need to create this review here
‫based on the data.
‫But before we do that, let's actually call the mixin here
‫in each iteration of the review.
‫So +reviewCard with the current review, right?
‫So, let's just take a look at what
‫a review actually looks like.
‫And we have the reviews here.
‫But indeed, they will not be really useful
‫because the user is not populated here.
‫So let's actually go to a Postman
‫and take a look at the final populated reviews in there.
‫So let's say get review on tour.
‫Because that will then be a complete review.
‫So we have the review field, the rating, and then the user.
‫And what we're interested in here
‫is then user.name and user.photo.
‫All right, and so the username will be review.user.name.
‫Right?
‫So review.user.name.
‫And so all of this is necessary because of course
‫we have now multiple datasets related to one each other
‫and so with the populate function
‫they are all now kind of nested one into each other.
‫So let's use his name here as well.
‫All right.
‫And then here
‫we will not use his name.
‫Oh and I forgot the interpolation,
‫and then here it's the photo.
‫All right.
‫Here it's going to be the description.
‫And that's actually review.review, I believe.
‫So, yeah.
‫So review.review.
‫And this is the easy part and the hard part next
‫is going to be to display the actual rating,
‫because we have to display one of these elements here
‫for each of the number of stars that the review has.
‫So a five-star review needs all of these five stars.
‫But a four-star review only needs four of them
‫and then plus that we also want a gray star.
‫So basically to say four out of five, okay?
‫But let's first take a look, if this is actually working.
‫So everything except the rating.
‫So let's reload, and indeed, here we are,
‫with the users, then name, and the review text itself.
‫And let's now take care of actually displaying
‫the rating as well.
‫So what we're gonna do here is
‫to print the amount of stars in a loop.
‫So there are five possible stars
‫and so we loop from one to five.
‫Then in each star we test if the tour rating
‫is higher or equal to the current star.
‫And if so, we print a green star,
‫which stands for an actual star.
‫And if not, it is a gray star.
‫So again, which is just an inexistent star.
‫For example, to show three out of five, okay?
‫And that probably sounds a bit abstract,
‫so let's just implement it.
‫So each star in.
‫And now we don't have an array yet,
‫and so we simply create it.
‫So 1, 2, 3, 4, and 5,
‫which are all the possible stars.
‫Next up, let's copy this here.
‫And now the difference between a green star and a gray one
‫is that the green has the active modifier here,
‫and the gray one has inactive.
‫And so we will change that with a template string, okay?
‫And so just like before, we actually need this class name
‫as a class attribute here.
‫All right.
‫Then this should also be here.
‫Let's get rid of this.
‫And so now let's do that test that we just mentioned.
‫And again, the output of that will be that this year
‫is either active or inactive.
‫And so let's put some JavaScript right at this point.
‫And so what we're going to do here
‫is to test if the review.rating,
‫which is where the rating is stored,
‫is greater or equal than the current star.
‫So basically we're writing a turnery operator here.
‫And so if it is, then here we want to say,
‫active,
‫and if not,
‫then inactive.
‫And this looks kind of weird, I know.
‫So let's just exemplify that with a simple example.
‫So let's say that we have three stars out of five, okay?
‫So in the first iteration, star is one.
‫And so one is of course less than three.
‫And so the first star should, of course,
‫be a green one, and so that's why here we put out active,
‫which will then result in reviews_star--active.
‫Okay?
‫Then the same thing with the second and the third star.
‫So at that point we have three green stars.
‫But the fourth and the fifth one should be gray.
‫Okay?
‫And so in the fourth iteration here star is four.
‫So the test is is three greater than four?
‫No it's false and so it's inactive.
‫And so that will then be a gray star,
‫and the same thing for the last, so the fifth star.
‫All right, so let's test that.
‫And actually we cannot test it here,
‫because this forest hiker
‫has a perfect five out of five rating
‫and so all the reviews are five stars.
‫And so we need to come here to all tours.
‫And while this link is not really working just yet,
‫so you see it only edits like this,
‫this hash here.
‫And so let's quickly actually go ahead and fix that.
‫And that is in the header, so right here.
‫But we don't want that.
‫We simply want to go to our root page.
‫So that's just the slash.
‫So reload.
‫And now down there in the link you see
‫that that's exactly what we have.
‫And so indeed, we get back to our overview page.
‫So let's go to a page with a lower average.
‫And so that's the sport lover.
‫Let's see.
‫And of course you see that all the data
‫is now correct for this specific tour.
‫So again you see this 3.9 average.
‫You see all these different tour guides,
‫the different pictures,
‫and you see all the reviews.
‫And also you see that the stars are actually working.
‫So this first review is a five-star review.
‫And so you see five, four, one,
‫and then a bunch of four-star reviews down here.
‫Okay, so, this was a bit more confusing, this part,
‫but we still managed to get it work, right?
‫Now one thing that I wanted to just show you
‫is that we can actually also export,
‫basically a mixin into its separate file.
‫And so let's just copy this
‫and create a new mixin here,
‫or actually a new file.
‫And so since we're then going to include it
‫I will again prefix this with this underscore.
‫And let's call it reviewCard.pug.
‫Then paste it here.
‫And all the indentation is still correct,
‫and now all we need to do is to say,
‫include
‫_reviewCard.
‫And so if we try that now,
‫it should still work, which it does.
‫All right.
‫So we wrote a lot of code so far
‫and we're almost done.
‫All that's left to do is this call to action section.
‫And here all we really need to change
‫is this duration here.
‫So we have this nice slogan like,
‫10 days.
‫1 adventure.
‫Infinite memories.
‫All right?
‫But we actually need to replace the number of days
‫so that it's correct for this particular tour.
‫So let's create a template string for that.
‫So tour.duration.
‫And then also here we have some of the tour images, okay?
‫So let's do that as well.
‫So that's image.tours, or /tours and then slash
‫tour.images.
‫And remember that this is an array,
‫and I will simply use the first and the second element.
‫Or actually the second and the third
‫'cause I found out that these usually
‫look a bit better in the situation.
‫So,
‫let's copy that.
‫Put that here.
‫Oh and we're missing the closing bracket here.
‫And let's just add some alternative text.
‫Tour picture.
‫All right.
‫And I think that's actually it.
‫So just one last try.
‫You see that here it's blank right now.
‫But now indeed,
‫we have the same images here.
‫So this should be number two.
‫But still, now it says 14 days,
‫and so all of that is correct now.
‫Awesome.
‫That's fantastic.
‫That was a lot of work,
‫but I think it really paid off.
‫This page, I think looks absolutely fantastic.
‫It's really stunning.
‫And so now everything is connected.
‫So on each tour we can go back to all the tours
‫and take a look at all the other ones.
‫Let's see the park camper.
‫The park camper tour.
‫All the details.
‫All the different guides, images,
‫their reviews, and indeed these different images.
‫Great.
‫So you see this blank hole here in the middle of our page.
‫And so that's where the map is going to be next,
‫and so let's do that, actually right now
‫in the next lecture.