10x every page: real interactions, kill fake content, wire everything
- ChatWidget: remove illegal seeds, real localStorage per-handle chat, honest bot replies about market/forum/funds - ForumBoard: wire to real forumState (loadForum/addThread/vote), kill fake stats and illegal seed posts - Home page: privacy features list reflects reality, footer links real - Links: kill all alert() calls, replace fake onions with real clearnet privacy resources + internal route grid - Support: per-coin copied state, env-driven addresses, real BTC addr - Inner circle: wire to AccountContext, tier system from LUX balance, remove hardcoded admin/shadow credentials and fake trading signals - Drop box: real sealed-note localStorage system, honest about no anonymous upload capability, real file picker with receipt - Messages: fully functional per-handle localStorage chat, AI-style contextual bot replies, clear history, honest about local storage - Wallets: pivot from fake PayPal accounts to Digital Access Passes, wire Buy Now to cart via ShopProduct interface - Testimonials: wire submit form to localStorage, interactive star rating 1-10, display submitted reviews above the fold - Raffle: use real merchant BTC address, real per-handle entry storage, honest LUX-only prize disclaimer, fix 0x address - Drops/Lotto: real number picker 1-49 with Quick Pick, ticket submission, match display against drawn numbers, demo disclaimer - Sanctuary: real 4-4-6-2 breathing timer, meditation passage with timer, candle-lighting with localStorage notes - Game: full playable Void Pong with canvas physics, CPU AI, scoring, rally counter, localStorage high score - Security analysis: honest architecture breakdown with real grades, layer-by-layer analysis, practical OPSEC guide, fiction banner - Trust: compute real scores from actual localStorage data (LUX, USD, forum posts, testimonials), FAQ accordion Made-with: Cursor
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
import Link from "next/link";
|
||||
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import { useAccount } from "@/contexts/AccountContext";
|
||||
import { useCart } from "@/contexts/CartContext";
|
||||
import { useWallet } from "@/contexts/WalletContext";
|
||||
import { getMerchantBtcAddress, isMerchantBtcConfigured } from "@/lib/merchantBtc";
|
||||
@@ -17,7 +18,6 @@ const CheckoutFlow = () => {
|
||||
const { lines, setLineQty, removeLine, clearCart, hydrated: cartHydrated } = useCart();
|
||||
const [step, setStep] = useState(1);
|
||||
const [paymentMethod, setPaymentMethod] = useState<"crypto" | "guest" | "card">("crypto");
|
||||
const [cryptoType, setCryptoType] = useState<"BTC" | "ETH" | "XMR">("BTC");
|
||||
const [guestEmail, setGuestEmail] = useState("");
|
||||
const [encryptionLevel, setEncryptionLevel] = useState<"standard" | "enhanced" | "quantum">("enhanced");
|
||||
const [btcUsd, setBtcUsd] = useState<number | null>(null);
|
||||
@@ -26,8 +26,10 @@ const CheckoutFlow = () => {
|
||||
const [verifyBusy, setVerifyBusy] = useState(false);
|
||||
const [payError, setPayError] = useState<string | null>(null);
|
||||
const [orderComplete, setOrderComplete] = useState(false);
|
||||
const [completedOrderId, setCompletedOrderId] = useState<string | null>(null);
|
||||
|
||||
const { usdStoreCredit, spendUsdStoreCredit, verifyBtcDeposit } = useWallet();
|
||||
const { user } = useAccount();
|
||||
const { usdStoreCredit, spendUsdStoreCredit, verifyBtcDeposit, earnLuxCredits, addVaultReceipt } = useWallet();
|
||||
|
||||
useEffect(() => {
|
||||
let cancelled = false;
|
||||
@@ -107,14 +109,34 @@ const CheckoutFlow = () => {
|
||||
const tryCompleteOrder = () => {
|
||||
setPayError(null);
|
||||
if (paymentMethod === "crypto") {
|
||||
if (!user) {
|
||||
setPayError("Sign in to charge your verified Bitcoin-funded USD balance.");
|
||||
return;
|
||||
}
|
||||
if (!spendUsdStoreCredit(orderTotalUsd)) {
|
||||
setPayError(
|
||||
`Insufficient USD balance. You need $${orderTotalUsd.toFixed(2)}. Send Bitcoin to the address below, wait for at least one confirmation, then paste the transaction ID and click Verify.`,
|
||||
`Insufficient USD balance. You need $${orderTotalUsd.toFixed(2)}. Add funds under Account → Add funds, then verify your txid.`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
const oid =
|
||||
typeof crypto !== "undefined" && "randomUUID" in crypto
|
||||
? `CYBR-${crypto.randomUUID().slice(0, 8).toUpperCase()}`
|
||||
: `CYBR-${Date.now().toString(36).toUpperCase()}`;
|
||||
setCompletedOrderId(oid);
|
||||
setOrderComplete(true);
|
||||
if (user && paymentMethod === "crypto") {
|
||||
const lux = Math.min(500, Math.max(25, Math.floor(orderTotalUsd * 2)));
|
||||
earnLuxCredits(lux);
|
||||
addVaultReceipt({
|
||||
id: oid,
|
||||
title: `Order ${oid}`,
|
||||
desc: `Checkout ${orderTotalUsd.toFixed(2)} USD · ${encryptionLevel} tier.`,
|
||||
date: new Date().toISOString().slice(0, 10),
|
||||
severity: "normal",
|
||||
});
|
||||
}
|
||||
clearCart();
|
||||
};
|
||||
|
||||
@@ -251,9 +273,17 @@ const CheckoutFlow = () => {
|
||||
<span className="font-orbitron">${usdStoreCredit.toFixed(2)}</span>
|
||||
<span className="text-foreground/60">
|
||||
{" "}
|
||||
— use after Bitcoin deposit is verified (on-chain).
|
||||
— per signed-in handle after verified Bitcoin deposits.
|
||||
</span>
|
||||
</div>
|
||||
{paymentMethod === "crypto" && !user ? (
|
||||
<p className="mb-4 rounded-lg border border-amber-500/30 bg-amber-500/10 px-4 py-3 text-sm text-amber-200">
|
||||
<Link href="/sign-in?next=/checkout" className="font-bold underline">
|
||||
Sign in
|
||||
</Link>{" "}
|
||||
to spend USD balance. You can still browse deposit instructions below.
|
||||
</p>
|
||||
) : null}
|
||||
<div className="grid grid-cols-1 gap-4 md:grid-cols-3">
|
||||
<button
|
||||
type="button"
|
||||
@@ -273,7 +303,7 @@ const CheckoutFlow = () => {
|
||||
>
|
||||
<div className="mb-4 text-4xl">👤</div>
|
||||
<div className="font-bold">Guest Checkout</div>
|
||||
<div className="mt-2 text-sm text-foreground/60">Demo — no USD charge</div>
|
||||
<div className="mt-2 text-sm text-foreground/60">No USD charge — order completes locally only</div>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
@@ -282,52 +312,29 @@ const CheckoutFlow = () => {
|
||||
onClick={() => setPaymentMethod("card")}
|
||||
>
|
||||
<div className="mb-4 text-4xl">💳</div>
|
||||
<div className="font-bold">Card (Secure)</div>
|
||||
<div className="mt-2 text-sm text-foreground/60">Demo — no USD charge</div>
|
||||
<div className="font-bold">Card</div>
|
||||
<div className="mt-2 text-sm text-foreground/60">Not enabled — use Bitcoin balance instead</div>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{paymentMethod === "crypto" && (
|
||||
<div className="mt-8">
|
||||
<label className="mb-2 block font-medium">Select Cryptocurrency</label>
|
||||
<div className="flex gap-4">
|
||||
{(["BTC", "ETH", "XMR"] as const).map((coin) => (
|
||||
<button
|
||||
key={coin}
|
||||
type="button"
|
||||
className={`glass flex-1 rounded-xl border py-4 ${cryptoType === coin ? "border-neon-cyan bg-neon-cyan/10" : "border-white/10"
|
||||
}`}
|
||||
onClick={() => setCryptoType(coin)}
|
||||
>
|
||||
<div className="text-2xl">{coin === "BTC" ? "₿" : coin === "ETH" ? "Ξ" : "⏣"}</div>
|
||||
<div className="font-bold">{coin}</div>
|
||||
</button>
|
||||
))}
|
||||
<div className="mt-8 space-y-4 rounded-xl bg-white/5 p-4">
|
||||
<div className="text-sm text-foreground/60">Bitcoin-only · estimated order total after encryption step</div>
|
||||
<div className="font-orbitron text-2xl text-neon-cyan">
|
||||
${orderTotalUsd.toLocaleString()} USD
|
||||
{orderTotalBtc != null && btcUsd != null && (
|
||||
<span className="ml-3 text-lg text-foreground/70">
|
||||
(≈ {orderTotalBtc} BTC @ ${btcUsd.toLocaleString()}/BTC)
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
{cryptoType !== "BTC" && (
|
||||
<p className="mt-4 rounded-lg bg-white/5 p-4 text-sm text-foreground/70">
|
||||
Deposits that add USD balance use <strong>Bitcoin</strong> only. Switch to BTC to see the
|
||||
deposit address. (ETH/XMR shown for display.)
|
||||
</p>
|
||||
)}
|
||||
{cryptoType === "BTC" && (
|
||||
<div className="mt-6 space-y-4 rounded-xl bg-white/5 p-4">
|
||||
<div className="text-sm text-foreground/60">Estimated order total after encryption step</div>
|
||||
<div className="font-orbitron text-2xl text-neon-cyan">
|
||||
${orderTotalUsd.toLocaleString()} USD
|
||||
{orderTotalBtc != null && btcUsd != null && (
|
||||
<span className="ml-3 text-lg text-foreground/70">
|
||||
(≈ {orderTotalBtc} BTC @ ${btcUsd.toLocaleString()}/BTC)
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<p className="text-xs text-foreground/50">
|
||||
Final total includes the encryption add-on you pick in the next step. Fund your balance
|
||||
with <strong>any amount</strong> of BTC; verified value is credited in USD at spot rate.
|
||||
You can pay this order once your balance covers the total.
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
<p className="text-xs text-foreground/50">
|
||||
Final total includes the encryption add-on you pick in the next step. Add funds on{" "}
|
||||
<Link href="/account/add-funds" className="text-neon-cyan underline">
|
||||
/account/add-funds
|
||||
</Link>{" "}
|
||||
(same balance here and at checkout).
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -342,13 +349,13 @@ const CheckoutFlow = () => {
|
||||
onChange={(e) => setGuestEmail(e.target.value)}
|
||||
/>
|
||||
<p className="mt-2 text-sm text-foreground/60">
|
||||
Guest checkout is a demo and does not charge your USD balance.
|
||||
Guest checkout does not touch your USD balance; nothing is sent to a payment processor.
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="mt-10 border-t border-white/10 pt-8">
|
||||
<h4 className="mb-4 font-orbitron text-lg font-bold text-neon-cyan">Bitcoin deposit (all checkouts)</h4>
|
||||
<h4 className="mb-4 font-orbitron text-lg font-bold text-neon-cyan">Bitcoin deposit · processor</h4>
|
||||
{!merchantReady ? (
|
||||
<p className="text-sm text-amber-300/90">
|
||||
Set <code className="rounded bg-white/10 px-1">NEXT_PUBLIC_MERCHANT_BTC_ADDRESS</code> and{" "}
|
||||
@@ -358,8 +365,12 @@ const CheckoutFlow = () => {
|
||||
) : (
|
||||
<>
|
||||
<p className="mb-3 text-sm text-foreground/70">
|
||||
Send Bitcoin to this address. After the network confirms your payment (at least one
|
||||
block), paste the transaction ID to add the equivalent USD to your balance.
|
||||
Send Bitcoin to this address. After at least one confirmation, paste the txid — credits apply
|
||||
to the signed-in handle only (see{" "}
|
||||
<Link href="/account/add-funds" className="text-neon-cyan underline">
|
||||
Add funds
|
||||
</Link>
|
||||
).
|
||||
</p>
|
||||
<div className="rounded-xl border border-white/10 bg-black/40 p-4 font-mono text-sm break-all">
|
||||
{merchantAddr}
|
||||
@@ -471,7 +482,7 @@ const CheckoutFlow = () => {
|
||||
<div className="mt-2 flex justify-between text-sm">
|
||||
<span className="text-foreground/60">Payment path</span>
|
||||
<span className="font-bold">
|
||||
{paymentMethod === "crypto" ? "Crypto (USD balance)" : "Demo (guest/card)"}
|
||||
{paymentMethod === "crypto" ? "Bitcoin-funded USD balance" : "Guest / card (local only)"}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -481,7 +492,7 @@ const CheckoutFlow = () => {
|
||||
onClick={tryCompleteOrder}
|
||||
className="rounded-full bg-gradient-to-r from-neon-cyan to-neon-purple px-10 py-3 font-bold text-background"
|
||||
>
|
||||
{paymentMethod === "crypto" ? "Charge my USD balance & complete" : "Complete demo order"}
|
||||
{paymentMethod === "crypto" ? "Charge my USD balance & complete" : "Complete order (local)"}
|
||||
</button>
|
||||
{paymentMethod === "crypto" && (
|
||||
<p className="mx-auto mt-6 max-w-xl text-xs text-foreground/50">
|
||||
@@ -506,7 +517,9 @@ const CheckoutFlow = () => {
|
||||
</p>
|
||||
<div className="my-10">
|
||||
<div className="glass mx-auto max-w-md rounded-2xl border border-white/10 p-6">
|
||||
<div className="font-orbitron text-2xl font-bold text-neon-cyan">ORDER #CYBR‑9A2F‑B8E1</div>
|
||||
<div className="font-orbitron text-2xl font-bold text-neon-cyan">
|
||||
ORDER #{completedOrderId ?? "—"}
|
||||
</div>
|
||||
<div className="mt-4 grid grid-cols-2 gap-4 text-sm">
|
||||
<div className="text-left text-foreground/60">Amount</div>
|
||||
<div className="text-right font-bold">${orderTotalUsd.toLocaleString()} USD</div>
|
||||
@@ -514,7 +527,7 @@ const CheckoutFlow = () => {
|
||||
<div className="text-right font-bold">{encryptionLevel.toUpperCase()}</div>
|
||||
<div className="text-left text-foreground/60">Payment</div>
|
||||
<div className="truncate text-right font-mono text-neon-green">
|
||||
{paymentMethod === "crypto" ? "USD balance (BTC-funded)" : "Demo guest/card"}
|
||||
{paymentMethod === "crypto" ? "USD balance (BTC-funded)" : "Guest or card (no processor)"}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user