import React, { useState, useEffect } from 'react'; import { createPortal } from 'react-dom'; import { Button } from '../../ui/button'; import { Input } from '../../ui/input'; import { X, Key, Copy, Check, Loader2 } from 'lucide-react'; import { useToast } from '@/hooks/useToast'; import { cn } from '@/lib/utils'; interface CreateAPIKeyModalProps { onClose: () => void; onCreate: (keyData: { name: string; scopes: string[] }) => Promise<{ key?: string; id: string; name: string; prefix: string }>; } const SCOPES = [ { id: 'user.read', label: 'Read User Data' }, { id: 'user.write', label: 'Update User Profile' }, { id: 'tracks.read', label: 'Read Tracks' }, { id: 'tracks.upload', label: 'Upload Tracks' }, { id: 'sales.read', label: 'Read Sales Data' }, ]; export const CreateAPIKeyModal: React.FC = ({ onClose, onCreate, }) => { const toast = useToast(); const [step, setStep] = useState(1); const [name, setName] = useState(''); const [selectedScopes, setSelectedScopes] = useState(['user.read']); const [generatedKey, setGeneratedKey] = useState(''); const [isGenerating, setIsGenerating] = useState(false); const [mounted, setMounted] = useState(false); useEffect(() => { setMounted(true); return () => setMounted(false); }, []); const toggleScope = (id: string) => { setSelectedScopes((prev) => prev.includes(id) ? prev.filter((s) => s !== id) : [...prev, id], ); }; const handleGenerate = async (e?: React.MouseEvent) => { // Prevent any default behavior e?.preventDefault(); e?.stopPropagation(); // Validate form if (!name.trim()) { toast.error('Please enter a name for your API key'); return; } if (selectedScopes.length === 0) { toast.error('Please select at least one permission scope'); return; } setIsGenerating(true); try { // Call the parent's onCreate handler which makes the API call const result = await onCreate({ name: name.trim(), scopes: selectedScopes }); // If the API returns a full key, use it; otherwise generate a mock for display if (result.key) { setGeneratedKey(result.key); } else { // Fallback: generate a mock key for display (in case backend doesn't return full key) const mockKey = `vz_${Math.random().toString(36).substr(2, 8)}_${Math.random().toString(36).substr(2, 16)}`; setGeneratedKey(mockKey); } setStep(2); setIsGenerating(false); } catch (error) { // Error is already handled by the parent component // Just reset the loading state setIsGenerating(false); // Re-throw to ensure error is handled throw error; } }; const copyKey = () => { navigator.clipboard.writeText(generatedKey); toast.success('API Key copied to clipboard'); }; if (!mounted) return null; return createPortal(
{/* Header - Fixed */}

{step === 1 ? 'Create API Key' : 'API Key Generated'}

{/* Content - Scrollable */}
{step === 1 ? (
setName(e.target.value)} autoFocus disabled={isGenerating} className="bg-background/50 border-border focus:border-primary h-12 text-lg w-full" />
{SCOPES.map((scope) => ( ))}
) : (

Key Created Successfully

Please copy your API key now. For security reasons, it cannot be displayed again properly.

{generatedKey}
)}
{/* Footer - Fixed */}
{step === 1 ? ( <> ) : ( )}
, document.body ); };