bigblocks
Version:
Complete Bitcoin UI component library - authentication, social, wallet, market, inscriptions, and blockchain interactions for React
59 lines (58 loc) • 4.62 kB
JavaScript
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
import { ExclamationTriangleIcon, MobileIcon } from "@radix-ui/react-icons";
import React, { useState } from "react";
import { LoadingButton } from "../ui-components/LoadingButton.js";
import { QRCodeRenderer } from "../ui-components/QRCodeRenderer.js";
import { Alert, AlertDescription } from "../ui/alert.js";
import { Button } from "../ui/button.js";
import { Card, CardContent } from "../ui/card.js";
export function MemberExport({ profileName, onGenerateExport, }) {
const [qrData, setQrData] = useState(null);
const [expiresAt, setExpiresAt] = useState(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const handleGenerateExport = async () => {
setLoading(true);
setError(null);
try {
const result = await onGenerateExport();
setQrData(result.qrData);
setExpiresAt(result.expiresAt);
}
catch (err) {
setError(err instanceof Error ? err.message : "Failed to generate export QR");
}
finally {
setLoading(false);
}
};
const handleReset = React.useCallback(() => {
setQrData(null);
setExpiresAt(null);
setError(null);
}, []);
const getTimeRemaining = React.useCallback(() => {
if (!expiresAt)
return null;
const now = new Date();
const diff = expiresAt.getTime() - now.getTime();
if (diff <= 0)
return "Expired";
const minutes = Math.floor(diff / 60000);
const seconds = Math.floor((diff % 60000) / 1000);
return `${minutes}:${seconds.toString().padStart(2, "0")}`;
}, [expiresAt]);
React.useEffect(() => {
if (!expiresAt)
return;
const interval = setInterval(() => {
const remaining = getTimeRemaining();
if (remaining === "Expired") {
handleReset();
clearInterval(interval);
}
}, 1000);
return () => clearInterval(interval);
}, [expiresAt, getTimeRemaining, handleReset]);
return (_jsxs("div", { className: "flex flex-col gap-4", children: [_jsxs("div", { className: "flex flex-col items-center gap-1", children: [_jsx("h2", { className: "text-xl font-semibold", children: "Export to Mobile" }), _jsxs("p", { className: "text-sm text-muted-foreground", children: ["Export \"", profileName, "\" profile to use on your mobile device"] })] }), error && (_jsx(Alert, { variant: "destructive", children: _jsx(AlertDescription, { children: error }) })), !qrData ? (_jsxs(LoadingButton, { onClick: handleGenerateExport, loading: loading, className: "w-full", variant: "default", children: [_jsx(MobileIcon, { className: "h-4 w-4 mr-2" }), "Export to Mobile"] })) : (_jsxs("div", { className: "flex flex-col gap-4", children: [_jsx(Card, { className: "bg-muted/50 border", children: _jsx(CardContent, { className: "p-4", children: _jsx(QRCodeRenderer, { data: qrData, size: 256, qrStyle: "dots", themeAware: true, bgColor: "var(--background)", fgColor: "var(--primary)", logoImage: "https://cdn.jsdelivr.net/gh/radix-ui/icons@main/packages/radix-icons/icons/mobile.svg", logoWidth: 32, logoHeight: 32, logoOpacity: 0.7, style: { width: "100%", height: "auto" } }) }) }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsxs("div", { className: "flex justify-between items-center", children: [_jsx("span", { className: "text-sm text-muted-foreground", children: "Expires in:" }), _jsx("span", { className: "text-sm font-mono", children: getTimeRemaining() })] }), _jsx(Button, { onClick: handleReset, size: "default", variant: "secondary", className: "w-full", children: "Cancel" })] }), _jsxs(Alert, { className: "bg-amber-50 border-amber-200", children: [_jsx(ExclamationTriangleIcon, { className: "h-4 w-4" }), _jsxs(AlertDescription, { className: "text-amber-900", children: [_jsx("span", { className: "font-semibold", children: "Security Notice:" }), " This QR code contains a link to download your member backup. You'll need to enter your password on the mobile device to decrypt it."] })] }), _jsxs("div", { className: "flex flex-col gap-1", children: [_jsx("p", { className: "text-xs text-muted-foreground", children: "1. Scan this QR code on your mobile device" }), _jsx("p", { className: "text-xs text-muted-foreground", children: "2. Enter your password when prompted" }), _jsx("p", { className: "text-xs text-muted-foreground", children: "3. The member backup will be downloaded" })] })] }))] }));
}