6.22.0: Авторасчёт сроков товаров по истории
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 1m23s
All checks were successful
Build and Push Docker Image / build-and-push (push) Successful in 1m23s
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -10,7 +10,8 @@ function ShoppingItemDetail({ itemId, onClose, onRefresh, onItemCompleted, onNav
|
||||
const [item, setItem] = useState(null)
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [error, setError] = useState(null)
|
||||
const [volumeValue, setVolumeValue] = useState('')
|
||||
const [volumeRemaining, setVolumeRemaining] = useState('')
|
||||
const [volumePurchased, setVolumePurchased] = useState('')
|
||||
const [isCompleting, setIsCompleting] = useState(false)
|
||||
const [toastMessage, setToastMessage] = useState(null)
|
||||
|
||||
@@ -38,7 +39,8 @@ function ShoppingItemDetail({ itemId, onClose, onRefresh, onItemCompleted, onNav
|
||||
setItem(null)
|
||||
setLoading(true)
|
||||
setError(null)
|
||||
setVolumeValue('')
|
||||
setVolumeRemaining('')
|
||||
setVolumePurchased('')
|
||||
}
|
||||
}, [itemId, fetchItem])
|
||||
|
||||
@@ -48,13 +50,21 @@ function ShoppingItemDetail({ itemId, onClose, onRefresh, onItemCompleted, onNav
|
||||
setIsCompleting(true)
|
||||
try {
|
||||
const payload = {}
|
||||
if (volumeValue.trim()) {
|
||||
payload.volume = parseFloat(volumeValue)
|
||||
if (isNaN(payload.volume)) {
|
||||
throw new Error('Неверное значение объёма')
|
||||
if (volumeRemaining.trim()) {
|
||||
payload.volume_remaining = parseFloat(volumeRemaining)
|
||||
if (isNaN(payload.volume_remaining)) {
|
||||
throw new Error('Неверное значение остатка')
|
||||
}
|
||||
} else {
|
||||
payload.volume = item.last_volume ?? item.volume_base
|
||||
payload.volume_remaining = item.estimated_remaining ?? 0
|
||||
}
|
||||
if (volumePurchased.trim()) {
|
||||
payload.volume_purchased = parseFloat(volumePurchased)
|
||||
if (isNaN(payload.volume_purchased)) {
|
||||
throw new Error('Неверное значение докупки')
|
||||
}
|
||||
} else {
|
||||
payload.volume_purchased = item.median_purchased ?? item.volume_base ?? 1
|
||||
}
|
||||
|
||||
const response = await authFetch(`/api/shopping/items/${itemId}/complete`, {
|
||||
@@ -169,42 +179,78 @@ function ShoppingItemDetail({ itemId, onClose, onRefresh, onItemCompleted, onNav
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="shopping-item-complete-row">
|
||||
<label className="progression-label">Объём</label>
|
||||
<div className="progression-input-wrapper">
|
||||
<input
|
||||
type="number"
|
||||
step="any"
|
||||
value={volumeValue}
|
||||
onChange={(e) => setVolumeValue(e.target.value)}
|
||||
placeholder={(item.last_volume ?? item.volume_base)?.toString() || '1'}
|
||||
className="progression-input"
|
||||
/>
|
||||
<div className="progression-controls-capsule">
|
||||
<button
|
||||
type="button"
|
||||
className="progression-control-btn progression-control-minus"
|
||||
onClick={() => {
|
||||
const base = item.last_volume ?? item.volume_base ?? 1
|
||||
const current = volumeValue.trim() ? parseFloat(volumeValue) : base
|
||||
const step = item.volume_base || 1
|
||||
setVolumeValue((current - step).toString())
|
||||
}}
|
||||
>
|
||||
−
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="progression-control-btn progression-control-plus"
|
||||
onClick={() => {
|
||||
const base = item.last_volume ?? item.volume_base ?? 1
|
||||
const current = volumeValue.trim() ? parseFloat(volumeValue) : base
|
||||
const step = item.volume_base || 1
|
||||
setVolumeValue((current + step).toString())
|
||||
}}
|
||||
>
|
||||
+
|
||||
</button>
|
||||
<div style={{ display: 'flex', gap: '0.5rem', alignItems: 'flex-end', marginBottom: '0.75rem' }}>
|
||||
<div style={{ flex: 1 }}>
|
||||
<label className="progression-label">Остаток</label>
|
||||
<div className="progression-input-wrapper">
|
||||
<input
|
||||
type="number"
|
||||
step="any"
|
||||
value={volumeRemaining}
|
||||
onChange={(e) => setVolumeRemaining(e.target.value)}
|
||||
placeholder={item.estimated_remaining != null ? Math.round(item.estimated_remaining * 10) / 10 + '' : '0'}
|
||||
className="progression-input"
|
||||
/>
|
||||
{volumeRemaining && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setVolumeRemaining('')}
|
||||
style={{
|
||||
position: 'absolute',
|
||||
right: '8px',
|
||||
top: '50%',
|
||||
transform: 'translateY(-50%)',
|
||||
background: 'none',
|
||||
border: 'none',
|
||||
color: '#9ca3af',
|
||||
cursor: 'pointer',
|
||||
fontSize: '1.1rem',
|
||||
padding: '4px',
|
||||
lineHeight: 1,
|
||||
}}
|
||||
>
|
||||
✕
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div style={{ flex: 1 }}>
|
||||
<label className="progression-label">Докуплено</label>
|
||||
<div className="progression-input-wrapper">
|
||||
<input
|
||||
type="number"
|
||||
step="any"
|
||||
value={volumePurchased}
|
||||
onChange={(e) => setVolumePurchased(e.target.value)}
|
||||
placeholder={(item.median_purchased ?? item.volume_base ?? 1).toString()}
|
||||
className="progression-input"
|
||||
/>
|
||||
<div className="progression-controls-capsule">
|
||||
<button
|
||||
type="button"
|
||||
className="progression-control-btn progression-control-minus"
|
||||
onClick={() => {
|
||||
const base = item.median_purchased ?? item.volume_base ?? 1
|
||||
const current = volumePurchased.trim() ? parseFloat(volumePurchased) : base
|
||||
const step = item.volume_base || 1
|
||||
setVolumePurchased(Math.max(0, current - step).toString())
|
||||
}}
|
||||
>
|
||||
−
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="progression-control-btn progression-control-plus"
|
||||
onClick={() => {
|
||||
const base = item.median_purchased ?? item.volume_base ?? 1
|
||||
const current = volumePurchased.trim() ? parseFloat(volumePurchased) : base
|
||||
const step = item.volume_base || 1
|
||||
setVolumePurchased((current + step).toString())
|
||||
}}
|
||||
>
|
||||
+
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user