1
00:00:03,000 --> 00:00:05,647
In the previous section we focused on

2
00:00:05,647 --> 00:00:07,793
how to fetch data from an API.

3
00:00:07,793 --> 00:00:09,868
How to refresh the data using

4
00:00:09,868 --> 00:00:12,945
Incremental Static Regeneration, and so on.

5
00:00:13,660 --> 00:00:15,847
In this section we'll focus more

6
00:00:15,847 --> 00:00:17,350
on the user interface.

7
00:00:17,350 --> 00:00:20,494
In our HomePage at the moment we're displaying

8
00:00:20,494 --> 00:00:22,545
a very basic list of products.

9
00:00:22,545 --> 00:00:25,620
So let's start by designing a nicer HomePage.

10
00:00:26,393 --> 00:00:28,801
For each product we currently display

11
00:00:28,801 --> 00:00:30,037
a simple text link.

12
00:00:30,037 --> 00:00:32,899
But I'd like to have a product card instead,

13
00:00:32,899 --> 00:00:35,046
showing not just the product name

14
00:00:35,046 --> 00:00:37,128
but also an image and the price.

15
00:00:37,888 --> 00:00:39,762
So what I'm going to do is

16
00:00:39,762 --> 00:00:42,715
extract this code into its own component,

17
00:00:42,715 --> 00:00:44,228
called "ProductCard".

18
00:00:45,654 --> 00:00:47,125
And this will be a typical

19
00:00:47,125 --> 00:00:48,540
React function component.

20
00:00:50,920 --> 00:00:52,666
It will render the same code

21
00:00:52,666 --> 00:00:54,100
we had in the HomePage.

22
00:00:54,662 --> 00:00:56,249
Let's not forget to export

23
00:00:56,249 --> 00:00:58,445
the component function as "default".

24
00:00:59,495 --> 00:01:02,404
We also need to import the "Link" component.

25
00:01:02,904 --> 00:01:05,474
Since we're displaying the product properties,

26
00:01:05,474 --> 00:01:07,765
we'll need to the "product" in the props.

27
00:01:08,320 --> 00:01:11,009
At this point we can replace the old code

28
00:01:11,009 --> 00:01:13,436
with the new "ProductCard" component,

29
00:01:15,186 --> 00:01:17,067
which expects a "product" prop

30
00:01:17,067 --> 00:01:18,635
so let's pass that value.

31
00:01:20,252 --> 00:01:21,458
Ok. As things stand

32
00:01:21,458 --> 00:01:23,869
the page will look the same as before,

33
00:01:23,869 --> 00:01:26,343
because we just moved some code around.

34
00:01:26,969 --> 00:01:28,627
But now we can go and add

35
00:01:28,627 --> 00:01:30,815
some styling to this ProductCard.

36
00:01:32,535 --> 00:01:34,760
Let's start by adding a "border",

37
00:01:34,760 --> 00:01:35,973
so we can also see

38
00:01:35,973 --> 00:01:38,534
how much space each ProductCard takes.

39
00:01:39,168 --> 00:01:41,676
Next, I mentioned I would like to show an image.

40
00:01:43,634 --> 00:01:45,655
To start with I'm going to use

41
00:01:45,655 --> 00:01:48,080
a placeholder from "dummyimage.com".

42
00:01:48,647 --> 00:01:52,097
We can specify the dimensions in the URL,

43
00:01:52,097 --> 00:01:53,359
like "320x240".

44
00:01:53,943 --> 00:01:55,611
Each "img" element requires

45
00:01:55,611 --> 00:01:57,897
an "alt" attribute for accessibility,

46
00:01:57,897 --> 00:02:00,801
but in this case I think we can leave it empty,

47
00:02:00,801 --> 00:02:03,642
because this image will represent the product,

48
00:02:03,642 --> 00:02:05,372
and we're already displaying

49
00:02:05,372 --> 00:02:06,978
the "product.title" below,

50
00:02:06,978 --> 00:02:09,326
so if somebody is browsing our website

51
00:02:09,326 --> 00:02:10,622
using a screen reader

52
00:02:10,622 --> 00:02:12,909
the "product.title" already describes

53
00:02:12,909 --> 00:02:14,392
what this link is about.

54
00:02:15,447 --> 00:02:17,698
Now, if you have ESLint enabled

55
00:02:17,698 --> 00:02:20,166
you may see an error on this line,

56
00:02:20,166 --> 00:02:23,070
saying something like "don't use ".

57
00:02:23,070 --> 00:02:25,611
Just ignore it and continue anyway,

58
00:02:25,611 --> 00:02:28,951
it's only a suggestion from the Next.js rules.

59
00:02:28,951 --> 00:02:32,145
We'll make it go away later in this section.

60
00:02:33,008 --> 00:02:34,333
Anyway, if we save this,

61
00:02:34,333 --> 00:02:36,430
we can now see the placeholder images.

62
00:02:36,985 --> 00:02:38,700
We could do with some spacing

63
00:02:38,700 --> 00:02:40,236
between each product card.

64
00:02:40,795 --> 00:02:43,168
Let's add some margin on the Y axis,

65
00:02:43,668 --> 00:02:44,639
and this looks a bit better.

66
00:02:47,901 --> 00:02:50,499
However there is some blank space on the right

67
00:02:50,499 --> 00:02:52,024
that doesn't look so great.

68
00:02:52,580 --> 00:02:56,684
Let's set an explicit "width" for each ProductCard.

69
00:02:56,684 --> 00:03:00,304
"w-80" in Tailwind is effectively 320 pixels.

70
00:03:00,884 --> 00:03:02,773
This way each card should be

71
00:03:02,773 --> 00:03:04,728
as wide as the picture. Good.

