@@ -17,6 +17,7 @@ import {
1717} from '@/components/emcn'
1818import { useSession } from '@/lib/auth/auth-client'
1919import { useUserPermissionsContext } from '@/app/workspace/[workspaceId]/providers/workspace-permissions-provider'
20+ import { SettingsSection } from '@/app/workspace/[workspaceId]/settings/components/settings-section/settings-section'
2021import {
2122 type ApiKey ,
2223 useApiKeys ,
@@ -146,20 +147,17 @@ export function ApiKeys() {
146147 Click "Create API Key" above to get started
147148 </ div >
148149 ) : (
149- < div className = 'flex flex-col gap-4.5 ' >
150- < >
151- { /* Workspace section */ }
152- { ! searchTerm . trim ( ) ? (
153- < div className = 'flex flex-col gap-2' >
154- < div className = 'font-medium text-[var(--text-secondary )] text-sm' >
155- Workspace
150+ < div className = 'flex flex-col gap-6 ' >
151+ { /* Workspace section */ }
152+ { ! searchTerm . trim ( ) ? (
153+ < SettingsSection label = 'Workspace' >
154+ { workspaceKeys . length === 0 ? (
155+ < div className = 'text-[var(--text-muted )] text-sm' >
156+ No workspace API keys yet
156157 </ div >
157- { workspaceKeys . length === 0 ? (
158- < div className = 'text-[var(--text-muted)] text-sm' >
159- No workspace API keys yet
160- </ div >
161- ) : (
162- workspaceKeys . map ( ( key ) => (
158+ ) : (
159+ < div className = 'flex flex-col gap-2' >
160+ { workspaceKeys . map ( ( key ) => (
163161 < div key = { key . id } className = 'flex items-center justify-between gap-3' >
164162 < div className = 'flex min-w-0 flex-col justify-center gap-[1px]' >
165163 < div className = 'flex items-center gap-1.5' >
@@ -185,14 +183,13 @@ export function ApiKeys() {
185183 Delete
186184 </ Chip >
187185 </ div >
188- ) )
189- ) }
190- </ div >
191- ) : filteredWorkspaceKeys . length > 0 ? (
192- < div className = 'flex flex-col gap-2' >
193- < div className = 'font-medium text-[var(--text-secondary)] text-sm' >
194- Workspace
186+ ) ) }
195187 </ div >
188+ ) }
189+ </ SettingsSection >
190+ ) : filteredWorkspaceKeys . length > 0 ? (
191+ < SettingsSection label = 'Workspace' >
192+ < div className = 'flex flex-col gap-2' >
196193 { filteredWorkspaceKeys . map ( ( { key } ) => (
197194 < div key = { key . id } className = 'flex items-center justify-between gap-3' >
198195 < div className = 'flex min-w-0 flex-col justify-center gap-[1px]' >
@@ -221,12 +218,13 @@ export function ApiKeys() {
221218 </ div >
222219 ) ) }
223220 </ div >
224- ) : null }
221+ </ SettingsSection >
222+ ) : null }
225223
226- { /* Personal section */ }
227- { ( ! searchTerm . trim ( ) || filteredPersonalKeys . length > 0 ) && (
224+ { /* Personal section */ }
225+ { ( ! searchTerm . trim ( ) || filteredPersonalKeys . length > 0 ) && (
226+ < SettingsSection label = 'Personal' >
228227 < div className = 'flex flex-col gap-2' >
229- < div className = 'font-medium text-[var(--text-secondary)] text-sm' > Personal</ div >
230228 { filteredPersonalKeys . map ( ( { key } ) => {
231229 const isConflict = conflicts . includes ( key . name )
232230 return (
@@ -265,61 +263,63 @@ export function ApiKeys() {
265263 )
266264 } ) }
267265 </ div >
268- ) }
266+ </ SettingsSection >
267+ ) }
269268
270- { /* Show message when search has no results across both sections */ }
271- { searchTerm . trim ( ) &&
272- filteredPersonalKeys . length === 0 &&
273- filteredWorkspaceKeys . length === 0 &&
274- ( personalKeys . length > 0 || workspaceKeys . length > 0 ) && (
275- < div className = 'py-4 text-center text-[var(--text-muted)] text-sm' >
276- No API keys found matching "{ searchTerm } "
277- </ div >
278- ) }
279- </ >
269+ { /* Show message when search has no results across both sections */ }
270+ { searchTerm . trim ( ) &&
271+ filteredPersonalKeys . length === 0 &&
272+ filteredWorkspaceKeys . length === 0 &&
273+ ( personalKeys . length > 0 || workspaceKeys . length > 0 ) && (
274+ < div className = 'py-4 text-center text-[var(--text-muted)] text-sm' >
275+ No API keys found matching "{ searchTerm } "
276+ </ div >
277+ ) }
280278 </ div >
281279 ) }
282280
283281 { /* Allow Personal API Keys Toggle */ }
284282 { ! isLoading && canManageWorkspaceKeys && (
285283 < Tooltip . Provider delayDuration = { 150 } >
286- < div className = 'mt-6 flex items-center justify-between' >
287- < div className = 'flex items-center gap-2' >
288- < span className = 'font-medium text-[var(--text-secondary)] text-sm' >
289- Allow personal API keys
290- </ span >
291- < Tooltip . Root >
292- < Tooltip . Trigger asChild >
293- < button
294- type = 'button'
295- className = 'rounded-full p-1 text-[var(--text-muted)] transition hover-hover:text-[var(--text-primary)]'
296- >
297- < Info className = 'size-[12px]' strokeWidth = { 2 } />
298- </ button >
299- </ Tooltip . Trigger >
300- < Tooltip . Content side = 'top' className = 'max-w-xs text-small' >
301- Allow collaborators to create and use their own keys with billing charged to
302- them.
303- </ Tooltip . Content >
304- </ Tooltip . Root >
284+ < SettingsSection label = 'Permissions' >
285+ < div className = 'flex items-center justify-between' >
286+ < div className = 'flex items-center gap-2' >
287+ < span className = 'text-[14px] text-[var(--text-body)]' >
288+ Allow personal API keys
289+ </ span >
290+ < Tooltip . Root >
291+ < Tooltip . Trigger asChild >
292+ < button
293+ type = 'button'
294+ className = 'rounded-full p-1 text-[var(--text-muted)] transition hover-hover:text-[var(--text-primary)]'
295+ >
296+ < Info className = 'size-[12px]' strokeWidth = { 2 } />
297+ </ button >
298+ </ Tooltip . Trigger >
299+ < Tooltip . Content side = 'top' className = 'max-w-xs text-small' >
300+ Allow collaborators to create and use their own keys with billing charged to
301+ them.
302+ </ Tooltip . Content >
303+ </ Tooltip . Root >
304+ </ div >
305+ { isLoadingSettings ? null : (
306+ < Switch
307+ checked = { allowPersonalApiKeys }
308+ disabled = { ! canManageWorkspaceKeys || updateSettingsMutation . isPending }
309+ onCheckedChange = { async ( checked ) => {
310+ try {
311+ await updateSettingsMutation . mutateAsync ( {
312+ workspaceId,
313+ allowPersonalApiKeys : checked ,
314+ } )
315+ } catch ( error ) {
316+ logger . error ( 'Error updating workspace settings:' , { error } )
317+ }
318+ } }
319+ />
320+ ) }
305321 </ div >
306- { isLoadingSettings ? null : (
307- < Switch
308- checked = { allowPersonalApiKeys }
309- disabled = { ! canManageWorkspaceKeys || updateSettingsMutation . isPending }
310- onCheckedChange = { async ( checked ) => {
311- try {
312- await updateSettingsMutation . mutateAsync ( {
313- workspaceId,
314- allowPersonalApiKeys : checked ,
315- } )
316- } catch ( error ) {
317- logger . error ( 'Error updating workspace settings:' , { error } )
318- }
319- } }
320- />
321- ) }
322- </ div >
322+ </ SettingsSection >
323323 </ Tooltip . Provider >
324324 ) }
325325 </ div >
0 commit comments