generated from Flycro/laravel-nuxt
feat: Realtime for Votes + Deadlines
parent
b1cb25c823
commit
5c0dab3448
|
|
@ -0,0 +1,40 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Events\Deadline;
|
||||||
|
|
||||||
|
use App\Models\Deadline;
|
||||||
|
use Illuminate\Broadcasting\InteractsWithSockets;
|
||||||
|
use Illuminate\Broadcasting\PrivateChannel;
|
||||||
|
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
|
||||||
|
use Illuminate\Foundation\Events\Dispatchable;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
|
class DeadlineCreated implements ShouldBroadcast
|
||||||
|
{
|
||||||
|
use Dispatchable, InteractsWithSockets, SerializesModels;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new event instance.
|
||||||
|
*/
|
||||||
|
public function __construct(public Deadline $deadline)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
public function broadcastAs(): string
|
||||||
|
{
|
||||||
|
return 'DeadlineCreated';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the channels the event should broadcast on.
|
||||||
|
*
|
||||||
|
* @return array<int, \Illuminate\Broadcasting\Channel>
|
||||||
|
*/
|
||||||
|
public function broadcastOn(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
new PrivateChannel('Deadline'),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Events\Vote;
|
||||||
|
|
||||||
|
use App\Models\Vote;
|
||||||
|
use Illuminate\Broadcasting\InteractsWithSockets;
|
||||||
|
use Illuminate\Broadcasting\PrivateChannel;
|
||||||
|
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
|
||||||
|
use Illuminate\Foundation\Events\Dispatchable;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
|
class VoteCreated implements ShouldBroadcast
|
||||||
|
{
|
||||||
|
use Dispatchable, InteractsWithSockets, SerializesModels;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new event instance.
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
public Vote $vote
|
||||||
|
)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
}
|
||||||
|
|
||||||
|
public function broadcastAs(): string
|
||||||
|
{
|
||||||
|
return 'VoteCreated';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the channels the event should broadcast on.
|
||||||
|
*
|
||||||
|
* @return array<int, \Illuminate\Broadcasting\Channel>
|
||||||
|
*/
|
||||||
|
public function broadcastOn(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
new PrivateChannel('Vote'),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\Events\Deadline\DeadlineCreated;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
|
@ -16,6 +17,13 @@ class Deadline extends Model
|
||||||
'target_chapter',
|
'target_chapter',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
protected static function booted() :void
|
||||||
|
{
|
||||||
|
static::created(static function ($deadline) {
|
||||||
|
event(new DeadlineCreated($deadline));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public function bookRecommendation()
|
public function bookRecommendation()
|
||||||
{
|
{
|
||||||
return $this->belongsTo(BookRecommendation::class);
|
return $this->belongsTo(BookRecommendation::class);
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\Events\Vote\VoteCreated;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
|
@ -14,6 +15,13 @@ class Vote extends Model
|
||||||
'book_recommendation_id',
|
'book_recommendation_id',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
protected static function booted() :void
|
||||||
|
{
|
||||||
|
static::created(static function ($vote) {
|
||||||
|
broadcast(new VoteCreated($vote))->toOthers();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
public function user()
|
public function user()
|
||||||
{
|
{
|
||||||
return $this->belongsTo(User::class);
|
return $this->belongsTo(User::class);
|
||||||
|
|
|
||||||
|
|
@ -83,6 +83,12 @@ onMounted(() => {
|
||||||
bookRecommendationStore.createRecommendationWS(e.bookRecommendation)
|
bookRecommendationStore.createRecommendationWS(e.bookRecommendation)
|
||||||
})
|
})
|
||||||
authStore.socketId = $echo.socketId()
|
authStore.socketId = $echo.socketId()
|
||||||
|
|
||||||
|
$echo.private(`Vote`)
|
||||||
|
.listen('.VoteCreated', (e) => {
|
||||||
|
console.log(e)
|
||||||
|
bookRecommendationStore.createVoteWS(e.vote)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@ import ConfirmUserDeadline from '~/components/modal/ConfirmUserDeadline.vue'
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
bookRecommendationId: number
|
bookRecommendationId: number
|
||||||
}>()
|
}>()
|
||||||
|
const { $echo } = useNuxtApp()
|
||||||
|
const authStore = useAuthStore()
|
||||||
|
|
||||||
const { refresh: deadlineRefresh, status: deadlineStatus, data: deadlines } = useFetch(() => `book-recommendations/${props.bookRecommendationId}/deadlines`)
|
const { refresh: deadlineRefresh, status: deadlineStatus, data: deadlines } = useFetch(() => `book-recommendations/${props.bookRecommendationId}/deadlines`)
|
||||||
|
|
||||||
|
|
@ -40,6 +42,13 @@ const rows = computed(() => {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
$echo.private(`Deadline`)
|
||||||
|
.listen('.DeadlineCreated', (e) => {
|
||||||
|
deadlineRefresh()
|
||||||
|
})
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,6 @@ export default defineNuxtPlugin({
|
||||||
|
|
||||||
// Conditionally add X-Socket-ID header if socket is connected
|
// Conditionally add X-Socket-ID header if socket is connected
|
||||||
if (auth.isLoggedIn && auth.socketId) {
|
if (auth.isLoggedIn && auth.socketId) {
|
||||||
console.log('auth.socketId', auth.socketId)
|
|
||||||
const socketHeaders = {
|
const socketHeaders = {
|
||||||
'X-Socket-ID': auth.socketId,
|
'X-Socket-ID': auth.socketId,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -123,6 +123,17 @@ export const useBookRecommendationStore = defineStore('bookRecommendations', ()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const createVoteWS = async (data: Partial<Vote>) => {
|
||||||
|
const index = recommendations.value.findIndex(r => r.id === data.book_recommendation_id)
|
||||||
|
// check if vote already exists otherwise add an empty array
|
||||||
|
if (index !== -1) {
|
||||||
|
if (!recommendations.value[index]?.votes) {
|
||||||
|
recommendations.value[index].votes = []
|
||||||
|
}
|
||||||
|
recommendations.value[index].votes.push(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function resetRecommendations() {
|
function resetRecommendations() {
|
||||||
recommendations.value = []
|
recommendations.value = []
|
||||||
}
|
}
|
||||||
|
|
@ -133,6 +144,7 @@ export const useBookRecommendationStore = defineStore('bookRecommendations', ()
|
||||||
updateRecommendationWS,
|
updateRecommendationWS,
|
||||||
deleteRecommendationWS,
|
deleteRecommendationWS,
|
||||||
createRecommendationWS,
|
createRecommendationWS,
|
||||||
|
createVoteWS,
|
||||||
statusOptions,
|
statusOptions,
|
||||||
fetchRecommendations,
|
fetchRecommendations,
|
||||||
fetchRecommendationsStatus,
|
fetchRecommendationsStatus,
|
||||||
|
|
|
||||||
|
|
@ -9,3 +9,11 @@ Broadcast::channel('App.Models.User.{ulid}', function ($user, $ulid) {
|
||||||
Broadcast::channel('BookRecommendation', function ($user) {
|
Broadcast::channel('BookRecommendation', function ($user) {
|
||||||
return $user;
|
return $user;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Broadcast::channel('Vote', function ($user) {
|
||||||
|
return $user;
|
||||||
|
});
|
||||||
|
|
||||||
|
Broadcast::channel('Deadline', function ($user) {
|
||||||
|
return $user;
|
||||||
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue