Javascript dont enter if statement when its true

I’m trying to make online version of Windows XP, and I’m currently on making moving multiple selected apps on desktop grid and I encounter some error in my functions’ logic however I do not know why it occurs. So the problem only appears when I move at least 3 items at the same time. When I move more than 3 apps to the place when other apps exists, it just overrides one of the apps. I’ve tried to debug it and I find the moment when it fails however I don’t know why because it don’t enter one of my if statements however is I print the condition after statement it returns true. So to visualize it better I will first show this issue on the UI.

So if we have 5 apps on desktop
problem visualization 1

and I will select 3 of them and then move it to column one and rows 0,1,2 one of the apps will disappear
problem screenshot 2
problem screenshot 3

So looking at the code first thing you need to know is that all of the frontend code is written in vue, i represent grid as 2 dimensional array and store it in data. if the grid slot is empty i represent it as null and if not it contains object with informations like app title, icon, selcted and id.

<div class="desktop-row" v-for="(row, rowIndex) in desktopGridLayout" :key="rowIndex">
        <div class="desktop-slot" v-for="(slot, slotIndex) in row" :key="slotIndex" ref="appSlots">
            <div class="app-wrapper"  v-if="slot" @mousedown="registerGrab($event, slot)" @touchstart="registerGrab($event, slot)" @click="selectApp($event, slot)" :class="{
                selected: slot.selected
            }" :id="`slot${slot.id}`" @dblclick="slot.edit = true">
                <div class="image-container">
                    <img :src="slot.icon" :alt="slot.title">
                    <div class="select-overlay" :style="{
                        maskImage: `url(${slot.icon})`
                    }">

                    </div>
                </div>
                <input type="text" v-if="slot.edit" v-model="slot.title">
                <h3 v-else>{{slot.title}}</h3>
            </div>
        </div>
    </div>

I also have array of object containg apps inforamtions (title, id, icon, row, col, selected)

apps: [
                {
                    id: 0,
                    title: "Kosz bardzo długa nazwa",
                    icon: "icons/Recycle Bin (empty).png",
                    row: 0,
                    col: 0,
                    selected: false,
                    edit: false,
                },
                {
                    id: 1,
                    title: "Mój komputer",
                    icon: "icons/My Computer.png",
                    row: 1,
                    col: 0,
                    selected: false,
                    edit: false,
                }
            ],

So I can use it to re-render grid to resize to make this responsive. To move and re-render grid, I use update grid function which gets the number of columns and rows as arguments and then re-render the grid.

updateGrid(numOfRows = this.desktopGridLayout.length, numOfCols = this.desktopGridLayout[0].length) {
            // console.error("new grid update");
            const newGrid = []
            for (let i = 0; i < numOfRows; i++) {
                newGrid.push([])
                for (let j = 0; j < numOfCols; j++) {
                    newGrid[i].push(null)
                }
            }
            this.apps.sort((a,b) => {
                let rowDiff = a.row - b.row
                let colDiff = a.col - b.col
                if (colDiff === 0) {
                    return rowDiff
                }
                return colDiff
            }).sort(function (x, y) {
                return (x === y) ? 0 : x ? 1 : -1;
            }).forEach(app => {
                let row = app.row
                let col = app.col
                if (row >= newGrid.length ) {
                    row = newGrid.length - 1
                } else if (row < 0) {
                    row = 0
                }

                if (col >= newGrid[0].length ) {
                    col = newGrid[0].length - 1
                } else if (col < 0) {
                    col = 0
                }

                // console.log("Moving app: ", app.title, " from: ", app.row, app.col, " to: ", row, col)
                if (newGrid[row][col] !== null) {
                    // console.log("Slot is occupied moving occupied app down")
                    this.moveAppDown(row, col, newGrid)
                }

                console.log(`Selected app finished on (${row}, ${col}) ${newGrid[row][col]}`)


                newGrid[row][col] = {
                    title: app.title,
                    icon: app.icon,
                    id: app.id,
                    selected: app.selected
                }

                this.apps[this.apps.indexOf(app)] = {
                    ...app,
                    row: row,
                    col: col
                }
            })
            this.desktopGridLayout = newGrid
        }

If the app will be placed on the place of other app, it will trigger the move app down function. However, here is the problem because after watching consol log some apps don’t enter the if even is the slot is not empty, and I don’t have idea why.

