1- import { useState } from 'react' ;
1+ import { useId , useState } from 'react' ;
22import { useTranslation } from 'react-i18next' ;
33import {
44 Button ,
@@ -73,22 +73,30 @@ export function APITokensPage() {
7373 name : string ;
7474 } | null > ( null ) ;
7575 const [ copied , setCopied ] = useState ( false ) ;
76+ const devModeSwitchId = useId ( ) ;
7677
7778 // Form state
7879 const [ name , setName ] = useState ( '' ) ;
7980 const [ description , setDescription ] = useState ( '' ) ;
8081 const [ projectID , setProjectID ] = useState < string > ( '0' ) ;
8182 const [ expiresAt , setExpiresAt ] = useState ( '' ) ;
83+ const [ devMode , setDevMode ] = useState ( false ) ;
8284 const [ showProjectPicker , setShowProjectPicker ] = useState ( false ) ;
8385
8486 const resetForm = ( ) => {
8587 setName ( '' ) ;
8688 setDescription ( '' ) ;
8789 setProjectID ( '0' ) ;
8890 setExpiresAt ( '' ) ;
91+ setDevMode ( false ) ;
8992 setShowProjectPicker ( false ) ;
9093 } ;
9194
95+ const closeEditDialog = ( ) => {
96+ setEditingToken ( null ) ;
97+ resetForm ( ) ;
98+ } ;
99+
92100 const handleSubmit = ( e : React . FormEvent ) => {
93101 e . preventDefault ( ) ;
94102 createToken . mutate (
@@ -121,13 +129,11 @@ export function APITokensPage() {
121129 description,
122130 projectID : parseInt ( projectID ) || 0 ,
123131 expiresAt : expiresAt ? new Date ( expiresAt ) . toISOString ( ) : undefined ,
132+ devMode,
124133 } ,
125134 } ,
126135 {
127- onSuccess : ( ) => {
128- setEditingToken ( null ) ;
129- resetForm ( ) ;
130- } ,
136+ onSuccess : ( ) => closeEditDialog ( ) ,
131137 } ,
132138 ) ;
133139 } ;
@@ -139,13 +145,6 @@ export function APITokensPage() {
139145 } ) ;
140146 } ;
141147
142- const handleToggleDevMode = ( token : APIToken ) => {
143- updateToken . mutate ( {
144- id : token . id ,
145- data : { devMode : ! token . devMode } ,
146- } ) ;
147- } ;
148-
149148 const handleDelete = ( ) => {
150149 if ( ! deletingToken ) return ;
151150 deleteToken . mutate ( deletingToken . id , {
@@ -159,6 +158,7 @@ export function APITokensPage() {
159158 setDescription ( token . description ) ;
160159 setProjectID ( token . projectID . toString ( ) ) ;
161160 setExpiresAt ( token . expiresAt ? token . expiresAt . split ( 'T' ) [ 0 ] : '' ) ;
161+ setDevMode ( ! ! token . devMode ) ;
162162 } ;
163163
164164 const handleCopyToken = async ( ) => {
@@ -268,7 +268,6 @@ export function APITokensPage() {
268268 < TableHead > { t ( 'apiTokens.tokenPrefix' ) } </ TableHead >
269269 < TableHead > { t ( 'apiTokens.project' ) } </ TableHead >
270270 < TableHead > { t ( 'common.status' ) } </ TableHead >
271- < TableHead > { t ( 'apiTokens.devMode' ) } </ TableHead >
272271 < TableHead > { t ( 'apiTokens.usage' ) } </ TableHead >
273272 < TableHead > { t ( 'apiTokens.lastUsed' ) } </ TableHead >
274273 < TableHead className = "text-right" > { t ( 'common.actions' ) } </ TableHead >
@@ -332,27 +331,6 @@ export function APITokensPage() {
332331 ) }
333332 </ div >
334333 </ TableCell >
335- < TableCell >
336- < div className = "flex items-center gap-2" >
337- < Switch
338- checked = { ! ! token . devMode }
339- onCheckedChange = { ( ) => handleToggleDevMode ( token ) }
340- disabled = { updateToken . isPending }
341- />
342- { token . devMode ? (
343- < Badge
344- variant = "default"
345- className = "text-xs bg-blue-500/10 text-blue-500 border-blue-500/20"
346- >
347- { t ( 'apiTokens.devModeEnabled' ) }
348- </ Badge >
349- ) : (
350- < Badge variant = "secondary" className = "text-xs" >
351- { t ( 'apiTokens.devModeDisabled' ) }
352- </ Badge >
353- ) }
354- </ div >
355- </ TableCell >
356334 < TableCell >
357335 < div className = "flex items-center gap-1 text-sm text-text-secondary" >
358336 < Hash className = "h-3 w-3" />
@@ -503,7 +481,11 @@ export function APITokensPage() {
503481 { /* Edit Dialog */ }
504482 < Dialog
505483 open = { ! ! editingToken }
506- onOpenChange = { ( open : boolean ) => ! open && setEditingToken ( null ) }
484+ onOpenChange = { ( open : boolean ) => {
485+ if ( ! open ) {
486+ closeEditDialog ( ) ;
487+ }
488+ } }
507489 >
508490 < DialogContent >
509491 < DialogHeader >
@@ -567,8 +549,31 @@ export function APITokensPage() {
567549 min = { new Date ( ) . toISOString ( ) . split ( 'T' ) [ 0 ] }
568550 />
569551 </ div >
552+ < div className = "flex items-center justify-between" >
553+ < label
554+ htmlFor = { devModeSwitchId }
555+ className = "text-xs font-medium text-text-secondary uppercase tracking-wider"
556+ >
557+ { t ( 'apiTokens.devMode' ) }
558+ </ label >
559+ < div className = "flex items-center gap-2" >
560+ < Switch
561+ id = { devModeSwitchId }
562+ checked = { devMode }
563+ onCheckedChange = { setDevMode }
564+ disabled = { updateToken . isPending }
565+ />
566+ < span className = "text-xs text-text-muted" >
567+ { devMode ? t ( 'apiTokens.devModeEnabled' ) : t ( 'apiTokens.devModeDisabled' ) }
568+ </ span >
569+ </ div >
570+ </ div >
570571 < DialogFooter >
571- < Button type = "button" variant = "outline" onClick = { ( ) => setEditingToken ( null ) } >
572+ < Button
573+ type = "button"
574+ variant = "outline"
575+ onClick = { closeEditDialog }
576+ >
572577 { t ( 'common.cancel' ) }
573578 </ Button >
574579 < Button type = "submit" disabled = { updateToken . isPending || ! name } >
0 commit comments