تماشای این درس نیاز به اشتراک حرفه‌ای دارد.

Mark All as Read1:01

And there's also a clear all button down here somewhere. So that's the way I'm going to make ours work. So we have to click on it before it's marked as read. I'm going to start with marking all as read as that should be pretty simple. So back to our code, Comment notifications, let's go to markAllAsRead. Okay. And let's add a wire:click on this. wire:click. Let's say markAllAsRead. Okay.

Let's say markAllAsRead. Okay. Let's make that method in our class here, CommentNotifications. Let's make a new method down here. Let me just move this up. Say markAllAsRead. Okay. And if you take a look at the documentation for notifications, you'll see that you can markAllAsRead like this.

And if you take a look at the documentation for notifications, you'll see that you can mark all as read like this. So just call it on the collection of notifications itself, or the collection of unread notifications. So let's go ahead and grab this, go here, paste this in, should be the logged in user. So let's do that instead of user. So auth()->user(). And let's go ahead and add some auth here as well. We don't really need it, but let's try to stay consistent. So let's just grab something from here. And we have to be logged in to do this functionality.

So let's just grab something from here. And we have to be logged in to do this functionality. So let's use this here. Okay. Let's import response. And let's see if this works. Actually, let's make sure we close the dialog as well. So back to our view comment notifications, let's also add a click handler for Alpine to hide the dialog. So click is false.

Close the dialog. It doesn't update this yet, but if you take a look at the database and I refresh, you'll see that this readAt timestamp is added. So if I were to refresh the page, it should be zero now. Cool. So it did work. So we can make it refresh automatically if we want to do that. And we do. So we have these two methods already: getNotificationCount and also getNotifications.

So we have these two methods already. getNotificationCount and also getNotifications. So we can just call these after we mark them as read. So let's do that. This getNotificationCount and that should update the badge and getNotifications should update the notifications and make it empty. So let's try that again. I'm going to put this back manually. So let's just set these to null again. Okay.

So let's just set these to null again. Okay. So I set them to null again. They should reappear here when they refresh. Okay. And let's try that again. So if I mark all as read, it should automatically close the dialogue like it did before, but it should also reset the badge and the list of notifications. Okay. So everything is working.

Mark Single Notification4:38

So they're back at null. And there should be four here again. And now let's work on marking individual notifications as read. So same thing. We just have to call markAsRead on the individual notification. So let's do that. So back to our Blade view for comment notifications. So where's the 4-H here right here. So let's put this back. So the dialogue closes when we click on it, but we also want to markAsRead and we

So let's put this back. So the dialogue closes when we click on it, but we also want to mark it as read and we also want to maintain the functionality that goes to that Idea when we click on it. So we're going to call another method here on the Livewire component. So let's put it underneath here. Say wire:click equals markAsRead. So we need the notification to be passed into this method because we need access to that notification so we can call the method on it. But if I pass in the notification, it's going to be passed in as a string. So let's pass in the notificationId here instead.

But if I pass in the notification, it's going to be passed in as a string. So let's pass in the notificationId here instead. So let's just say notificationId. And let's make sure it's wire:click.prevent. So it doesn't do the default action I mean. So the functionality of clicking the link will no longer be there, but we'll make sure to add it in our method here. So let's make that method. Let's put it up here.

So let's make that method. Let's put it up here. Mark as read notificationId. So again, let's do auth here to be consistent, to make sure the User has to be logged in. And let's go ahead and grab the notification so we can do notification. And the corresponding model is called DatabaseNotification. And if I press tab here, it should import that. Let's check. Yeah, this one right here. Okay.

Yeah, this one right here. Okay. And we can use findOrFail by the passed in notification_id. So we grab that notification again, and then we can mark it as read. So notification->markAsRead(). Okay. Sorry, not notification_id notification. Okay. So let's try this out. First, it's not going to go to the Idea anymore.

So let's try this out. First, it's not going to go to the Idea anymore. But let's see if it marks the notification as read. So let's try the first one here. Should close it. And we get an error 404 not found. So there's a space here. Not sure if that's the issue. Let's try if that fixes it. Refresh.