moveAppDown(rowIndex, colIndex, grid = this.desktopGridLayout) {
            let newColIndex = colIndex;
            let newRowIndex = rowIndex + 1;

            if (newRowIndex >= grid.length) {
                newRowIndex = 0

                newColIndex = colIndex + 1
                if (newColIndex >= grid[0].length) {
                    const emptySlotRow = grid.find(row => row.some(col => col === null))

                    newRowIndex = grid.indexOf(emptySlotRow)
                    newColIndex = grid[newRowIndex].indexOf(null)
                }
            }

            // console.log("Moving", grid[rowIndex][colIndex].title, "from", rowIndex, colIndex, "occupied slot to", newRowIndex, newColIndex)
            if (grid[newRowIndex][newColIndex] !== null) {
                console.log("entering reccurention")
                this.moveAppDown(newRowIndex, newColIndex)
            }

            const app = this.apps.filter(app => app ? app.id === grid[rowIndex][colIndex].id : false)[0]

            console.log(`Moved app finished on (${newRowIndex}, ${newColIndex})`, grid[newRowIndex][newColIndex], grid[newRowIndex][newColIndex] !== null)

            grid[newRowIndex][newColIndex] = grid[rowIndex][colIndex]
            grid[rowIndex][colIndex] = null

            this.apps[this.apps.indexOf(app)] = {
                ...app,
                row: newRowIndex,
                col: newColIndex
            }
        }

I will also provide you function that handle app movement on grab, but there are still some parts of the code missing because this component is huge, and I don’t want to make this text so long. That’s why you can also see a full component as well as a project on this GitHub repo. https://github.com/kremobil/Portfolio/blob/main/resources/js/Components/Desktop.vue

Here are also handle Grab function I talked about

handleGrab(mouseX, mouseY) {
            const app = this.apps.filter(app => app.id === this.grabActive)[0]
            const appWrapper = app.element.querySelector(".app-wrapper")
            appWrapper.style.position = "absolute";
            appWrapper.style.top = mouseY + this.grabOffset.y + "px"
            appWrapper.style.left = mouseX + this.grabOffset.x + "px"
            appWrapper.style.zIndex = 500

            // also move selected objects
            this.apps.filter(app => app.selected && app.id !== this.grabActive).forEach(selectedApp => {
                const yOffset = selectedApp.element.getBoundingClientRect().y - app.element.getBoundingClientRect().y
                const xOffset = selectedApp.element.getBoundingClientRect().x - app.element.getBoundingClientRect().x

                const selectedAppWrapper = selectedApp.element.querySelector(".app-wrapper")
                selectedAppWrapper.style.position = "absolute";
                selectedAppWrapper.style.top = mouseY + this.grabOffset.y + yOffset + "px"
                selectedAppWrapper.style.left = mouseX + this.grabOffset.x + xOffset + "px"
                selectedAppWrapper.style.zIndex = 500
            })

            const xDiff = mouseX - this.mouseStartingPosition.x
            const yDiff = mouseY - this.mouseStartingPosition.y

            if (Math.abs(xDiff) > 10 || Math.abs(yDiff) > 10) {
                this.blockNextClick = true

                let nextRowIndex = app.row
                let nextColIndex = app.col

                if (xDiff < -((this.iconSize.width / 5) * 3 + this.iconSize.gap)) {
                    this.mouseStartingPosition.x -= this.iconSize.width + this.iconSize.gap
                    nextColIndex = nextColIndex - 1 > 0 ? nextColIndex - 1 : 0

                } else if (xDiff > ((this.iconSize.width / 5) * 3 + this.iconSize.gap)) {
                    this.mouseStartingPosition.x += this.iconSize.width + this.iconSize.gap
                    nextColIndex = nextColIndex + 1 >= this.desktopGridLayout[0].length ? this.desktopGridLayout[0].length - 1 : nextColIndex + 1
                }

                if (yDiff < -((this.iconSize.height / 5) * 3 + this.iconSize.gap)) {
                    this.mouseStartingPosition.y -= this.iconSize.height + this.iconSize.gap
                    nextRowIndex = nextRowIndex - 1 > 0 ? nextRowIndex - 1 : 0
                } else if (yDiff > ((this.iconSize.height / 5) * 3 + this.iconSize.gap)) {
                    this.mouseStartingPosition.y += this.iconSize.height + this.iconSize.gap
                    nextRowIndex = nextRowIndex + 1 >= this.desktopGridLayout.length ? this.desktopGridLayout.length - 1 : nextRowIndex + 1
                }

                if(app.row !== nextRowIndex || app.col !== nextColIndex) {
                    // update other selected apps
                    this.apps = this.apps.map(selectedApp => {
                        let nextSelectedRowIndex = nextRowIndex - app.row
                        let nextSelectedColIndex = nextColIndex - app.col

                        return {
                            ...selectedApp,
                            row: selectedApp.selected || selectedApp.id === app.id ? selectedApp.row + nextSelectedRowIndex : selectedApp.row,
                            col: selectedApp.selected || selectedApp.id === app.id ? selectedApp.col + nextSelectedColIndex : selectedApp.col
                        }
                    })
                }
            }
        }

and also here are the screen of console log when the error occures

console screenshot