Create A Blog With Prisma & NextJS | part 4

Create A Blog With Prisma & NextJS | part 4


Create A Blog With Prisma & NextJS | part 4

How To Create A Blog With Prisma \u0026 NextJS part 4
Enjoy!
The project is full compatible with latest Prisma \u0026 Nodejs versions for arm64
Project: https://github.com/daniellaera/prisma

Closed captions sponsored by Prisma

#prisma #nextjs

00:00 intro
00:18 create page
5:21 form submission logic
9:32 post request api
14:05 creation form test
15:30 drafts page
24:00 fixing JSON serialisation
29:06 rendering drafts


Content

2.18 -> - [Instructor] All right guys,
3.013 -> let's continue this tutorial,
4.87 -> and we want to implement
6.86 -> the create route that we don't have at the moment.
10.72 -> So we want to implement this,
12.36 -> in the API folder, for the backend.
17.5 -> So in pages,
19.02 -> I want to have,
20.43 -> a create.tsx file.
25.26 -> And I wanna call it, Post
35.44 -> and return.
37.66 -> Just something for,
42.06 -> the moment.
47.506 -> Export the default Post.
50.95 -> Okay, So I wanna again,
52.99 -> have a session,
55.918 -> because we have to check if we are authenticated or not.
66.005 -> So useSession from next-auth/client.
70.07 -> I wanna create, another hook,
74.87 -> for the title.
80.756 -> SetTitle,
83.27 -> This time it will be,
84.103 -> useState from react.
92.26 -> And the other one will be,
96.34 -> the content, so
105.865 -> useState again.
108.3 -> And, I don't know if you remember,
112.15 -> in the last video we used the toast,
116.3 -> for popping up,
119.87 -> the confirmation of our actions.
124.16 -> So, I wanna render,
128.51 -> first of all, if we are loading this,
132.74 -> stage of loading,
134.74 -> return a div of loading,
140.07 -> not authenticated.
146.581 -> We want to return,
150.894 -> I wanna bring a Layout that I already,
155.12 -> have it here.
158.19 -> So just make the imports,
161.41 -> we can use,
164.09 -> Okay, problem is that this is going to,
170 -> this is maybe, Layout.
175 -> Shall have to correct this,
177.76 -> the Flex, useColorModeValue,
182.46 -> the Stack,
185.63 -> the Heading,
189.745 -> the Text,
196.726 -> ChakraLink.
198 -> So instead of importing, the link,
201.04 -> because we have to import the link,
202.92 -> from the next, link,
206.75 -> we can also import,
210.96 -> link as,
216.053 -> ChakraLink.
223.074 -> I want to remove the, Layout,
226.55 -> so, the Layout actually was from the components
232.33 -> Layout.
233.163 -> So basically, if we are not authenticated here,
237.16 -> we are rendering, sign in to your account,
241.66 -> to create posts.
243.74 -> And, if we are authenticated,
248.1 -> so, we want to continue,
250.85 -> writing this part,
252.77 -> and again, I will,
256.42 -> bring the layout that I already have.
262.92 -> Instead of having this,
265.03 -> maybe just continue importing,
269.82 -> the Box.
273.8 -> FormControl,
276.62 -> Input.
281.17 -> We have a Textarea.
285.24 -> We have a Button.
289.667 -> CheckCircleIcon.
292.81 -> This one again,
293.96 -> we have the Link this time from,
298.29 -> next CloseIcon.
302.12 -> And make sure we have imported
305.88 -> the correct Link here,
309.5 -> and want to create a form submission,
312.7 -> submitData function.
314.24 -> So, yeah,
316.46 -> we have to create this,
320.44 -> after the loading,
321.72 -> so const submitData,
330.71 -> equal async,
335.22 -> can pass e
336.42 -> as a React.SyntheticEvent.
349.58 -> First of all, I want to preventDefault,
354.96 -> try, catch block,
356.45 -> and in the try,
359.983 -> I wanna declare a body,
363.42 -> instructor, title and content.
369.02 -> Then await fetch,
380.97 -> wanna go in localhost,
384.113 -> host yeah, it was correct.
387.84 -> Then I wanna go in the API,
390.73 -> and then post,
393.04 -> we don't have this route already,
395.31 -> but, we will create in a while.
399.92 -> We can have a method of POST,
407.16 -> the headers,
412.59 -> is an object of,
419.73 -> Content-Type,
431.08 -> application/json.
435.48 -> And the body will be,
438.54 -> JSON.stringify
442.77 -> the body.
447.11 -> And, we can then,
451.21 -> outside this, await,
457.51 -> Router.push.
464.51 -> I'm not sure I imported the correct one.
470.4 -> Let's try again.
475.1 -> Maybe is the correct one.
478.19 -> So, Router.push from next router,
483.47 -> you can also import,
488.74 -> like this.
491.65 -> So, we have the push,
495.16 -> and,
499.62 -> after we created the Post,
501.42 -> we want to push on the drafts route,
504.28 -> and we'll implement everything later.
507.74 -> So catch, error,
513.23 -> simple, console.log
518.12 -> of the error.
520.23 -> So this submit data,
522.83 -> we used on the form onSubmit.
528.36 -> And if we tried to render,
534.09 -> or create,
535.41 -> we have now this, this form,
538.78 -> and let's try to log out.
542.48 -> and as you can see, we have protected the route,
546.05 -> if we are not authenticated.
547.91 -> So, sign into your account to create posts,
551.28 -> this is what we were going to do,
554.63 -> and again, we have the form here.
558.72 -> But now we want to create this,
563.45 -> backend, API end point here,
566.83 -> so we don't have Post, in the API.
570.16 -> So I'm going to create,
575.07 -> post folder inside of it,
577.41 -> I want to create,
580.1 -> an index.type script file.
585.3 -> And, I want to export default,
591.617 -> async function, just call it,
595.86 -> handle request
598.33 -> of NextApi.
607.23 -> Request,
611.96 -> and the response
613.81 -> of NextApi,
620.44 -> response from next.
626.475 -> We want create,
628.49 -> the object of title and content,
634.42 -> we want to, catch this
636.95 -> from the request.body.
642.35 -> I again, I need a session,
646.45 -> so, this case will be
648.79 -> await getSession
653.34 -> from next-auth/client,
659.06 -> pass the request,
663.49 -> and then we can write the result,
666.98 -> and, this will be prisma,
672.421 -> but we want to declare prisma as we did before,
678.77 -> the next-auth, so PrismaClient.
684.724 -> PrismaClient.
685.99 -> So prisma.post.create,
693.02 -> and we start to create, to pass the object.
695.62 -> So the data,
700.81 -> we have the title,
703.084 -> of title,
705.3 -> that we can, catch from the request body.
710.85 -> The content, is the content.
716 -> And now we want to link the author,
718.74 -> as you can see,
720.18 -> we have the author,
722 -> so if you don't have this, suggestion here,
726.39 -> that means you have a problem.
728.12 -> So, we want to pass,
731.84 -> how do we do this?
733 -> Connect,
738.71 -> we can pass, the email
743.83 -> and we get this from the, session,
747.37 -> if we have,
748.498 -> the session.user.email.
756.82 -> So if we take a look in the session,
759.97 -> we should get this user.email.
763.32 -> So, the session,
768.195 -> the user, link the user,
770.58 -> and user as the email,
773.39 -> so this is the connection.
775.74 -> So every post we create,
777.63 -> we should have inside the author,
782.117 -> and in this author object,
784.03 -> we have the email,
785.45 -> of the user
788.83 -> that we connected,
791.98 -> creating this post.
796.54 -> Now outside this create block,
799.39 -> we can render,
801.63 -> the result,
806.68 -> so this create, backend API end point,
811.82 -> is ready to be tested, in the request.
817.72 -> I wanna test this in my, form actually,
821.37 -> but in the create, for the moment,
825.29 -> instead of using drafts here,
827.48 -> if we don't,
829.38 -> If we don't have the route at the moment,
831.83 -> just avoid and let's stay on the home
836.28 -> for the moment,
837.2 -> we will fix this later when we have all of the routes.
840.08 -> So, I wanna just give it a try,
844.842 -> and get the Lorrem texts,
849.92 -> create,
852.06 -> and we have not found,
856.83 -> let's check the code.
861.4 -> Okay, I think I should move the post,
869.64 -> because this has nothing to do with the auth,
873.021 -> it was inside the auth, but let's refresh the server.
882.879 -> Let's try again on the create,
890.44 -> Lorrem of texts,
892.07 -> clean this stuff here,
895.169 -> the create, should be successful.
900.219 -> Let's go in the SQLite Explorer,
906.41 -> and we have our post here, so amazing.
910.82 -> So, now we start to implement this route,
916.73 -> and pushing it after the creation,
919.24 -> and having the drafts route here,
923.96 -> and trying to get some content.
931.37 -> Okay, let's create this page here,
934.32 -> so drafts.tsx
939.08 -> import React from react.
945.35 -> Okay, so I want to create,
949.879 -> const Drafts,
952.352 -> React.functional component.
958.243 -> And I wanna pass Props,
961.87 -> this type will have, props parameter,
969.2 -> and I want to create actually this,
973.35 -> this props here.
975.25 -> So I declare type, Props,
983.72 -> drafts, PostProps,
990.27 -> and we'll create also this one,
994.25 -> as, a type.
1005.19 -> So this one will have the id of the number,
1012.52 -> title of, string,
1021.27 -> the author as an object of,
1025.65 -> name; string,
1030.69 -> email; string,
1039.01 -> null.
1044.08 -> We have the content of string,
1049.74 -> published, boolean
1053.87 -> and createdAt, Date.
1064.9 -> Into also export default, Drafts.
1078.374 -> And for the moment,
1079.207 -> we want to return,
1080.29 -> just, div, here
1084.95 -> and format again, the session, hook,
1094.832 -> useSession from next-auth/client.
1097.67 -> So,
1101.35 -> if we are authenticated,
1104.91 -> if we are not authenticated,
1106.92 -> we want to quick render something.
1111.49 -> We want to import our friend,
1115.65 -> the Layout, yeah.
1120.64 -> And inside here,
1121.9 -> we can create,
1125.69 -> Flex container,
1130.694 -> we can use this stuff,
1134.55 -> the Stack.
1138.56 -> And as before,
1142.55 -> we are kind of protecting this route.
1149.25 -> If we're not authenticated,
1151.15 -> and we have to import this time the link,
1156.01 -> could be from the Chakra.
1162.56 -> Then we want to render,
1168.38 -> the layout again.
1173.61 -> Here and inside this Layout,
1177.28 -> I wanna bring, just a container
1179.44 -> for having a kind of a title inside here,
1184.63 -> and simpleGrid if we have drafts,
1191.31 -> Drafts or otherwise, no drafts.
1194.5 -> But, if we try to get on this, as you can see,
1200.23 -> we don't have props.drafts.length,
1201.98 -> because we didn't query inside,
1205.85 -> this component, we have to bring,
1210.19 -> the, all of the drafts
1211.55 -> so we can basically create a function.
1218.42 -> And I want to, maybe create,
1224.55 -> variable called,
1226.36 -> getServerSideProps of type,
1237.45 -> GetServerSideProps, equal async,
1247.3 -> request, response.
1254.91 -> I wanna check for the session,
1260.61 -> await to getSession,
1268.99 -> and pass, the request.
1283.206 -> If we don't have this session, we can,
1288.69 -> return a statusCode of 403,
1293.02 -> otherwise we read and we return,
1298.595 -> the props, drafts,
1307.596 -> empty array.
1315.84 -> squid, the drafts,
1317.84 -> and await prisma,
1320.93 -> and again, go in the auth.
1325.65 -> I will show you maybe later how we can globally
1328.21 -> have this, Prisma variable
1331.25 -> instead of declaring, every time.
1335.17 -> Prisma client in every component,
1338.73 -> for the moment, let's do this.
1341.88 -> This is equal.
1348.082 -> Okay now we have the post,
1351.43 -> to findMany and query all of the post,
1355.74 -> so we can do where,
1360.91 -> the author,
1365.994 -> as the email,
1368.69 -> from the session.user,
1375.46 -> the email,
1378.74 -> and also for published,
1385.44 -> where published is false.
1387.26 -> And under this where,
1392.82 -> column, so add the include,
1400.05 -> the author.
1407.397 -> We select,
1410.25 -> name of true,
1413.67 -> we want to save this,
1416.11 -> now under this findMany.
1420.18 -> We want to return the props,
1428.88 -> and the drafts object here.
1434.58 -> So if we just refresh this,
1436.87 -> what do we have here?
1439.81 -> Okay, so this is a common error that we have,
1442.88 -> because, we cannot serialized as JSON,
1448.03 -> this is about date.
1449.67 -> So what we can do,
1453.18 -> in this case is to create,
1456.69 -> babelrc, and in the babelrc,
1463.455 -> we can declare presets.
1470.43 -> So we have the next/babel,
1478.418 -> and we can use the plugins that we have installed, I think,
1484.45 -> superjson, yeah, that's it.
1487.38 -> Superjson, the plugins will be,
1496.097 -> superjson-next.
1503.4 -> So if we restart the server,
1510.06 -> we have drafts, of course,
1511.55 -> because we are passing through this condition.
1516.09 -> We have drafts,
1517.63 -> but we have to render the drafts of course.
1520.58 -> So under this return here,
1527.16 -> after the Container,
1529.43 -> we want to,
1533.47 -> props.drafts.map
1538.85 -> and want to pass
1542.577 -> the post here.
1551.557 -> And inside here, I want to bring another Container,
1554.52 -> ready and let's see this one,
1561.57 -> together.
1563.62 -> So router,
1567.04 -> it's from router.
1569.43 -> I'm not sure, again, this was imported correctly,
1574.6 -> but,
1579.65 -> we can have the box,
1583.59 -> and the blog,
1585.58 -> the author.
1588.94 -> Okay, the blog, author, I want a quick,
1591.1 -> just a quick component,
1594.98 -> and up above all of this stuff,
1598.49 -> just for having a separate avatar for years.
1603.21 -> So we can create, here
1606.629 -> the, BlogAuthorPost.
1609.06 -> So after this, type here,
1612.85 -> I can create an interface of,
1618.378 -> BlogAuthorPost.
1626.87 -> We'll have a date of Date,
1630.99 -> name of string.
1637.93 -> Now we can export.
1640.74 -> I know that you can separate all of these components,
1643.35 -> in a components folder,
1646.37 -> but, for being faster,
1649.14 -> let's just create this inside of here.
1654.82 -> React.FC
1663.67 -> interface,
1666.47 -> equal props.
1674.91 -> Again, we want to use this session,
1678.87 -> maybe restructure this,
1685.25 -> loading, useSession.
1694.362 -> So if, loading,
1699.79 -> return simple div, Loading,
1704.55 -> you can also return a spinner
1705.77 -> or something like this.
1707.78 -> Have fun finding maybe a spinner
1710.43 -> and check all your components,
1714.29 -> or we return.
1719.99 -> We already have.
1723.15 -> Stack here,
1727.03 -> we have the Avatar
1729.887 -> and in the Avatar, we can pass the in source,
1732.57 -> the session user image.
1736.3 -> So, since now we have this BlogAuthor,
1740.76 -> we can use,
1743.23 -> here. So,
1744.95 -> if I saved this,
1746.73 -> as you can see, in my Drafts,
1749.74 -> we have the Draft,
1751.56 -> that I had before, that I created.
1755.53 -> So I have my Avatar,
1756.88 -> and with the date, that we have created.
1761.491 -> So I think we have here, a Link,
1769.28 -> yeah, on this Container,
1771.74 -> on every Container I click,
1773.29 -> I have this Router push,
1774.97 -> push on the post ID.
1778.22 -> But of course, now we have an error,
1782.27 -> because we have to implement this.
1785.86 -> But just to try again, the creation of a new post,
1794.62 -> it's for being sure that,
1797.99 -> post two,
1801.01 -> maybe a cool face, create.
1805.78 -> Okay, so as you can see,
1807.83 -> when we push on the drafts route,
1810.68 -> we have the post,
1814.772 -> and we implement, maybe a detail
1818.271 -> or the publish button here,
1822.59 -> or the delete.
1825.04 -> So all this stuff,
1826.79 -> we'll continue implementing this, in the next video.
1830.31 -> Thank you guys for watching.
1831.24 -> And I'll see you in the next one.

Source: https://www.youtube.com/watch?v=IP0YQdHVt3I