Files
dark-lord/components/AccountCreation.tsx
drjones 78a071ba02 Harden onion boot flow and deepen site surfaces
Add persistent onion key backup and restore, improve startup resilience, and flesh out the major site verticals with richer navigation, search coverage, and operator documentation.

Made-with: Cursor
2026-04-07 21:35:52 -07:00

173 lines
6.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"use client";
import Link from "next/link";
import { useState } from "react";
const AccountCreation = () => {
const [step, setStep] = useState(1);
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const [recoveryPhrase, setRecoveryPhrase] = useState("");
const [encryptionKey, setEncryptionKey] = useState("");
const [generated, setGenerated] = useState(false);
const generateRecovery = () => {
const phrases = [
"phantom quantum glacier nexus",
"crimson velvet paradox silence",
"neon abyss whisper eclipse",
"zero trace ghost protocol",
];
const randomPhrase = phrases[Math.floor(Math.random() * phrases.length)];
setRecoveryPhrase(randomPhrase);
setEncryptionKey(btoa(Date.now().toString()).slice(0, 16));
setGenerated(true);
};
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
if (step < 3) {
setStep(step + 1);
} else {
alert("Identity provisioned. Keys derived locally — backup your recovery phrase offline.");
}
};
return (
<div className="glass mx-auto max-w-2xl rounded-3xl border border-white/10 p-10">
<h2 className="mb-8 font-orbitron text-4xl font-bold text-center">CREATE SHADOW IDENTITY</h2>
{/* Steps */}
<div className="mb-10 flex justify-between">
{[1, 2, 3].map((s) => (
<div key={s} className="flex flex-col items-center">
<div
className={`flex h-12 w-12 items-center justify-center rounded-full border-2 text-lg font-bold ${step >= s
? "border-neon-cyan bg-neon-cyan/20 text-neon-cyan"
: "border-white/20 text-foreground/40"
}`}
>
{s}
</div>
<div className="mt-2 text-sm">
{s === 1 && "Credentials"}
{s === 2 && "Recovery"}
{s === 3 && "Encryption"}
</div>
</div>
))}
</div>
<form onSubmit={handleSubmit}>
{step === 1 && (
<div className="space-y-6">
<div>
<label className="mb-2 block font-medium">Shadow Alias</label>
<input
type="text"
className="glass w-full rounded-xl border border-white/10 bg-transparent p-4"
placeholder="e.g., Ghost_23"
value={username}
onChange={(e) => setUsername(e.target.value)}
required
/>
<p className="mt-2 text-sm text-foreground/60">Never your real name. This alias is encrypted.</p>
</div>
<div>
<label className="mb-2 block font-medium">ZeroKnowledge Password</label>
<input
type="password"
className="glass w-full rounded-xl border border-white/10 bg-transparent p-4"
placeholder="••••••••••"
value={password}
onChange={(e) => setPassword(e.target.value)}
required
/>
<p className="mt-2 text-sm text-foreground/60">We never store your password. Its used to derive your encryption key.</p>
</div>
</div>
)}
{step === 2 && (
<div className="space-y-6">
<div>
<label className="mb-2 block font-medium">Recovery Phrase</label>
<div className="glass rounded-xl border border-neon-cyan/30 p-6 font-mono text-center text-lg">
{generated ? recoveryPhrase : "Click generate to create"}
</div>
<button
type="button"
className="mt-4 w-full rounded-full bg-gradient-to-r from-neon-cyan to-neon-purple py-3 font-bold text-background"
onClick={generateRecovery}
>
GENERATE RECOVERY PHRASE
</button>
<p className="mt-4 text-sm text-foreground/60">
Write this down physically. Its the only way to recover your account. We do not store it.
</p>
</div>
</div>
)}
{step === 3 && (
<div className="space-y-6">
<div>
<label className="mb-2 block font-medium">Encryption Key</label>
<div className="glass rounded-xl border border-neon-green/30 p-6 font-mono text-center text-lg">
{encryptionKey || "Not generated"}
</div>
<p className="mt-4 text-sm text-foreground/60">
This key encrypts all your data locally. It is derived from your password and never leaves your device.
</p>
</div>
<div className="rounded-xl bg-gradient-to-r from-neon-cyan/10 to-neon-purple/10 p-6">
<h3 className="font-bold">Identity Summary</h3>
<div className="mt-4 grid grid-cols-2 gap-4 text-sm">
<div>Alias</div>
<div className="font-mono">{username || "—"}</div>
<div>Recovery Phrase</div>
<div className="font-mono truncate">{recoveryPhrase || "—"}</div>
<div>Encryption</div>
<div className="font-mono text-neon-green">AES256GCM</div>
</div>
</div>
</div>
)}
<div className="mt-10 flex justify-between">
<button
type="button"
className="glass rounded-full px-8 py-3 font-medium disabled:opacity-30"
onClick={() => setStep(step - 1)}
disabled={step === 1}
>
Back
</button>
<button
type="submit"
className="rounded-full bg-gradient-to-r from-neon-cyan to-neon-purple px-10 py-3 font-bold text-background"
>
{step === 3 ? "COMPLETE IDENTITY CREATION" : "CONTINUE →"}
</button>
</div>
</form>
<div className="mt-10 border-t border-white/10 pt-8 text-center text-sm text-foreground/40">
<p>Keys and aliases never leave this browser profile. Clear storage = identity loss.</p>
<p className="mt-4 text-foreground/55">
For a <strong className="text-neon-cyan/90">live stall session</strong> tied to wallet and activity feeds, use{" "}
<Link href="/sign-up" className="text-neon-cyan underline hover:text-neon-purple">
create account
</Link>{" "}
or{" "}
<Link href="/sign-in" className="text-neon-cyan underline hover:text-neon-purple">
sign in
</Link>
.
</p>
</div>
</div>
);
};
export default AccountCreation;