@@ -32,6 +32,7 @@ import {
32
32
PanelLeftCloseIcon ,
33
33
ChevronsUpDownIcon ,
34
34
LogOutIcon ,
35
+ CreditCardIcon ,
35
36
} from "lucide-react" ;
36
37
import { useLocation , Link , useNavigate } from "react-router-dom" ;
37
38
import { t } from "i18next" ;
@@ -46,7 +47,7 @@ export const Sidebar = () => {
46
47
const activeTab = location . pathname ;
47
48
const { EnjoyApp, cable, displayPreferences, setDisplayPreferences } =
48
49
useContext ( AppSettingsProviderContext ) ;
49
- const [ isOpen , setIsOpen ] = useState ( true ) ;
50
+ const [ isCollapsed , setIsCollapsed ] = useState ( false ) ;
50
51
51
52
useEffect ( ( ) => {
52
53
if ( ! cable ) return ;
@@ -61,40 +62,40 @@ export const Sidebar = () => {
61
62
62
63
// Save the sidebar state to cache
63
64
useEffect ( ( ) => {
64
- EnjoyApp . cacheObjects . set ( "sidebarOpen" , isOpen ) ;
65
- } , [ isOpen ] ) ;
65
+ EnjoyApp . cacheObjects . set ( "sidebarOpen" , isCollapsed ) ;
66
+ } , [ isCollapsed ] ) ;
66
67
67
68
// Restore the sidebar state from cache
68
69
useEffect ( ( ) => {
69
70
EnjoyApp . cacheObjects . get ( "sidebarOpen" ) . then ( ( value ) => {
70
71
if ( value !== undefined ) {
71
- setIsOpen ( ! ! value ) ;
72
+ setIsCollapsed ( ! ! value ) ;
72
73
}
73
74
} ) ;
74
75
} , [ ] ) ;
75
76
76
77
return (
77
78
< div
78
79
className = { `h-[calc(100vh-2rem)] pt-8 transition-all relative draggable-region ${
79
- isOpen ? "w-48 " : "w-12 "
80
+ isCollapsed ? "w-12 " : "w-48 "
80
81
} `}
81
82
data-testid = "sidebar"
82
83
>
83
84
< div
84
85
className = { `fixed top-0 left-0 h-full bg-muted ${
85
- isOpen ? "w-48 " : "w-12 "
86
+ isCollapsed ? "w-12 " : "w-48 "
86
87
} `}
87
88
>
88
89
< ScrollArea className = "w-full h-full pb-12 pt-8" >
89
- < SidebarHeader isOpen = { isOpen } />
90
+ < SidebarHeader isCollapsed = { isCollapsed } />
90
91
< div className = "grid gap-2 mb-4" >
91
92
< SidebarItem
92
93
href = "/"
93
94
label = { t ( "sidebar.home" ) }
94
95
tooltip = { t ( "sidebar.home" ) }
95
96
active = { activeTab === "/" }
96
97
Icon = { HomeIcon }
97
- isOpen = { isOpen }
98
+ isCollapsed = { isCollapsed }
98
99
/>
99
100
100
101
< SidebarItem
@@ -103,7 +104,7 @@ export const Sidebar = () => {
103
104
tooltip = { t ( "sidebar.chats" ) }
104
105
active = { activeTab . startsWith ( "/chats" ) }
105
106
Icon = { MessagesSquareIcon }
106
- isOpen = { isOpen }
107
+ isCollapsed = { isCollapsed }
107
108
/>
108
109
109
110
< SidebarItem
@@ -112,7 +113,7 @@ export const Sidebar = () => {
112
113
tooltip = { t ( "sidebar.courses" ) }
113
114
active = { activeTab . startsWith ( "/courses" ) }
114
115
Icon = { GraduationCapIcon }
115
- isOpen = { isOpen }
116
+ isCollapsed = { isCollapsed }
116
117
/>
117
118
118
119
< Separator />
@@ -123,7 +124,7 @@ export const Sidebar = () => {
123
124
tooltip = { t ( "sidebar.audios" ) }
124
125
active = { activeTab . startsWith ( "/audios" ) }
125
126
Icon = { HeadphonesIcon }
126
- isOpen = { isOpen }
127
+ isCollapsed = { isCollapsed }
127
128
/>
128
129
129
130
< SidebarItem
@@ -132,7 +133,7 @@ export const Sidebar = () => {
132
133
tooltip = { t ( "sidebar.videos" ) }
133
134
active = { activeTab . startsWith ( "/videos" ) }
134
135
Icon = { VideoIcon }
135
- isOpen = { isOpen }
136
+ isCollapsed = { isCollapsed }
136
137
/>
137
138
138
139
< SidebarItem
@@ -141,7 +142,7 @@ export const Sidebar = () => {
141
142
tooltip = { t ( "sidebar.documents" ) }
142
143
active = { activeTab . startsWith ( "/documents" ) }
143
144
Icon = { NewspaperIcon }
144
- isOpen = { isOpen }
145
+ isCollapsed = { isCollapsed }
145
146
/>
146
147
147
148
< Separator />
@@ -153,7 +154,7 @@ export const Sidebar = () => {
153
154
active = { activeTab . startsWith ( "/conversations" ) }
154
155
Icon = { BotIcon }
155
156
testid = "sidebar-conversations"
156
- isOpen = { isOpen }
157
+ isCollapsed = { isCollapsed }
157
158
/>
158
159
159
160
< SidebarItem
@@ -163,7 +164,7 @@ export const Sidebar = () => {
163
164
active = { activeTab . startsWith ( "/pronunciation_assessments" ) }
164
165
Icon = { SpeechIcon }
165
166
testid = "sidebar-pronunciation-assessments"
166
- isOpen = { isOpen }
167
+ isCollapsed = { isCollapsed }
167
168
/>
168
169
169
170
< SidebarItem
@@ -172,7 +173,7 @@ export const Sidebar = () => {
172
173
tooltip = { t ( "sidebar.notes" ) }
173
174
active = { activeTab === "/notes" }
174
175
Icon = { NotebookPenIcon }
175
- isOpen = { isOpen }
176
+ isCollapsed = { isCollapsed }
176
177
/>
177
178
178
179
< SidebarItem
@@ -181,7 +182,7 @@ export const Sidebar = () => {
181
182
tooltip = { t ( "sidebar.vocabulary" ) }
182
183
active = { activeTab . startsWith ( "/vocabulary" ) }
183
184
Icon = { BookMarkedIcon }
184
- isOpen = { isOpen }
185
+ isCollapsed = { isCollapsed }
185
186
/>
186
187
187
188
< Separator />
@@ -192,15 +193,15 @@ export const Sidebar = () => {
192
193
variant = { displayPreferences ? "default" : "ghost" }
193
194
id = "preferences-button"
194
195
className = { `w-full ${
195
- isOpen ? "justify-start " : "justify-center "
196
+ isCollapsed ? "justify-center " : "justify-start "
196
197
} `}
197
198
data-tooltip-id = "global-tooltip"
198
199
data-tooltip-content = { t ( "sidebar.preferences" ) }
199
200
data-tooltip-place = "right"
200
201
onClick = { ( ) => setDisplayPreferences ( true ) }
201
202
>
202
203
< SettingsIcon className = "size-4" />
203
- { isOpen && (
204
+ { ! isCollapsed && (
204
205
< span className = "ml-2" > { t ( "sidebar.preferences" ) } </ span >
205
206
) }
206
207
</ Button >
@@ -228,16 +229,18 @@ export const Sidebar = () => {
228
229
size = "sm"
229
230
variant = "ghost"
230
231
className = { `w-full non-draggable-region ${
231
- isOpen ? "justify-start " : "justify-center "
232
+ isCollapsed ? "justify-center " : "justify-start "
232
233
} `}
233
- onClick = { ( ) => setIsOpen ( ! isOpen ) }
234
+ onClick = { ( ) => setIsCollapsed ( ! isCollapsed ) }
234
235
>
235
- { isOpen ? (
236
- < PanelLeftCloseIcon className = "size-4" />
237
- ) : (
236
+ { isCollapsed ? (
238
237
< PanelLeftOpenIcon className = "size-4" />
238
+ ) : (
239
+ < PanelLeftCloseIcon className = "size-4" />
240
+ ) }
241
+ { ! isCollapsed && (
242
+ < span className = "ml-2" > { t ( "sidebar.collapse" ) } </ span >
239
243
) }
240
- { isOpen && < span className = "ml-2" > { t ( "sidebar.collapse" ) } </ span > }
241
244
</ Button >
242
245
</ div >
243
246
</ div >
@@ -252,9 +255,9 @@ const SidebarItem = (props: {
252
255
active : boolean ;
253
256
Icon : LucideIcon ;
254
257
testid ?: string ;
255
- isOpen : boolean ;
258
+ isCollapsed : boolean ;
256
259
} ) => {
257
- const { href, label, tooltip, active, Icon, testid, isOpen } = props ;
260
+ const { href, label, tooltip, active, Icon, testid, isCollapsed } = props ;
258
261
259
262
return (
260
263
< Link
@@ -268,38 +271,47 @@ const SidebarItem = (props: {
268
271
< Button
269
272
size = "sm"
270
273
variant = { active ? "default" : "ghost" }
271
- className = { `w-full ${ isOpen ? "justify-start " : "justify-center " } ` }
274
+ className = { `w-full ${ isCollapsed ? "justify-center " : "justify-start " } ` }
272
275
>
273
276
< Icon className = "size-4" />
274
- { isOpen && < span className = "ml-2" > { label } </ span > }
277
+ { ! isCollapsed && < span className = "ml-2" > { label } </ span > }
275
278
</ Button >
276
279
</ Link >
277
280
) ;
278
281
} ;
279
282
280
- const SidebarHeader = ( props : { isOpen : boolean } ) => {
281
- const { isOpen } = props ;
282
- const { user, logout } = useContext ( AppSettingsProviderContext ) ;
283
+ const SidebarHeader = ( props : { isCollapsed : boolean } ) => {
284
+ const { isCollapsed } = props ;
285
+ const { user, logout, refreshAccount, setDisplayDepositDialog } = useContext (
286
+ AppSettingsProviderContext
287
+ ) ;
288
+ const [ open , setOpen ] = useState ( false ) ;
283
289
const navigate = useNavigate ( ) ;
284
290
291
+ useEffect ( ( ) => {
292
+ if ( open ) {
293
+ refreshAccount ?.( ) ;
294
+ }
295
+ } , [ open ] ) ;
296
+
285
297
if ( ! user ) {
286
298
return null ;
287
299
}
288
300
289
301
return (
290
302
< div className = "py-3 px-1 sticky top-0 bg-muted z-10 non-draggable-region" >
291
- < DropdownMenu >
303
+ < DropdownMenu open = { open } onOpenChange = { setOpen } >
292
304
< DropdownMenuTrigger asChild >
293
305
< Button
294
306
variant = "ghost"
295
307
className = { `w-full h-12 hover:bg-background ${
296
- isOpen ? "justify-start " : "justify-center px-1 "
308
+ isCollapsed ? "justify-center px-1 " : "justify-start "
297
309
} `}
298
310
>
299
311
< Avatar className = "size-8" >
300
312
< AvatarImage src = { user . avatarUrl } />
301
313
</ Avatar >
302
- { isOpen && (
314
+ { ! isCollapsed && (
303
315
< >
304
316
< div className = "ml-2 flex flex-col leading-none" >
305
317
< span className = "text-left text-sm font-medium line-clamp-1" >
@@ -334,6 +346,14 @@ const SidebarHeader = (props: { isOpen: boolean }) => {
334
346
< UsersRoundIcon className = "size-4 ml-auto" />
335
347
</ DropdownMenuItem >
336
348
< DropdownMenuSeparator />
349
+ < DropdownMenuItem
350
+ onSelect = { ( ) => setDisplayDepositDialog ( true ) }
351
+ className = "cursor-pointer"
352
+ >
353
+ < span className = "flex-1 truncate" > ${ user . balance } </ span >
354
+ < CreditCardIcon className = "size-4 ml-auto" />
355
+ </ DropdownMenuItem >
356
+ < DropdownMenuSeparator />
337
357
< DropdownMenuItem onSelect = { logout } className = "cursor-pointer" >
338
358
< span > { t ( "logout" ) } </ span >
339
359
< LogOutIcon className = "size-4 ml-auto" />
0 commit comments