1+ import { useAuthStore } from "@features/auth/stores/authStore" ;
12import {
23 type SettingsCategory ,
34 useSettingsDialogStore ,
45} from "@features/settings/stores/settingsDialogStore" ;
6+ import { useSeat } from "@hooks/useSeat" ;
57import {
68 ArrowLeft ,
79 ArrowsClockwise ,
810 CaretRight ,
911 Code ,
12+ CreditCard ,
1013 Folder ,
1114 GearSix ,
1215 HardDrives ,
1316 Keyboard ,
1417 Palette ,
1518 Plugs ,
19+ SignOut ,
1620 TrafficSignal ,
1721 TreeStructure ,
18- User ,
1922 Wrench ,
2023} from "@phosphor-icons/react" ;
21- import { Box , Flex , ScrollArea , Text } from "@radix-ui/themes" ;
24+ import { Avatar , Box , Flex , ScrollArea , Text } from "@radix-ui/themes" ;
25+ import { useQuery } from "@tanstack/react-query" ;
2226import { type ReactNode , useEffect } from "react" ;
2327import { useHotkeys } from "react-hotkeys-hook" ;
24- import { AccountSettings } from "./sections/AccountSettings" ;
2528import { AdvancedSettings } from "./sections/AdvancedSettings" ;
2629import { ClaudeCodeSettings } from "./sections/ClaudeCodeSettings" ;
2730import { EnvironmentsSettings } from "./sections/environments/EnvironmentsSettings" ;
2831import { GeneralSettings } from "./sections/GeneralSettings" ;
2932import { McpServersSettings } from "./sections/McpServersSettings" ;
3033import { PersonalizationSettings } from "./sections/PersonalizationSettings" ;
34+ import { PlanUsageSettings } from "./sections/PlanUsageSettings" ;
3135import { ShortcutsSettings } from "./sections/ShortcutsSettings" ;
3236import { SignalSourcesSettings } from "./sections/SignalSourcesSettings" ;
3337import { UpdatesSettings } from "./sections/UpdatesSettings" ;
@@ -43,7 +47,7 @@ interface SidebarItem {
4347
4448const SIDEBAR_ITEMS : SidebarItem [ ] = [
4549 { id : "general" , label : "General" , icon : < GearSix size = { 16 } /> } ,
46- { id : "account " , label : "Account " , icon : < User size = { 16 } /> } ,
50+ { id : "plan-usage " , label : "Plan & Usage " , icon : < CreditCard size = { 16 } /> } ,
4751 { id : "workspaces" , label : "Workspaces" , icon : < Folder size = { 16 } /> } ,
4852 { id : "worktrees" , label : "Worktrees" , icon : < TreeStructure size = { 16 } /> } ,
4953 {
@@ -71,7 +75,7 @@ const SIDEBAR_ITEMS: SidebarItem[] = [
7175
7276const CATEGORY_TITLES : Record < SettingsCategory , string > = {
7377 general : "General" ,
74- account : "Account " ,
78+ "plan-usage" : "Plan & Usage " ,
7579 workspaces : "Workspaces" ,
7680 worktrees : "Worktrees" ,
7781 environments : "Environments" ,
@@ -87,7 +91,7 @@ const CATEGORY_TITLES: Record<SettingsCategory, string> = {
8791
8892const CATEGORY_COMPONENTS : Record < SettingsCategory , React . ComponentType > = {
8993 general : GeneralSettings ,
90- account : AccountSettings ,
94+ "plan-usage" : PlanUsageSettings ,
9195 workspaces : WorkspacesSettings ,
9296 worktrees : WorktreesSettings ,
9397 environments : EnvironmentsSettings ,
@@ -104,6 +108,17 @@ const CATEGORY_COMPONENTS: Record<SettingsCategory, React.ComponentType> = {
104108export function SettingsDialog ( ) {
105109 const { isOpen, activeCategory, close, setCategory } =
106110 useSettingsDialogStore ( ) ;
111+ const { client, isAuthenticated } = useAuthStore ( ) ;
112+ const { seat, planLabel } = useSeat ( ) ;
113+
114+ const { data : user } = useQuery ( {
115+ queryKey : [ "currentUser" ] ,
116+ queryFn : async ( ) => {
117+ if ( ! client ) return null ;
118+ return await client . getCurrentUser ( ) ;
119+ } ,
120+ enabled : ! ! client && isAuthenticated ,
121+ } ) ;
107122
108123 useHotkeys ( "escape" , close , {
109124 enabled : isOpen ,
@@ -129,13 +144,50 @@ export function SettingsDialog() {
129144
130145 const ActiveComponent = CATEGORY_COMPONENTS [ activeCategory ] ;
131146
147+ const initials = user
148+ ? user . first_name && user . last_name
149+ ? `${ user . first_name [ 0 ] } ${ user . last_name [ 0 ] } ` . toUpperCase ( )
150+ : ( user . email ?. substring ( 0 , 2 ) . toUpperCase ( ) ?? "U" )
151+ : null ;
152+
132153 return (
133154 < div
134155 className = "fixed inset-0 z-[100] flex"
135156 style = { { backgroundColor : "var(--color-background)" } }
136157 data-overlay = "settings"
137158 >
138- < div className = "flex h-full w-[256px] shrink-0 flex-col border-gray-6 border-r pt-8" >
159+ < div className = "flex h-full w-[256px] shrink-0 flex-col border-gray-6 border-r" >
160+ < div
161+ className = "drag"
162+ style = { {
163+ height : 36 ,
164+ flexShrink : 0 ,
165+ borderBottom : "1px solid var(--gray-6)" ,
166+ } }
167+ />
168+
169+ { isAuthenticated && user && initials && (
170+ < Flex
171+ align = "center"
172+ gap = "3"
173+ px = "3"
174+ py = "3"
175+ style = { { borderBottom : "1px solid var(--gray-5)" } }
176+ >
177+ < Avatar size = "2" fallback = { initials } radius = "full" color = "amber" />
178+ < Flex direction = "column" style = { { minWidth : 0 } } >
179+ < Text size = "2" weight = "medium" truncate >
180+ { user . email }
181+ </ Text >
182+ { seat && (
183+ < Text size = "1" style = { { color : "var(--gray-9)" } } >
184+ { planLabel } Plan
185+ </ Text >
186+ ) }
187+ </ Flex >
188+ </ Flex >
189+ ) }
190+
139191 < button
140192 type = "button"
141193 className = "mt-2 flex cursor-pointer items-center gap-2 border-0 bg-transparent px-3 py-2 text-left font-mono text-[12px] text-gray-11 transition-colors hover:bg-gray-3"
@@ -157,56 +209,81 @@ export function SettingsDialog() {
157209 ) ) }
158210 </ div >
159211 </ ScrollArea >
212+
213+ { isAuthenticated && (
214+ < button
215+ type = "button"
216+ className = "flex cursor-pointer items-center gap-2 border-0 border-gray-5 border-t bg-transparent px-3 py-2.5 text-left font-mono text-[12px] text-gray-9 transition-colors hover:bg-gray-3 hover:text-gray-11"
217+ onClick = { ( ) => useAuthStore . getState ( ) . logout ( ) }
218+ >
219+ < SignOut size = { 14 } />
220+ < span > Sign out</ span >
221+ </ button >
222+ ) }
160223 </ div >
161224
162- < div className = "relative flex flex-1 justify-center overflow-hidden pt-8" >
163- < svg
164- aria-hidden = "true"
165- style = { {
166- position : "absolute" ,
167- bottom : 0 ,
168- left : 0 ,
169- width : "100%" ,
170- height : "100%" ,
171- pointerEvents : "none" ,
172- opacity : 0.4 ,
173- maskImage : "linear-gradient(to top, black 0%, transparent 100%)" ,
174- WebkitMaskImage :
175- "linear-gradient(to top, black 0%, transparent 100%)" ,
176- } }
177- >
178- < defs >
179- < pattern
180- id = "settings-dot-pattern"
181- patternUnits = "userSpaceOnUse"
182- width = "8"
183- height = "8"
184- >
185- < circle cx = "0" cy = "0" r = "1" fill = "var(--gray-6)" />
186- < circle cx = "0" cy = "8" r = "1" fill = "var(--gray-6)" />
187- < circle cx = "8" cy = "8" r = "1" fill = "var(--gray-6)" />
188- < circle cx = "8" cy = "0" r = "1" fill = "var(--gray-6)" />
189- < circle cx = "4" cy = "4" r = "1" fill = "var(--gray-6)" />
190- </ pattern >
191- </ defs >
192- < rect width = "100%" height = "100%" fill = "url(#settings-dot-pattern)" />
193- </ svg >
194- < ScrollArea
225+ < div className = "relative flex flex-1 flex-col overflow-hidden" >
226+ < div
227+ className = "drag"
195228 style = { {
196- height : "100%" ,
197- width : "100%" ,
198- maxWidth : "800px " ,
229+ height : 36 ,
230+ flexShrink : 0 ,
231+ borderBottom : "1px solid var(--gray-6) " ,
199232 } }
200- >
201- < Box p = "6" style = { { position : "relative" , zIndex : 1 } } >
202- < Flex direction = "column" gap = "4" >
203- < Text size = "4" weight = "medium" >
204- { CATEGORY_TITLES [ activeCategory ] }
205- </ Text >
206- < ActiveComponent />
207- </ Flex >
208- </ Box >
209- </ ScrollArea >
233+ />
234+ < div className = "relative flex flex-1 justify-center overflow-hidden" >
235+ < svg
236+ aria-hidden = "true"
237+ style = { {
238+ position : "absolute" ,
239+ bottom : 0 ,
240+ left : 0 ,
241+ width : "100%" ,
242+ height : "100%" ,
243+ pointerEvents : "none" ,
244+ opacity : 0.4 ,
245+ maskImage : "linear-gradient(to top, black 0%, transparent 100%)" ,
246+ WebkitMaskImage :
247+ "linear-gradient(to top, black 0%, transparent 100%)" ,
248+ } }
249+ >
250+ < defs >
251+ < pattern
252+ id = "settings-dot-pattern"
253+ patternUnits = "userSpaceOnUse"
254+ width = "8"
255+ height = "8"
256+ >
257+ < circle cx = "0" cy = "0" r = "1" fill = "var(--gray-6)" />
258+ < circle cx = "0" cy = "8" r = "1" fill = "var(--gray-6)" />
259+ < circle cx = "8" cy = "8" r = "1" fill = "var(--gray-6)" />
260+ < circle cx = "8" cy = "0" r = "1" fill = "var(--gray-6)" />
261+ < circle cx = "4" cy = "4" r = "1" fill = "var(--gray-6)" />
262+ </ pattern >
263+ </ defs >
264+ < rect
265+ width = "100%"
266+ height = "100%"
267+ fill = "url(#settings-dot-pattern)"
268+ />
269+ </ svg >
270+ < ScrollArea
271+ style = { {
272+ height : "100%" ,
273+ width : "100%" ,
274+ maxWidth : "800px" ,
275+ } }
276+ >
277+ < Box p = "6" style = { { position : "relative" , zIndex : 1 } } >
278+ < Flex direction = "column" gap = "4" >
279+ < Text size = "4" weight = "medium" >
280+ { CATEGORY_TITLES [ activeCategory ] }
281+ </ Text >
282+ < ActiveComponent />
283+ </ Flex >
284+ </ Box >
285+ </ ScrollArea >
286+ </ div >
210287 </ div >
211288 </ div >
212289 ) ;
0 commit comments