diff --git a/frontend/src/app/dashboard/api-keys/page.tsx b/frontend/src/app/dashboard/api-keys/page.tsx index 2907b73..fc28f84 100644 --- a/frontend/src/app/dashboard/api-keys/page.tsx +++ b/frontend/src/app/dashboard/api-keys/page.tsx @@ -1,11 +1,7 @@ 'use client'; import { useState, useEffect } from 'react'; -import { Zap, Plus, AlertCircle } from 'lucide-react'; -import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; -import { Button } from '@/components/ui/button'; -import { Separator } from '@/components/ui/separator'; -import { Alert, AlertDescription } from '@/components/ui/alert'; +import { Zap, Plus, AlertCircle, Clock } from 'lucide-react'; import { useUser } from '@/app/dashboard/useUser'; import { useApiKeys } from './useApiKeys'; import { MAX_API_KEYS, type ApiKey } from './types'; @@ -16,6 +12,7 @@ import { RevokeKeyDialog } from './RevokeKeyDialog'; import { WebhookSnippet } from './WebhookSnippet'; import { useToast } from '@/components/ui/toast'; import { useI18n } from '@/lib/i18n'; +import { cn } from '@/lib/utils'; export default function ApiKeysPage() { const { t } = useI18n(); @@ -122,8 +119,8 @@ export default function ApiKeysPage() { return (
-
-

{t('apiKeys.loading')}

+
+

{t('apiKeys.loading')}

); @@ -134,70 +131,94 @@ export default function ApiKeysPage() { } return ( -
-
-

{t('apiKeys.title')}

-

- {t('apiKeys.subtitle')} -

+
+ {/* ── Editorial Header ───────────────────────────────────── */} +
+ {t('apiKeys.sectionTitle')} +

+ {t('apiKeys.title')} +

+

{t('apiKeys.subtitle')}

+ {/* API Error */} {apiError && ( - - - {apiError} - +
+ + {apiError} +
)} - - -
-
- -
-
- {t('apiKeys.sectionTitle')} - {t('apiKeys.sectionDesc')} -
+ {/* ── Main Card ──────────────────────────────────────────── */} +
+ {/* Section header */} +
+
+
- - - -
-
-

- {t('apiKeys.keysUsed', { total, max: MAX_API_KEYS })} -

-

- {maxKeysReached ? ( - {t('apiKeys.maxReached')} - ) : ( - t(MAX_API_KEYS - total !== 1 ? 'apiKeys.canGeneratePlural' : 'apiKeys.canGenerate', { count: MAX_API_KEYS - total }) - )} -

-
- +
+

+ {t('apiKeys.sectionTitle')} +

+

+ {t('apiKeys.sectionDesc')} +

+
- -
- + {/* Key count + generate button */} +
+
+

+ {t('apiKeys.keysUsed', { total, max: MAX_API_KEYS })} +

+

+ {maxKeysReached ? ( + {t('apiKeys.maxReached')} + ) : ( + t(MAX_API_KEYS - total !== 1 ? 'apiKeys.canGeneratePlural' : 'apiKeys.canGenerate', { count: MAX_API_KEYS - total }) + )} +

+
+ +
- + {/* Production key display area */} +
+
+

+ {t('apiKeys.sectionTitle')} +

+

+ {keys.length > 0 ? `${keys[0].key_prefix}************************************` : 'No keys generated'} +

+
+
+ +
+
+ {/* Key table */} + +
+ + {/* Webhook snippet */} + {/* Dialogs */} -
- +
+
-

{t('context.proTitle')}

-

- {t('context.proDesc')} -

+

{t('context.proTitle')}

+

{t('context.proDesc')}

- + + +
); } return ( -
-
-

{t('context.title')}

-

- {t('context.subtitle')} -

+
+ {/* ── Editorial Header ───────────────────────────────────── */} +
+ {t('context.presets.title')} +

+ {t('context.title')} +

+

{t('context.subtitle')}

- {/* Presets */} - - - - {t('context.presets.title')} - - {t('context.presets.desc')} - - -
- {PRESETS.map(p => ( - - ))} +
+ {/* ── Professional Presets ──────────────────────────────── */} +
+
+ +

+ {t('context.presets.title')} +

- - +

{t('context.presets.desc')}

- {/* System Prompt */} - - - - {t('context.instructions.title')} - - {t('context.instructions.desc')} - - -