@@ -7,16 +7,17 @@ import {
7
7
FormGroup ,
8
8
Typography ,
9
9
} from '@mui/material' ;
10
- import { useState } from 'react' ;
10
+ import { useCallback , useState } from 'react' ;
11
11
import {
12
12
AutocompleteValue ,
13
13
ComboBox ,
14
14
CustomButton ,
15
15
LanguageSelect ,
16
+ NativeSelect ,
16
17
Text ,
17
18
} from 'shared/components' ;
18
19
import { Color , Severity , TextFieldVariant , Variant } from 'shared/enums' ;
19
- import { useDialog } from 'shared/hooks' ;
20
+ import { useDialog , useWindowProperties } from 'shared/hooks' ;
20
21
21
22
import { useCommonTranslation , usePublicTranslation } from 'configs/i18n' ;
22
23
import { useAppDispatch , useAppSelector } from 'configs/redux' ;
@@ -28,6 +29,200 @@ import {
28
29
selectFilteredPublicExamSessions ,
29
30
} from 'redux/selectors/examSessions' ;
30
31
32
+ const municipalityToComboBoxOption = ( m : string ) => ( {
33
+ value : m ,
34
+ label : m ,
35
+ } ) ;
36
+
37
+ const SelectMunicipality = ( ) => {
38
+ const municipalities = useAppSelector ( examSessionsSelector ) . municipalities ;
39
+ const { municipality } = useAppSelector ( examSessionsSelector ) . filters ;
40
+ const dispatch = useAppDispatch ( ) ;
41
+ const onMunicipalityChange = useCallback (
42
+ ( municipality ?: string ) => {
43
+ dispatch ( setPublicExamSessionFilters ( { municipality } ) ) ;
44
+ } ,
45
+ [ dispatch ]
46
+ ) ;
47
+
48
+ const { t } = usePublicTranslation ( {
49
+ keyPrefix : 'yki.pages.registrationPage' ,
50
+ } ) ;
51
+ const { isPhone } = useWindowProperties ( ) ;
52
+
53
+ return (
54
+ < div className = "public-exam-session-filters__filter public-exam-session-filters__municipality" >
55
+ < Typography
56
+ variant = "h3"
57
+ component = "label"
58
+ htmlFor = "public-exam-session-filters__municipality-filter"
59
+ >
60
+ { t ( 'labels.selectMunicipality' ) }
61
+ </ Typography >
62
+ { isPhone ? (
63
+ < NativeSelect
64
+ id = "public-exam-session-filters__municipality-filter"
65
+ onChange = { ( e ) => {
66
+ onMunicipalityChange ( e . target . value as string ) ;
67
+ } }
68
+ placeholder = { t ( 'labels.selectMunicipality' ) }
69
+ value = {
70
+ municipality ? municipalityToComboBoxOption ( municipality ) : null
71
+ }
72
+ values = { municipalities . map ( municipalityToComboBoxOption ) }
73
+ />
74
+ ) : (
75
+ < ComboBox
76
+ id = "public-exam-session-filters__municipality-filter"
77
+ variant = { TextFieldVariant . Outlined }
78
+ values = { municipalities . map ( municipalityToComboBoxOption ) }
79
+ value = {
80
+ municipality ? municipalityToComboBoxOption ( municipality ) : null
81
+ }
82
+ onChange = { ( _ , v : AutocompleteValue ) => {
83
+ const municipality = v ?. value ;
84
+ onMunicipalityChange ( municipality ) ;
85
+ } }
86
+ label = { t ( 'labels.selectMunicipality' ) }
87
+ aria-label = { t ( 'labels.selectMunicipality' ) }
88
+ />
89
+ ) }
90
+ </ div >
91
+ ) ;
92
+ } ;
93
+
94
+ const SelectExamLanguage = ( {
95
+ showError,
96
+ onFilterChange,
97
+ } : {
98
+ showError : boolean ;
99
+ onFilterChange : ( filter : Partial < ExamSessionFilters > ) => void ;
100
+ } ) => {
101
+ const { language } = useAppSelector ( examSessionsSelector ) . filters ;
102
+
103
+ const { t } = usePublicTranslation ( {
104
+ keyPrefix : 'yki.pages.registrationPage' ,
105
+ } ) ;
106
+ const translateCommon = useCommonTranslation ( ) ;
107
+ const translateLanguage = ( language : string ) =>
108
+ translateCommon ( 'languages.' + language ) ;
109
+ const languages = Object . values ( ExamLanguage ) ;
110
+
111
+ return (
112
+ < FormControl
113
+ className = "public-exam-session-filters__filter"
114
+ error = { showError && ! language }
115
+ >
116
+ < Typography
117
+ variant = "h3"
118
+ component = "label"
119
+ htmlFor = "public-exam-session-filters__language-filter"
120
+ sx = { showError && ! language ? { color : 'error.main' } : { } }
121
+ >
122
+ { translateCommon ( 'language' ) } { ' ' }
123
+ < span className = "public-exam-session-filters__hint" >
124
+ { t ( 'filters.selectExamDetails.required' ) }
125
+ </ span >
126
+ </ Typography >
127
+ < LanguageSelect
128
+ id = "public-exam-session-filters__language-filter"
129
+ primaryLanguages = { [
130
+ ExamLanguage . ALL ,
131
+ ExamLanguage . FIN ,
132
+ ExamLanguage . SWE ,
133
+ ExamLanguage . ENG ,
134
+ ] }
135
+ languages = { languages }
136
+ translateLanguage = { translateLanguage }
137
+ variant = { TextFieldVariant . Outlined }
138
+ value = {
139
+ language
140
+ ? { value : language , label : translateLanguage ( language ) }
141
+ : null
142
+ }
143
+ onLanguageChange = { ( v ) => {
144
+ const language = v as ExamLanguage | undefined ;
145
+ onFilterChange ( { language } ) ;
146
+ } }
147
+ label = { t ( 'labels.selectLanguage' ) }
148
+ aria-label = { t ( 'labels.selectLanguage' ) }
149
+ showError = { showError && ! language }
150
+ helperText = { showError && ! language ? t ( 'filters.errors.required' ) : '' }
151
+ />
152
+ </ FormControl >
153
+ ) ;
154
+ } ;
155
+
156
+ const SelectExamLevel = ( {
157
+ showError,
158
+ onFilterChange,
159
+ } : {
160
+ showError : boolean ;
161
+ onFilterChange : ( filter : Partial < ExamSessionFilters > ) => void ;
162
+ } ) => {
163
+ const { level } = useAppSelector ( examSessionsSelector ) . filters ;
164
+
165
+ const translateCommon = useCommonTranslation ( ) ;
166
+ const { t } = usePublicTranslation ( {
167
+ keyPrefix : 'yki.pages.registrationPage' ,
168
+ } ) ;
169
+
170
+ const levelToComboBoxOption = ( v : ExamLevel ) => ( {
171
+ value : v . toString ( ) ,
172
+ label : translateCommon ( 'languageLevel.' + v . toString ( ) ) ,
173
+ } ) ;
174
+ const levelValues = Object . values ( ExamLevel ) . map ( levelToComboBoxOption ) ;
175
+
176
+ const errorStyles = { color : 'error.main' } ;
177
+ const { isPhone } = useWindowProperties ( ) ;
178
+
179
+ return (
180
+ < FormControl
181
+ className = "public-exam-session-filters__filter"
182
+ error = { showError && ! level }
183
+ >
184
+ < Typography
185
+ variant = "h3"
186
+ component = "label"
187
+ htmlFor = "public-exam-session-filters__level-filter"
188
+ sx = { showError && ! level ? errorStyles : { } }
189
+ >
190
+ { translateCommon ( 'level' ) } { ' ' }
191
+ < span className = "public-exam-session-filters__hint" >
192
+ { t ( 'filters.selectExamDetails.required' ) }
193
+ </ span >
194
+ </ Typography >
195
+ { isPhone ? (
196
+ < NativeSelect
197
+ id = "public-exam-session-filters__level-filter"
198
+ onChange = { ( e ) => {
199
+ const level = e . target . value as ExamLevel | undefined ;
200
+ onFilterChange ( { level } ) ;
201
+ } }
202
+ placeholder = { t ( 'labels.selectLevel' ) }
203
+ value = { level ? levelToComboBoxOption ( level ) : null }
204
+ values = { levelValues }
205
+ />
206
+ ) : (
207
+ < ComboBox
208
+ id = "public-exam-session-filters__level-filter"
209
+ variant = { TextFieldVariant . Outlined }
210
+ values = { levelValues }
211
+ value = { level ? levelToComboBoxOption ( level ) : null }
212
+ onChange = { ( _ , v : AutocompleteValue ) => {
213
+ const level = v ?. value as ExamLevel | undefined ;
214
+ onFilterChange ( { level } ) ;
215
+ } }
216
+ label = { t ( 'labels.selectLevel' ) }
217
+ aria-label = { t ( 'labels.selectLevel' ) }
218
+ showError = { showError && ! level }
219
+ helperText = { showError && ! level ? t ( 'filters.errors.required' ) : '' }
220
+ />
221
+ ) }
222
+ </ FormControl >
223
+ ) ;
224
+ } ;
225
+
31
226
export const PublicExamSessionFilters = ( {
32
227
onApplyFilters,
33
228
} : {
@@ -41,15 +236,9 @@ export const PublicExamSessionFilters = ({
41
236
42
237
const { showDialog } = useDialog ( ) ;
43
238
44
- const { filters, municipalities } = useAppSelector ( examSessionsSelector ) ;
45
239
const filteredExamSessions = useAppSelector ( selectFilteredPublicExamSessions ) ;
46
- const {
47
- language,
48
- level,
49
- municipality,
50
- excludeFullSessions,
51
- excludeNonOpenSessions,
52
- } = filters ;
240
+ const { language, level, excludeFullSessions, excludeNonOpenSessions } =
241
+ useAppSelector ( examSessionsSelector ) . filters ;
53
242
54
243
const dispatch = useAppDispatch ( ) ;
55
244
const onFilterChange = ( filter : Partial < ExamSessionFilters > ) => {
@@ -59,7 +248,7 @@ export const PublicExamSessionFilters = ({
59
248
const [ showError , setShowError ] = useState ( false ) ;
60
249
61
250
const handleSubmitBtnClick = ( ) => {
62
- if ( ! filters . language || ! filters . level ) {
251
+ if ( ! language || ! level ) {
63
252
setShowError ( true ) ;
64
253
showDialog ( {
65
254
severity : Severity . Error ,
@@ -78,22 +267,6 @@ export const PublicExamSessionFilters = ({
78
267
}
79
268
} ;
80
269
81
- const languages = Object . values ( ExamLanguage ) ;
82
- const translateLanguage = ( language : string ) =>
83
- translateCommon ( 'languages.' + language ) ;
84
-
85
- const levelToComboBoxOption = ( v : ExamLevel ) => ( {
86
- value : v . toString ( ) ,
87
- label : translateCommon ( 'languageLevel.' + v . toString ( ) ) ,
88
- } ) ;
89
- const levelValues = Object . values ( ExamLevel ) . map ( levelToComboBoxOption ) ;
90
- const municipalityToComboBoxOption = ( m : string ) => ( {
91
- value : m ,
92
- label : m ,
93
- } ) ;
94
-
95
- const errorStyles = { color : 'error.main' } ;
96
-
97
270
return (
98
271
< div className = "public-exam-session-filters" >
99
272
< div className = "public-exam-session-filters__dropdown-filters-container" >
@@ -104,106 +277,17 @@ export const PublicExamSessionFilters = ({
104
277
</ Text >
105
278
</ legend >
106
279
< div className = "public-exam-session-filters__dropdown-filters-box" >
107
- < FormControl
108
- className = "public-exam-session-filters__filter"
109
- error = { showError && ! language }
110
- >
111
- < Typography
112
- variant = "h3"
113
- component = "label"
114
- htmlFor = "public-exam-session-filters__language-filter"
115
- sx = { showError && ! language ? { color : 'error.main' } : { } }
116
- >
117
- { translateCommon ( 'language' ) } { ' ' }
118
- < span className = "public-exam-session-filters__hint" >
119
- { t ( 'filters.selectExamDetails.required' ) }
120
- </ span >
121
- </ Typography >
122
- < LanguageSelect
123
- id = "public-exam-session-filters__language-filter"
124
- primaryLanguages = { [
125
- ExamLanguage . ALL ,
126
- ExamLanguage . FIN ,
127
- ExamLanguage . SWE ,
128
- ExamLanguage . ENG ,
129
- ] }
130
- languages = { languages }
131
- translateLanguage = { translateLanguage }
132
- variant = { TextFieldVariant . Outlined }
133
- value = {
134
- language
135
- ? { value : language , label : translateLanguage ( language ) }
136
- : null
137
- }
138
- onChange = { ( _ , v : AutocompleteValue ) => {
139
- const language = v ?. value as ExamLanguage | undefined ;
140
- onFilterChange ( { language } ) ;
141
- } }
142
- label = { t ( 'labels.selectLanguage' ) }
143
- aria-label = { t ( 'labels.selectLanguage' ) }
144
- showError = { showError && ! language }
145
- helperText = {
146
- showError && ! language ? t ( 'filters.errors.required' ) : ''
147
- }
148
- />
149
- </ FormControl >
150
- < FormControl
151
- className = "public-exam-session-filters__filter"
152
- error = { showError && ! level }
153
- >
154
- < Typography
155
- variant = "h3"
156
- component = "label"
157
- htmlFor = "public-exam-session-filters__level-filter"
158
- sx = { showError && ! level ? errorStyles : { } }
159
- >
160
- { translateCommon ( 'level' ) } { ' ' }
161
- < span className = "public-exam-session-filters__hint" >
162
- { t ( 'filters.selectExamDetails.required' ) }
163
- </ span >
164
- </ Typography >
165
- < ComboBox
166
- id = "public-exam-session-filters__level-filter"
167
- variant = { TextFieldVariant . Outlined }
168
- values = { levelValues }
169
- value = { level ? levelToComboBoxOption ( level ) : null }
170
- onChange = { ( _ , v : AutocompleteValue ) => {
171
- const level = v ?. value as ExamLevel | undefined ;
172
- onFilterChange ( { level } ) ;
173
- } }
174
- label = { t ( 'labels.selectLevel' ) }
175
- aria-label = { t ( 'labels.selectLevel' ) }
176
- showError = { showError && ! level }
177
- helperText = {
178
- showError && ! level ? t ( 'filters.errors.required' ) : ''
179
- }
180
- />
181
- </ FormControl >
280
+ < SelectExamLanguage
281
+ showError = { showError }
282
+ onFilterChange = { onFilterChange }
283
+ />
284
+ < SelectExamLevel
285
+ showError = { showError }
286
+ onFilterChange = { onFilterChange }
287
+ />
182
288
</ div >
183
289
</ fieldset >
184
- < div className = "public-exam-session-filters__filter public-exam-session-filters__municipality" >
185
- < Typography
186
- variant = "h3"
187
- component = "label"
188
- htmlFor = "public-exam-session-filters__municipality-filter"
189
- >
190
- { t ( 'labels.selectMunicipality' ) }
191
- </ Typography >
192
- < ComboBox
193
- id = "public-exam-session-filters__municipality-filter"
194
- variant = { TextFieldVariant . Outlined }
195
- values = { municipalities . map ( municipalityToComboBoxOption ) }
196
- value = {
197
- municipality ? municipalityToComboBoxOption ( municipality ) : null
198
- }
199
- onChange = { ( _ , v : AutocompleteValue ) => {
200
- const municipality = v ?. value ;
201
- onFilterChange ( { municipality } ) ;
202
- } }
203
- label = { t ( 'labels.selectMunicipality' ) }
204
- aria-label = { t ( 'labels.selectMunicipality' ) }
205
- />
206
- </ div >
290
+ < SelectMunicipality />
207
291
</ div >
208
292
< Box className = "public-exam-session-filters__toggle-box" >
209
293
< FormControl component = "fieldset" variant = { TextFieldVariant . Standard } >
0 commit comments