From cfba36410a417b5b5ff824aca828e4349aaaf6da Mon Sep 17 00:00:00 2001 From: Alina Lobova Date: Tue, 15 Apr 2025 20:58:42 +0300 Subject: [PATCH 1/2] added sorting of the list of opponents: online users are displayed before offline users. --- .../widgets/pages/lobby/CreateGameDialog.jsx | 99 ++++++++++++++----- 1 file changed, 73 insertions(+), 26 deletions(-) diff --git a/services/app/apps/codebattle/assets/js/widgets/pages/lobby/CreateGameDialog.jsx b/services/app/apps/codebattle/assets/js/widgets/pages/lobby/CreateGameDialog.jsx index 69fec409f..feaadcb6a 100644 --- a/services/app/apps/codebattle/assets/js/widgets/pages/lobby/CreateGameDialog.jsx +++ b/services/app/apps/codebattle/assets/js/widgets/pages/lobby/CreateGameDialog.jsx @@ -35,29 +35,68 @@ const unchosenTask = { id: null }; const OpponentSelect = memo(({ setOpponent, opponent }) => { const dispatch = useDispatch(); const currentUserId = useSelector(selectors.currentUserIdSelector); + const { presenceList } = useSelector(selectors.lobbyDataSelector); + console.log('presenceList:', presenceList); + const loadOptions = useCallback( + (inputValue, callback) => { + const queryParamsString = qs.stringify({ + q: { + name_ilike: inputValue, + }, + }); - const loadOptions = useCallback((inputValue, callback) => { - const queryParamsString = qs.stringify({ - q: { - name_ilike: inputValue, - }, - }); + axios + .get(`/api/v1/users?${queryParamsString}`) + .then(({ data }) => { + const { users: apiUsers } = camelizeKeys(data); + const filteredApiUsers = apiUsers.filter( + ({ id }) => id !== currentUserId, + ); + const onlineUsersFromPresence = presenceList + .map(p => p.user) + .filter(user => user.id !== currentUserId); + const combinedUsersMap = new Map(); - axios - .get(`/api/v1/users?${queryParamsString}`) - .then(({ data }) => { - const { users } = camelizeKeys(data); + filteredApiUsers.forEach(user => { + const isOnline = presenceList.some( + presence => String(presence.id) === String(user.id), + ); + combinedUsersMap.set(user.id, { ...user, online: isOnline }); + }); - const options = users - .filter(({ id }) => currentUserId !== id) - .map(user => ({ label: , value: user })); + onlineUsersFromPresence.forEach(onlineUser => { + if (!combinedUsersMap.has(onlineUser.id)) { + combinedUsersMap.set(onlineUser.id, { + ...onlineUser, + online: true, + }); + } + }); - callback(options); - }) - .catch(error => { - dispatch(actions.setError(error)); - }); - }, [currentUserId, dispatch]); + const combinedUsers = Array.from(combinedUsersMap.values()); + + const sortedUsers = combinedUsers.sort((a, b) => { + const aOnline = a.online; + const bOnline = b.online; + if (aOnline === bOnline) { + return 0; + } + return aOnline ? -1 : 1; + }); + + const options = sortedUsers.map(user => ({ + label: , + value: user, + })); + + callback(options); + }) + .catch(error => { + dispatch(actions.setError(error)); + }); + }, + [currentUserId, dispatch, presenceList], + ); return ( { function CreateGameDialog({ hideModal }) { const dispatch = useDispatch(); - const { gameOptions: givenGameOptions, opponentInfo } = useSelector(selectors.modalSelector); + const { gameOptions: givenGameOptions, opponentInfo } = useSelector( + selectors.modalSelector, + ); const [opponent, setOpponent] = useState(opponentInfo); const [chosenTask, setChosenTask] = useState(unchosenTask); const [chosenTags, setChosenTags] = useState([]); @@ -148,13 +189,19 @@ function CreateGameDialog({ hideModal }) { const isInvite = gameType === 'invite'; const isTaskChosen = chosenTask.id !== null; - const handleTimeoutChange = useCallback(e => setGameTimeout(e.target.value * 60), [setGameTimeout]); + const handleTimeoutChange = useCallback( + e => setGameTimeout(e.target.value * 60), + [setGameTimeout], + ); - const switchGameLevel = useCallback(level => { - setGameLevel(level); - setChosenTask(unchosenTask); - setChosenTags([]); - }, [setGameLevel, setChosenTask, setChosenTags]); + const switchGameLevel = useCallback( + level => { + setGameLevel(level); + setChosenTask(unchosenTask); + setChosenTags([]); + }, + [setGameLevel, setChosenTask, setChosenTags], + ); const createGame = () => { if (isInvite && opponent) { From 38baaea5fbaf9c822174572dcb0f9aa022040f6b Mon Sep 17 00:00:00 2001 From: Alina Lobova Date: Fri, 18 Apr 2025 18:51:18 +0300 Subject: [PATCH 2/2] removed the console.log --- .../assets/js/widgets/pages/lobby/CreateGameDialog.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/app/apps/codebattle/assets/js/widgets/pages/lobby/CreateGameDialog.jsx b/services/app/apps/codebattle/assets/js/widgets/pages/lobby/CreateGameDialog.jsx index feaadcb6a..c9436478b 100644 --- a/services/app/apps/codebattle/assets/js/widgets/pages/lobby/CreateGameDialog.jsx +++ b/services/app/apps/codebattle/assets/js/widgets/pages/lobby/CreateGameDialog.jsx @@ -36,7 +36,7 @@ const OpponentSelect = memo(({ setOpponent, opponent }) => { const dispatch = useDispatch(); const currentUserId = useSelector(selectors.currentUserIdSelector); const { presenceList } = useSelector(selectors.lobbyDataSelector); - console.log('presenceList:', presenceList); + const loadOptions = useCallback( (inputValue, callback) => { const queryParamsString = qs.stringify({