@@ -25,49 +25,79 @@ interface BarcodeOptions {
2525 bcid : string
2626 text : string
2727 scale : number
28- includetext : boolean
2928 textxalign : string
3029}
3130
3231declare global {
3332 interface Window {
3433 bwipjs : {
35- toCanvas : ( canvas : HTMLCanvasElement , options : BarcodeOptions ) => void
36- }
34+ toCanvas : ( canvas : HTMLCanvasElement , options : { } ) => void
35+ } ,
36+ symdesc ?: Record < string , { sym : string ; desc : string ; text : string ; opts : string } > ;
3737 }
3838}
3939
40+ let selectedOptions : Record < string , string > = { } ;
41+
4042export default function BarcodeGenerator ( ) {
43+ // Load bwip-js library
44+ const bwipLibscript = document . createElement ( "script" )
45+ bwipLibscript . src = "https://cdn.jsdelivr.net/npm/[email protected] /dist/bwip-js-min.js" 46+ bwipLibscript . async = true
47+ document . head . appendChild ( bwipLibscript )
48+ // Load symdesc
49+ const descScript = document . createElement ( "script" )
50+ descScript . src = "https://cdn.jsdelivr.net/npm/[email protected] /lib/symdesc.js" 51+ descScript . async = true
52+ document . head . appendChild ( descScript )
53+
4154 const [ barcodeText , setBarcodeText ] = useState ( "AAA1234;BBB1234" )
42- const [ symbology , setSymbology ] = useState ( "code128 " )
43- const [ showText , setShowText ] = useState ( true )
55+ const [ symbology , setSymbology ] = useState ( "" )
56+ const [ initialSymbology , setInitialSymbology ] = useState ( "" ) ;
4457 const [ darkMode , setDarkMode ] = useState ( false )
4558 const [ barcodes , setBarcodes ] = useState < string [ ] > ( [ ] )
4659 const [ isGenerating , setIsGenerating ] = useState ( false )
60+ const [ options , setOptions ] = useState < Record < string , string > > ( { } ) ;
61+
62+ const [ error , setError ] = useState < string | null > ( null ) ; // State to store error messages
4763
4864 useEffect ( ( ) => {
65+
4966 // Load saved preferences
5067 const savedDarkMode = localStorage . getItem ( "darkModeEnabled" ) === "true"
5168 const savedSymbology = localStorage . getItem ( "lastSymbology" )
5269 const savedRequest = localStorage . getItem ( "lastRequest" )
5370
5471 if ( savedDarkMode ) setDarkMode ( true )
55- if ( savedSymbology ) setSymbology ( savedSymbology )
72+ if ( savedSymbology ) {
73+ console . log ( "savedSymbology: " , savedSymbology ) ;
74+ setInitialSymbology ( savedSymbology )
75+ setSymbology ( savedSymbology )
76+ }
77+ else {
78+ setInitialSymbology ( "code128" )
79+ setSymbology ( "code128" )
80+ }
5681 if ( savedRequest ) setBarcodeText ( savedRequest )
5782
58- // Load bwip-js library
59- const script = document . createElement ( "script" )
60- script . src = "https://cdn.jsdelivr.net/npm/[email protected] /dist/bwip-js-min.js" 61- script . async = true
62- document . head . appendChild ( script )
6383
6484 return ( ) => {
65- if ( document . head . contains ( script ) ) {
66- document . head . removeChild ( script )
85+ if ( document . head . contains ( bwipLibscript ) ) {
86+ document . head . removeChild ( bwipLibscript )
87+ }
88+ if ( document . head . contains ( descScript ) ) {
89+ document . head . removeChild ( descScript )
6790 }
6891 }
6992 } , [ ] )
7093
94+ useEffect ( ( ) => {
95+ console . log ( `effect triggered by: ${ symbology } ` ) ;
96+ if ( ! symbology ) return ;
97+ loadOptions ( symbology ) ;
98+ if ( symbology === initialSymbology ) return ;
99+ } , [ symbology ] )
100+
71101 useEffect ( ( ) => {
72102 localStorage . setItem ( "darkModeEnabled" , darkMode . toString ( ) )
73103 if ( darkMode ) {
@@ -77,15 +107,85 @@ export default function BarcodeGenerator() {
77107 }
78108 } , [ darkMode ] )
79109
110+ function loadOptionsRecords ( symbOptions : string ) : Record < string , string > {
111+ let records : Record < string , string > = { } ;
112+ if ( ! symbOptions || symbOptions . length === 0 ) {
113+ return records ;
114+ }
115+ const defOptions = symbOptions . split ( " " ) ;
116+ for ( const defOption of defOptions ) {
117+ if ( defOption . includes ( "=" ) ) {
118+ const [ key , value ] = defOption . split ( "=" ) ;
119+ records [ key ] = value ;
120+ }
121+ else {
122+ records [ defOption ] = "false" ;
123+ }
124+ }
125+ return records ;
126+ }
127+
128+ const loadOptions = ( symbology : string ) => {
129+ selectedOptions = { }
130+ if ( window . symdesc ) {
131+ const symbologyInfo = window . symdesc [ symbology ] ;
132+ if ( symbologyInfo ) {
133+ console . log ( `loading options for symbology: ${ symbology } ` ) ;
134+ let storedOptions = localStorage . getItem ( storedOptionsKey ( symbology ) ) ;
135+ console . log ( `loading ${ storedOptionsKey ( symbology ) } ` , storedOptions ) ;
136+ if ( storedOptions && storedOptions != "{}" ) {
137+ const storedOptionsObj : Record < string , string > = JSON . parse ( storedOptions )
138+ console . log ( "storedOptionsObj: " , storedOptionsObj ) ;
139+ setOptions ( storedOptionsObj )
140+ selectedOptions = storedOptionsObj
141+ }
142+ else {
143+ const defaultOptions = loadOptionsRecords ( symbologyInfo . opts ) ;
144+ console . log ( "defaultOptions: " , defaultOptions ) ;
145+ setOptions ( defaultOptions ) ;
146+ selectedOptions = defaultOptions ;
147+ }
148+
149+ } else {
150+ console . log ( `no options available for symbology: ${ symbology } ` ) ;
151+ setOptions ( { } ) ;
152+ }
153+ } else {
154+ console . log ( `loading options failed, no symdesc available` ) ;
155+ setOptions ( { } ) ;
156+ }
157+ } ;
158+
159+ const handleInputChange = ( key : string , value : string ) => {
160+ selectedOptions [ key ] = value ;
161+ } ;
162+
163+ const handleSwitchChange = ( key : string , value : boolean ) => {
164+ selectedOptions [ key ] = value ? "true" : "false" ;
165+ } ;
166+
167+ const storedOptionsKey = ( symbology : string ) => {
168+ return `stored_${ symbology } _opts` ;
169+ }
170+
171+
172+
173+
80174 const generateBarcodes = async ( ) => {
81175 if ( ! barcodeText . trim ( ) ) {
82- setBarcodes ( [ ] )
176+ setBarcodes ( [ ] ) ;
177+ setError ( null ) ;
83178 return
84179 }
85180
86- setIsGenerating ( true )
87- localStorage . setItem ( "lastRequest" , barcodeText )
88- localStorage . setItem ( "lastSymbology" , symbology )
181+ setBarcodes ( [ ] ) ;
182+ setIsGenerating ( true ) ;
183+ setError ( null ) ;
184+
185+ localStorage . setItem ( "lastRequest" , barcodeText ) ;
186+ localStorage . setItem ( "lastSymbology" , symbology ) ;
187+ localStorage . setItem ( storedOptionsKey ( symbology ) , JSON . stringify ( selectedOptions ) ) ;
188+ console . log ( `storing ${ storedOptionsKey ( symbology ) } ` , selectedOptions ) ;
89189
90190 try {
91191 // Determine separator
@@ -115,22 +215,28 @@ export default function BarcodeGenerator() {
115215 const canvas = document . createElement ( "canvas" )
116216
117217 for ( const entry of entries ) {
118- const options : BarcodeOptions = {
119- bcid : symbology ,
120- text : entry ,
121- scale : 3 ,
122- includetext : showText ,
123- textxalign : "center" ,
218+ let options = { } ;
219+
220+ for ( const [ key , value ] of Object . entries ( selectedOptions ) ) {
221+ options [ key ] = value ;
124222 }
125223
224+ options . text = entry ;
225+ options . bcid = symbology ;
226+ options . scale = 3 ;
227+
228+ console . log ( "generating barcodes using: " , options ) ;
126229 try {
127230 window . bwipjs . toCanvas ( canvas , options )
128231 generatedBarcodes . push ( canvas . toDataURL ( "image/png" ) )
129232 } catch ( error ) {
130- console . error ( "Error generating barcode for:" , entry , error )
233+ console . error ( "Error generating barcode for:" , entry , error ) ;
234+ setError ( `Failed to generate barcode for: ${ entry }
235+ ${ error }
236+ ` ) ;
237+ return ;
131238 }
132239 }
133-
134240 setBarcodes ( generatedBarcodes )
135241 } catch ( error ) {
136242 console . error ( "Error generating barcodes:" , error )
@@ -306,7 +412,7 @@ export default function BarcodeGenerator() {
306412 </ CardHeader >
307413 < CardContent className = "space-y-4 pt-4" >
308414 < div >
309- < Label htmlFor = "symbology" className = "text-sm font-medium mb-2 block text-foreground" >
415+ < Label htmlFor = "symbology" className = "text-sm font-bold mb-2 block text-foreground" >
310416 Symbology
311417 </ Label >
312418 < Select value = { symbology } onValueChange = { setSymbology } >
@@ -315,23 +421,79 @@ export default function BarcodeGenerator() {
315421 </ SelectTrigger >
316422 < SelectContent >
317423 < SelectItem value = "code128" > Code 128</ SelectItem >
318- < SelectItem value = "datamatrix" > Data Matrix</ SelectItem >
319- < SelectItem value = "gs1datamatrix" > GS1 Data Matrix</ SelectItem >
424+ < SelectItem value = "interleaved2of5" > Interleaved 2 of 5</ SelectItem >
320425 < SelectItem value = "pdf417" > PDF417</ SelectItem >
321426 < SelectItem value = "qrcode" > QR Code</ SelectItem >
427+ < SelectItem value = "dotcode" > Dot code</ SelectItem >
428+ < SelectItem value = "datamatrix" > Data Matrix</ SelectItem >
429+ < SelectItem value = "gs1datamatrix" > GS1 Data Matrix</ SelectItem >
430+ < SelectItem value = "ean5" > EAN-5</ SelectItem >
431+ < SelectItem value = "ean8" > EAN-13</ SelectItem >
322432 </ SelectContent >
323433 </ Select >
324434 </ div >
325- < div className = "flex items-center space-x-2" >
326- < Switch id = "show-text" checked = { showText } onCheckedChange = { setShowText } />
327- < Label htmlFor = "show-text" className = "text-sm font-medium text-foreground" >
328- Show text below barcode
329- </ Label >
435+
436+ < div >
437+
438+
439+
440+ { Object . entries ( options ) . length > 0 ? (
441+ < >
442+ < Label htmlFor = "symbology" className = "text-sm font-bold mb-2 block text-foreground" >
443+ Options
444+ </ Label >
445+ < ul className = "text-gray-700 list-disc list-inside space-y-2" >
446+ { Object . entries ( options ) . map ( ( [ key , value ] , index ) => {
447+ const hasBoolValue = value === "true" || value === "false" ;
448+ if ( hasBoolValue ) {
449+ //Switch input
450+ return (
451+ < div key = { index } className = "flex items-center space-x-2" >
452+ < Switch
453+ id = { `${ symbology } _option_${ key } ` }
454+ defaultChecked = { value === "true" }
455+ onCheckedChange = { ( checked ) => handleSwitchChange ( key , checked ) } />
456+ < Label htmlFor = { `${ symbology } _option_${ key } ` } className = "text-sm font-medium text-foreground" >
457+ { key }
458+ </ Label >
459+ </ div >
460+ ) ;
461+ } else {
462+ return (
463+ //Text input
464+ < div key = { `${ symbology } _option_${ key } ` } className = "flex items-center" >
465+ < Label htmlFor = { `${ symbology } _option_${ key } ` } className = "text-sm font-medium text-foreground mr-4" >
466+ { key } :
467+ </ Label >
468+ < input
469+ id = { `${ symbology } _option_${ key } ` }
470+ type = "text"
471+ defaultValue = { value }
472+ onChange = { ( e ) => handleInputChange ( key , e . target . value ) }
473+ className = "w-16 border border-gray-300 rounded-lg p-1 text-sm"
474+ />
475+ </ div >
476+ ) ;
477+ }
478+ } ) }
479+ </ ul >
480+ </ >
481+ ) : (
482+ < p className = "text-gray-500 italic" > No hay opciones disponibles</ p >
483+ ) }
484+
330485 </ div >
331486 </ CardContent >
332487 </ Card >
333488 </ div >
334489
490+ { /*Errors*/ }
491+ { error && (
492+ < div className = "error-message bg-red-100 text-red-700 p-4 my-4 rounded" >
493+ < strong > Error:</ strong > { error }
494+ </ div >
495+ ) }
496+
335497 { /* Barcodes Display */ }
336498 { barcodes . length > 0 && (
337499 < Card className = "bg-card/80 backdrop-blur-sm border-border" >
0 commit comments