The Views: Create a new view for the product details page

As we have created a beautiful page for displaying the list of products, now it is time for displaying the details of a product. On clicking an item from the products list we shall load a new page displaying the details. In this lesson, we shall create that page.

  1. We shall create a new view and copy the content of the products view
  2. We shall keep the same header and footer but replace the code for the main content
  3. We shall hide the seller’s information if the user is not logged in

Step 1: The first thing we’ll do is – create a new file inside the views folder, let’s name it product.blade.php . (Notice the difference: it product (singular) not products, or you may name it anything)

Step 2: Now copy the content of the products view. To maintain a consistent look throughout the website, we shall use the same header and footer on all the pages. So the structure of the product details page will be similar to the products list page, we only have to change the main content portion. Let me add some comments to distinguish the different portions of the page. I am collapsing these divs for clarity.

Are you thinking that this is not a good idea—-!!— to write the same code again and again?

-If yes then you are absolutely right, duplication of code is bad. It will make it difficult to maintain and scale the app. For example, one day if we decide to add a new item to the menu of the nav bar we would have to change the code in all the pages.

So is there any better way to write this code?

-Yes, of course. I will show you that soon but first, let us design the product details page.

Step 3: First, remove the code under the section main content, and add a new div. Inside this div add two more divs, as we shall display the product image on the left half and some text information on the right half.

<!-- Main content -->
<div class="">
    <div>Left half</div>
    <div>Right half</div>
</div>

Now, let’s load this page on the browser! But wait; have we added a route for this page? No!!…. then open the file web.php of the route folder and add a route.

Step 4: Add a new route similar to one for products, the URI this time will be product/{id}. We shall also define a route parameter called id to capture the product id passed through the URL. We can define a route parameter using curly brackets like this-

Route::get('/product/{id}',function(){
   return view('product');
 });

At this moment we are not using the ID, and we are simply returning the view for product details. Once we start working with the database we will use this id to retrieve the details of a particular product.

Step 5: Now, let’s go to the products list page, and wrap the div for the product item by an anchor tag as we want a product card to be clickable. On clicking a product we shall load the details for that product. To the href attribute we shall pass /product/1 we shall pass the actual id instead of 1 here for each product when we start displaying actual products.

<div class="grid grid-cols-4 gap-4 p-4">
        @for($i = 0; $i < 10; $i++)
        <a href="/product/1">
          <div class="bg-white rounded shadow overflow-hidden">
            <img src="https://images.unsplash.com/photo-1505740420928-5e560c06d30e?ixid=MnwxMjA3fDB8MHxzZWFyY2h8Mnx8cHJvZHVjdHxlbnwwfHwwfHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=600&q=60"/>
            <div class="p-4">
              <div class="font-semibold text-sm">Headphone</div>
              <div class="text-xs text-gray-500">Excellent quality Headphone at a low price</div>
            </div>
            <div class=" border-t px-4 py-2 font-bold text-sm">$20</div>
          </div>
        </a>
        @endfor
      </div>

Step 6: Click on any product from the list and a product details page gets loaded.

Step 7: Now, back in the product view…..
-Let’s add the classes flex and m-4 to the parent div to place the children side by side.
-And the class w-1/2 to both of the children to divide the space into two halves.
We shall display an image on the left half and some product-related information on the right half.

<!-- Main content -->
      <div class="flex m-4">
        <div class="w-1/2">Left half</div>
        <div class="w-1/2">Right half</div>
      </div>

Now the page looks like this-

Step 8: Let’s display the image on the left, I’ll copy the image element from the product list page and add it here.
– Add rounded to the div to make the corners round
– Add some shadow using the class shadow
– And add overflow-hidden to … well, hide the overflow, so that the image does not move out of the borders of the div.
– To the <img/> tag add the class object-cover and w-full to resize the image to cover the parent div.

<!-- Main content -->
      <div class="flex m-4">
        <div class="w-1/2 rounded overflow-hidden shadow">
          <img class="object-cover w-full" src="https://images.unsplash.com/photo-1505740420928-5e560c06d30e?ixid=MnwxMjA3fDB8MHxzZWFyY2h8Mnx8cHJvZHVjdHxlbnwwfHwwfHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=600&q=60"/>
        </div>
        <div class="w-1/2">Right half</div>
      </div>

Now reload the page….

It looks good, doesn’t it! Now let’s add content to the right half.