So let's go back here. And let's add that functionality back. So we can say return, redirect, route, and we are going to the idea.show page. And let's pass in the idea. And we have that idea from the notification data. So notification data. And it's the ideaSlug that we need. ideaSlug. And if you don't remember, we're storing this in the data field. You can see here, this is the ideaSlug.

And if you don't remember, we're storing this in the data field. You can see here, this is the idea slug. Where is it? Right here. So if you pass this into this method, or this redirect route, then it should go to that page. So let's try that out. Okay. Refresh. We still have three here.

I'm going to remove that for now because I just added mail to show how database notifications work. So let me remove the mail driver in our Comment added notification. So up here, let's just remove mail for now. Okay. And it's just database. So let's try that again. So it should scroll to the last comments, scroll to comment. Okay. So we have that scrolling functionality in place, and I want to scroll to the particular

Scroll to Comment10:10

Okay. So we have that scrolling functionality in place, and I want to scroll to the particular Comment when we click on the notification here. Okay. So we click on it, it goes to that page and it scrolls directly to this Comment. So when I click on this, I want to tell this particular request, the one that just happened, that I want to scroll to a particular Comment. So how do we do that? So the way I did it was I made use of flash variables. So usually you make use of flash variables to flash a message after you submit a form.

So the way I did it was I made use of flash variables. So usually you make use of flash variables to flash a message after you submit a form. So I'm doing this in the AddIdea form. So let's take a look at that. AddIdea. Or is it CreateIdea? Yeah. So right here, session flash, and we flash a success message. And this only shows on this particular request. So right after we redirect.

And this only shows on this particular request. So right after we redirect. So we want to do something similar. Let's grab this back here, not here, here, and let's add a flash variable here. Let's call it scrollToComment, scrollToComment, and we can pass in a value as well. So I want to pass in the commentId here. So let's do that. commentId. And we also have to grab the comment. So let's do that as well.

And we also have to grab the comment. So let's do that as well. So let's say comment is Comment::find. And again, we can grab the commentID from our notificationData, so notificationData['commentID'], because we're storing that in there. So let's try this to import comment. And let's just echo out this flash variable to see if it works. So we can do this anywhere. I'll do it in here because I believe this is where I'm showing the success message. So let's just duplicate this.

I'll do it in here because I believe this is where I'm showing the success message. So let's just duplicate this. And I named it the variable scrollToComment. And we don't need this for now. Let's just echo it out here so we can do this. Actually, we have to wrap it in braces. So let's save that. First let me check if this actually renders somewhere on the page. Does this show? And it does actually show, but all the way down here behind the debug bar.

Does this show? And it does actually show, but all the way down here behind the debug bar. So it does show. Okay. Let me just put it in the middle to make sure I can see it when I echo out the variable. Does this work? Okay. So there it is. Let's do the same for this. Let me grab this and just wrap it here so we can see it if it does exist.

So it should go to this page. Okay. And it should echo out the commentId here. Awesome. So what we can do here is add an id on all the comment containers so we can scroll to it using JavaScript. So let's do that. I believe it's called ideaComment. And we can put an id on this container. So let's say id equals, say, comment- and the commentId.

And we can put an id on this container. So let's say id equals, say, comment- and the commentId. commentId. Okay. And like I said in the previous video, if you don't want to expose this information on your front end, you can use a package to obfuscate this. But I don't think it's a big deal for comments. Okay. So let's see if that works. So if I view the source here or inspect it, you'll see that each comment should now have

So let's see if that works. So if I view the source here or inspect it, you'll see that each Comment should now have an ID. So each Comment container. So not this one, but this one. Okay. Cool. So I'm looking at this right here. Comment 507. Okay.

Comment 507. Okay. So now, where is our code that scrolls to a particular comment? So that code lives in addComment, I believe, right here. We're making use of Livewire's hooks to hook into that event. So we have two cases here. So this case, let me get rid of this. So this case is for pagination. So let's put a comment here called pagination. And this case is for when we add a comment.

So let's put a Comment here called pagination. And this case is for when we add a Comment. So in both cases, they scroll to a Comment. So let's say adding Comment. Okay. Now I'm going to put this new case for scrolling to a Comment after we click on a notification in here, just so they're grouped together. So it doesn't really make sense because it has nothing to do with the add Comment component, but it does make sense because they're grouped together, at least to me. So if you want, you can put it in a component that makes more sense, for example, IdeaComments.

