@@ -38,7 +38,7 @@ function SkeletonRow() {
3838function ApiKeysSkeleton ( ) {
3939 return (
4040 < div className = "h-full lg:grid lg:grid-cols-[1fr_18rem]" >
41- < div className = "divide-y border-b lg:border-b-0 lg:border-r " >
41+ < div className = "divide-y border-b lg:border-r lg:border-b-0 " >
4242 < SkeletonRow />
4343 < SkeletonRow />
4444 < SkeletonRow />
@@ -52,20 +52,16 @@ function ApiKeysSkeleton() {
5252 ) ;
5353}
5454
55- function EmptyState ( { onCreateNew } : { onCreateNew : ( ) => void } ) {
55+ function EmptyState ( ) {
5656 return (
5757 < div className = "flex h-full flex-col items-center justify-center p-8 text-center" >
5858 < div className = "mb-4 flex h-16 w-16 items-center justify-center rounded-full bg-primary/10" >
5959 < KeyIcon className = "text-primary" size = { 28 } weight = "duotone" />
6060 </ div >
6161 < h3 className = "mb-1 font-semibold text-lg" > No API keys yet</ h3 >
62- < p className = "mb-6 max-w-sm text-muted-foreground text-sm" >
62+ < p className = "max-w-sm text-muted-foreground text-sm" >
6363 Create your first API key to start integrating with our platform
6464 </ p >
65- < Button onClick = { onCreateNew } >
66- < PlusIcon className = "mr-2" size = { 16 } />
67- Create API Key
68- </ Button >
6965 </ div >
7066 ) ;
7167}
@@ -94,36 +90,42 @@ export function ApiKeySettings({ organization }: ApiKeySettingsProps) {
9490 const [ selectedKeyId , setSelectedKeyId ] = useState < string | null > ( null ) ;
9591
9692 const { data, isLoading, isError, refetch } = useQuery ( {
97- ...orpc . apikeys . list . queryOptions ( { input : { organizationId : organization . id } } ) ,
93+ ...orpc . apikeys . list . queryOptions ( {
94+ input : { organizationId : organization . id } ,
95+ } ) ,
9896 refetchOnMount : true ,
9997 refetchOnReconnect : true ,
10098 staleTime : 0 ,
10199 } ) ;
102100
103101 const items = data ?? [ ] ;
104102 const activeCount = items . filter ( ( k ) => k . enabled && ! k . revokedAt ) . length ;
103+ const isEmpty = items . length === 0 ;
105104
106105 if ( isLoading ) return < ApiKeysSkeleton /> ;
107106 if ( isError ) return < ErrorState onRetry = { refetch } /> ;
108- if ( items . length === 0 ) return < EmptyState onCreateNew = { ( ) => setShowCreateDialog ( true ) } /> ;
109107
110108 return (
111109 < >
112110 < div className = "h-full lg:grid lg:grid-cols-[1fr_18rem]" >
113- { /* Keys List */ }
114- < div className = "flex flex-col border-b lg:border-b-0 lg:border-r" >
115- < div className = "flex-1 divide-y overflow-y-auto" >
116- { items . map ( ( apiKey ) => (
117- < ApiKeyRow
118- apiKey = { apiKey }
119- key = { apiKey . id }
120- onSelect = { ( id ) => {
121- setSelectedKeyId ( id ) ;
122- setShowDetailDialog ( true ) ;
123- } }
124- />
125- ) ) }
126- </ div >
111+ { /* Keys List / Empty State */ }
112+ < div className = "flex flex-col border-b lg:border-r lg:border-b-0" >
113+ { isEmpty ? (
114+ < EmptyState />
115+ ) : (
116+ < div className = "flex-1 divide-y overflow-y-auto" >
117+ { items . map ( ( apiKey ) => (
118+ < ApiKeyRow
119+ apiKey = { apiKey }
120+ key = { apiKey . id }
121+ onSelect = { ( id ) => {
122+ setSelectedKeyId ( id ) ;
123+ setShowDetailDialog ( true ) ;
124+ } }
125+ />
126+ ) ) }
127+ </ div >
128+ ) }
127129 </ div >
128130
129131 { /* Sidebar */ }
@@ -135,22 +137,31 @@ export function ApiKeySettings({ organization }: ApiKeySettingsProps) {
135137 </ Button >
136138
137139 { /* Stats Card */ }
138- < div className = "flex items-center gap-3 rounded border bg-background p-4" >
139- < div className = "flex h-10 w-10 items-center justify-center rounded bg-primary/10" >
140- < ShieldCheckIcon className = "text-primary" size = { 20 } weight = "duotone" />
141- </ div >
142- < div >
143- < p className = "font-semibold tabular-nums" >
144- { activeCount } < span className = "font-normal text-muted-foreground" > / { items . length } </ span >
145- </ p >
146- < p className = "text-muted-foreground text-sm" > Active keys</ p >
140+ { ! isEmpty && (
141+ < div className = "flex items-center gap-3 rounded border bg-background p-4" >
142+ < div className = "flex h-10 w-10 items-center justify-center rounded bg-primary/10" >
143+ < ShieldCheckIcon
144+ className = "text-primary"
145+ size = { 20 }
146+ weight = "duotone"
147+ />
148+ </ div >
149+ < div >
150+ < p className = "font-semibold tabular-nums" >
151+ { activeCount } { " " }
152+ < span className = "font-normal text-muted-foreground" >
153+ / { items . length }
154+ </ span >
155+ </ p >
156+ < p className = "text-muted-foreground text-sm" > Active keys</ p >
157+ </ div >
147158 </ div >
148- </ div >
159+ ) }
149160
150161 { /* Actions */ }
151162 < Button asChild className = "w-full justify-start" variant = "outline" >
152163 < a
153- href = "https://www.databuddy.cc/docs/api-keys "
164+ href = "https://www.databuddy.cc/docs/getting-started "
154165 rel = "noopener noreferrer"
155166 target = "_blank"
156167 >
@@ -163,7 +174,8 @@ export function ApiKeySettings({ organization }: ApiKeySettingsProps) {
163174 < div className = "mt-auto rounded border border-dashed bg-background/50 p-4" >
164175 < p className = "mb-2 font-medium text-sm" > Security reminder</ p >
165176 < p className = "text-muted-foreground text-xs leading-relaxed" >
166- Keep your API keys secure. Never share them publicly or commit them to version control.
177+ Keep your API keys secure. Never share them publicly or commit
178+ them to version control.
167179 </ p >
168180 </ div >
169181 </ aside >
0 commit comments