
Join the Conversation!
Subscribing gives you access to the comments so you can share your ideas, ask questions, and connect with others.
"Please login to view comments"
Subscribing gives you access to the comments so you can share your ideas, ask questions, and connect with others.
Complete source code for this lesson is available at
How did you manage to remove the blur property and reach here?
Upgrading gives you access to quizzes so you can test your knowledge, track progress, and improve your skills.
By logging in, you'll unlock full access to this and other free tutorials on JSM Pro.
Why? Logging in lets us personalize your learning experience, track your progress, and keep you in the loop with new workshops, coding tips, and platform updates.
You'll also be the first to know about upcoming launches, events, and exclusive discounts.
No spam—just helpful content to level up your skills.
If that sounds fair, go ahead and log in to continue →
Enter your name and email to get instant access
##Looks like we found a thief monkey By the way, I liked the trick how you reached till here. You have a good sense of humor. You will improve a lot if you join our course with this passion.
var
(function-scoped, outdated)let
(block-scoped, modern and recommended)const
(block-scoped, cannot be reassigned)_
, or $
let let = 5;
is invalid)myVar
and myvar
are different)string
, number
, boolean
, null
, undefined
, bigint
, symbol
Objects
, Arrays
, Functions
Subscribing gives you access to a brief, insightful summary of each lecture to stay on track.
00:00:00 Now that we have this wonderful profile page, it will act as a place from which we can edit or delete our questions and answers.
00:00:10 So what do you say that we go ahead and install a Shantzian component that will allow us to do that?
00:00:17 A component on its own won't actually do the functionality, of course, but it'll open up a dialog asking us if we're sure we want to perform that often
00:00:27 destructive action, such as deleting a question.
00:00:29 So let's go ahead and install it.
00:00:32 That's just going to be mpx.shatsian.addlatest.addalertdialog.
00:00:37 So back into the code base, I'll open up a second terminal, update it if you need to.
00:00:43 And now I'll just say mpx.shatsian.addlatest.addalertdialog.
00:00:50 We got a new version of ShadCN 2.4, which is cool.
00:00:53 And then I'll use legacy peer depths to install it.
00:00:56 There we go.
00:00:57 That's great.
00:00:58 Now head over to app, root, profile, and then head over to the ID of the profile.
00:01:06 which is a dynamic page for our own or somebody else's profile.
00:01:10 And to it, we have to pass a prop that allows us to decide whether we want to show those actions on specific cards or not.
00:01:17 So when do we show them and when do we not?
00:01:19 Well, of course, we show them if they're our own questions and answers.
00:01:23 So right below where we have our question card, there we go, we're mapping over it right here, we can pass an additional prop to it.
00:01:30 So I'll expand this.
00:01:32 And I'll pass a new prop, which is going to be called showActionBtns.
00:01:38 And I'll make it equal to, to a Boolean equality.
00:01:42 We want to check if loggedIn user?user?id is triple equal to, to the ID of that specific question's author.
00:01:56 So question.author.underscoreID.
00:02:00 If that is the case, well, that must mean that this is the owner and they should be able to delete that question.
00:02:06 Let's also copy this part, head over down to where we're rendering the answers, and let's paste it here as well.
00:02:14 Show action btns is equal to loggedInUser.user.id, but instead of the question author ID, here we'll have the answer that author.id.
00:02:25 And let's also increase the gap right here in between the answers.
00:02:29 So I'll set it to about 10. Perfect.
00:02:33 Now, you can see that both of these two components are complaining right now, saying that they don't know what these action button prop is.
00:02:41 But before we go ahead and add that prop to the answer in the question card, let's actually create a new component that allows us to display those buttons
00:02:50 in the first place.
00:02:51 So I'll head over into the components folder, into the user folder, and create a new file called edit delete action.tsx and here I'll run RAFCE.
00:03:07 Now we can head over into the question card component and we can import it and use it right here.
00:03:14 But before we have to get access to the prop that we created.
00:03:18 So I'll say show action buttons coming from props or BTNs is equal to false by default unless we pass something else.
00:03:28 So let's also add it to props, showActionBTNs, optional of a type boolean.
00:03:34 Now let's head into this div down.
00:03:36 Let's change the item start to item center because now we'll have some more stuff to show and then give this div a class name of flex1 so it extends a
00:03:47 bit more.
00:03:48 Next, we want to go below the div that contains the links and the title.
00:03:52 And here, we want to check whether show action buttons is true.
00:03:57 And if it is, we want to render the edit delete action.
00:04:03 Like this, make sure to import it from components.
00:04:06 And to it, you want to pass a prop of type question, because here we're editing or deleting a question.
00:04:12 And you can pass the item ID.
00:04:14 So that's going to be the ID either of the question or the answer.
00:04:18 And that's going to be just the underscore ID since we're already on it.
00:04:21 So now you can head over into this edit delete action and accept those props.
00:04:26 I'll destructure the type and the item ID.
00:04:30 And I'll define those as props just above.
00:04:33 So I'll say interface of props.
00:04:36 The type will be of a type String.
00:04:39 And the item ID will be of a type String as well.
00:04:43 And now we can import this alert dialog from Schatzian.
00:04:47 So head over to Schatzian alert dialog and copy the imports first.
00:04:51 Paste them right at the top.
00:04:53 and then copy the usage as well.
00:04:55 Don't paste it immediately, but rather first create a div right here that'll have a class name equal to flex, items-center,
00:05:06 justify-end, because we want to show that edit and delete icon at the end of the line of the card, a gap of three in between the elements,
00:05:15 and then max small devices Within that div, we want to check if type is triple equal to question, in which case we will also allow the users to edit it.
00:05:28 So for now, I will just render an image right there.
00:05:32 Of course, coming from NextImage, so make sure to import it and give it a source equal to forward slash icons, forward slash edit dot SVG,
00:05:42 an alt tag of edit, a width of about 14, a height of about 14 as well, a class name equal to cursor dash pointer, so we know that it is clickable,
00:05:56 and object dash contain.
00:05:58 And you can also give it an on click.
00:06:00 which will be equal to handleEdit, which is a function we have to create right here within the function const handleEdit.
00:06:11 is going to be equal to an asynchronous callback function, which we'll call very soon.
00:06:16 Okay.
00:06:16 So now if you save this and declare it as a client render component at the top by giving it a use client directive and go back to your profile,
00:06:26 you should be able to see a little edit icon at the right side of each one of your posts.
00:06:31 Looking great.
00:06:33 But now let's actually add one for the delete as well.
00:06:37 So just below this type is equal to question.
00:06:41 I want to render an alert dialog.
00:06:43 So I'll simply paste everything that I copied over from Shaziem.
00:06:48 But we'll style it a bit.
00:06:49 This alert dialogue trigger will have a class name equal to cursor dash pointer, and it won't just say open.
00:06:58 Rather, what we want to do is render an image within it.
00:07:03 So I'll render an image with a source equal to forward slash icons, forward slash trash dot SVG with an alt tag of trash.
00:07:14 a width 14, height also 14, and we can just save it right there.
00:07:20 If you do that, you should be able to see a little trash icon up here as well.
00:07:24 And if you click it, we have a new model.
00:07:27 Now, it might be good to put this to the side so we can see how it looks in mobile, and we can continue styling this model even further.
00:07:34 Let's go below the dialog and let's focus on the content.
00:07:37 I'll give it a class name equal to background, dash light 800, underscore dark 300. That'll already make it look a bit more like it's made to be here.
00:07:49 Next, we have the title.
00:07:51 In this case, we can say, are you absolutely sure?
00:07:54 And then we have a description.
00:07:56 I'll say something like this action cannot be undone, this will permanently delete your, and now we can either say if the type is triple equal to question,
00:08:08 we can then say question lowercase, else we'll say answer, and remove it from our servers, like this.
00:08:14 So we only click this if you're 100% sure that it'll delete it.
00:08:18 Next, within the footer, we can style this cancel button a bit by giving it a class name of BTN.
00:08:25 So this will say cancel.
00:08:26 And then finally we have continue.
00:08:28 We can style this alert dialogue action by giving it a class name of exclamation mark, which means important to override some default styles,
00:08:39 border, primary 100. Also, BG primary 500 and text-light-700.
00:08:48 All with this exclamation mark at the start, so we override the styles.
00:08:53 Okay, this is looking good.
00:08:55 Maybe we can make the text even lighter to something like 800. There we go.
00:08:59 And let's also give it an onClick equal to handleDelete.
00:09:04 And now we can duplicate it right above to create a similar thing that we had for the handleEdit.
00:09:10 Okay, great.
00:09:11 So now, if you click on the delete, a new model appears.
00:09:15 For the edit, we won't show the model, we'll likely just redirect to the edit page, which is going to be similar to our create form.
00:09:23 So let's actually implement those two functions.
00:09:25 Starting with the delete, I'll say if type is triple equal to question, We then have to implement an action for deleting that question.
00:09:36 So I'll say call API to delete question, but I'll still show a toast with a title of question deleted with a description.
00:09:46 Your question has been deleted successfully.
00:09:50 Or I will do an else if the type is triple equal to answer.
00:09:56 In that case, we need to, of course, call our API to delete an answer.
00:10:00 And I'll also show a toast that'll have a title of answer deleted and your answer has been deleted successfully.
00:10:08 and make sure to import the toast from Hook's Toast.
00:10:11 So now, if we try doing this, you'll see question deleted, even though, let's be honest, nothing happened because we didn't yet implement the logic for
00:10:20 something to happen.
00:10:21 And now what are we going to do with the edit?
00:10:23 Well, let's just try to redirect because, you know, typically with edits, you want to redirect the user to the same form that they used to create that resource,
00:10:33 but this time pre-filled with all that information.
00:10:36 So I'll say router.
00:10:38 And this router, we have to first, of course, instantiate right here at the top by saying const router is equal to use router coming from next navigation.
00:10:50 And then that allows you to do router.push, and I want to push it to forward slash questions, forward slash.
00:10:59 itemId forward slash edit.
00:11:03 Of course, turn it into a template string.
00:11:05 So we actually fill in this item ID dynamically and save it.
00:11:09 If you reload the page right now and then try clicking the edit icon, you'll notice that we are redirected to the question details page and not questions
00:11:19 edit page.
00:11:20 So this means that there has to be some kind of a mistake within our edit page.
00:11:24 So head over to edit.
00:11:26 That's this one right here within questions ID, edit page dot dsx.
00:11:31 And let's see if we're redirecting to the question details page for some reason.
00:11:36 It looks like we are, right here.
00:11:38 Redirect to question details.
00:11:41 So it's saying question.author, oh, .toString.
00:11:45 No, we don't want to stringify the author.
00:11:47 We want to stringify the .author.underscoreID.toString.
00:11:52 If you do this, head back over to your profile and then click edit.
00:11:57 Now you'll get redirected to our edit form with all of the information pre-filled.
00:12:03 That's exactly what we wanted to see.
00:12:04 So now we want to implement the same thing that we added to the questions, but now to the answer card.
00:12:09 So head over into the answer card.
00:12:13 Make sure to import that prop that we're now passing through.
00:12:17 That'll be right here at the end.
00:12:19 ShowActionBTNs by default set to false.
00:12:24 And we can also add it to our props.
00:12:26 ShowActionBTNs of a type boolean.
00:12:29 And now right below this span, I'll say show action btns.
00:12:35 If that is true, then render this div right here.
00:12:40 And within that div, render the edit delete action, this time with a type of answer.
00:12:50 And don't forget to pass the item ID of underscore ID.
00:12:54 This time, this is the ID of the answer.
00:12:57 So now, if you head over to Answers, you'll also be able to see a little trash can right here.
00:13:02 Let's also style that a bit better by giving it a class name, equal to background, dash light 800. Let's also give it a flex dash center,
00:13:13 absolute positioning, minus right dash 2, minus top 5. a size of 9, and a rounded dash full.
00:13:24 If you do this, you'll notice that it'll disappear for a second.
00:13:28 We also have to add relative right here to this article to make sure that the absolute positioning is working right, and then head over into the EditDelete action,
00:13:37 make this first class name a dynamic one, So a template string, and then if the type is triple equal to answer, in that case,
00:13:48 also give it a gap of zero and justify-center.
00:13:54 This will nicely position this icon at the top right.
00:13:57 So now on the top posts are the questions.
00:13:59 We have those two here.
00:14:01 And in this case, since we have the upward and downward here for the answers, I put it right here above.
00:14:06 It opens up and it's ready to call that delete action.
00:14:10 Also, quickly check out the question details page.
00:14:13 So if you head over to a specific question and click into it, here I want to make sure that we're passing the right info to it.
00:14:22 So quickly head over into the questions ID page.
00:14:26 So that is this one right here, questions ID page.
00:14:30 And here where we have the user avatar at the top, just make sure we're passing the right author.
00:14:35 We have to do that for the ID.
00:14:37 for the name, but we can also pass the image URL.
00:14:40 So this will be the author.image.
00:14:44 So now you can see that the proper image will appear right here.
00:14:47 And we got that fixed as well.
00:14:48 So now that we have these actions right here, the edit already works, but for the delete, the edit just already redirects,
00:14:56 but we haven't yet implemented the action that'll do the edit functionality.
00:15:01 And then delete also just opens up the model.
00:15:03 So the UI is done.
00:15:05 And now I'm going to commit this by saying implement edit and delete buttons UI, commit and sync.
00:15:16 And in the next lesson, you'll focus on implementing the server actions that'll deal with the functionality of editing and deleting questions and answers.
00:15:27 This is going to be one of the first features that I want you to try on your own, because we have done that so, so many times.
00:15:35 Remember that cycle of first creating an action type right here, then after that, we define a validation for a specific action,
00:15:45 then after that, we actually head over into the question actions, and then implement an action, and then we end up using it within the code.
00:15:54 I want to see how you can handle that on your own, but of course, with a lot of my help, because I took the time to write not just the instructions on
00:16:02 how we can replicate it or provide you with the code, but actually to provide you with the hints to guide you through implementing this on your own.
00:16:09 Writing that actually took me more time than it would take me to record the lesson.
00:16:13 but I wanted you to go through that realization and aha moment on your own.
00:16:17 So go ahead and implement the functionality for edit and delete.