@@ -4,28 +4,52 @@ import { useLabelStore } from "../../store/labelStore";
44import { inputCls , labelCls } from "../ui/formStyles" ;
55import {
66 CLOCK_FORMAT_VALUES ,
7+ CLOCK_LANGUAGE_VALUES ,
8+ CLOCK_MODE_VALUES ,
9+ CLOCK_TOLERANCE_DEFAULT ,
10+ CLOCK_TOLERANCE_RANGE ,
711 isClockFormat ,
12+ isClockLanguage ,
13+ isClockMode ,
814 type ClockFormat ,
15+ type ClockLanguage ,
16+ type ClockMode ,
917} from "../../types/ObjectType" ;
1018import {
19+ BoundedIntControl ,
1120 ZplCommandLabel ,
1221 ZplEnumSelect ,
22+ ZplEnumSubSelect ,
1323 ZplField ,
24+ ZplSubField ,
1425} from "./zplFieldPrimitives" ;
1526
1627type LocClockTime = ReturnType < typeof useT > [ "printerSettings" ] [ "clockTime" ] ;
1728
18- /** Explicit value → locale-key map. `satisfies` makes both a
19- * missing enum-value entry (here) and a missing locale key (in
20- * the locale shape) compile errors — the earlier template-literal
21- * helper used an `as`-cast that bypassed the second direction. */
29+ /** Explicit value → locale-key maps for all three enums in this
30+ * tab. `satisfies` makes both a missing enum-value entry (here)
31+ * and a missing locale key (in the locale shape) compile errors. */
2232const CLOCK_FORMAT_LABEL_KEYS = {
2333 '0' : 'clockFormat0' ,
2434 '1' : 'clockFormat1' ,
2535 '2' : 'clockFormat2' ,
2636 '3' : 'clockFormat3' ,
2737} as const satisfies Record < ClockFormat , keyof LocClockTime > ;
2838
39+ const CLOCK_MODE_LABEL_KEYS = {
40+ S : 'clockModeS' ,
41+ T : 'clockModeT' ,
42+ TOL : 'clockModeTOL' ,
43+ } as const satisfies Record < ClockMode , keyof LocClockTime > ;
44+
45+ const CLOCK_LANGUAGE_LABEL_KEYS = {
46+ '1' : 'clockLanguage1' , '2' : 'clockLanguage2' , '3' : 'clockLanguage3' ,
47+ '4' : 'clockLanguage4' , '5' : 'clockLanguage5' , '6' : 'clockLanguage6' ,
48+ '7' : 'clockLanguage7' , '8' : 'clockLanguage8' , '9' : 'clockLanguage9' ,
49+ '10' : 'clockLanguage10' , '11' : 'clockLanguage11' , '12' : 'clockLanguage12' ,
50+ '13' : 'clockLanguage13' ,
51+ } as const satisfies Record < ClockLanguage , keyof LocClockTime > ;
52+
2953/** Tab 3 of the Printer Settings Modal — clock/time setup commands.
3054 * All three live in the Setup-Script output (EEPROM-persistent),
3155 * not the per-label ZPL block. ^ST is modelled as a static user-
@@ -37,6 +61,7 @@ export function ClockAndTimeTab() {
3761 const setLabelConfig = useLabelStore ( ( s ) => s . setLabelConfig ) ;
3862 const loc = t . printerSettings . clockTime ;
3963 const clockId = useId ( ) ;
64+ const modeId = useId ( ) ;
4065
4166 return (
4267 < div className = "flex flex-col gap-4" >
@@ -70,6 +95,65 @@ export function ClockAndTimeTab() {
7095 defaultLabel = { t . printerSettings . defaultOption }
7196 optionLabel = { ( m ) => loc [ CLOCK_FORMAT_LABEL_KEYS [ m ] ] }
7297 />
98+
99+ { /* All three ^SL inputs live under one parent tag — mode +
100+ (conditional) tolerance share the first positional slot,
101+ language is the second. ZplSubField keeps the per-row
102+ labels without duplicating the ^SL command tag (same
103+ pattern as ^KN name+description in IdentityTab and ^PR
104+ triple in PrintQualityTab). */ }
105+ < ZplField >
106+ < ZplCommandLabel text = { loc . clockMode } command = "^SL" htmlFor = { modeId } />
107+ < select
108+ id = { modeId }
109+ className = { inputCls }
110+ value = { label . clockMode ?? "" }
111+ onChange = { ( e ) => {
112+ const v = e . target . value ;
113+ const nextMode = isClockMode ( v ) ? v : undefined ;
114+ // Schema's cross-field rule pairs `clockMode === 'TOL'`
115+ // with a defined `clockTolerance` (and vice versa). Seed
116+ // the default the moment the user picks TOL, and clear
117+ // the tolerance the moment they leave TOL — without
118+ // this the store would briefly hold an invalid combo
119+ // (TOL without tolerance) which the schema rejects.
120+ const nextTolerance = nextMode === 'TOL'
121+ ? label . clockTolerance ?? CLOCK_TOLERANCE_DEFAULT
122+ : undefined ;
123+ setLabelConfig ( { clockMode : nextMode , clockTolerance : nextTolerance } ) ;
124+ } }
125+ >
126+ < option value = "" > { t . printerSettings . defaultOption } </ option >
127+ { CLOCK_MODE_VALUES . map ( ( m ) => (
128+ < option key = { m } value = { m } > { loc [ CLOCK_MODE_LABEL_KEYS [ m ] ] } </ option >
129+ ) ) }
130+ </ select >
131+ { label . clockMode === 'TOL' && (
132+ < ZplSubField label = { loc . clockTolerance } >
133+ { ( id ) => (
134+ < BoundedIntControl
135+ id = { id }
136+ min = { CLOCK_TOLERANCE_RANGE . min }
137+ max = { CLOCK_TOLERANCE_RANGE . max }
138+ value = { label . clockTolerance }
139+ onChange = { ( v ) => setLabelConfig ( { clockTolerance : v } ) }
140+ />
141+ ) }
142+ </ ZplSubField >
143+ ) }
144+ < ZplEnumSubSelect
145+ label = { loc . clockLanguage }
146+ values = { CLOCK_LANGUAGE_VALUES }
147+ isValid = { isClockLanguage }
148+ value = { label . clockLanguage }
149+ onChange = { ( v ) => setLabelConfig ( { clockLanguage : v } ) }
150+ defaultLabel = { t . printerSettings . defaultOption }
151+ optionLabel = { ( m ) => `${ m } – ${ loc [ CLOCK_LANGUAGE_LABEL_KEYS [ m ] ] } ` }
152+ />
153+ < span className = { `${ labelCls } normal-case tracking-normal text-muted/70` } >
154+ { loc . clockSlPersistenceHint }
155+ </ span >
156+ </ ZplField >
73157 </ div >
74158 ) ;
75159}
0 commit comments