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..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
@@ -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);
+
+ 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) {