UNPKG

bigblocks

Version:

Complete Bitcoin UI component library - authentication, social, wallet, market, inscriptions, and blockchain interactions for React

67 lines (66 loc) 7.8 kB
"use client"; import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime"; import { CheckCircledIcon, CrossCircledIcon, InfoCircledIcon, RocketIcon, } from "@radix-ui/react-icons"; import { useState } from "react"; import { CONTAINER_WIDTHS } from "../../lib/layout-constants.js"; import { cn } from "../../lib/utils.js"; import { LoadingButton } from "../ui-components/LoadingButton.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 { Dialog, DialogClose, DialogContent, DialogTitle, } from "../ui/dialog.js"; import { Progress } from "../ui/progress.js"; import { ProfileCard } from "./ProfileCard.js"; /** * ProfilePublisher - Publish BAP profiles to the Bitcoin blockchain * * Features: * - Profile preview before publishing * - Cost estimation display * - Publishing progress indication * - Transaction ID display on success * - Error handling with retry * - Confirmation dialog */ export function ProfilePublisher({ profile, onPublish, onSuccess, onError, estimatedCost = "~0.0001 BSV", className = "", }) { const [showConfirmDialog, setShowConfirmDialog] = useState(false); const [isPublishing, setIsPublishing] = useState(false); const [publishProgress, setPublishProgress] = useState(0); const [result, setResult] = useState(null); const handlePublish = async () => { setIsPublishing(true); setPublishProgress(10); setResult(null); try { // Simulate progress setPublishProgress(30); // Call the publish function const { txid } = await onPublish(profile.id); setPublishProgress(80); // Small delay for UX await new Promise((resolve) => setTimeout(resolve, 500)); setPublishProgress(100); setResult({ success: true, txid }); onSuccess?.(txid); // Close dialog after success setTimeout(() => { setShowConfirmDialog(false); setIsPublishing(false); setPublishProgress(0); }, 2000); } catch (error) { const errorMessage = error instanceof Error ? error.message : "Failed to publish profile"; setResult({ success: false, error: errorMessage }); onError?.(errorMessage); setIsPublishing(false); setPublishProgress(0); } }; if (profile.isPublished) { return (_jsx(Card, { className: cn(className), style: { maxWidth: CONTAINER_WIDTHS.CARD_MEDIUM }, children: _jsxs(CardContent, { className: "flex flex-col gap-3 items-center py-8", children: [_jsx(CheckCircledIcon, { className: "h-12 w-12 text-green-600" }), _jsx("p", { className: "text-base font-medium", children: "Profile Already Published" }), _jsx("p", { className: "text-sm text-muted-foreground", children: "This profile is already on the blockchain" })] }) })); } return (_jsxs(_Fragment, { children: [_jsx(Card, { className: cn(className), style: { maxWidth: CONTAINER_WIDTHS.CARD_MEDIUM }, children: _jsx(CardContent, { className: "p-6", children: _jsxs("div", { className: "flex flex-col gap-4", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("p", { className: "text-lg font-bold", children: "Publish Profile" }), _jsx(Badge, { variant: "secondary", className: "bg-orange-100 text-orange-700", children: "Unpublished" })] }), _jsxs(Alert, { children: [_jsx(InfoCircledIcon, { className: "h-4 w-4" }), _jsx(AlertDescription, { children: "Publishing your profile to the blockchain makes it permanent and discoverable by others. This action cannot be undone." })] }), _jsx(ProfileCard, { profile: profile, showActions: false, compact: true }), _jsx(Card, { children: _jsx(CardContent, { className: "p-4", children: _jsxs("div", { className: "flex justify-between items-center", children: [_jsx("p", { className: "text-sm font-medium", children: "Estimated Cost" }), _jsx("p", { className: "text-sm font-mono", children: estimatedCost })] }) }) }), _jsxs(Button, { size: "lg", onClick: () => setShowConfirmDialog(true), className: "w-full", children: [_jsx(RocketIcon, { className: "mr-2 h-4 w-4" }), "Publish to Blockchain"] })] }) }) }), _jsx(Dialog, { open: showConfirmDialog, onOpenChange: setShowConfirmDialog, children: _jsxs(DialogContent, { className: "max-w-[450px]", children: [_jsx(DialogTitle, { children: "Confirm Profile Publishing" }), _jsx("div", { className: "flex flex-col gap-4 mt-4", children: !result ? (_jsxs(_Fragment, { children: [_jsx("p", { className: "text-sm text-muted-foreground", children: "You are about to publish your profile to the Bitcoin blockchain. This will make your profile information permanent and publicly visible." }), _jsx(Card, { children: _jsx(CardContent, { className: "p-4", children: _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx("p", { className: "text-sm font-medium", children: "Profile Details" }), _jsxs("p", { className: "text-xs text-muted-foreground", children: ["Name: ", profile.name || "Unnamed"] }), _jsxs("p", { className: "text-xs text-muted-foreground", children: ["Address: ", profile.address.slice(0, 8), "...", profile.address.slice(-6)] }), profile.description && (_jsxs("p", { className: "text-xs text-muted-foreground", children: ["Bio: ", profile.description.slice(0, 50), "..."] }))] }) }) }), _jsx(Card, { children: _jsx(CardContent, { className: "p-4", children: _jsxs("div", { className: "flex justify-between items-center", children: [_jsx("p", { className: "text-sm font-medium", children: "Transaction Cost" }), _jsx("p", { className: "text-sm font-bold font-mono", children: estimatedCost })] }) }) }), isPublishing && _jsx(Progress, { value: publishProgress }), _jsxs("div", { className: "flex gap-3 justify-end", children: [_jsx(DialogClose, { asChild: true, children: _jsx(Button, { variant: "secondary", disabled: isPublishing, children: "Cancel" }) }), _jsxs(LoadingButton, { loading: isPublishing, onClick: handlePublish, children: [_jsx(RocketIcon, { className: "mr-2 h-4 w-4" }), isPublishing ? "Publishing..." : "Confirm & Publish"] })] })] })) : (_jsx(_Fragment, { children: result.success ? (_jsxs("div", { className: "flex flex-col gap-3 items-center py-4", children: [_jsx(CheckCircledIcon, { className: "h-12 w-12 text-green-600" }), _jsx("p", { className: "text-base font-medium text-center", children: "Profile Published Successfully!" }), _jsx("p", { className: "text-sm text-muted-foreground text-center", children: "Your profile is now permanently stored on the blockchain." }), result.txid && (_jsx(Card, { className: "w-full", children: _jsx(CardContent, { className: "p-3", children: _jsxs("div", { className: "flex flex-col gap-1", children: [_jsx("p", { className: "text-xs font-medium", children: "Transaction ID" }), _jsx("p", { className: "text-xs font-mono break-all", children: result.txid })] }) }) }))] })) : (_jsxs("div", { className: "flex flex-col gap-3 items-center py-4", children: [_jsx(CrossCircledIcon, { className: "h-12 w-12 text-destructive" }), _jsx("p", { className: "text-base font-medium text-center", children: "Publishing Failed" }), _jsx("p", { className: "text-sm text-muted-foreground text-center", children: result.error || "An error occurred while publishing your profile." }), _jsxs("div", { className: "flex gap-3 justify-end", children: [_jsx(DialogClose, { asChild: true, children: _jsx(Button, { variant: "secondary", children: "Close" }) }), _jsx(Button, { onClick: handlePublish, children: "Try Again" })] })] })) })) })] }) })] })); }