Files
dark-lord/app/support/page.tsx
drjones 2f928fbdc4 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
2026-04-16 00:55:28 -07:00

157 lines
6.9 KiB
TypeScript

"use client";
import Link from "next/link";
import { useMemo, useState } from "react";
import ThemedLayout from "@/components/layouts/ThemedLayout";
import { isMerchantBtcConfigured, getMerchantBtcAddress } from "@/lib/merchantBtc";
type Coin = "BTC" | "ETH" | "XMR";
function getAddresses() {
return {
BTC: (process.env.NEXT_PUBLIC_MERCHANT_BTC_ADDRESS || "").trim() || "bc1q — set NEXT_PUBLIC_MERCHANT_BTC_ADDRESS",
ETH: (process.env.NEXT_PUBLIC_ETH_ADDRESS || "").trim() || "0x — set NEXT_PUBLIC_ETH_ADDRESS",
XMR: (process.env.NEXT_PUBLIC_XMR_ADDRESS || "").trim() || "4A — set NEXT_PUBLIC_XMR_ADDRESS",
};
}
export default function SupportPage() {
const [copied, setCopied] = useState<Record<Coin, boolean>>({ BTC: false, ETH: false, XMR: false });
const btcReady = isMerchantBtcConfigured();
const btcAddr = getMerchantBtcAddress();
const addresses = useMemo(() => getAddresses(), []);
const copy = async (coin: Coin) => {
const addr = coin === "BTC" && btcReady ? btcAddr : addresses[coin];
try {
await navigator.clipboard.writeText(addr);
setCopied((p) => ({ ...p, [coin]: true }));
window.setTimeout(() => setCopied((p) => ({ ...p, [coin]: false })), 1800);
} catch {
// ignore
}
};
const displayAddr = (coin: Coin) =>
coin === "BTC" && btcReady ? btcAddr : addresses[coin];
const configured = {
BTC: btcReady,
ETH: Boolean((process.env.NEXT_PUBLIC_ETH_ADDRESS || "").trim()),
XMR: Boolean((process.env.NEXT_PUBLIC_XMR_ADDRESS || "").trim()),
};
return (
<ThemedLayout theme="editorial" siteTitle="THE OFFERING" siteSubtitle="Optional support · transparent tip jar">
<section className="container mx-auto max-w-5xl px-4 py-12">
<div className="theme-card rounded-3xl p-10 md:p-14">
<div className="text-center">
<div className="mb-3 text-[10px] uppercase tracking-widest opacity-70">optional ritual</div>
<h1 className="text-4xl font-bold md:text-5xl">
THE <span className="theme-accent">OFFERING</span>
</h1>
<p className="mx-auto mt-6 max-w-3xl text-lg opacity-80">
If this operation kept you online, throw fuel on the fire. Infrastructure and onion mirrors cost time and
hardware.
</p>
<p className="mx-auto mt-3 max-w-3xl text-sm opacity-60">
Transparent tip jar choose your asset and amount. No paywalls, no pressure, no analytics. To
configure addresses, set the corresponding env vars in{" "}
<code className="rounded bg-white/10 px-1">.env.local</code> and restart Next.
</p>
</div>
<div className="mt-12 grid grid-cols-1 gap-6 md:grid-cols-3">
{(["BTC", "ETH", "XMR"] as Coin[]).map((coin) => {
const addr = displayAddr(coin);
const isConfigured = configured[coin];
return (
<div key={coin} className="theme-card rounded-2xl p-6">
<div className="mb-1 flex items-center justify-between">
<div className="text-2xl font-bold theme-accent">{coin}</div>
{!isConfigured && (
<span className="rounded-full bg-amber-500/20 px-2 py-0.5 text-[10px] text-amber-300">
Not configured
</span>
)}
</div>
<div className="mt-3 min-h-[3.5rem] rounded-xl bg-black/40 p-3 font-mono text-xs theme-accent break-all">
{isConfigured ? addr : (
<span className="opacity-40">
Set{" "}
<code>
NEXT_PUBLIC_{coin === "BTC" ? "MERCHANT_BTC" : coin}_ADDRESS
</code>{" "}
in .env.local
</span>
)}
</div>
<button
type="button"
className={`mt-4 w-full rounded-full border-2 border-current px-5 py-3 text-sm font-bold transition-all ${
isConfigured
? "theme-accent bg-current text-white hover:opacity-90"
: "opacity-40 cursor-not-allowed"
}`}
onClick={() => void copy(coin)}
disabled={!isConfigured}
>
{copied[coin] ? "✓ COPIED" : `COPY ${coin} ADDRESS`}
</button>
</div>
);
})}
</div>
<div className="mt-12 grid grid-cols-1 gap-6 md:grid-cols-2">
<div className="theme-card rounded-2xl p-6">
<div className="mb-3 font-bold">What you're supporting</div>
<ul className="space-y-2 text-sm text-foreground/70">
<li className="flex items-start gap-2"><span></span> Onion mirror hosting and key backup infrastructure</li>
<li className="flex items-start gap-2"><span></span> More Vault unlocks, drops, and forum rings</li>
<li className="flex items-start gap-2"><span></span> More UI weirdness (the good kind)</li>
<li className="flex items-start gap-2"><span></span> The README staying accurate</li>
</ul>
</div>
<div className="theme-card rounded-2xl p-6">
<div className="mb-3 font-bold">Where to go next</div>
<div className="flex flex-wrap gap-3">
<Link
href="/account/add-funds"
className="rounded-full border border-neon-green/40 px-5 py-2 text-sm font-bold text-neon-green hover:bg-neon-green/10"
>
Add funds
</Link>
<Link
href="/market"
className="rounded-full border border-white/20 px-5 py-2 text-sm font-bold hover:border-neon-cyan/40"
>
Market
</Link>
<Link
href="/forum"
className="rounded-full border border-white/20 px-5 py-2 text-sm font-bold hover:border-neon-cyan/40"
>
Forum
</Link>
<Link
href="/"
className="rounded-full bg-neon-cyan/15 border border-neon-cyan/30 px-5 py-2 text-sm font-bold text-neon-cyan hover:bg-neon-cyan/20"
>
Hub
</Link>
</div>
</div>
</div>
<div className="mt-10 rounded-xl bg-white/5 p-4 text-center text-xs text-foreground/50">
Confirm any BTC address against the signed message on the hub before sending. Same bytes, every time.
If the address differs from a prior session, treat it as a compromise do not proceed.
</div>
</div>
</section>
</ThemedLayout>
);
}