@@ -70,13 +70,19 @@ function getTimeAxisLabels(timeUnit, startDate, endDate) {
7070 current . add ( 1 , 'week' ) ;
7171 }
7272 } else if ( timeUnit === 'last6months' ) {
73- let current = end . clone ( ) . startOf ( 'month' ) . subtract ( 5 , 'month' ) ;
73+ let current = end
74+ . clone ( )
75+ . startOf ( 'month' )
76+ . subtract ( 5 , 'month' ) ;
7477 for ( let k = 0 ; k < 6 ; k += 1 ) {
7578 labels . push ( current . format ( 'MMM YYYY' ) ) ;
7679 current . add ( 1 , 'month' ) ;
7780 }
7881 } else if ( timeUnit === 'year' ) {
79- let current = end . clone ( ) . startOf ( 'month' ) . subtract ( 11 , 'month' ) ;
82+ let current = end
83+ . clone ( )
84+ . startOf ( 'month' )
85+ . subtract ( 11 , 'month' ) ;
8086 for ( let k = 0 ; k < 12 ; k += 1 ) {
8187 labels . push ( current . format ( 'MMM YYYY' ) ) ;
8288 current . add ( 1 , 'month' ) ;
@@ -107,7 +113,9 @@ function buildFilterKey(category, selectedVillages, selectedProperties) {
107113// Generate mock chart data (replace with API when backend is ready)
108114function generateMockData ( timeUnit , startDate , endDate , filterKey ) {
109115 const labels = getTimeAxisLabels ( timeUnit , startDate , endDate ) ;
110- const rangeKey = `${ moment ( startDate ) . format ( 'YYYY-MM-DD' ) } |${ moment ( endDate ) . format ( 'YYYY-MM-DD' ) } ` ;
116+ const rangeKey = `${ moment ( startDate ) . format ( 'YYYY-MM-DD' ) } |${ moment ( endDate ) . format (
117+ 'YYYY-MM-DD' ,
118+ ) } `;
111119 const baseSeed = hashString ( `${ timeUnit } |${ rangeKey } |${ filterKey } ` ) ;
112120
113121 return labels . map ( ( label , i ) => {
@@ -118,12 +126,8 @@ function generateMockData(timeUnit, startDate, endDate, filterKey) {
118126 const vacancyJitter = unitNoise ( rowSeed , 'v' ) * 14 ;
119127 return {
120128 time : label ,
121- cancellationRate : Math . round (
122- Math . max ( 0 , Math . min ( 55 , 5 + cancelWave + cancelJitter ) ) ,
123- ) ,
124- vacancyRate : Math . round (
125- Math . max ( 0 , Math . min ( 55 , 12 + vacancyWave + vacancyJitter ) ) ,
126- ) ,
129+ cancellationRate : Math . round ( Math . max ( 0 , Math . min ( 55 , 5 + cancelWave + cancelJitter ) ) ) ,
130+ vacancyRate : Math . round ( Math . max ( 0 , Math . min ( 55 , 12 + vacancyWave + vacancyJitter ) ) ) ,
127131 } ;
128132 } ) ;
129133}
@@ -164,7 +168,9 @@ const customSelectStyles = darkMode => ({
164168} ) ;
165169
166170function CancellationImpactOnVacancy ( { darkMode } ) {
167- const defaultStart = moment ( ) . subtract ( 6 , 'months' ) . toDate ( ) ;
171+ const defaultStart = moment ( )
172+ . subtract ( 6 , 'months' )
173+ . toDate ( ) ;
168174 const defaultEnd = moment ( ) . toDate ( ) ;
169175
170176 const [ startDate , setStartDate ] = useState ( defaultStart ) ;
@@ -197,7 +203,9 @@ function CancellationImpactOnVacancy({ darkMode }) {
197203 ] ) ;
198204 }
199205 } ) ( ) ;
200- return ( ) => { mounted = false ; } ;
206+ return ( ) => {
207+ mounted = false ;
208+ } ;
201209 } , [ ] ) ;
202210
203211 // Mock property options (grouped by village for now)
@@ -211,15 +219,18 @@ function CancellationImpactOnVacancy({ darkMode }) {
211219 setPropertyOptions ( props ) ;
212220 } , [ ] ) ;
213221
214- const filterKey = useMemo (
215- ( ) => buildFilterKey ( category , selectedVillages , selectedProperties ) ,
216- [ category , selectedVillages , selectedProperties ] ,
217- ) ;
222+ const filterKey = useMemo ( ( ) => buildFilterKey ( category , selectedVillages , selectedProperties ) , [
223+ category ,
224+ selectedVillages ,
225+ selectedProperties ,
226+ ] ) ;
218227
219- const chartData = useMemo (
220- ( ) => generateMockData ( timeUnit , startDate , endDate , filterKey ) ,
221- [ timeUnit , startDate , endDate , filterKey ] ,
222- ) ;
228+ const chartData = useMemo ( ( ) => generateMockData ( timeUnit , startDate , endDate , filterKey ) , [
229+ timeUnit ,
230+ startDate ,
231+ endDate ,
232+ filterKey ,
233+ ] ) ;
223234
224235 const xAxisLabel = useMemo ( ( ) => {
225236 if ( timeUnit === 'week' ) return 'Days' ;
@@ -236,12 +247,17 @@ function CancellationImpactOnVacancy({ darkMode }) {
236247 </ div >
237248
238249 < div className = { `${ styles . filters } ${ darkMode ? styles . darkFilters : '' } ` } >
239- < div className = { styles . filterGroup } >
240- < label className = { `${ styles . filterLabel } ${ darkMode ? styles . darkFilterLabel : '' } ` } >
250+ < fieldset className = { `${ styles . filterGroup } ${ styles . filterGroupFieldset } ` } >
251+ < legend
252+ className = { `${ styles . filterLegend } ${ styles . filterLabel } ${
253+ darkMode ? styles . darkFilterLabel : ''
254+ } `}
255+ >
241256 Dates
242- </ label >
257+ </ legend >
243258 < div className = { styles . dateRange } >
244259 < DatePicker
260+ id = "cancellation-impact-start-date"
245261 selected = { startDate }
246262 onChange = { date => setStartDate ( date ) }
247263 selectsStart
@@ -252,6 +268,7 @@ function CancellationImpactOnVacancy({ darkMode }) {
252268 />
253269 < span className = { styles . dateSeparator } > to</ span >
254270 < DatePicker
271+ id = "cancellation-impact-end-date"
255272 selected = { endDate }
256273 onChange = { date => setEndDate ( date ) }
257274 selectsEnd
@@ -262,13 +279,17 @@ function CancellationImpactOnVacancy({ darkMode }) {
262279 className = { darkMode ? styles . datePickerDark : styles . datePicker }
263280 />
264281 </ div >
265- </ div >
282+ </ fieldset >
266283
267284 < div className = { styles . filterGroup } >
268- < label className = { `${ styles . filterLabel } ${ darkMode ? styles . darkFilterLabel : '' } ` } >
285+ < label
286+ className = { `${ styles . filterLabel } ${ darkMode ? styles . darkFilterLabel : '' } ` }
287+ htmlFor = "cancellation-impact-category"
288+ >
269289 Category
270290 </ label >
271291 < select
292+ id = "cancellation-impact-category"
272293 value = { category }
273294 onChange = { e => {
274295 setCategory ( e . target . value ) ;
@@ -286,11 +307,19 @@ function CancellationImpactOnVacancy({ darkMode }) {
286307 </ div >
287308
288309 < div className = { styles . filterGroup } >
289- < label className = { `${ styles . filterLabel } ${ darkMode ? styles . darkFilterLabel : '' } ` } >
310+ < label
311+ className = { `${ styles . filterLabel } ${ darkMode ? styles . darkFilterLabel : '' } ` }
312+ htmlFor = {
313+ category === 'village'
314+ ? 'cancellation-impact-villages-select'
315+ : 'cancellation-impact-properties-select'
316+ }
317+ >
290318 { category === 'village' ? 'Villages' : 'Properties' }
291319 </ label >
292320 { category === 'village' ? (
293321 < Select
322+ inputId = "cancellation-impact-villages-select"
294323 isMulti
295324 options = { villageOptions }
296325 value = { selectedVillages }
@@ -301,6 +330,7 @@ function CancellationImpactOnVacancy({ darkMode }) {
301330 />
302331 ) : (
303332 < Select
333+ inputId = "cancellation-impact-properties-select"
304334 isMulti
305335 options = { propertyOptions }
306336 value = { selectedProperties }
@@ -313,10 +343,14 @@ function CancellationImpactOnVacancy({ darkMode }) {
313343 </ div >
314344
315345 < div className = { styles . filterGroup } >
316- < label className = { `${ styles . filterLabel } ${ darkMode ? styles . darkFilterLabel : '' } ` } >
346+ < label
347+ className = { `${ styles . filterLabel } ${ darkMode ? styles . darkFilterLabel : '' } ` }
348+ htmlFor = "cancellation-impact-time-unit"
349+ >
317350 X-axis units
318351 </ label >
319352 < select
353+ id = "cancellation-impact-time-unit"
320354 value = { timeUnit }
321355 onChange = { e => setTimeUnit ( e . target . value ) }
322356 className = { `${ styles . select } ${ darkMode ? styles . selectDark : '' } ` }
0 commit comments