To accomplish the emoji click and count functionality without reloading the page, you can use JavaScript along with AJAX to send requests to the server. Since you mentioned you're more comfortable with JavaScript, I'll provide a solution using vanilla JavaScript and Laravel's built-in AJAX support through Axios.
First, you'll need to add a route and a controller method to handle the emoji reactions. This method will create or delete the CommentReaction record and return the updated count.
Here's an example of what the controller method might look like:
// CommentReactionController.php
public function toggleReaction(Request $request)
{
$request->validate([
'comment_id' => 'required|integer',
'reaction' => 'required|string',
]);
$user = auth()->user();
$commentId = $request->input('comment_id');
$reaction = $request->input('reaction');
$existingReaction = CommentReaction::where('comment_id', $commentId)
->where('user_id', $user->id)
->where('reaction', $reaction)
->first();
if ($existingReaction) {
$existingReaction->delete();
} else {
CommentReaction::create([
'comment_id' => $commentId,
'user_id' => $user->id,
'reaction' => $reaction,
]);
}
$count = CommentReaction::where('comment_id', $commentId)
->where('reaction', $reaction)
->count();
return response()->json(['count' => $count]);
}
Next, add a route for this controller method in your web.php:
// web.php
Route::post('/comments/reaction', 'CommentReactionController@toggleReaction')->name('comments.reaction');
Now, let's add the JavaScript to handle the click event and update the count without reloading the page. You can include this script in your Blade template:
<script>
document.addEventListener('DOMContentLoaded', function() {
const emojis = document.querySelectorAll('.emoji');
emojis.forEach(emoji => {
emoji.addEventListener('click', function() {
const commentId = this.closest('.card').dataset.commentId; // Assuming you have a data attribute for comment ID
const reaction = this.dataset.reaction;
axios.post('{{ route('comments.reaction') }}', {
comment_id: commentId,
reaction: reaction
})
.then(response => {
this.textContent = `${reaction} ${response.data.count}`;
})
.catch(error => {
console.error('Error:', error);
});
});
});
});
</script>
Make sure to include the CSRF token in your Axios headers if it's not already globally set:
<script>
window.axios.defaults.headers.common['X-CSRF-TOKEN'] = document.querySelector('meta[name="csrf-token"]').getAttribute('content');
</script>
Lastly, ensure that each comment card has a data-comment-id attribute that stores the comment's ID, and each emoji span has the data-reaction attribute set to the corresponding emoji.
<div class="card mb-g border shadow-0" data-comment-id="{{ $comment->id }}">
<!-- ... -->
<div class="emoji-reactions">
<span class="emoji badge badge-pill badge-primary p-1" title="Like" data-reaction="š">š 999</span>
<!-- ... -->
</div>
</div>
This solution uses JavaScript to handle the click events and Axios to send AJAX requests to the server. The server-side logic creates or deletes the CommentReaction record and returns the updated count, which is then displayed on the page without a reload.