diff --git a/src/components/grids/device-grid.tsx b/src/components/grids/device-grid.tsx index 01ccfcd..adb773e 100644 --- a/src/components/grids/device-grid.tsx +++ b/src/components/grids/device-grid.tsx @@ -15,72 +15,60 @@ export function DeviceGrid({ totalSeats?: number; }) { const getMachineNumber = useMachineNumber(); - const deviceMap = new Map(); + const parsedDevices = devices + .map((device, index) => ({ + device, + index, + number: getMachineNumber(device.id || ""), + })) + .sort((a, b) => { + const aNumber = a.number > 0 ? a.number : Number.MAX_SAFE_INTEGER; + const bNumber = b.number > 0 ? b.number : Number.MAX_SAFE_INTEGER; - let maxMachineNumber = 0; - devices.forEach((device) => { - const number = getMachineNumber(device.id || ""); - if (number > maxMachineNumber) maxMachineNumber = number; - }); + if (aNumber !== bNumber) { + return aNumber - bNumber; + } - const seatCount = - typeof totalSeats === "number" && totalSeats > 0 ? totalSeats : maxMachineNumber; - - devices.forEach((device) => { - const number = getMachineNumber(device.id || ""); - if (number > 0 && number <= seatCount) deviceMap.set(number, device); - }); - - const columnsPerSide = 4; - const rightCount = Math.ceil(seatCount / 2); - const leftCount = seatCount - rightCount; - const totalRows = Math.max( - Math.ceil(rightCount / columnsPerSide), - Math.ceil(leftCount / columnsPerSide) - ); - - const buildRowPositions = (side: "left" | "right", rowIndexFromBottom: number) => { - const start = - side === "right" - ? rowIndexFromBottom * columnsPerSide + 1 - : rightCount + 1 + rowIndexFromBottom * columnsPerSide; - const end = - side === "right" - ? Math.min(start + columnsPerSide - 1, rightCount) - : Math.min(start + columnsPerSide - 1, seatCount); - - const count = Math.max(0, end - start + 1); - const positions = Array(columnsPerSide).fill(null); - - if (count === 0) { - return positions; - } - - const numbers: number[] = []; - for (let n = end; n >= start; n -= 1) { - numbers.push(n); - } - - const offset = side === "right" ? 0 : columnsPerSide - count; - numbers.forEach((n, index) => { - positions[offset + index] = n; + return a.index - b.index; }); - return positions; - }; + const seatCount = + typeof totalSeats === "number" && totalSeats > 0 ? totalSeats : parsedDevices.length; + const rightCapacity = Math.ceil(seatCount / 2); + const inRangeCount = parsedDevices.filter( + (item) => item.number > 0 && item.number <= seatCount + ).length; + const useThresholdSplit = + seatCount > 0 && inRangeCount >= Math.ceil(parsedDevices.length * 0.6); - const renderSeat = (position: number | null, key: string) => { - if (!position) { - return
; - } + let rightDevices = parsedDevices; + let leftDevices: typeof parsedDevices = []; - const device = deviceMap.get(position); + if (useThresholdSplit) { + rightDevices = parsedDevices.filter( + (item) => item.number > 0 && item.number <= rightCapacity + ); + leftDevices = parsedDevices.filter((item) => item.number > rightCapacity); + + const unassigned = parsedDevices.filter( + (item) => item.number <= 0 || item.number > seatCount + ); + leftDevices = [...leftDevices, ...unassigned]; + } else { + const splitIndex = Math.ceil(parsedDevices.length / 2); + rightDevices = parsedDevices.slice(0, splitIndex); + leftDevices = parsedDevices.slice(splitIndex); + } + + const renderDevice = (item: (typeof parsedDevices)[number]) => { + const device = item.device; + const position = item.number > 0 ? item.number : item.index + 1; const macAddress = device?.networkInfos?.[0]?.macAddress || device?.id; const folderStatus = folderStatuses?.get(macAddress); return ( { - const rowIndexFromBottom = totalRows - 1 - rowIndex; - const leftPositions = buildRowPositions("left", rowIndexFromBottom); - const rightPositions = buildRowPositions("right", rowIndexFromBottom); - - return ( -
- {leftPositions.map((position, i) => - renderSeat(position, `left-${rowIndex}-${i}`) - )} - - {/* Đường chia giữa */} -
-
-
- - {rightPositions.map((position, i) => - renderSeat(position, `right-${rowIndex}-${i}`) - )} -
- ); - }; + const gridTemplateColumns = "repeat(auto-fit, minmax(6rem, 6rem))"; return (
-
- {Array.from({ length: totalRows }).map((_, i) => renderRow(i))} +
+
+ {leftDevices.map(renderDevice)} +
+ +
+
+
+ +
+ {rightDevices.map(renderDevice)} +