72
00:03:05,384 --> 00:03:07,553
Now, let's style the product title.

73
00:03:07,553 --> 00:03:10,155
I'll add a "div", so we can group together

74
00:03:10,155 --> 00:03:12,447
everything that goes below the image.

75
00:03:13,070 --> 00:03:15,478
And the title could be an "h2" heading.

76
00:03:15,978 --> 00:03:17,884
Let me move the "product.title" inside.

77
00:03:19,111 --> 00:03:21,867
I'm using an "h2" to help search engines

78
00:03:21,867 --> 00:03:23,797
understand that each product

79
00:03:23,797 --> 00:03:26,761
is like a different section of our website.

80
00:03:27,399 --> 00:03:30,006
Now, let's add some spacing around the text.

81
00:03:32,132 --> 00:03:34,439
We could use some padding, say "p-2".

82
00:03:34,939 --> 00:03:36,870
And we could also make the title text

83
00:03:36,870 --> 00:03:37,861
a bit more visible,

84
00:03:39,105 --> 00:03:40,610
by setting "text-lg",

85
00:03:41,805 --> 00:03:43,493
and maybe also "font-bold".

86
00:03:45,371 --> 00:03:46,540
Ok, that looks fine.

87
00:03:47,040 --> 00:03:50,158
Next, we want to display the price for each product,

88
00:03:50,158 --> 00:03:51,477
so let's add a "span",

89
00:03:52,037 --> 00:03:53,875
and here we'll show the price,

90
00:03:53,875 --> 00:03:55,285
for example 15 dollars.

91
00:03:55,847 --> 00:03:58,600
But we don't want the price to be below the title,

92
00:03:58,600 --> 00:04:00,638
we'd like it to be on the right side.

93
00:04:01,194 --> 00:04:03,801
So let's change this "div" to use Flexbox.

94
00:04:05,894 --> 00:04:08,334
This displays all the elements inside it

95
00:04:08,334 --> 00:04:09,310
on the same row.

96
00:04:09,871 --> 00:04:12,525
Now we can use "justify-between"

97
00:04:12,525 --> 00:04:16,505
to add all the space between those two elements.

98
00:04:17,088 --> 00:04:19,218
It seems that the price is showing

99
00:04:19,218 --> 00:04:20,971
a bit higher than the title.

100
00:04:21,533 --> 00:04:23,872
So let's also add "items-baseline"

101
00:04:23,872 --> 00:04:26,211
that should align them vertically.

102
00:04:26,779 --> 00:04:28,685
Ok, I think that's looking good.

103
00:04:29,185 --> 00:04:30,554
What we should do now

104
00:04:30,554 --> 00:04:32,182
is display the real price

105
00:04:32,182 --> 00:04:34,202
rather than a hard-coded value.

106
00:04:34,832 --> 00:04:36,675
And for that we'll need to modify

107
00:04:36,675 --> 00:04:39,189
the function where we fetch the product data.

108
00:04:40,698 --> 00:04:42,752
We just need to add the "price"

109
00:04:42,752 --> 00:04:45,069
to the fields that we pass through,

110
00:04:45,069 --> 00:04:47,851
because the CMS does return that property.

111
00:04:48,483 --> 00:04:50,120
And now in the ProductCard

112
00:04:50,120 --> 00:04:53,268
we should be able to display that "product.price".

113
00:04:54,449 --> 00:04:56,099
Ok, it's showing the price,

114
00:04:56,099 --> 00:04:57,564
but it's a plain number.

115
00:04:58,125 --> 00:05:00,733
We should really display it as a monetary amount.

116
00:05:01,233 --> 00:05:02,529
Just to do it quickly,

117
00:05:02,529 --> 00:05:04,416
I'll prepend a dollar sign here,

118
00:05:04,975 --> 00:05:07,682
and also always show 2 decimal places.

119
00:05:07,682 --> 00:05:10,674
Just to be clear, this is not the best way

120
00:05:10,674 --> 00:05:12,170
to format currencies.

121
00:05:12,170 --> 00:05:14,521
A better approach would be to use

122
00:05:14,521 --> 00:05:16,587
the Internationalization API.

123
00:05:17,372 --> 00:05:19,747
But this works for this simple example.

124
00:05:19,747 --> 00:05:22,793
We can see the prices formatted as dollar amounts.

125
00:05:23,354 --> 00:05:25,733
Now, I'd like to make some final tweaks

126
00:05:25,733 --> 00:05:27,136
to the card appearance.

127
00:05:27,698 --> 00:05:30,021
Tailwind includes a "shadow" class

128
00:05:30,021 --> 00:05:32,960
that will show a little shadow on each box,

129
00:05:33,531 --> 00:05:36,773
so each card appears to be slightly raised.

130
00:05:37,273 --> 00:05:39,842
I'm also going to show a different shadow

131
00:05:39,842 --> 00:05:41,221
for the "hover" state.

132
00:05:41,784 --> 00:05:44,653
In this case we can use a "shadow-xl",

133
00:05:44,653 --> 00:05:45,786
or extra-large.

134
00:05:46,362 --> 00:05:49,207
This way when we move the mouse over a card

135
00:05:49,207 --> 00:05:50,994
it will give the impression

136
00:05:50,994 --> 00:05:52,913
of raising itself a bit more.

137
00:05:53,546 --> 00:05:55,789
Ok. I think that's enough for now.

138
00:05:56,712 --> 00:05:58,794
Later on we'll obviously show

139
00:05:58,794 --> 00:06:01,093
the real product images as well.

140
00:06:01,093 --> 00:06:03,822
But this is a nice little ProductCard,

141
00:06:03,822 --> 00:06:05,905
styled up using Tailwind CSS.

