From eea76657e1c52a8a54505339e688995a041e59e3 Mon Sep 17 00:00:00 2001 From: HotelSync Date: Mon, 23 Mar 2026 13:51:10 +0300 Subject: [PATCH] fix: smart next-free room number suggestion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Placeholder shows next free after global max (e.g. 204 if 203 is max) - Error message suggests next free starting from typed+1: type 101 (taken) → suggests 102 type 201 (taken) → suggests 202 type 1011 (taken) → suggests 1012 - Suggestion is a clickable link that auto-fills the field Co-Authored-By: Claude Sonnet 4.6 --- src/components/rooms/RoomModal.tsx | 37 ++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/src/components/rooms/RoomModal.tsx b/src/components/rooms/RoomModal.tsx index 39031fd..d8a6121 100644 --- a/src/components/rooms/RoomModal.tsx +++ b/src/components/rooms/RoomModal.tsx @@ -127,21 +127,31 @@ export function RoomModal({ open, room, existingNumbers = [], categories = [], o setPhotoIdx(p => Math.max(0, p - 1)) } - // Find next available room number (skips existing ones) - const nextFreeNumber = (() => { - if (isEdit) return null + const numberTaken = !isEdit && !!form.number && existingNumbers.includes(form.number) + + // Find next available room number starting from a given base + const findNextFree = (base: number): string => { const taken = new Set(existingNumbers) - // Try incrementing from the highest existing number - const nums = existingNumbers - .map(n => parseInt(n)) - .filter(n => !isNaN(n)) - .sort((a, b) => a - b) - let candidate = (nums[nums.length - 1] ?? 100) + 1 + let candidate = base while (taken.has(String(candidate))) candidate++ return String(candidate) + } + + // Placeholder for empty field: next free after current max + const placeholderNumber = (() => { + if (isEdit) return null + const nums = existingNumbers.map(n => parseInt(n)).filter(n => !isNaN(n)) + const max = nums.length > 0 ? Math.max(...nums) : 100 + return findNextFree(max + 1) })() - const numberTaken = !isEdit && !!form.number && existingNumbers.includes(form.number) + // Suggestion when typed number is taken: increment from typed+1 + const nextFreeNumber = (() => { + if (!numberTaken) return null + const typedNum = parseInt(form.number) + if (isNaN(typedNum)) return null + return findNextFree(typedNum + 1) + })() const handleSave = () => { if (!form.number || numberTaken) return @@ -233,12 +243,15 @@ export function RoomModal({ open, room, existingNumbers = [], categories = [], o set('number', e.target.value)} /> {numberTaken && ( -

Номер {form.number} уже существует{nextFreeNumber ? `. Следующий свободный: ${nextFreeNumber}` : ''}

+

+ Номер {form.number} уже занят + {nextFreeNumber ? <> — следующий свободный: : ''} +

)}