Update market, account, and onion operations
Capture the current CyberLux UI, commerce, messaging, and Tor ops updates so local main can be pushed to the remote. Made-with: Cursor
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useEffect, useCallback } from "react";
|
||||
import { useState, useEffect, useCallback, useMemo } from "react";
|
||||
import Link from "next/link";
|
||||
import PayWithUsdBalanceButton from "@/components/PayWithUsdBalanceButton";
|
||||
import ThemedLayout from "@/components/layouts/ThemedLayout";
|
||||
import { getMerchantBtcAddress, isMerchantBtcConfigured } from "@/lib/merchantBtc";
|
||||
import { useAccount } from "@/contexts/AccountContext";
|
||||
@@ -58,9 +59,50 @@ export default function RafflePage() {
|
||||
const [txid, setTxid] = useState("");
|
||||
const [status, setStatus] = useState<"idle" | "success" | "error">("idle");
|
||||
const [errMsg, setErrMsg] = useState("");
|
||||
const [btcUsd, setBtcUsd] = useState<number | null>(null);
|
||||
const btcAddr = getMerchantBtcAddress();
|
||||
const btcReady = isMerchantBtcConfigured();
|
||||
|
||||
const ticketUsd = useMemo(() => {
|
||||
const r = btcUsd ?? 96000;
|
||||
const v = parseFloat(TICKET_PRICE_BTC) * r;
|
||||
return Math.round(v * 100) / 100;
|
||||
}, [btcUsd]);
|
||||
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
void (async () => {
|
||||
try {
|
||||
const res = await fetch(
|
||||
"https://api.coingecko.com/api/v3/simple/price?ids=bitcoin&vs_currencies=usd",
|
||||
{ cache: "no-store" },
|
||||
);
|
||||
const j = (await res.json()) as { bitcoin?: { usd?: number } };
|
||||
if (!cancelled && j.bitcoin?.usd && Number.isFinite(j.bitcoin.usd)) setBtcUsd(j.bitcoin.usd);
|
||||
} catch {
|
||||
if (!cancelled) setBtcUsd(96000);
|
||||
}
|
||||
})();
|
||||
return () => {
|
||||
cancelled = true;
|
||||
};
|
||||
}, []);
|
||||
|
||||
const registerBalanceTicket = useCallback(() => {
|
||||
const t = `balance-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
|
||||
const entry: Entry = {
|
||||
handle: user?.username ?? "anon",
|
||||
txid: t,
|
||||
ts: new Date().toISOString(),
|
||||
};
|
||||
const cur = loadEntries();
|
||||
const updated = [...cur, entry];
|
||||
saveEntries(updated);
|
||||
setEntries(updated);
|
||||
setStatus("success");
|
||||
setTimeout(() => setStatus("idle"), 4000);
|
||||
}, [user?.username]);
|
||||
|
||||
useEffect(() => {
|
||||
setEntries(loadEntries());
|
||||
const tick = () => setRemaining(getNextDraw() - Date.now());
|
||||
@@ -121,6 +163,7 @@ export default function RafflePage() {
|
||||
<div className="border-2 border-white p-5 text-center">
|
||||
<div className="mb-1 text-[10px] uppercase text-white/60">Ticket Price</div>
|
||||
<div className="text-2xl font-black">{TICKET_PRICE_BTC} BTC</div>
|
||||
<div className="mt-1 text-[11px] text-[#00ff41]/80">≈ ${ticketUsd.toFixed(2)} USD @ spot</div>
|
||||
</div>
|
||||
<div className="border-2 border-white p-5 text-center">
|
||||
<div className="mb-1 text-[10px] uppercase text-white/60">Entries This Round</div>
|
||||
@@ -182,6 +225,21 @@ export default function RafflePage() {
|
||||
<p className="mt-3 text-sm text-red-400">{errMsg}</p>
|
||||
)}
|
||||
|
||||
<div className="mt-6 border-2 border-[#00ff41]/40 bg-black/50 p-4">
|
||||
<h4 className="mb-2 text-sm font-black uppercase text-[#00ff41]">Pay with USD balance</h4>
|
||||
<p className="mb-3 text-[11px] text-white/60 leading-relaxed">
|
||||
Same ticket — charges your Bitcoin-funded USD balance at ≈ ${ticketUsd.toFixed(2)} (live BTC spot). No separate txid needed.
|
||||
</p>
|
||||
<PayWithUsdBalanceButton
|
||||
amountUsd={ticketUsd}
|
||||
title="Shadow Raffle ticket"
|
||||
description="Weekly draw entry"
|
||||
luxBonus={50}
|
||||
onSuccess={registerBalanceTicket}
|
||||
size="sm"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{!user && (
|
||||
<p className="mt-3 text-xs text-white/50">
|
||||
<Link href="/sign-in?next=/raffle" className="text-[#00ff41] underline">Sign in</Link>{" "}
|
||||
|
||||
Reference in New Issue
Block a user