fix: smart next-free room number suggestion
- 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 <noreply@anthropic.com>
This commit is contained in:
@@ -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
|
||||
<input
|
||||
type="text"
|
||||
className={cn('input', numberTaken && 'border-red-400 focus:ring-red-400')}
|
||||
placeholder={nextFreeNumber ?? '101'}
|
||||
placeholder={placeholderNumber ?? '101'}
|
||||
value={form.number}
|
||||
onChange={e => set('number', e.target.value)}
|
||||
/>
|
||||
{numberTaken && (
|
||||
<p className="text-xs text-red-500 mt-1">Номер {form.number} уже существует{nextFreeNumber ? `. Следующий свободный: ${nextFreeNumber}` : ''}</p>
|
||||
<p className="text-xs text-red-500 mt-1">
|
||||
Номер {form.number} уже занят
|
||||
{nextFreeNumber ? <> — следующий свободный: <button type="button" className="underline font-medium" onClick={() => set('number', nextFreeNumber)}>{nextFreeNumber}</button></> : ''}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
|
||||
Reference in New Issue
Block a user