Step 9: Let’s copy the divs for the product title and product description from the products list page, and paste it here, inside the div for the right half. Let’s copy the description div once again to display a long description, let me also add some text here.
– Let me try changing the font sizes and see if it make any difference.
– First, I’ll remove the text-sm class from the title, and replace text-xs with text-sm in the description div to make them look a little bigger.
– Add a top margin with mt-2 to the div for the long description.

<!-- Right half -->
        <div class="w-1/2 rounded bg-white ml-2 p-4 shadow">
            <div class="font-semibold">Headphone</div>
            <div class="text-sm text-gray-500">Excellent quality Headphone at a low price</div>
            <div class="text-xs text-gray-500 mt-2">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</div>
        </div>

Now it looks better, so move on to the next component. We shall display the seller’s information below this description.

Step 10: So let’s add a new div. Let’s add some top margin to it with mt-4.
– Inside this div add two more div, first for a label ‘Sold by:’, we’ll make it smaller with text-xs, a little bold with font-semibold, and we’ll change the text color to gray using the class text-gray.
– Now copy this div twice- one for displaying the phone number (So change the label) and the other for the email (Let’s change the label to Email address). Let’s reduce the top margin for these two a little using mt-2 so that they look like parts of the same group of information with the seller’s name. I am also adding some arbitrary values here.

<!-- Seller Information -->
            <div class="mt-4">
              <div class="text-xs text-gray font-semibold">Sold by:</div>
              <div class="text-sm text-gray-500">John Doe</div>
            </div>
            <div class="mt-2">
              <div class="text-xs text-gray font-semibold">Phone number:</div>
              <div class="text-sm text-gray-500">012356789</div>
            </div>
            <div class="mt-2">
              <div class="text-xs text-gray font-semibold">Email address:</div>
              <div class="text-sm text-gray-500">abc@example.com</div>
            </div>

Now, once the CSS gets compiled reload the page once….. and it looks beautiful.

Now we are left with the most important piece of information, the price of the product. Let’s display the price at this portion, the bottom right of this card. Is it going to look good? What do you think? Let’s try and see it …

Step 11: Add a new div,
– We shall place it absolutely at the bottom right corner of the div for the right half. For that, we shall add the classes absolute bottom-0 right-0.

<!-- Product Price -->
<div class="absolute bottom-0 right-0 bg-green-500 px-4 py-2 m-6 rounded-full">
  <div class="text-white font-bold text-sm">$20</div>
</div>

-Now the class absolute to work we have make the parent div relative using the class relative .


<!-- Right half -->
        <div class="w-1/2 rounded bg-white ml-2 p-6 shadow relative">

            <div class="font-semibold">Headphone</div>
            <div class="text-sm text-gray-500">Excellent quality Headphone at a low price</div>
            <div class="text-xs text-gray-500 mt-2">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</div>

            <!-- Seller Information -->
            <div class="mt-4">
              <div class="text-xs text-gray font-semibold">Sold by:</div>
              <div class="text-sm text-gray-500">John Doe</div>
            </div>
            <div class="mt-2">
              <div class="text-xs text-gray font-semibold">Phone number:</div>
              <div class="text-sm text-gray-500">012356789</div>
            </div>
            <div class="mt-2">
              <div class="text-xs text-gray font-semibold">Email address:</div>
              <div class="text-sm text-gray-500">abc@example.com</div>
            </div>

            <!-- Product Price -->
            <div class="absolute bottom-0 right-0 bg-green-500 px-4 py-2 m-6 rounded-full">
              <div class="text-white font-bold text-sm">$20</div>
            </div>

        </div>

