77 PlusIcon ,
88} from "@heroicons/react/20/solid" ;
99import { DialogClose } from "@radix-ui/react-dialog" ;
10- import { type MetaFunction , Form , useFetcher , useSearchParams } from "@remix-run/react" ;
10+ import { type MetaFunction , Form , useSearchParams } from "@remix-run/react" ;
1111import { useEffect , useState } from "react" ;
12- import { typedjson , useTypedLoaderData } from "remix-typedjson" ;
12+ import { typedjson , useTypedFetcher , useTypedLoaderData } from "remix-typedjson" ;
1313import { z } from "zod" ;
1414import { AdminDebugTooltip } from "~/components/admin/debugTooltip" ;
1515import { CopyableText } from "~/components/primitives/CopyableText" ;
@@ -104,7 +104,7 @@ const CreateApiKeySchema = z.object({
104104 presetId : z . string ( ) . trim ( ) . min ( 1 ) ,
105105 taskScope : z . enum ( [ "all" , "selected" ] ) . optional ( ) ,
106106 taskIdentifiers : z
107- . array ( z . string ( ) )
107+ . array ( z . string ( ) . trim ( ) . min ( 1 , "Task identifiers cannot be blank" ) )
108108 . max ( MAX_API_KEY_TASK_IDENTIFIERS , {
109109 message : `You can select at most ${ MAX_API_KEY_TASK_IDENTIFIERS } tasks` ,
110110 } )
@@ -560,8 +560,9 @@ function NewApiKeyDialog({
560560 availableTasks : string [ ] ;
561561 presets : ApiKeyPreset [ ] | null ;
562562} ) {
563- const fetcher = useFetcher < typeof action > ( ) ;
563+ const fetcher = useTypedFetcher < typeof action > ( ) ;
564564 const actionData = fetcher . data as ApiKeyActionData | undefined ;
565+ const [ showError , setShowError ] = useState ( false ) ;
565566 const [ open , setOpen ] = useState ( false ) ;
566567 const [ name , setName ] = useState ( "" ) ;
567568 const [ expiresAt , setExpiresAt ] = useState < Date > ( ) ;
@@ -572,8 +573,14 @@ function NewApiKeyDialog({
572573 const [ createdApiKey , setCreatedApiKey ] = useState < string > ( ) ;
573574
574575 useEffect ( ( ) => {
575- if ( fetcher . state === "idle" && actionData ?. ok && actionData . action === "create" ) {
576+ if ( fetcher . state !== "idle" ) {
577+ return ;
578+ }
579+
580+ if ( actionData ?. ok && actionData . action === "create" ) {
576581 setCreatedApiKey ( actionData . apiKey ) ;
582+ } else if ( actionData && ! actionData . ok ) {
583+ setShowError ( true ) ;
577584 }
578585 } , [ actionData , fetcher . state ] ) ;
579586
@@ -593,6 +600,7 @@ function NewApiKeyDialog({
593600 setTaskScope ( "all" ) ;
594601 setSelectedTasks ( [ ] ) ;
595602 setCreatedApiKey ( undefined ) ;
603+ setShowError ( false ) ;
596604 }
597605 } }
598606 >
@@ -635,7 +643,7 @@ function NewApiKeyDialog({
635643 />
636644 </ div >
637645 ) : (
638- < fetcher . Form method = "post" >
646+ < fetcher . Form method = "post" onSubmit = { ( ) => setShowError ( false ) } >
639647 < input type = "hidden" name = "action" value = "create" />
640648 { expiresAt ? (
641649 < input type = "hidden" name = "expiresAt" value = { expiresAt . toISOString ( ) } />
@@ -741,7 +749,7 @@ function NewApiKeyDialog({
741749 </ InputGroup >
742750 ) : null }
743751
744- { actionData && ! actionData . ok ? (
752+ { showError && actionData && ! actionData . ok ? (
745753 < Paragraph variant = "small" className = "text-error" >
746754 { actionData . error }
747755 </ Paragraph >
0 commit comments