bigblocks
Version:
Complete Bitcoin UI component library - authentication, social, wallet, market, inscriptions, and blockchain interactions for React
15 lines • 8.4 kB
JSON
{
"name": "ui-components-transactionprogress",
"type": "registry:component",
"dependencies": [],
"devDependencies": [],
"registryDependencies": [],
"files": [
{
"path": "components/ui-components/TransactionProgress.tsx",
"type": "registry:component",
"content": "\"use client\";\nimport {\n\tCheckCircledIcon,\n\tClockIcon,\n\tCross2Icon,\n\tExternalLinkIcon,\n\tInfoCircledIcon,\n\tUpdateIcon,\n} from \"@radix-ui/react-icons\";\nimport { SPACING } from \"../../lib/layout-constants.js\";\nimport { cn } from \"../../lib/utils.js\";\nimport { Alert, AlertDescription } from \"../ui/alert.js\";\nimport { Badge } from \"../ui/badge.js\";\nimport { Button } from \"../ui/button.js\";\nimport { Card, CardContent } from \"../ui/card.js\";\nimport { Progress } from \"../ui/progress.js\";\n\nexport enum TransactionStatus {\n\tPreparing = \"preparing\",\n\tBroadcasting = \"broadcasting\",\n\tPending = \"pending\",\n\tConfirmed = \"confirmed\",\n\tFailed = \"failed\",\n}\n\nexport interface TransactionProgressProps {\n\tstatus: TransactionStatus;\n\ttxid?: string;\n\tconfirmations?: number;\n\trequiredConfirmations?: number;\n\terror?: string;\n\testimatedTime?: number; // in seconds\n\tonRetry?: () => void;\n\tonClose?: () => void;\n\tshowDetails?: boolean;\n\tclassName?: string;\n}\n\nexport function TransactionProgress({\n\tstatus,\n\ttxid,\n\tconfirmations = 0,\n\trequiredConfirmations = 6,\n\terror,\n\testimatedTime,\n\tonRetry,\n\tonClose,\n\tshowDetails = true,\n\tclassName = \"\",\n}: TransactionProgressProps) {\n\tconst getStatusIcon = () => {\n\t\tswitch (status) {\n\t\t\tcase TransactionStatus.Preparing:\n\t\t\t\treturn <UpdateIcon className=\"animate-spin h-5 w-5\" />;\n\t\t\tcase TransactionStatus.Broadcasting:\n\t\t\t\treturn <UpdateIcon className=\"animate-spin h-5 w-5\" />;\n\t\t\tcase TransactionStatus.Pending:\n\t\t\t\treturn <ClockIcon className=\"h-5 w-5\" />;\n\t\t\tcase TransactionStatus.Confirmed:\n\t\t\t\treturn <CheckCircledIcon className=\"h-5 w-5 text-green-600\" />;\n\t\t\tcase TransactionStatus.Failed:\n\t\t\t\treturn <Cross2Icon className=\"h-5 w-5 text-destructive\" />;\n\t\t}\n\t};\n\n\tconst getStatusText = () => {\n\t\tswitch (status) {\n\t\t\tcase TransactionStatus.Preparing:\n\t\t\t\treturn \"Preparing transaction...\";\n\t\t\tcase TransactionStatus.Broadcasting:\n\t\t\t\treturn \"Broadcasting to network...\";\n\t\t\tcase TransactionStatus.Pending:\n\t\t\t\treturn `Waiting for confirmations (${confirmations}/${requiredConfirmations})`;\n\t\t\tcase TransactionStatus.Confirmed:\n\t\t\t\treturn \"Transaction confirmed!\";\n\t\t\tcase TransactionStatus.Failed:\n\t\t\t\treturn \"Transaction failed\";\n\t\t}\n\t};\n\n\tconst getStatusColor = () => {\n\t\tswitch (status) {\n\t\t\tcase TransactionStatus.Preparing:\n\t\t\tcase TransactionStatus.Broadcasting:\n\t\t\t\treturn \"default\";\n\t\t\tcase TransactionStatus.Pending:\n\t\t\t\treturn \"secondary\";\n\t\t\tcase TransactionStatus.Confirmed:\n\t\t\t\treturn \"default\"; // Will use green text color in the badge\n\t\t\tcase TransactionStatus.Failed:\n\t\t\t\treturn \"destructive\";\n\t\t}\n\t};\n\n\tconst getProgress = () => {\n\t\tif (status === TransactionStatus.Preparing) return 10;\n\t\tif (status === TransactionStatus.Broadcasting) return 30;\n\t\tif (status === TransactionStatus.Pending) {\n\t\t\treturn 30 + (70 * confirmations) / requiredConfirmations;\n\t\t}\n\t\tif (status === TransactionStatus.Confirmed) return 100;\n\t\treturn 0;\n\t};\n\n\tconst formatTime = (seconds: number) => {\n\t\tif (seconds < 60) return `${seconds} seconds`;\n\t\tconst minutes = Math.floor(seconds / 60);\n\t\treturn `${minutes} minute${minutes > 1 ? \"s\" : \"\"}`;\n\t};\n\n\treturn (\n\t\t<Card className={className}>\n\t\t\t<CardContent className=\"pt-6\">\n\t\t\t\t<div className=\"space-y-4\">\n\t\t\t\t\t{/* Header */}\n\t\t\t\t\t<div className=\"flex items-center justify-between\">\n\t\t\t\t\t\t<div className=\"flex items-center gap-2\">\n\t\t\t\t\t\t\t{getStatusIcon()}\n\t\t\t\t\t\t\t<p className=\"text-base font-medium\">{getStatusText()}</p>\n\t\t\t\t\t\t</div>\n\t\t\t\t\t\t<Badge\n\t\t\t\t\t\t\tvariant={\n\t\t\t\t\t\t\t\tgetStatusColor() as\n\t\t\t\t\t\t\t\t\t| \"default\"\n\t\t\t\t\t\t\t\t\t| \"secondary\"\n\t\t\t\t\t\t\t\t\t| \"destructive\"\n\t\t\t\t\t\t\t\t\t| \"outline\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\tstatus === TransactionStatus.Pending &&\n\t\t\t\t\t\t\t\t\t\"bg-amber-100 text-amber-900\",\n\t\t\t\t\t\t\t\tstatus === TransactionStatus.Confirmed &&\n\t\t\t\t\t\t\t\t\t\"bg-green-100 text-green-900\",\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{status.charAt(0).toUpperCase() + status.slice(1)}\n\t\t\t\t\t\t</Badge>\n\t\t\t\t\t</div>\n\n\t\t\t\t\t{/* Progress Bar */}\n\t\t\t\t\t{status !== TransactionStatus.Failed && (\n\t\t\t\t\t\t<Progress\n\t\t\t\t\t\t\tvalue={getProgress()}\n\t\t\t\t\t\t\tclassName={cn(\n\t\t\t\t\t\t\t\t\"w-full\",\n\t\t\t\t\t\t\t\tstatus === TransactionStatus.Pending && \"[&>div]:bg-amber-500\",\n\t\t\t\t\t\t\t\tstatus === TransactionStatus.Confirmed &&\n\t\t\t\t\t\t\t\t\t\"[&>div]:bg-green-500\",\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t/>\n\t\t\t\t\t)}\n\n\t\t\t\t\t{/* Transaction Details */}\n\t\t\t\t\t{showDetails && txid && (\n\t\t\t\t\t\t<dl className=\"space-y-2\">\n\t\t\t\t\t\t\t<div className=\"flex\">\n\t\t\t\t\t\t\t\t<dt className=\"text-sm text-muted-foreground min-w-[120px]\">\n\t\t\t\t\t\t\t\t\tTransaction\n\t\t\t\t\t\t\t\t</dt>\n\t\t\t\t\t\t\t\t<dd className=\"text-sm\">\n\t\t\t\t\t\t\t\t\t<a\n\t\t\t\t\t\t\t\t\t\thref={`https://whatsonchain.com/tx/${txid}`}\n\t\t\t\t\t\t\t\t\t\ttarget=\"_blank\"\n\t\t\t\t\t\t\t\t\t\trel=\"noopener noreferrer\"\n\t\t\t\t\t\t\t\t\t\tclassName=\"text-primary hover:underline inline-flex items-center gap-1\"\n\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t{txid.substring(0, 8)}...{txid.substring(txid.length - 8)}\n\t\t\t\t\t\t\t\t\t\t<ExternalLinkIcon className=\"h-3 w-3\" />\n\t\t\t\t\t\t\t\t\t</a>\n\t\t\t\t\t\t\t\t</dd>\n\t\t\t\t\t\t\t</div>\n\n\t\t\t\t\t\t\t{status === TransactionStatus.Pending && (\n\t\t\t\t\t\t\t\t<div className=\"flex\">\n\t\t\t\t\t\t\t\t\t<dt className=\"text-sm text-muted-foreground min-w-[120px]\">\n\t\t\t\t\t\t\t\t\t\tConfirmations\n\t\t\t\t\t\t\t\t\t</dt>\n\t\t\t\t\t\t\t\t\t<dd className=\"text-sm\">\n\t\t\t\t\t\t\t\t\t\t{confirmations} / {requiredConfirmations}\n\t\t\t\t\t\t\t\t\t</dd>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t)}\n\n\t\t\t\t\t\t\t{estimatedTime && status === TransactionStatus.Pending && (\n\t\t\t\t\t\t\t\t<div className=\"flex\">\n\t\t\t\t\t\t\t\t\t<dt className=\"text-sm text-muted-foreground min-w-[120px]\">\n\t\t\t\t\t\t\t\t\t\tEst. Time\n\t\t\t\t\t\t\t\t\t</dt>\n\t\t\t\t\t\t\t\t\t<dd className=\"text-sm\">{formatTime(estimatedTime)}</dd>\n\t\t\t\t\t\t\t\t</div>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</dl>\n\t\t\t\t\t)}\n\n\t\t\t\t\t{/* Error Details */}\n\t\t\t\t\t{status === TransactionStatus.Failed && error && (\n\t\t\t\t\t\t<Alert variant=\"destructive\">\n\t\t\t\t\t\t\t<InfoCircledIcon className=\"h-4 w-4\" />\n\t\t\t\t\t\t\t<AlertDescription>{error}</AlertDescription>\n\t\t\t\t\t\t</Alert>\n\t\t\t\t\t)}\n\n\t\t\t\t\t{/* Actions */}\n\t\t\t\t\t{(onRetry || onClose) && (\n\t\t\t\t\t\t<div className=\"flex gap-2 justify-end\">\n\t\t\t\t\t\t\t{status === TransactionStatus.Failed && onRetry && (\n\t\t\t\t\t\t\t\t<Button onClick={onRetry} variant=\"default\" size=\"sm\">\n\t\t\t\t\t\t\t\t\tRetry Transaction\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t{status === TransactionStatus.Confirmed && onClose && (\n\t\t\t\t\t\t\t\t<Button onClick={onClose} variant=\"secondary\" size=\"sm\">\n\t\t\t\t\t\t\t\t\tClose\n\t\t\t\t\t\t\t\t</Button>\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\n\t\t\t\t\t{/* Helpful Tips */}\n\t\t\t\t\t{status === TransactionStatus.Pending && (\n\t\t\t\t\t\t<Alert className=\"bg-blue-50 border-blue-200\">\n\t\t\t\t\t\t\t<InfoCircledIcon className=\"h-4 w-4 text-blue-600\" />\n\t\t\t\t\t\t\t<AlertDescription className=\"text-blue-900\">\n\t\t\t\t\t\t\t\tYour transaction has been broadcast. Bitcoin transactions\n\t\t\t\t\t\t\t\ttypically confirm within 10-30 minutes.\n\t\t\t\t\t\t\t</AlertDescription>\n\t\t\t\t\t\t</Alert>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t</CardContent>\n\t\t</Card>\n\t);\n}\n",
"target": "<%- config.aliases.components %>/transactionprogress.tsx"
}
]
}