but it does make sense because they're grouped together, at least to me. So if you want, you can put it in a component that makes more sense, for example, Idea Comments, but then they will be separated. And this is not even an Alpine component. So for now, I'm just going to put it in here. So in this case, we don't need to use Livewire hook. We just have to listen for that session variable. So we still want it within x-init. And let's grab what we have here. Okay.

So it's a comment to scroll to. Okay. And we're grabbing it from the ID. So it's a comment and we can get it from the session variable. So session scroll to comment. Okay. And hopefully I did that correctly. So let's try it out. Do we still have any notifications left? We do not.

And it does work. Awesome. However, this is not going to work for all cases because we do have pagination on our comments here. So for example, where's this comment testing data, testing data. So it's all the way down here. So if I had pagination, this would not work if this were on a different page. So I think I can show you that if I change the commentsPerPage to something low. So let's say 2 instead of 20. Now this comment should not be on the first page.

Handle Pagination Scrolling18:56

I mean, it still goes to the page, but it doesn't know where the comment lives in terms of the pagination for it. So given the list of comments for this particular Idea and the comment we're looking for, we can calculate what page it's on. So let's go ahead and do that. So I'll leave it at two for now. Let's go back to our comment notifications. So we're going to need the list of comments. So we have to grab that from the idea. So let's grab the idea as well.

So we have to grab that from the Idea. So let's grab the Idea as well. Let's say idea, find notificationData, ideaId, okay. Import Idea. And we can grab the comments from the Idea like this. Say comments is idea.comments. So let's see if this works for now. So I'll just dial up that. Okay. And let's try that out.

Okay. And let's try that out. Let me not mark it as red for now. Okay. So let's see if we get the list of comments for this particular Idea. And we do. There are 14 ideas and it does seem to work, but we need them in incrementing IDs starting from zero or one. So let's say pluck ID. So we just have an array of IDs.

So let's say pluck ID. So we just have an array of IDs. Okay. So let's see what we get. Try that again. Okay. So now we have an array and we have incrementing IDs, like I said, which is what we need. And we also have the corresponding comment ID. So now let's go ahead and search for the comment that we're trying to scroll to. So let's do that.

So now let's go ahead and search for the Comment that we're trying to scroll to. So let's do that. Actually, let me pluck it from up here. So let's make it use the query builder here. So we don't load everything into memory and then we can do pluck(ID). That should be the same. Let's try that one more time. Okay. Still the same. So like I said, we need the ID of the Comment we're searching for or the index of the Comment.

Still the same. So like I said, we need the ID of the Comment we're searching for or the index of the Comment we're searching for. So if we're searching for Comment 503, we want 7 for the index. Okay. So let's make another variable for that. Say indexOfComment, and we can use the search method on the Collection. So it's $comments search for the commentId. Okay. So in this case, which Comment are we looking for?

Okay. So in this case, which Comment are we looking for? Let's see. So which Comment is this? This one is scroll to Comment. So which one is that? Or I can just check the database, which is easier. So it's ID 511. So let me put that back. So we're looking for 511.

So let me put that back. So we're looking for 511. So let me comment that out for now. And let's try that again. So again, this is 511. We're looking for this comment right here. So it's the last one. So if I dd and dump the search method, it should be 13, because that's what we're looking for. Okay.

for. Okay. So let's die and dump the index of Comment now. index of Comment should be 511 or sorry, 13. That's correct. And let me just put this back, because I'm going to show you the formula now. So bring that back up. So the formula is, or the formula to get the page is the index of the Comment. So in this case, 13 divided by the pagination count. So right now it's 2 for us, because I set it to 2.

But we don't need the decimal. So it should be on page five. So am I correct? Is one comment on page five? And it is. Cool. So that formula does work. So let's go ahead and translate that into code. So let's say $page equals, let's say index of $comment divided by $comment. And if you take a look at the comment here, and the corresponding model, you can grab

So let's say $page equals, let's say index of comment divided by comment. And if you take a look at the comment here, and the corresponding model, you can grab the perPage using this method, getPerPage. So back here, comment, getPerPage. And we want to add one. And like I said, we don't need the decimal. So we can just cast it to an integer. So that's the page. And we can go to that page directly in this redirect. Remember, the page is part of the query string up here, right here.

