6262 @input =" handleSearchInput"
6363 @keydown =" handleKeyDown"
6464 type =" text"
65- :placeholder =" scannerEnabled ? 'Scanner Ready - Scan barcode now' : 'Search by item code, name or scan barcode' "
65+ :placeholder =" searchPlaceholder "
6666 :class =" [
67- 'w-full text-sm border rounded-md px-3 py-2 pl-10 pr-10 focus:outline-none transition-all',
68- scannerEnabled
67+ 'w-full text-sm border rounded-md px-3 py-2 pl-10 pr-28 focus:outline-none transition-all',
68+ autoAddEnabled
69+ ? 'border-blue-400 bg-blue-50 focus:ring-2 focus:ring-blue-500 focus:border-transparent'
70+ : scannerEnabled
6971 ? 'border-green-400 bg-green-50 focus:ring-2 focus:ring-green-500 focus:border-transparent'
7072 : 'border-gray-300 focus:ring-2 focus:ring-blue-500 focus:border-transparent'
7173 ]"
7274 aria-label =" Search items"
7375 />
74- <!-- Barcode Scan Icon -->
75- <div class =" absolute inset-y-0 right-0 pr-3 flex items-center" >
76+ <!-- Barcode Scan Icon and Auto-Add Toggle -->
77+ <div class =" absolute inset-y-0 right-0 pr-3 flex items-center gap-1 " >
7678 <button
7779 @click =" toggleBarcodeScanner"
7880 :class =" [
8789 <path stroke-linecap =" round" stroke-linejoin =" round" stroke-width =" 2" d =" M12 4v1m6 11h2m-6 0h-2v4m0-11v3m0 0h.01M12 12h4.01M16 20h4M4 12h4m12 0h.01M5 8h2a1 1 0 001-1V5a1 1 0 00-1-1H5a1 1 0 00-1 1v2a1 1 0 001 1zm12 0h2a1 1 0 001-1V5a1 1 0 00-1-1h-2a1 1 0 00-1 1v2a1 1 0 001 1zM5 20h2a1 1 0 001-1v-2a1 1 0 00-1-1H5a1 1 0 00-1 1v2a1 1 0 001 1z" />
8890 </svg >
8991 </button >
92+ <button
93+ @click =" toggleAutoAdd"
94+ :class =" [
95+ 'p-1 rounded transition-all flex items-center gap-1 text-xs font-medium px-2',
96+ autoAddEnabled
97+ ? 'bg-blue-100 hover:bg-blue-200 text-blue-700'
98+ : 'hover:bg-gray-100 text-gray-600'
99+ ]"
100+ :title =" autoAddEnabled ? 'Auto-Add: ON - Press Enter to add items to cart' : 'Auto-Add: OFF - Click to enable automatic cart addition on Enter'"
101+ >
102+ <svg class =" w-3.5 h-3.5" fill =" none" stroke =" currentColor" viewBox =" 0 0 24 24" >
103+ <path stroke-linecap =" round" stroke-linejoin =" round" stroke-width =" 2" d =" M12 4v16m8-8H4" />
104+ </svg >
105+ <span >Auto</span >
106+ </button >
90107 </div >
91108 </div >
92109 <div class =" flex items-center space-x-0.5 bg-gray-100 rounded-md p-0.5" >
@@ -392,8 +409,11 @@ const lastKeyTime = ref(0)
392409const barcodeBuffer = ref (" " )
393410const searchInputRef = ref (null )
394411const scannerEnabled = ref (false )
412+ const autoAddEnabled = ref (false )
395413const itemThreshold = ref (50 ) // Threshold for auto-switching to list view
396414const userManuallySetView = ref (false ) // Track if user manually changed view mode
415+ const scannerInputDetected = ref (false ) // Track if current input is from scanner
416+ const autoSearchTimer = ref (null ) // Timer for auto-search when typing stops
397417
398418// Pagination state
399419const currentPage = ref (1 )
@@ -413,6 +433,26 @@ const totalPages = computed(() => {
413433 return Math .ceil (filteredItems .value .length / itemsPerPage .value )
414434})
415435
436+ const SEARCH_PLACEHOLDERS = Object .freeze ({
437+ auto: " Auto-Add ON - Type or scan barcode" ,
438+ scanner: " Scanner ON - Enable Auto for automatic addition" ,
439+ default: " Search by item code, name or scan barcode" ,
440+ })
441+
442+ const searchMode = computed (() => {
443+ if (autoAddEnabled .value ) {
444+ return " auto"
445+ }
446+
447+ if (scannerEnabled .value ) {
448+ return " scanner"
449+ }
450+
451+ return " default"
452+ })
453+
454+ const searchPlaceholder = computed (() => SEARCH_PLACEHOLDERS [searchMode .value ])
455+
416456// Watch for cart items and pos profile changes
417457watch (
418458 () => props .cartItems ,
@@ -475,21 +515,43 @@ function handleKeyDown(event) {
475515 const currentTime = Date .now ()
476516 const timeDiff = currentTime - lastKeyTime .value
477517
478- // If Enter is pressed, always trigger search
518+ // If Enter/newline is pressed, trigger barcode search
479519 if (event .key === " Enter" ) {
480520 event .preventDefault ()
481- handleBarcodeSearch ()
521+
522+ const isFromScanner = scannerInputDetected .value
523+
524+ // Auto-add if Auto-Add mode is enabled (regardless of manual typing vs scanner)
525+ if (autoAddEnabled .value ) {
526+ // Auto-add enabled - add item directly to cart
527+ handleBarcodeSearch (true ) // Pass true to indicate auto-add
528+ } else {
529+ // Auto-add disabled - normal search behavior
530+ handleBarcodeSearch (false )
531+ }
532+
533+ // Reset detection
482534 barcodeBuffer .value = " "
535+ scannerInputDetected .value = false
536+
537+ // Clear auto-search timer since Enter was pressed
538+ if (autoSearchTimer .value ) {
539+ clearTimeout (autoSearchTimer .value )
540+ autoSearchTimer .value = null
541+ }
542+
483543 return
484544 }
485545
486546 // Barcode scanners typically input very fast (< 50ms between characters)
487547 // If time between keystrokes is very short, it's likely a barcode scanner
488- if (timeDiff < 50 && event .key .length === 1 ) {
548+ if (timeDiff < 50 && event .key .length === 1 && barcodeBuffer . value . length > 0 ) {
489549 barcodeBuffer .value += event .key
490- } else {
550+ scannerInputDetected .value = true // Mark as scanner input
551+ } else if (event .key .length === 1 ) {
491552 // Manual typing - reset buffer
492- barcodeBuffer .value = event .key .length === 1 ? event .key : " "
553+ barcodeBuffer .value = event .key
554+ scannerInputDetected .value = false // Mark as manual input
493555 }
494556
495557 lastKeyTime .value = currentTime
@@ -499,36 +561,61 @@ function handleKeyDown(event) {
499561function handleSearchInput (event ) {
500562 const value = event .target .value
501563 itemStore .setSearchTerm (value)
564+
565+ // Clear any existing timer
566+ if (autoSearchTimer .value ) {
567+ clearTimeout (autoSearchTimer .value )
568+ autoSearchTimer .value = null
569+ }
570+
571+ // If Auto-Add is enabled and user is typing, automatically trigger search after they stop
572+ if (autoAddEnabled .value && value .trim ().length > 0 ) {
573+ // Wait 500ms after user stops typing, then auto-search and add
574+ autoSearchTimer .value = setTimeout (() => {
575+ handleBarcodeSearch (true ) // Auto-add mode
576+ }, 500 ) // 500ms delay after typing stops
577+ }
502578}
503579
504580function handleItemClick (item ) {
505581 emit (" item-selected" , item)
506582}
507583
508- async function handleBarcodeSearch () {
584+ async function handleBarcodeSearch (forceAutoAdd = false ) {
509585 const barcode = searchTerm .value .trim ()
510586
511587 if (! barcode) {
512588 return
513589 }
514590
515- // If scanner is enabled, always try to add to cart automatically
516- const shouldAutoAdd = scannerEnabled .value
591+ // Auto-add if explicitly requested (from scanner newline detection)
592+ // OR if both scanner and auto-add modes are enabled
593+ const shouldAutoAdd = forceAutoAdd || (scannerEnabled .value && autoAddEnabled .value )
517594
518595 try {
519596 // First try exact barcode lookup via API
520597 const item = await itemStore .searchByBarcode (barcode)
521598
522599 if (item) {
523- // Item found by barcode - add to cart immediately
524- emit (" item-selected" , item)
600+ // Item found by barcode - add to cart immediately with auto-add flag
601+ emit (" item-selected" , item, shouldAutoAdd )
525602 itemStore .clearSearch ()
526- toast .create ({
527- title: " Item Added" ,
528- text: ` ${ item .item_name } added to cart` ,
529- icon: " check" ,
530- iconClasses: " text-green-600" ,
531- })
603+
604+ if (shouldAutoAdd) {
605+ toast .create ({
606+ title: " ✓ Auto-Added" ,
607+ text: ` ${ item .item_name } added to cart` ,
608+ icon: " check" ,
609+ iconClasses: " text-blue-600" ,
610+ })
611+ } else {
612+ toast .create ({
613+ title: " Item Added" ,
614+ text: ` ${ item .item_name } added to cart` ,
615+ icon: " check" ,
616+ iconClasses: " text-green-600" ,
617+ })
618+ }
532619 return
533620 }
534621 } catch (error) {
@@ -537,14 +624,24 @@ async function handleBarcodeSearch() {
537624
538625 // Fallback: If only one item matches in filtered results, auto-select it
539626 if (filteredItems .value .length === 1 ) {
540- emit (" item-selected" , filteredItems .value [0 ])
627+ emit (" item-selected" , filteredItems .value [0 ], shouldAutoAdd )
541628 itemStore .clearSearch ()
542- toast .create ({
543- title: " Item Added" ,
544- text: ` ${ filteredItems .value [0 ].item_name } added to cart` ,
545- icon: " check" ,
546- iconClasses: " text-green-600" ,
547- })
629+
630+ if (shouldAutoAdd) {
631+ toast .create ({
632+ title: " ✓ Auto-Added" ,
633+ text: ` ${ filteredItems .value [0 ].item_name } added to cart` ,
634+ icon: " check" ,
635+ iconClasses: " text-blue-600" ,
636+ })
637+ } else {
638+ toast .create ({
639+ title: " Item Added" ,
640+ text: ` ${ filteredItems .value [0 ].item_name } added to cart` ,
641+ icon: " check" ,
642+ iconClasses: " text-green-600" ,
643+ })
644+ }
548645 } else if (filteredItems .value .length === 0 ) {
549646 toast .create ({
550647 title: " Item Not Found" ,
@@ -580,6 +677,11 @@ async function handleBarcodeSearch() {
580677function toggleBarcodeScanner () {
581678 scannerEnabled .value = ! scannerEnabled .value
582679
680+ // Disable auto-add when scanner is disabled
681+ if (! scannerEnabled .value ) {
682+ autoAddEnabled .value = false
683+ }
684+
583685 // Focus on search input when enabling scanner
584686 if (scannerEnabled .value ) {
585687 const input = searchInputRef .value || document .getElementById (" item-search" )
@@ -589,7 +691,7 @@ function toggleBarcodeScanner() {
589691
590692 toast .create ({
591693 title: " Barcode Scanner Enabled" ,
592- text: " Scan barcode to automatically add items to cart " ,
694+ text: " Click 'Auto' button to automatically add items when you press Enter " ,
593695 icon: " check" ,
594696 iconClasses: " text-green-600" ,
595697 })
@@ -603,6 +705,44 @@ function toggleBarcodeScanner() {
603705 }
604706}
605707
708+ function toggleAutoAdd () {
709+ // Auto-add works independently - no need for scanner mode
710+ autoAddEnabled .value = ! autoAddEnabled .value
711+
712+ // Auto-enable scanner mode when auto-add is enabled
713+ if (autoAddEnabled .value && ! scannerEnabled .value ) {
714+ scannerEnabled .value = true
715+ }
716+
717+ // Clear any pending timer when toggling off
718+ if (! autoAddEnabled .value && autoSearchTimer .value ) {
719+ clearTimeout (autoSearchTimer .value )
720+ autoSearchTimer .value = null
721+ }
722+
723+ if (autoAddEnabled .value ) {
724+ toast .create ({
725+ title: " Auto-Add Enabled" ,
726+ text: " Type or scan barcode - items will be added automatically after 0.5s" ,
727+ icon: " check" ,
728+ iconClasses: " text-blue-600" ,
729+ })
730+
731+ // Focus on search input
732+ const input = searchInputRef .value || document .getElementById (" item-search" )
733+ if (input) {
734+ input .focus ()
735+ }
736+ } else {
737+ toast .create ({
738+ title: " Auto-Add Disabled" ,
739+ text: " Items will require manual selection" ,
740+ icon: " alert-circle" ,
741+ iconClasses: " text-gray-600" ,
742+ })
743+ }
744+ }
745+
606746function formatCurrency (amount ) {
607747 return formatCurrencyUtil (parseFloat (amount || 0 ), props .currency )
608748}
0 commit comments