1
- import { supportedLngs } from '@app-builder/services/i18n/i18n-config' ;
1
+ import {
2
+ sampleDateFormats ,
3
+ sampleHoursFormats ,
4
+ supportedLngs ,
5
+ } from '@app-builder/services/i18n/i18n-config' ;
2
6
import { initServerServices } from '@app-builder/services/init.server' ;
3
7
import { parseForm } from '@app-builder/utils/input-validation' ;
4
8
import { getRoute } from '@app-builder/utils/routes' ;
5
- import { type ActionFunctionArgs , json } from '@remix-run/node' ;
9
+ import { type ActionFunctionArgs } from '@remix-run/node' ;
6
10
import { useFetcher } from '@remix-run/react' ;
7
11
import { useTranslation } from 'react-i18next' ;
8
12
import { redirectBack } from 'remix-utils/redirect-back' ;
9
- import { Select } from 'ui-design-system' ;
13
+ import { Button , MenuCommand } from 'ui-design-system' ;
10
14
import * as z from 'zod' ;
11
15
12
16
import { setToastMessage } from '../../../components/MarbleToaster' ;
17
+ import { useFormatPreferencesHook } from '../../../utils/format' ;
13
18
14
19
const formSchema = z . object ( {
15
- preferredLanguage : z . enum ( supportedLngs ) ,
20
+ preferredLanguage : z . enum ( supportedLngs ) . optional ( ) ,
21
+ preferredDate : z . enum ( Object . keys ( sampleDateFormats ) as [ string , ...string [ ] ] ) . optional ( ) ,
22
+ preferredHours : z . enum ( Object . keys ( sampleHoursFormats ) as [ string , ...string [ ] ] ) . optional ( ) ,
16
23
} ) ;
17
24
25
+ // Helper function to get human-readable language names
26
+ function getLanguageDisplayName ( languageCode : string ) : string {
27
+ const languageNames : Record < string , string > = {
28
+ en : 'English' ,
29
+ fr : 'Français' ,
30
+ ar : 'العربية' ,
31
+ } ;
32
+
33
+ return languageNames [ languageCode ] ?? languageCode ;
34
+ }
35
+
18
36
export async function action ( { request } : ActionFunctionArgs ) {
19
37
const { i18nextService, toastSessionService } = initServerServices ( request ) ;
20
38
21
39
try {
22
- const { preferredLanguage } = await parseForm ( request , formSchema ) ;
40
+ const { preferredLanguage, preferredDate, preferredHours } = await parseForm (
41
+ request ,
42
+ formSchema ,
43
+ ) ;
44
+
45
+ const headers = new Headers ( ) ;
23
46
24
- const { cookie } = await i18nextService . setLanguage ( request , preferredLanguage ) ;
47
+ // Set language if provided
48
+ if ( preferredLanguage ) {
49
+ const { cookie } = await i18nextService . setLanguage ( request , preferredLanguage ) ;
50
+ headers . append ( 'Set-Cookie' , cookie ) ;
51
+ }
52
+
53
+ // Set date format if provided
54
+ if ( preferredDate ) {
55
+ const { cookie } = await i18nextService . setDateFormat ( request , preferredDate ) ;
56
+ headers . append ( 'Set-Cookie' , cookie ) ;
57
+ }
58
+
59
+ // Set hours format if provided
60
+ if ( preferredHours ) {
61
+ const { cookie } = await i18nextService . setHoursFormat ( request , preferredHours ) ;
62
+ headers . append ( 'Set-Cookie' , cookie ) ;
63
+ }
25
64
26
65
return redirectBack ( request , {
27
66
fallback : getRoute ( '/scenarios' ) ,
28
- headers : {
29
- 'Set-Cookie' : cookie ,
30
- } ,
67
+ headers,
31
68
} ) ;
32
69
} catch ( _error ) {
33
70
const toastSession = await toastSessionService . getSession ( request ) ;
@@ -36,7 +73,7 @@ export async function action({ request }: ActionFunctionArgs) {
36
73
messageKey : 'common:errors.unknown' ,
37
74
} ) ;
38
75
39
- return json (
76
+ return Response . json (
40
77
{
41
78
success : false as const ,
42
79
} ,
@@ -56,27 +93,99 @@ export function LanguagePicker() {
56
93
const {
57
94
i18n : { language } ,
58
95
} = useTranslation < 'common' > ( ) ;
96
+ const formatPreferences = useFormatPreferencesHook ( ) ;
59
97
const fetcher = useFetcher < typeof action > ( ) ;
60
98
61
99
if ( supportedLngs . every ( ( lng : string ) => lng . startsWith ( 'en' ) ) ) return null ;
62
100
101
+ console . log ( 'language' , language ) ;
63
102
return (
64
- < Select . Default
65
- value = { language }
66
- onValueChange = { ( newPreferredLanguage ) => {
67
- fetcher . submit (
68
- { preferredLanguage : newPreferredLanguage } ,
69
- { method : 'POST' , action : getRoute ( '/ressources/user/language' ) } ,
70
- ) ;
71
- } }
72
- >
73
- { supportedLngs . map ( ( lng ) => {
74
- return (
75
- < Select . DefaultItem key = { lng } value = { lng } >
76
- { lng }
77
- </ Select . DefaultItem >
78
- ) ;
79
- } ) }
80
- </ Select . Default >
103
+ < div className = "flex flex-col gap-2" >
104
+ < MenuCommand . Menu >
105
+ < MenuCommand . Trigger >
106
+ < Button variant = "secondary" className = "h-10 gap-2" >
107
+ { getLanguageDisplayName ( language ) }
108
+ < MenuCommand . Arrow />
109
+ </ Button >
110
+ </ MenuCommand . Trigger >
111
+ < MenuCommand . Content sameWidth >
112
+ < MenuCommand . List >
113
+ { supportedLngs . map ( ( lng ) => {
114
+ return (
115
+ < MenuCommand . Item
116
+ key = { lng }
117
+ value = { lng }
118
+ onSelect = { ( selectedLanguage ) => {
119
+ fetcher . submit (
120
+ { preferredLanguage : selectedLanguage } ,
121
+ { method : 'POST' , action : getRoute ( '/ressources/user/language' ) } ,
122
+ ) ;
123
+ } }
124
+ >
125
+ { getLanguageDisplayName ( lng ) }
126
+ </ MenuCommand . Item >
127
+ ) ;
128
+ } ) }
129
+ </ MenuCommand . List >
130
+ </ MenuCommand . Content >
131
+ </ MenuCommand . Menu >
132
+ < MenuCommand . Menu >
133
+ < MenuCommand . Trigger >
134
+ < Button variant = "secondary" className = "h-10 gap-2" >
135
+ { formatPreferences . dateFormatDisplay || 'Unknown Format' }
136
+ < MenuCommand . Arrow />
137
+ </ Button >
138
+ </ MenuCommand . Trigger >
139
+ < MenuCommand . Content sameWidth >
140
+ < MenuCommand . List >
141
+ { Object . values ( sampleDateFormats ) . map ( ( dateFormat ) => {
142
+ return (
143
+ < MenuCommand . Item
144
+ key = { dateFormat . value }
145
+ value = { dateFormat . value }
146
+ onSelect = { ( selectedDate ) => {
147
+ fetcher . submit (
148
+ { preferredDate : selectedDate } ,
149
+ { method : 'POST' , action : getRoute ( '/ressources/user/language' ) } ,
150
+ ) ;
151
+ } }
152
+ >
153
+ { dateFormat . displayName }
154
+ </ MenuCommand . Item >
155
+ ) ;
156
+ } ) }
157
+ </ MenuCommand . List >
158
+ </ MenuCommand . Content >
159
+ </ MenuCommand . Menu >
160
+ < MenuCommand . Menu >
161
+ < MenuCommand . Trigger >
162
+ < Button variant = "secondary" className = "h-10 gap-2" >
163
+ { formatPreferences . hoursFormatDisplay || 'Unknown Format' }
164
+ < MenuCommand . Arrow />
165
+ </ Button >
166
+ </ MenuCommand . Trigger >
167
+
168
+ < MenuCommand . Content sameWidth >
169
+ < MenuCommand . List >
170
+ { Object . values ( sampleHoursFormats ) . map ( ( hoursFormat ) => {
171
+ return (
172
+ < MenuCommand . Item
173
+ key = { hoursFormat . value }
174
+ value = { hoursFormat . value }
175
+ onSelect = { ( selectedHours ) => {
176
+ fetcher . submit (
177
+ { preferredHours : selectedHours } ,
178
+ { method : 'POST' , action : getRoute ( '/ressources/user/language' ) } ,
179
+ ) ;
180
+ } }
181
+ >
182
+ { hoursFormat . displayName }
183
+ </ MenuCommand . Item >
184
+ ) ;
185
+ } ) }
186
+ </ MenuCommand . List >
187
+ </ MenuCommand . Content >
188
+ </ MenuCommand . Menu >
189
+ </ div >
81
190
) ;
82
191
}
0 commit comments