Missing Comment Error25:56

Awesome. Third Comment is here. Okay, so everything is working. Okay, let's make sure to handle the case when we delete the comment. So for example, this comment corresponds to this notification. And if we were to delete it, we would have an error. So let's delete this comment. Okay. Notification still exists, but it will result in an error, because the comment does not exist.

Notification still exists, but it will result in an error, because the Comment does not exist. There we go. So let's go ahead and make sure to handle this case. So in our code here, we can check if the comment or even the idea does not exist in here. So we can say, if, say, not comment. So if it wasn't found, then we can do something in here. So let's, I'm going to flash a message here. Let me just grab this. So similar to when we created an Idea, instead of a success message, it's going to be an

Let me just grab this. So similar to when we created an Idea, instead of a success message, it's going to be an error message. So let me just replace this, actually. So success message, let's say error message, errorMessage, and let's say this Comment no longer exists. Okay. And we'll redirect back to the index page, because that's where we'll show the message. So return redirect route('idea.index'), okay. And let's do the same for ideas.

So return, redirect, route, idea.index, okay. And let's do the same for ideas. So let's put that here. And let's say, if not idea, okay. And say this idea no longer exists. So again, if you don't remember, in our app.blade.php, we have this XNotificationSuccess component, which shows a message, but right now it only shows success messages. So for example, actually, let's see if this works first. So we deleted that comment, but the notification still exists, and now we should just redirect back to the homepage.

So we deleted that Comment, but the notification still exists, and now we should just redirect back to the homepage. Okay, cool. But like I said, I want a message here. And just to remind you how the success message looks like, let's add a new Idea and submit the form, and you'll see it in the bottom right. But I want an X instead of a check mark here to show that it's an error message instead. So let's go ahead and do that. So back to our app.blade.php. So we have this success message, but let's add another one here.

So back to our app.blade.php. So we have this success message, but let's add another one here. Remember, now we have a session variable for errorMessage instead of successMessage. So let's see what we can do here. Changes to errorMessage. The message display is errorMessage now. Okay. But let's add a new type here for our notification success. So maybe this should be another name so we don't confuse it with actual notifications. Maybe like popUpSuccess or something.

So maybe this should be another name so we don't confuse it with actual notifications. Maybe like pop up success or something. I don't know. Naming things is hard. We'll just leave it. But we want a new type here to say it's an error message. So we can say type equals error, and the default will be success. So nothing else breaks. So let me save that. Let's go into that component.

So let me save that. Let's go into that component. So it's a notification success, and the only difference here is the icon and the icons right here. Actually, we have to add the type up here. And like I said, let's default it to success. So our existing notifications don't break success, okay? But like I just did here, we are passing an error here. Okay. Now for the icon.

Okay. Now for the icon. So that's the SVG. So we can wrap this in a conditional. So say if type equals success, then it's going to be a checkmark like it currently is. Okay. But if it's error, then it should be an X. So it changes to error. Let's grab an X icon from Heroicons, let's say, close here maybe. Let's grab this one.

Refactor Scroll Helper31:21

That's here. Let's go back to 20. Okay. Let's go back to our comment notifications. Let's mark it as red again. And this is kind of long, this method. So I'm just going to extract some of it to another helper method. So this is marking it as red up to here. But all of this other stuff is for scrolling to the comment. So let's grab all of this.

But all of this other stuff is for scrolling to the Comment. So let's grab all of this. Okay. Okay. Let's make a new method here. Say scrollToComment. Let's accept the notification here because we need access to that. And let's go ahead and paste that code in. Okay. And we can call it after we mark this notification as read.

So this one no longer exists. So this should work. It should mark it as red and show our error message. Okay. But the other ones should scroll to the comment. So say another comment. And there it is. Cool. Still works. But now it marks it as red because I uncommented that code.

Still works. But now it marks it as red because I uncommented that code. Okay. So as always, let's go ahead and make a commit here. This is episode 62. git add, git commit episode 62, mark notification as red.

دوست دارید گاهی خبرهای Laracasts را ایمیل کنیم؟