I want my Total BTC data in Bitcoin-Payment.tsx to be taken and when I click the "Pay with BTC" button, I want it to be directed to the 2nd page, BtcPaymentConfirmation.tsx, and I want the total data on the 1st page to appear in the "amount:" section, along with the 8-digit random order number. Can you help me?
//btc-payment.tsx page(1.page)
"use client";
import AnimationContainer from "@/components/global/animation-container";
import React, { useState, useEffect } from "react";
import axios from "axios";
import { FaCreditCard, FaMoneyBillWave } from "react-icons/fa";
import { useRouter } from "next/compat/router";
const BtcPayment = () => {
const [selectedProduct, setSelectedProduct] = useState<string | null>(null);
const [selectedCardSubType, setSelectedCardSubType] = useState<string | null>(null);
const [selectedBalanceType, setSelectedBalanceType] = useState<string | null>(null);
const [isLoading, setIsLoading] = useState(false);
const [btcRate, setBtcRate] = useState<number | null>(null);
const router = useRouter();
const handlePayment = () => {
const orderNumber = Math.floor(10000000 + Math.random() * 90000000).toString();
const total = selectedProduct
? (selectedProduct === "Virtual Subscription" && selectedBalanceType
? {
"$50": 5,
"$100": 10,
"$200": 20,
}[selectedBalanceType] || 0
: products.find(p => p.name === selectedProduct)?.usdPrice! || 0) / (btcRate || 1)
: 0;
if (total > 0) {
if (router) {
router.push({
pathname: "/BtcPaymentConfirmation",
query: { orderNumber, btcAmount: total.toFixed(4) },
});
}
} else {
console.error("Total amount is zero or invalid");
}
};
// Updated products with random names and options
const products = [
{ name: "Digital Product A", usdPrice: 100, icon: <FaCreditCard /> },
{ name: "Digital Product B", usdPrice: 200, icon: <FaCreditCard /> },
{ name: "Virtual Subscription", usdPrice: 50, icon: <FaMoneyBillWave /> },
];
useEffect(() => {
const fetchBtcRate = async () => {
try {
const response = await axios.get("https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=usd");
setBtcRate(response.data.bitcoin.usd);
} catch (error) {
console.error("Error fetching BTC rate:", error);
}
};
fetchBtcRate();
const interval = setInterval(fetchBtcRate, 60000);
return () => clearInterval(interval);
}, []);
const handleProductSelect = (productName: string) => {
setSelectedProduct(productName === selectedProduct ? null : productName);
setSelectedCardSubType(null);
setSelectedBalanceType(null);
};
const total = selectedProduct
? (selectedProduct === "Virtual Subscription" && selectedBalanceType
? {
"$50": 5,
"$100": 10,
"$200": 20,
}[selectedBalanceType] || 0
: products.find(p => p.name === selectedProduct)?.usdPrice! || 0) / (btcRate || 1)
: 0;
return (
<div className="flex flex-col items-center justify-center py-20">
<AnimationContainer delay={0.1}>
<h1 className="text-2xl md:text-4xl lg:text-5xl font-semibold font-heading text-center mt-6 !leading-tight">
Select Your Product
</h1>
<p className="text-base md:text-lg mt-6 text-center text-muted-foreground">
Choose the product you want to purchase with BTC.
</p>
</AnimationContainer>
<div className="mt-10 w-full max-w-md">
<div className="flex flex-col items-center mt-4 space-y-4">
{products.map((product) => (
<button
key={product.name}
className={`w-full p-2 rounded border flex items-center justify-between ${
selectedProduct === product.name
? "bg-primary text-primary-foreground"
: "bg-white text-black"
}`}
onClick={() => handleProductSelect(product.name)}
>
<span className="flex items-center space-x-2">
{product.icon}
<span>{product.name}</span>
</span>
<span>{btcRate ? (product.usdPrice / btcRate).toFixed(4) : "Loading..."} BTC</span>
</button>
))}
{selectedProduct && (selectedProduct === "Digital Product A" || selectedProduct === "Digital Product B") && (
<div className="mt-6 w-full max-w-xs border-t pt-4">
<p className="text-center mb-2">Choose Card Type</p>
<div className="flex justify-center space-x-4">
{["Visa", "MasterCard", "American Express"].map((cardType) => (
<button
key={cardType}
className={`px-4 py-2 rounded border ${
selectedCardSubType === cardType
? "bg-primary text-primary-foreground"
: "bg-white text-black"
}`}
onClick={() => setSelectedCardSubType(cardType)}
>
{cardType}
</button>
))}
</div>
</div>
)}
{selectedProduct === "Virtual Subscription" && (
<div className="mt-6 w-full max-w-xs border-t pt-4">
<p className="text-center mb-2">Choose Balance Type</p>
<div className="flex justify-center space-x-4">
{["$50", "$100", "$200"].map((balanceType) => (
<button
key={balanceType}
className={`px-4 py-2 rounded border ${
selectedBalanceType === balanceType
? "bg-primary text-primary-foreground"
: "bg-white text-black"
}`}
onClick={() => setSelectedBalanceType(balanceType)}
>
{balanceType}
</button>
))}
</div>
</div>
)}
</div>
<div className="mt-6 text-center">
<p className="text-lg font-medium">
Total: {total.toFixed(4)} BTC
</p>
<button
className="inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 active:scale-95 transition-all bg-primary text-primary-foreground hover:bg-primary/90 primary h-9 px-4 py-2 mt-4"
disabled={
isLoading ||
!selectedProduct ||
((selectedProduct === "Digital Product A" || selectedProduct === "Digital Product B") && !selectedCardSubType) ||
(selectedProduct === "Virtual Subscription" && !selectedBalanceType)
}
onClick={handlePayment}
>
{isLoading ? (
<span className="loader mr-2"></span>
) : (
"Pay with BTC"
)}
</button>
</div>
{selectedProduct && (
<div className="mt-6 text-center">
<p className="text-lg font-semibold">Selected Product: {selectedProduct}</p>
{selectedProduct === "Virtual Subscription" && selectedBalanceType && (
<p className="text-md">Balance Type: {selectedBalanceType}</p>
)}
{(selectedProduct === "Digital Product A" || selectedProduct === "Digital Product B") && selectedCardSubType && (
<p className="text-md">Card Type: {selectedCardSubType}</p>
)}
</div>
)}
</div>
<style jsx>{`
.loader {
border: 4px solid rgba(255, 255, 255, 0.3);
border-top: 4px solid #ffffff;
border-radius: 50%;
width: 24px;
height: 24px;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}
`}</style>
</div>
);
};
export default BtcPayment;
//BtcPaymentConfirmation.tsx (2.page)
"use client"
import { BorderBeam } from "@/components/ui/border-beam";
import { useEffect, useState } from "react";
import { Copy } from 'lucide-react'; // Importing the Copy icon
const BtcPaymentConfirmation = () => {
const [timeLeft, setTimeLeft] = useState(900); // 15-minute countdown
const [copyMessage, setCopyMessage] = useState(""); // State for copy feedback
const walletAddress = "bc1qmpph23yp6dgqwd2dzee02djauevp9d57rqw8nu"; // Replace with actual wallet address
// Google Charts API URL for QR code generation
const qrCodeUrl = `https://api.qrserver.com/v1/create-qr-code/?size=180x180&data=${encodeURIComponent(walletAddress)}`;
// Countdown timer
useEffect(() => {
if (timeLeft > 0) {
const timer = setInterval(() => setTimeLeft(prev => prev - 1), 1000);
return () => clearInterval(timer);
}
}, [timeLeft]);
const formatTime = (seconds: number) => {
const minutes = Math.floor(seconds / 60);
const remainingSeconds = seconds % 60;
return `${minutes}:${remainingSeconds < 10 ? '0' : ''}${remainingSeconds}`;
};
const percentageLeft = (timeLeft / 900) * 100; // Calculate percentage left
// Function to copy wallet address
const copyToClipboard = () => {
navigator.clipboard.writeText(walletAddress).then(() => {
setCopyMessage("Copied!"); // Show feedback message
setTimeout(() => setCopyMessage(""), 2000); // Clear message after 2 seconds
}).catch(err => {
console.error('Failed to copy: ', err);
});
};
return (
<div className="flex items-center justify-center min-h-screen">
<div className="shadow-md rounded-lg p-8 w-full max-w-lg text-center border border-white">
<h1 className="text-2xl md:text-4xl lg:text-5xl font-semibold font-heading mt-4 mb-4">Payment Confirmation</h1>
<p className="text-lg font-semibold mb-2">Order Number:</p>
<p className="text-lg mb-4 font-semibold font-heading">Amount:</p>
<div className="relative mt-4 border-2 border-violet-500 rounded p-1 inline-block"> {/* Tighter frame design */}
<img src={qrCodeUrl} alt="QR Code" width={180} height={180} className="mx-auto" />
</div>
<p className="text-center mt-2">Scan to Pay</p>
<div className="mt-6">
<p className="text-center text-sm font-semibold font-heading">Wallet Address:</p>
<div className="flex items-center justify-center">
<p className="text-sm font-semibold font-heading mr-2">{walletAddress}</p>
<button
onClick={copyToClipboard}
className="p-2 text-white rounded flex items-center justify-center"
aria-label="Copy wallet address"
>
<Copy className="h-5 w-5" />
</button>
</div>
{copyMessage && <p className="text-white font-semibold font-heading mt-2">{copyMessage}</p>} {/* Feedback message */}
</div>
<div className="mt-6 text-lg font-semibold font-heading text-white">
<span className="text-transparent bg-gradient-to-r from-violet-500 to-fuchsia-500 bg-clip-text inline-block">
Complete your payment in: {formatTime(timeLeft)}
</span>
</div>
{/* Countdown bar */}
<div className="mt-4 h-4 bg-gray-500 rounded">
<div
className="h-full bg-white rounded"
style={{ width: `${percentageLeft}%` }}
/>
</div>
</div>
</div>
);
};
export default BtcPaymentConfirmation;