import React from 'react' import axios from 'axios' import {toast} from 'react-hot-toast' import {StockBatch, StockEntry, StockPosition, StockSection} from '@/types' import {FontAwesomeIcon} from '@fortawesome/react-fontawesome' import {faCheckCircle, faTimesCircle} from '@fortawesome/free-solid-svg-icons' interface Props { onClose: () => void selectedBatch: StockBatch selectedSection: StockSection | null selectedPosition: StockPosition | null } const SetStockModal: React.FC = ({onClose, selectedBatch, selectedSection, selectedPosition}) => { const [quantity, setQuantity] = React.useState('') const [isDropdownOpen, setIsDropdownOpen] = React.useState(false) const [selectedEntry, setSelectedEntry] = React.useState(null) const [loading, setLoading] = React.useState(false) const [isSuggestionsOpen, setIsSuggestionsOpen] = React.useState(false) const [activeTab, setActiveTab] = React.useState<'batch' | 'item'>('item') const handleSelect = (entry: StockEntry) => { setSelectedEntry(entry) setIsDropdownOpen(false) } const parsedQty = parseInt(quantity, 10) const isNumber = !isNaN(parsedQty) const maxItem = selectedEntry ? selectedEntry.count - selectedEntry.count_stocked : 0 const capacity = selectedSection ? selectedSection.capacity : 0 const exceedsItem = isNumber && parsedQty > maxItem const exceedsCapacity = isNumber && parsedQty > capacity const hasError = exceedsItem || exceedsCapacity const readyToScan = selectedEntry !== null && isNumber && parsedQty >= 1 && !exceedsItem && !exceedsCapacity // Called when “Simulate Scan (ID=3)” is clicked const handleScan = async () => { if(activeTab === 'batch') { if (!selectedBatch || !selectedPosition) return } else { if (!selectedEntry || !selectedSection) return if (!readyToScan) { toast.error('Please fix validation errors before confirming.') return } } setLoading(true) const toastId = toast.loading('Storing…') try { let response if (activeTab === 'batch') { response = await axios.post( '/api/pdaView/setBatchSection', { batch_id: selectedBatch.id, position_id: selectedPosition?.position_id, }, { withCredentials: true } ) } else { response = await axios.post( '/api/pdaView/setStockSection', { entry_id: selectedEntry?.id, section_id: selectedSection?.section_id, count_to_be_stored: parsedQty, }, { withCredentials: true } ) } // now 'response' is defined no matter which branch ran const { data } = response console.log('data', data) if (!data.success) { toast.dismiss(toastId) switch (data.error) { case 'validation_failed': toast.error('Validation failed. Check inputs.') break case 'not_found': toast.error('Entry or section not found.') break case 'section_occupied': toast.error('That section is already occupied.') break case 'insufficient_capacity': toast.error('Not enough capacity in this section.') break case 'server_error': default: toast.error(data.message ?? 'Server error during storing.') break } setLoading(false) return } toast.dismiss(toastId) toast.success('Stored successfully.') resetAndClose() } catch (err: any) { toast.dismiss() if (err.response && err.response.data) { const payload = err.response.data if (payload.error === 'validation_failed') { toast.error('Validation failed. Check inputs.') } else if (payload.error === 'not_found') { toast.error('Entry or section not found.') } else if (payload.error === 'section_occupied') { toast.error('That section is already occupied.') } else if (payload.error === 'insufficient_capacity') { toast.error('Not enough capacity in this section.') } else { toast.error(payload.message || 'Unknown error occurred.') } } else { toast.error('Network error. Please try again.') } setLoading(false) } } const resetAndClose = () => { setQuantity('') setSelectedEntry(null) setLoading(false) setIsSuggestionsOpen(false) setIsDropdownOpen(false) onClose() } return (

Store Stock

{activeTab === 'batch' && (
{(selectedSection || selectedPosition) && (
Selected position: {selectedPosition ? selectedPosition.storage_address : selectedSection ? selectedSection.position.storage_address : ""}
)}
{loading ? 'Storing…' : (selectedSection || selectedPosition) ? 'Waiting for confirm' : 'Waiting for section scan...'}
)} {activeTab === 'item' && (
{/* Product Dropdown */}
    {selectedBatch.stock_entries.map((entry) => { const stocked = entry.count_stocked const total = entry.count const remaining = total - stocked const selectable = remaining > 0 return (
  • ) })} {selectedBatch.stock_entries.length === 0 && (
  • No items available
  • )}
{/* Quantity Input */}
setQuantity(e.target.value)} className={`input input-bordered w-full ${hasError ? 'border-red-500' : ''}`} min="1" max={selectedEntry ? maxItem : undefined} required /> {selectedEntry && ( Max items: {maxItem} | Capacity: {capacity} )} {/* Validation Messages */} {(exceedsItem || exceedsCapacity) && (
{exceedsItem && (
Item quantity exceeded
)} {exceedsCapacity && (
Maximum capacity exceeded
)}
)} {/* Success indicator if valid */} {readyToScan && (
Ready to store
)}
{selectedSection && (
Selected section: {selectedSection.storage_address}
)} {/* Buttons: Suggested Sections & Simulate Scan */}
{/* Waiting for scan indicator */} {readyToScan && !loading && (
{loading ? 'Storing…' : selectedSection ? 'Waiting for confirm' : 'Waiting for section scan...'}
)} {/* Cancel Button */}
{/* Suggested Sections Modal */} {isSuggestionsOpen && (

Suggested Sections

  • Section A (ID: 1)
  • Section B (ID: 2)
  • Section C (ID: 3)
  • Section D (ID: 4)
)}
)}
) } export default SetStockModal