bigblocks
Version:
Complete Bitcoin UI component library - authentication, social, wallet, market, inscriptions, and blockchain interactions for React
53 lines (52 loc) • 5.74 kB
JavaScript
"use client";
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { CheckIcon, CopyIcon, DotsHorizontalIcon, ExternalLinkIcon, InfoCircledIcon, Pencil1Icon, RocketIcon, } from "@radix-ui/react-icons";
import React from "react";
import { BitcoinAvatar } from "../ui-components/BitcoinAvatar.js";
import { Badge } from "../ui/badge.js";
import { Button } from "../ui/button.js";
import { Card } from "../ui/card.js";
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from "../ui/dropdown-menu.js";
/**
* ProfileViewer displays a complete view of a BAP profile
*
* Features:
* - Profile avatar, name, and description
* - Bitcoin address with copy functionality
* - Published/unpublished status
* - Edit and publish actions
* - Responsive layout
*/
export function ProfileViewer({ profile, showAddress = true, showPublishStatus = true, showActions = true, onEdit, onPublish, className = "", variant = "surface", size = "3", }) {
const [copied, setCopied] = React.useState(false);
const handleCopyAddress = async () => {
try {
await navigator.clipboard.writeText(profile.address);
setCopied(true);
setTimeout(() => setCopied(false), 2000);
}
catch (error) {
console.error("Failed to copy address:", error);
}
};
const getDisplayName = () => {
// Priority order for name fields
return (profile.name ||
profile.alternateName ||
profile.givenName ||
profile.familyName ||
profile.legalName ||
"Unnamed Profile");
};
const getInitials = (name) => {
if (!name)
return "?";
return name
.split(" ")
.map((word) => word[0])
.join("")
.toUpperCase()
.slice(0, 2);
};
return (_jsx(Card, { className: `p-6 max-w-2xl ${className}`, children: _jsxs("div", { className: "flex flex-col gap-4", children: [_jsxs("div", { className: "flex items-start gap-4", children: [_jsx(BitcoinAvatar, { size: "lg", src: profile.image, alt: getDisplayName(), fallback: getInitials(getDisplayName()) }), _jsxs("div", { className: "flex flex-col gap-1 flex-1", children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("h2", { className: "text-xl font-bold", children: getDisplayName() }), showPublishStatus && (_jsx(Badge, { variant: profile.isPublished ? "default" : "secondary", className: `text-xs ${profile.isPublished ? "text-green-700" : "text-orange-700"}`, children: profile.isPublished ? "Published" : "Unpublished" }))] }), profile.description && (_jsx("p", { className: "text-sm text-muted-foreground", children: profile.description }))] }), showActions && (onEdit || onPublish) && (_jsxs(DropdownMenu, { children: [_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(Button, { variant: "ghost", size: "sm", className: "rounded-full", children: _jsx(DotsHorizontalIcon, { className: "h-4 w-4" }) }) }), _jsxs(DropdownMenuContent, { children: [onEdit && (_jsxs(DropdownMenuItem, { onClick: onEdit, children: [_jsx(Pencil1Icon, { className: "h-4 w-4 mr-2" }), "Edit Profile"] })), onPublish && !profile.isPublished && (_jsxs(DropdownMenuItem, { onClick: onPublish, children: [_jsx(RocketIcon, { className: "h-4 w-4 mr-2" }), "Publish to Blockchain"] }))] })] }))] }), _jsxs("div", { className: "space-y-3", children: [_jsxs("div", { className: "flex items-center", children: [_jsx("div", { className: "w-24 text-sm text-muted-foreground", children: "Profile ID" }), _jsx("div", { className: "flex-1", children: _jsx("p", { className: "text-sm text-muted-foreground", children: profile.id }) })] }), showAddress && (_jsxs("div", { className: "flex items-center", children: [_jsx("div", { className: "w-24 text-sm text-muted-foreground", children: "Address" }), _jsxs("div", { className: "flex-1 flex items-center gap-2", children: [_jsxs("p", { className: "text-sm font-mono", children: [profile.address.slice(0, 8), "...", profile.address.slice(-6)] }), _jsx(Button, { variant: "ghost", size: "sm", onClick: handleCopyAddress, children: copied ? (_jsx(CheckIcon, { className: "h-3 w-3" })) : (_jsx(CopyIcon, { className: "h-3 w-3" })) }), _jsx(Button, { variant: "ghost", size: "sm", asChild: true, children: _jsx("a", { href: `https://whatsonchain.com/address/${profile.address}`, target: "_blank", rel: "noopener noreferrer", children: _jsx(ExternalLinkIcon, { className: "h-3 w-3" }) }) })] })] })), profile.isPublished && (_jsxs("div", { className: "flex items-center", children: [_jsx("div", { className: "w-24 text-sm text-muted-foreground", children: "Status" }), _jsxs("div", { className: "flex-1 flex items-center gap-2", children: [_jsx("div", { className: "w-2 h-2 rounded-full bg-green-500" }), _jsx("p", { className: "text-sm text-green-700", children: "Published to blockchain" })] })] }))] }), !profile.isPublished && (_jsx(Card, { className: "p-3 bg-orange-50 border border-orange-200", children: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(InfoCircledIcon, { className: "h-4 w-4 text-orange-600" }), _jsx("p", { className: "text-sm text-orange-700", children: "This profile is not yet published to the blockchain." })] }) })), showActions && (onEdit || (onPublish && !profile.isPublished)) && (_jsx("div", { className: "border-t pt-4 mt-2", children: _jsxs("div", { className: "flex gap-2 justify-end", children: [onEdit && (_jsx(Button, { variant: "outline", size: "sm", onClick: onEdit, children: "Edit" })), onPublish && !profile.isPublished && (_jsx(Button, { variant: "default", size: "sm", onClick: onPublish, children: "Publish" }))] }) }))] }) }));
}