bigblocks
Version:
Complete Bitcoin UI component library - authentication, social, wallet, market, inscriptions, and blockchain interactions for React
83 lines (82 loc) • 6.54 kB
JavaScript
"use client";
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { CheckCircledIcon, ClockIcon, Cross2Icon, ExternalLinkIcon, InfoCircledIcon, UpdateIcon, } from "@radix-ui/react-icons";
import { cn } from "../../lib/utils.js";
import { Alert, AlertDescription } from "../ui/alert.js";
import { Badge } from "../ui/badge.js";
import { Button } from "../ui/button.js";
import { Card, CardContent } from "../ui/card.js";
import { Progress } from "../ui/progress.js";
export var TransactionStatus;
(function (TransactionStatus) {
TransactionStatus["Preparing"] = "preparing";
TransactionStatus["Broadcasting"] = "broadcasting";
TransactionStatus["Pending"] = "pending";
TransactionStatus["Confirmed"] = "confirmed";
TransactionStatus["Failed"] = "failed";
})(TransactionStatus || (TransactionStatus = {}));
export function TransactionProgress({ status, txid, confirmations = 0, requiredConfirmations = 6, error, estimatedTime, onRetry, onClose, showDetails = true, className = "", }) {
const getStatusIcon = () => {
switch (status) {
case TransactionStatus.Preparing:
return _jsx(UpdateIcon, { className: "animate-spin h-5 w-5" });
case TransactionStatus.Broadcasting:
return _jsx(UpdateIcon, { className: "animate-spin h-5 w-5" });
case TransactionStatus.Pending:
return _jsx(ClockIcon, { className: "h-5 w-5" });
case TransactionStatus.Confirmed:
return _jsx(CheckCircledIcon, { className: "h-5 w-5 text-green-600" });
case TransactionStatus.Failed:
return _jsx(Cross2Icon, { className: "h-5 w-5 text-destructive" });
}
};
const getStatusText = () => {
switch (status) {
case TransactionStatus.Preparing:
return "Preparing transaction...";
case TransactionStatus.Broadcasting:
return "Broadcasting to network...";
case TransactionStatus.Pending:
return `Waiting for confirmations (${confirmations}/${requiredConfirmations})`;
case TransactionStatus.Confirmed:
return "Transaction confirmed!";
case TransactionStatus.Failed:
return "Transaction failed";
}
};
const getStatusColor = () => {
switch (status) {
case TransactionStatus.Preparing:
case TransactionStatus.Broadcasting:
return "default";
case TransactionStatus.Pending:
return "secondary";
case TransactionStatus.Confirmed:
return "default"; // Will use green text color in the badge
case TransactionStatus.Failed:
return "destructive";
}
};
const getProgress = () => {
if (status === TransactionStatus.Preparing)
return 10;
if (status === TransactionStatus.Broadcasting)
return 30;
if (status === TransactionStatus.Pending) {
return 30 + (70 * confirmations) / requiredConfirmations;
}
if (status === TransactionStatus.Confirmed)
return 100;
return 0;
};
const formatTime = (seconds) => {
if (seconds < 60)
return `${seconds} seconds`;
const minutes = Math.floor(seconds / 60);
return `${minutes} minute${minutes > 1 ? "s" : ""}`;
};
return (_jsx(Card, { className: className, children: _jsx(CardContent, { className: "pt-6", children: _jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-2", children: [getStatusIcon(), _jsx("p", { className: "text-base font-medium", children: getStatusText() })] }), _jsx(Badge, { variant: getStatusColor(), className: cn(status === TransactionStatus.Pending &&
"bg-amber-100 text-amber-900", status === TransactionStatus.Confirmed &&
"bg-green-100 text-green-900"), children: status.charAt(0).toUpperCase() + status.slice(1) })] }), status !== TransactionStatus.Failed && (_jsx(Progress, { value: getProgress(), className: cn("w-full", status === TransactionStatus.Pending && "[&>div]:bg-amber-500", status === TransactionStatus.Confirmed &&
"[&>div]:bg-green-500") })), showDetails && txid && (_jsxs("dl", { className: "space-y-2", children: [_jsxs("div", { className: "flex", children: [_jsx("dt", { className: "text-sm text-muted-foreground min-w-[120px]", children: "Transaction" }), _jsx("dd", { className: "text-sm", children: _jsxs("a", { href: `https://whatsonchain.com/tx/${txid}`, target: "_blank", rel: "noopener noreferrer", className: "text-primary hover:underline inline-flex items-center gap-1", children: [txid.substring(0, 8), "...", txid.substring(txid.length - 8), _jsx(ExternalLinkIcon, { className: "h-3 w-3" })] }) })] }), status === TransactionStatus.Pending && (_jsxs("div", { className: "flex", children: [_jsx("dt", { className: "text-sm text-muted-foreground min-w-[120px]", children: "Confirmations" }), _jsxs("dd", { className: "text-sm", children: [confirmations, " / ", requiredConfirmations] })] })), estimatedTime && status === TransactionStatus.Pending && (_jsxs("div", { className: "flex", children: [_jsx("dt", { className: "text-sm text-muted-foreground min-w-[120px]", children: "Est. Time" }), _jsx("dd", { className: "text-sm", children: formatTime(estimatedTime) })] }))] })), status === TransactionStatus.Failed && error && (_jsxs(Alert, { variant: "destructive", children: [_jsx(InfoCircledIcon, { className: "h-4 w-4" }), _jsx(AlertDescription, { children: error })] })), (onRetry || onClose) && (_jsxs("div", { className: "flex gap-2 justify-end", children: [status === TransactionStatus.Failed && onRetry && (_jsx(Button, { onClick: onRetry, variant: "default", size: "sm", children: "Retry Transaction" })), status === TransactionStatus.Confirmed && onClose && (_jsx(Button, { onClick: onClose, variant: "secondary", size: "sm", children: "Close" }))] })), status === TransactionStatus.Pending && (_jsxs(Alert, { className: "bg-blue-50 border-blue-200", children: [_jsx(InfoCircledIcon, { className: "h-4 w-4 text-blue-600" }), _jsx(AlertDescription, { className: "text-blue-900", children: "Your transaction has been broadcast. Bitcoin transactions typically confirm within 10-30 minutes." })] }))] }) }) }));
}