Step 12: We shall add some margin m-6, and make it look like a pill. For that let’s add the class rounded-full and add some padding. Let us add px-4 for horizontal padding and a little smaller, py-2 for vertical padding. Also, add a green background color using bg-green-500 (https://tailwindcss.com/docs/background-color)

Step 13: Now add div for the text inside, make the text while (text-white), bold (font-bold), and a little smaller using text-sm.

    <!-- Product Price -->
            <div class="absolute bottom-0 right-0 bg-green-500 px-4 py-2 m-6 rounded-full">
              <div class="text-white font-bold text-sm">$20</div>
            </div>

Step 14: Now compile the CSS and reload the page.

And, wow… the page looks beautiful, I am feeling happy. Now one thing is left before we can proceed to the next video- we have to hide the phone number and the email if the user is not logged in.

Step 15: To fix this let us first take a look at the code of the welcome view. Here this @auth directive of Blade is used to decide which links to display. If the user is logged in then this link is displayed otherwise the else block is considered for rendering.

@auth
   <a href="{{ url('/dashboard') }}" class="text-sm text-gray-700 underline">Dashboard</a>
@else
   <a href="{{ route('login') }}" class="text-sm text-gray-700 underline">Log in</a>

   @if (Route::has('register'))
    <a href="{{ route('register') }}" class="ml-4 text-sm text-gray-700 underline">Register</a>
   @endif
@endauth

Now we have to do something similar, right!

Step 16: So, come back to the product view. Let’s start with the phone number,
-add the @auth directive before the div for the phone number.
-add the @else directive after the phone number div and we also have to add the directive @endauth at the end.
-Now whatever we want to display to an un-authenticated user have to be added between @else and @endauth. This is the else block.
-Let copy the div for the phone number, paste it inside this else block, and replace the number with stars.
Now save and reload the page on the browser.

<!-- Seller Information -->
            <div class="mt-4">
              <div class="text-xs text-gray font-semibold">Sold by:</div>
              <div class="text-sm text-gray-500">John Doe</div>
            </div>
            <div class="mt-2">
              <div class="text-xs text-gray font-semibold">Phone number:</div>
              @auth
                <div class="text-sm text-gray-500">012356789</div>
              @else
                <div class="text-sm text-gray-500">**********</div>
              @endauth
            </div>
            <div class="mt-2">
              <div class="text-xs text-gray font-semibold">Email address:</div>
              <div class="text-sm text-gray-500">abc@example.com</div>
            </div>

Step 17: – Let’s also add a link to log in. Add an anchor tag , and pass the URI /login to to href. -Add classes text-xs and text-blue-500 to the anchor tag to make the text smaller and blue. -Now do the same for the email also.

<!-- Seller Information -->
            <div class="mt-4">
              <div class="text-xs text-gray font-semibold">Sold by:</div>
              <div class="text-sm text-gray-500">John Doe</div>
            </div>
            <div class="mt-2">
              <div class="text-xs text-gray font-semibold">Phone number:</div>
              @auth
                <div class="text-sm text-gray-500">012356789</div>
              @else
                <div class="text-sm text-gray-500">**********<a href="/login" class="text-xs text-blue-500">(Login to view)</a></div>
              @endauth
            </div>
            <div class="mt-2">
              <div class="text-xs text-gray font-semibold">Email address:</div>
              @auth
                <div class="text-sm text-gray-500">abc@example.com</div>
              @else
                <div class="text-sm text-gray-500">**********<a href="/login" class="text-xs text-blue-500">(Login to view)</a></div>
              @endauth
            </div>

Now our product details page looks complete. It looks good. Before proceeding to the next task I would ask you to try logging in and notice the difference once.

The Complete Code:

<html>
    <head>
        <title>Buy and Sell</title>
        <link rel="stylesheet" href="{{ asset('css/app.css') }}">
    </head>
    <body class="bg-gray-50">

      <!-- Header -->
      <nav>
        <div class="flex justify-between p-6 items-center">
          <div>
            <svg viewBox="0 0 651 192" fill="none" xmlns="http://www.w3.org/2000/svg" class="h-8 w-auto text-gray-700 sm:h-8">
                <g clip-path="url(#clip0)" fill="#EF3B2D">
                    <path d="M248.032 44.676h-16.466v100.23h47.394v-14.748h-30.928V44.676zM337.091 87.202c-2.101-3.341-5.083-5.965-8.949-7.875-3.865-1.909-7.756-2.864-11.669-2.864-5.062 0-9.69.931-13.89 2.792-4.201 1.861-7.804 4.417-10.811 7.661-3.007 3.246-5.347 6.993-7.016 11.239-1.672 4.249-2.506 8.713-2.506 13.389 0 4.774.834 9.26 2.506 13.459 1.669 4.202 4.009 7.925 7.016 11.169 3.007 3.246 6.609 5.799 10.811 7.66 4.199 1.861 8.828 2.792 13.89 2.792 3.913 0 7.804-.955 11.669-2.863 3.866-1.908 6.849-4.533 8.949-7.875v9.021h15.607V78.182h-15.607v9.02zm-1.431 32.503c-.955 2.578-2.291 4.821-4.009 6.73-1.719 1.91-3.795 3.437-6.229 4.582-2.435 1.146-5.133 1.718-8.091 1.718-2.96 0-5.633-.572-8.019-1.718-2.387-1.146-4.438-2.672-6.156-4.582-1.719-1.909-3.032-4.152-3.938-6.73-.909-2.577-1.36-5.298-1.36-8.161 0-2.864.451-5.585 1.36-8.162.905-2.577 2.219-4.819 3.938-6.729 1.718-1.908 3.77-3.437 6.156-4.582 2.386-1.146 5.059-1.718 8.019-1.718 2.958 0 5.656.572 8.091 1.718 2.434 1.146 4.51 2.674 6.229 4.582 1.718 1.91 3.054 4.152 4.009 6.729.953 2.577 1.432 5.298 1.432 8.162-.001 2.863-.479 5.584-1.432 8.161zM463.954 87.202c-2.101-3.341-5.083-5.965-8.949-7.875-3.865-1.909-7.756-2.864-11.669-2.864-5.062 0-9.69.931-13.89 2.792-4.201 1.861-7.804 4.417-10.811 7.661-3.007 3.246-5.347 6.993-7.016 11.239-1.672 4.249-2.506 8.713-2.506 13.389 0 4.774.834 9.26 2.506 13.459 1.669 4.202 4.009 7.925 7.016 11.169 3.007 3.246 6.609 5.799 10.811 7.66 4.199 1.861 8.828 2.792 13.89 2.792 3.913 0 7.804-.955 11.669-2.863 3.866-1.908 6.849-4.533 8.949-7.875v9.021h15.607V78.182h-15.607v9.02zm-1.432 32.503c-.955 2.578-2.291 4.821-4.009 6.73-1.719 1.91-3.795 3.437-6.229 4.582-2.435 1.146-5.133 1.718-8.091 1.718-2.96 0-5.633-.572-8.019-1.718-2.387-1.146-4.438-2.672-6.156-4.582-1.719-1.909-3.032-4.152-3.938-6.73-.909-2.577-1.36-5.298-1.36-8.161 0-2.864.451-5.585 1.36-8.162.905-2.577 2.219-4.819 3.938-6.729 1.718-1.908 3.77-3.437 6.156-4.582 2.386-1.146 5.059-1.718 8.019-1.718 2.958 0 5.656.572 8.091 1.718 2.434 1.146 4.51 2.674 6.229 4.582 1.718 1.91 3.054 4.152 4.009 6.729.953 2.577 1.432 5.298 1.432 8.162 0 2.863-.479 5.584-1.432 8.161zM650.772 44.676h-15.606v100.23h15.606V44.676zM365.013 144.906h15.607V93.538h26.776V78.182h-42.383v66.724zM542.133 78.182l-19.616 51.096-19.616-51.096h-15.808l25.617 66.724h19.614l25.617-66.724h-15.808zM591.98 76.466c-19.112 0-34.239 15.706-34.239 35.079 0 21.416 14.641 35.079 36.239 35.079 12.088 0 19.806-4.622 29.234-14.688l-10.544-8.158c-.006.008-7.958 10.449-19.832 10.449-13.802 0-19.612-11.127-19.612-16.884h51.777c2.72-22.043-11.772-40.877-33.023-40.877zm-18.713 29.28c.12-1.284 1.917-16.884 18.589-16.884 16.671 0 18.697 15.598 18.813 16.884h-37.402zM184.068 43.892c-.024-.088-.073-.165-.104-.25-.058-.157-.108-.316-.191-.46-.056-.097-.137-.176-.203-.265-.087-.117-.161-.242-.265-.345-.085-.086-.194-.148-.29-.223-.109-.085-.206-.182-.327-.252l-.002-.001-.002-.002-35.648-20.524a2.971 2.971 0 00-2.964 0l-35.647 20.522-.002.002-.002.001c-.121.07-.219.167-.327.252-.096.075-.205.138-.29.223-.103.103-.178.228-.265.345-.066.089-.147.169-.203.265-.083.144-.133.304-.191.46-.031.085-.08.162-.104.25-.067.249-.103.51-.103.776v38.979l-29.706 17.103V24.493a3 3 0 00-.103-.776c-.024-.088-.073-.165-.104-.25-.058-.157-.108-.316-.191-.46-.056-.097-.137-.176-.203-.265-.087-.117-.161-.242-.265-.345-.085-.086-.194-.148-.29-.223-.109-.085-.206-.182-.327-.252l-.002-.001-.002-.002L40.098 1.396a2.971 2.971 0 00-2.964 0L1.487 21.919l-.002.002-.002.001c-.121.07-.219.167-.327.252-.096.075-.205.138-.29.223-.103.103-.178.228-.265.345-.066.089-.147.169-.203.265-.083.144-.133.304-.191.46-.031.085-.08.162-.104.25-.067.249-.103.51-.103.776v122.09c0 1.063.568 2.044 1.489 2.575l71.293 41.045c.156.089.324.143.49.202.078.028.15.074.23.095a2.98 2.98 0 001.524 0c.069-.018.132-.059.2-.083.176-.061.354-.119.519-.214l71.293-41.045a2.971 2.971 0 001.489-2.575v-38.979l34.158-19.666a2.971 2.971 0 001.489-2.575V44.666a3.075 3.075 0 00-.106-.774zM74.255 143.167l-29.648-16.779 31.136-17.926.001-.001 34.164-19.669 29.674 17.084-21.772 12.428-43.555 24.863zm68.329-76.259v33.841l-12.475-7.182-17.231-9.92V49.806l12.475 7.182 17.231 9.92zm2.97-39.335l29.693 17.095-29.693 17.095-29.693-17.095 29.693-17.095zM54.06 114.089l-12.475 7.182V46.733l17.231-9.92 12.475-7.182v74.537l-17.231 9.921zM38.614 7.398l29.693 17.095-29.693 17.095L8.921 24.493 38.614 7.398zM5.938 29.632l12.475 7.182 17.231 9.92v79.676l.001.005-.001.006c0 .114.032.221.045.333.017.146.021.294.059.434l.002.007c.032.117.094.222.14.334.051.124.088.255.156.371a.036.036 0 00.004.009c.061.105.149.191.222.288.081.105.149.22.244.314l.008.01c.084.083.19.142.284.215.106.083.202.178.32.247l.013.005.011.008 34.139 19.321v34.175L5.939 144.867V29.632h-.001zm136.646 115.235l-65.352 37.625V148.31l48.399-27.628 16.953-9.677v33.862zm35.646-61.22l-29.706 17.102V66.908l17.231-9.92 12.475-7.182v33.841z"/>
                </g>
            </svg>
          </div>
          <div >
            @if (Route::has('login'))
                <div class="">
                    @auth
                        <a href="{{ url('/dashboard') }}" class="text-sm text-gray-700 underline">Dashboard</a>
                    @else
                        <a href="{{ route('login') }}" class="text-sm text-gray-700 underline">Log in</a>



                        @if (Route::has('register'))
                            <a href="{{ route('register') }}" class="ml-4 text-sm text-gray-700 underline">Register</a>
                        @endif
                    @endauth
                </div>
            @endif
          </div>
        </div>
      </nav>
      <!-- Main content -->
      <div class="flex m-4">
        <!-- Left half -->
        <div class="w-1/2 rounded overflow-hidden shadow">
          <img class="object-cover w-full" src="https://images.unsplash.com/photo-1505740420928-5e560c06d30e?ixid=MnwxMjA3fDB8MHxzZWFyY2h8Mnx8cHJvZHVjdHxlbnwwfHwwfHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=600&q=60"/>
        </div>
        <!-- Right half -->
        <div class="w-1/2 rounded bg-white ml-2 p-6 shadow relative">

            <div class="font-semibold">Headphone</div>
            <div class="text-sm text-gray-500">Excellent quality Headphone at a low price</div>
            <div class="text-xs text-gray-500 mt-2">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</div>

            <!-- Seller Information -->
            <div class="mt-4">
              <div class="text-xs text-gray font-semibold">Sold by:</div>
              <div class="text-sm text-gray-500">John Doe</div>
            </div>
            <div class="mt-2">
              <div class="text-xs text-gray font-semibold">Phone number:</div>
              @auth
                <div class="text-sm text-gray-500">012356789</div>
              @else
                <div class="text-sm text-gray-500">**********<a href="/login" class="text-xs text-blue-500">(Login to view)</a></div>
              @endauth
            </div>
            <div class="mt-2">
              <div class="text-xs text-gray font-semibold">Email address:</div>
              @auth
                <div class="text-sm text-gray-500">abc@example.com</div>
              @else
                <div class="text-sm text-gray-500">**********<a href="/login" class="text-xs text-blue-500">(Login to view)</a></div>
              @endauth
            </div>

            <!-- Product Price -->
            <div class="absolute bottom-0 right-0 bg-green-500 px-4 py-2 m-6 rounded-full">
              <div class="text-white font-bold text-sm">$20</div>
            </div>

        </div>
      </div>

      <!-- Footer -->
      <div class="flex justify-between px-2 py-4 m-4 items-center border-t text-sm text-gray-500">
        <div>Created using Laravel and Tailwindcss</div>
        <div>Laravel v{{ Illuminate\Foundation\Application::VERSION }} (PHP v{{ PHP_VERSION }})</div>
      </div>
    </body>
</html>

Leave a Reply

Your email address will not be published.