'use client'; import { useState } from 'react'; import { ArrowRightIcon, DatabaseIcon, FunctionSquareIcon, KeyIcon, ShieldIcon, UserIcon, ZapIcon, } from 'lucide-react'; import { Badge } from '@kit/ui/badge'; import { Card, CardContent, CardHeader, CardTitle } from '@kit/ui/card'; import { Dialog, DialogContent, DialogHeader, DialogTitle, } from '@kit/ui/dialog'; import { Separator } from '@kit/ui/separator'; interface DatabaseFunction { name: string; signature: string; returnType: string; purpose: string; source: string; isSecurityDefiner: boolean; isTrigger: boolean; category: string; } interface FunctionBrowserProps { searchTerm: string; functions: DatabaseFunction[]; } const categoryColors: Record = { Triggers: 'bg-red-100 text-red-800', Authentication: 'bg-indigo-100 text-indigo-800', Accounts: 'bg-green-100 text-green-800', Permissions: 'bg-orange-100 text-orange-800', Invitations: 'bg-teal-100 text-teal-800', Billing: 'bg-yellow-100 text-yellow-800', Utilities: 'bg-blue-100 text-blue-800', 'Text Processing': 'bg-purple-100 text-purple-800', }; const categoryIcons: Record> = { Triggers: ZapIcon, Authentication: ShieldIcon, Accounts: UserIcon, Permissions: KeyIcon, Invitations: UserIcon, Billing: DatabaseIcon, Utilities: FunctionSquareIcon, 'Text Processing': FunctionSquareIcon, }; export function FunctionBrowser({ searchTerm, functions, }: FunctionBrowserProps) { const [selectedFunction, setSelectedFunction] = useState(null); const [isDialogOpen, setIsDialogOpen] = useState(false); // Filter functions based on search term const filteredFunctions = functions.filter( (func) => func.name.toLowerCase().includes(searchTerm.toLowerCase()) || func.purpose.toLowerCase().includes(searchTerm.toLowerCase()) || func.category.toLowerCase().includes(searchTerm.toLowerCase()) || func.source.toLowerCase().includes(searchTerm.toLowerCase()), ); // Group functions by category const functionsByCategory = filteredFunctions.reduce( (acc, func) => { if (!acc[func.category]) { acc[func.category] = []; } acc[func.category].push(func); return acc; }, {} as Record, ); const handleFunctionClick = (functionName: string) => { setSelectedFunction(functionName); setIsDialogOpen(true); }; const getReturnTypeColor = (returnType: string): string => { if (returnType === 'trigger') return 'bg-red-100 text-red-800'; if (returnType === 'boolean') return 'bg-green-100 text-green-800'; if (returnType === 'uuid') return 'bg-purple-100 text-purple-800'; if (returnType === 'text') return 'bg-blue-100 text-blue-800'; if (returnType === 'json' || returnType === 'jsonb') return 'bg-yellow-100 text-yellow-800'; if (returnType === 'TABLE') return 'bg-orange-100 text-orange-800'; return 'bg-gray-100 text-gray-800'; }; return (
{/* Summary */}

Total Functions

{filteredFunctions.length}

Categories

{Object.keys(functionsByCategory).length}

Security Definer

{filteredFunctions.filter((f) => f.isSecurityDefiner).length}

{/* Functions by Category */} {Object.entries(functionsByCategory).map( ([category, categoryFunctions]) => { const IconComponent = categoryIcons[category] || FunctionSquareIcon; return (
{category} {categoryFunctions.length} function {categoryFunctions.length !== 1 ? 's' : ''}
{categoryFunctions.map((func) => ( handleFunctionClick(func.name)} > {func.name}
{func.isSecurityDefiner && ( DEFINER )} {func.isTrigger && ( TRIGGER )}
{func.returnType}

{func.purpose}

{func.source} Click for details
))}
); }, )} {/* Function Details Dialog */} Function Details: {selectedFunction}
{(() => { const func = functions.find((f) => f.name === selectedFunction); if (!func) return null; return ( <>

Signature

{func.signature}

Purpose

{func.purpose}

Return Type

{func.returnType}

Source File

{func.source}

Properties

{func.category} {func.isSecurityDefiner && ( Security Definer )} {func.isTrigger && ( Trigger Function )}
); })()}
{filteredFunctions.length === 0 && (

{searchTerm ? 'No functions match your search' : 'No functions found'}

)}
); }