mirror of
https://github.com/ericasch6/scrum-poker-internal.git
synced 2026-10-13 23:32:09 +00:00
107 lines
2.7 KiB
TypeScript
107 lines
2.7 KiB
TypeScript
import { router } from '@inertiajs/vue3';
|
|
import { onScopeDispose, ref, shallowReadonly, watch } from 'vue';
|
|
|
|
import { getEcho } from '@/lib/echo';
|
|
import { home } from '@/routes';
|
|
import { join } from '@/routes/room';
|
|
import type {
|
|
CurrentRoomPlayer,
|
|
PokerRoom,
|
|
RoomStateChangedPayload,
|
|
} from '@/types/room';
|
|
|
|
const ROOM_EVENT = '.room.state.changed';
|
|
|
|
export function useRoomRealtime(
|
|
initialRoom: () => PokerRoom,
|
|
initialCurrentPlayer: () => CurrentRoomPlayer,
|
|
) {
|
|
const room = ref<PokerRoom>({ ...initialRoom() });
|
|
const currentPlayer = ref<CurrentRoomPlayer>({ ...initialCurrentPlayer() });
|
|
|
|
function handleRoomChange(payload: RoomStateChangedPayload): void {
|
|
if (
|
|
typeof payload.version !== 'number' ||
|
|
payload.version <= room.value.state_version
|
|
) {
|
|
return;
|
|
}
|
|
|
|
if (payload.change === 'room_deleted') {
|
|
router.visit(home().url, { replace: true });
|
|
|
|
return;
|
|
}
|
|
|
|
if (payload.change === 'room_closed') {
|
|
router.visit(
|
|
join({ query: { join_code: room.value.join_code } }).url,
|
|
{ replace: true },
|
|
);
|
|
|
|
return;
|
|
}
|
|
|
|
if (payload.state === null || payload.state === undefined) {
|
|
return;
|
|
}
|
|
|
|
room.value = {
|
|
...room.value,
|
|
...payload.state,
|
|
};
|
|
|
|
if (
|
|
payload.change === 'votes_reset' ||
|
|
payload.change === 'next_round'
|
|
) {
|
|
currentPlayer.value = {
|
|
...currentPlayer.value,
|
|
current_vote: null,
|
|
};
|
|
}
|
|
}
|
|
|
|
const stopWatchingRoom = watch(
|
|
() => initialRoom().id,
|
|
(nextRoomId, _previousRoomId, onCleanup) => {
|
|
const echo = getEcho();
|
|
const channelName = `rooms.${nextRoomId}`;
|
|
|
|
echo.channel(channelName).listen(ROOM_EVENT, handleRoomChange);
|
|
|
|
onCleanup(() => {
|
|
echo.leaveChannel(channelName);
|
|
});
|
|
},
|
|
{ immediate: true },
|
|
);
|
|
|
|
const stopWatchingInitialState = watch(
|
|
[initialRoom, initialCurrentPlayer],
|
|
([nextRoom, nextCurrentPlayer]) => {
|
|
room.value = { ...nextRoom };
|
|
currentPlayer.value = { ...nextCurrentPlayer };
|
|
},
|
|
{ deep: true },
|
|
);
|
|
|
|
onScopeDispose(() => {
|
|
stopWatchingRoom();
|
|
stopWatchingInitialState();
|
|
});
|
|
|
|
function setCurrentVote(value: string | null): void {
|
|
currentPlayer.value = {
|
|
...currentPlayer.value,
|
|
current_vote: value,
|
|
};
|
|
}
|
|
|
|
return {
|
|
room: shallowReadonly(room),
|
|
currentPlayer: shallowReadonly(currentPlayer),
|
|
setCurrentVote,
|
|
};
|
|
}
|