1- import { useState } from 'react' ;
1+ import { useState , useEffect } from 'react' ;
22import { BaseSettingsSection } from '../components/BaseSettingsSection' ;
33import { useDashboard } from '@irdashies/context' ;
44import {
55 BlindSpotMonitorWidgetSettings ,
66 SessionVisibilitySettings ,
7+ SettingsTabType ,
78} from '../types' ;
89import { SessionVisibility } from '../components/SessionVisibility' ;
910import { ToggleSwitch } from '../components/ToggleSwitch' ;
11+ import { TabButton } from '../components/TabButton' ;
1012
1113const SETTING_ID = 'blindspotmonitor' ;
1214
@@ -61,6 +63,15 @@ export const BlindSpotMonitorSettings = () => {
6163 config : migrateConfig ( savedSettings ?. config ) ,
6264 } ) ;
6365
66+ // Tab state with persistence
67+ const [ activeTab , setActiveTab ] = useState < SettingsTabType > (
68+ ( ) => ( localStorage . getItem ( 'bsmTab' ) as SettingsTabType ) || 'display'
69+ ) ;
70+
71+ useEffect ( ( ) => {
72+ localStorage . setItem ( 'bsmTab' , activeTab ) ;
73+ } , [ activeTab ] ) ;
74+
6475 if ( ! currentDashboard ) {
6576 return < > Loading...</ > ;
6677 }
@@ -75,128 +86,166 @@ export const BlindSpotMonitorSettings = () => {
7586 >
7687 { ( handleConfigChange ) => (
7788 < div className = "space-y-4" >
78- { /* Background Opacity */ }
79- < div className = "space-y-2" >
80- < label className = "text-slate-300" >
81- Background Opacity: { settings . config . background ?. opacity ?? 30 } %
82- </ label >
83- < input
84- type = "range"
85- min = "0"
86- max = "100"
87- step = "5"
88- value = { settings . config . background ?. opacity ?? 30 }
89- onChange = { ( e ) =>
90- handleConfigChange ( {
91- background : { opacity : parseInt ( e . target . value ) } ,
92- } )
93- }
94- className = "w-full"
95- />
96- </ div >
9789
98- { /* Distance Ahead */ }
99- < div className = "space-y-2" >
100- < label className = "text-slate-300" >
101- Distance Ahead: { settings . config . distAhead } m
102- </ label >
103- < input
104- type = "range"
105- min = "3"
106- max = "6"
107- step = "0.1"
108- value = { settings . config . distAhead }
109- onChange = { ( e ) =>
110- handleConfigChange ( { distAhead : parseFloat ( e . target . value ) } )
111- }
112- className = "w-full"
113- />
114- < p className = "text-slate-400 text-sm" >
115- Distance to car ahead in meters. Distance at which point line
116- starts to appear at the top.
117- </ p >
90+ { /* Tabs */ }
91+ < div className = "flex border-b border-slate-700/50" >
92+ < TabButton id = "display" activeTab = { activeTab } setActiveTab = { setActiveTab } >
93+ Display
94+ </ TabButton >
95+ < TabButton id = "options" activeTab = { activeTab } setActiveTab = { setActiveTab } >
96+ Options
97+ </ TabButton >
98+ < TabButton id = "visibility" activeTab = { activeTab } setActiveTab = { setActiveTab } >
99+ Visibility
100+ </ TabButton >
118101 </ div >
119102
120- { /* Distance Behind */ }
121- < div className = "space-y-2" >
122- < label className = "text-slate-300" >
123- Distance Behind: { settings . config . distBehind } m
124- </ label >
125- < input
126- type = "range"
127- min = "3"
128- max = "6"
129- step = "0.1"
130- value = { settings . config . distBehind }
131- onChange = { ( e ) =>
132- handleConfigChange ( { distBehind : parseFloat ( e . target . value ) } )
133- }
134- className = "w-full"
135- />
136- < p className = "text-slate-400 text-sm" >
137- Distance to car behind in meters. Distance at which point line
138- starts to appear at the bottom.
139- </ p >
140- </ div >
103+ < div className = "pt-4" >
141104
142- { /* Width */ }
143- < div className = "space-y-2" >
144- < label className = "text-slate-300" >
145- Width: { settings . config . width ?? 20 } px
146- </ label >
147- < input
148- type = "range"
149- min = "5"
150- max = "100"
151- step = "1"
152- value = { settings . config . width ?? 20 }
153- onChange = { ( e ) =>
154- handleConfigChange ( { width : parseInt ( e . target . value ) } )
155- }
156- className = "w-full"
157- />
158- < p className = "text-slate-400 text-sm" >
159- Width of the blind spot indicator in pixels.
160- </ p >
161- </ div >
105+ { /* DISPLAY TAB */ }
106+ { activeTab === 'display' && (
107+ < div className = "space-y-4" >
108+ < h3 className = "text-lg font-medium text-slate-200" > Display</ h3 >
109+ < div className = "pl-4 space-y-4" >
162110
163- { /* IsOnTrack Section */ }
164- < div className = "flex items-center justify-between" >
165- < div >
166- < h4 className = "text-md font-medium text-slate-300" >
167- Show only when on track
168- </ h4 >
169- < span className = "block text-xs text-slate-500" >
170- If enabled, blind spotter will only be shown when you are
171- driving.
172- </ span >
173- </ div >
174- < ToggleSwitch
175- enabled = { settings . config . showOnlyWhenOnTrack }
176- onToggle = { ( newValue ) =>
177- handleConfigChange ( {
178- showOnlyWhenOnTrack : newValue ,
179- } )
180- }
181- />
182- </ div >
111+ { /* Background Opacity */ }
112+ < div className = "space-y-2" >
113+ < label className = "text-slate-300" >
114+ Background Opacity: { settings . config . background ?. opacity ?? 30 } %
115+ </ label >
116+ < input
117+ type = "range"
118+ min = "0"
119+ max = "100"
120+ step = "5"
121+ value = { settings . config . background ?. opacity ?? 30 }
122+ onChange = { ( e ) =>
123+ handleConfigChange ( {
124+ background : { opacity : parseInt ( e . target . value ) } ,
125+ } )
126+ }
127+ className = "w-full"
128+ />
129+ </ div >
130+
131+ { /* Width */ }
132+ < div className = "space-y-2" >
133+ < label className = "text-slate-300" >
134+ Width: { settings . config . width ?? 20 } px
135+ </ label >
136+ < input
137+ type = "range"
138+ min = "5"
139+ max = "100"
140+ step = "1"
141+ value = { settings . config . width ?? 20 }
142+ onChange = { ( e ) =>
143+ handleConfigChange ( { width : parseInt ( e . target . value ) } )
144+ }
145+ className = "w-full"
146+ />
147+ < p className = "text-xs text-slate-500" >
148+ Width of the blind spot indicator in pixels.
149+ </ p >
150+ </ div >
151+
152+ </ div >
153+ </ div >
154+ ) }
155+
156+ { /* OPTIONS TAB */ }
157+ { activeTab === 'options' && (
158+ < div className = "space-y-4" >
159+ < h3 className = "text-lg font-medium text-slate-200" > Options</ h3 >
160+ < div className = "pl-4 space-y-4" >
161+
162+ { /* Distance Ahead */ }
163+ < div className = "space-y-2" >
164+ < label className = "text-slate-300" >
165+ Distance Ahead: { settings . config . distAhead } m
166+ </ label >
167+ < input
168+ type = "range"
169+ min = "3"
170+ max = "6"
171+ step = "0.1"
172+ value = { settings . config . distAhead }
173+ onChange = { ( e ) =>
174+ handleConfigChange ( { distAhead : parseFloat ( e . target . value ) } )
175+ }
176+ className = "w-full"
177+ />
178+ < p className = "text-xs text-slate-500" >
179+ Distance to car ahead in meters.
180+ </ p >
181+ </ div >
182+
183+ { /* Distance Behind */ }
184+ < div className = "space-y-2" >
185+ < label className = "text-slate-300" >
186+ Distance Behind: { settings . config . distBehind } m
187+ </ label >
188+ < input
189+ type = "range"
190+ min = "3"
191+ max = "6"
192+ step = "0.1"
193+ value = { settings . config . distBehind }
194+ onChange = { ( e ) =>
195+ handleConfigChange ( { distBehind : parseFloat ( e . target . value ) } )
196+ }
197+ className = "w-full"
198+ />
199+ < p className = "text-xs text-slate-500" >
200+ Distance to car behind in meters.
201+ </ p >
202+ </ div >
203+
204+ </ div >
205+ </ div >
206+ ) }
207+
208+ { /* VISIBILITY TAB */ }
209+ { activeTab === 'visibility' && (
210+ < div className = "space-y-4" >
211+
212+ < div className = "space-y-4" >
213+ < h3 className = "text-lg font-medium text-slate-200" >
214+ Session Visibility
215+ </ h3 >
216+ < div className = "space-y-3 pl-4" >
217+ < SessionVisibility
218+ sessionVisibility = { settings . config . sessionVisibility }
219+ handleConfigChange = { handleConfigChange }
220+ />
221+ </ div >
222+ </ div >
223+
224+ < div className = "flex items-center justify-between pt-4 border-t border-slate-700/50 pl-4" >
225+ < div >
226+ < h4 className = "text-md font-medium text-slate-300" >
227+ Show only when on track
228+ </ h4 >
229+ < span className = "block text-xs text-slate-500" >
230+ If enabled, blind spotter will only be shown when driving.
231+ </ span >
232+ </ div >
233+ < ToggleSwitch
234+ enabled = { settings . config . showOnlyWhenOnTrack }
235+ onToggle = { ( newValue ) =>
236+ handleConfigChange ( {
237+ showOnlyWhenOnTrack : newValue ,
238+ } )
239+ }
240+ />
241+ </ div >
242+
243+ </ div >
244+ ) }
183245
184- { /* Session Visibility Settings */ }
185- < div className = "space-y-4" >
186- < div className = "flex items-center justify-between" >
187- < h3 className = "text-lg font-medium text-slate-200" >
188- Session Visibility
189- </ h3 >
190- </ div >
191- < div className = "space-y-3 pl-4" >
192- < SessionVisibility
193- sessionVisibility = { settings . config . sessionVisibility }
194- handleConfigChange = { handleConfigChange }
195- />
196- </ div >
197246 </ div >
198247 </ div >
199248 ) }
200249 </ BaseSettingsSection >
201250 ) ;
202- } ;
251+ } ;
0 commit comments