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
106 lines
4.3 KiB
TypeScript
106 lines
4.3 KiB
TypeScript
"use client";
|
|
|
|
import { FormEvent, useEffect, useRef, useState } from "react";
|
|
import Link from "next/link";
|
|
import { useRouter } from "next/navigation";
|
|
import { useAccount } from "@/contexts/AccountContext";
|
|
import { FORUM_RINGS } from "@/lib/forumRings";
|
|
import { addThread } from "@/lib/forumState";
|
|
|
|
export default function VoidAggregateSubmitPage() {
|
|
const router = useRouter();
|
|
const { user, hydrated } = useAccount();
|
|
const prefilledAuthor = useRef(false);
|
|
const [topicSlug, setTopicSlug] = useState(FORUM_RINGS[0]!.slug);
|
|
const [title, setTitle] = useState("");
|
|
const [body, setBody] = useState("");
|
|
const [author, setAuthor] = useState("");
|
|
|
|
useEffect(() => {
|
|
if (!hydrated || !user || prefilledAuthor.current) return;
|
|
setAuthor(user.displayName);
|
|
prefilledAuthor.current = true;
|
|
}, [hydrated, user]);
|
|
|
|
useEffect(() => {
|
|
if (typeof window === "undefined") return;
|
|
const q = new URLSearchParams(window.location.search).get("ring");
|
|
if (q && FORUM_RINGS.some((r) => r.slug === q)) setTopicSlug(q);
|
|
}, []);
|
|
|
|
const onSubmit = (e: FormEvent) => {
|
|
e.preventDefault();
|
|
if (!title.trim() || !body.trim()) return;
|
|
const t = addThread({
|
|
topicSlug,
|
|
title,
|
|
body,
|
|
author,
|
|
});
|
|
router.push(`/forum/post/${t.id}`);
|
|
};
|
|
|
|
return (
|
|
<div className="mx-auto max-w-2xl">
|
|
<Link href="/forum" className="font-mono text-[11px] uppercase tracking-widest text-[#ff9a3c] hover:text-[#ffcb8a]">
|
|
← Back to feed
|
|
</Link>
|
|
<h2 className="mt-6 font-mono text-xl font-bold text-[#ffcb8a]">Create submission</h2>
|
|
<p className="mt-2 text-sm text-[#b8a995]">Pick a ring, write a title, drop your text. Unsigned posts are untrusted.</p>
|
|
|
|
<form onSubmit={onSubmit} className="mt-8 space-y-5 rounded-lg border border-[#3d3228] bg-[#120e0a]/90 p-6">
|
|
<div>
|
|
<label className="block font-mono text-[10px] uppercase tracking-widest text-[#ff9a3c]/80">Ring</label>
|
|
<select
|
|
value={topicSlug}
|
|
onChange={(e) => setTopicSlug(e.target.value)}
|
|
className="mt-2 w-full rounded border-2 border-[#3d3228] bg-[#0d0a07] px-4 py-3 font-mono text-sm text-[#e7d9c8] focus:border-[#ff9a3c] focus:outline-none"
|
|
>
|
|
{FORUM_RINGS.map((r) => (
|
|
<option key={r.slug} value={r.slug} className="bg-[#0d0a07]">
|
|
r/{r.shortName} — {r.title}
|
|
</option>
|
|
))}
|
|
</select>
|
|
</div>
|
|
<div>
|
|
<label className="block font-mono text-[10px] uppercase tracking-widest text-[#ff9a3c]/80">Display name</label>
|
|
<input
|
|
value={author}
|
|
onChange={(e) => setAuthor(e.target.value)}
|
|
className="mt-2 w-full rounded border-2 border-[#3d3228] bg-[#0d0a07] px-4 py-3 font-mono text-sm text-[#e7d9c8] placeholder:text-[#5c5044] focus:border-[#ff9a3c] focus:outline-none"
|
|
placeholder="Alias"
|
|
/>
|
|
</div>
|
|
<div>
|
|
<label className="block font-mono text-[10px] uppercase tracking-widest text-[#ff9a3c]/80">Title</label>
|
|
<input
|
|
value={title}
|
|
onChange={(e) => setTitle(e.target.value)}
|
|
required
|
|
className="mt-2 w-full rounded border-2 border-[#3d3228] bg-[#0d0a07] px-4 py-3 font-mono text-sm text-[#e7d9c8] placeholder:text-[#5c5044] focus:border-[#ff9a3c] focus:outline-none"
|
|
placeholder="Be specific — searchable titles get better replies"
|
|
/>
|
|
</div>
|
|
<div>
|
|
<label className="block font-mono text-[10px] uppercase tracking-widest text-[#ff9a3c]/80">Body</label>
|
|
<textarea
|
|
value={body}
|
|
onChange={(e) => setBody(e.target.value)}
|
|
required
|
|
rows={8}
|
|
className="mt-2 w-full rounded border-2 border-[#3d3228] bg-[#0d0a07] px-4 py-3 font-mono text-sm text-[#e7d9c8] placeholder:text-[#5c5044] focus:border-[#ff9a3c] focus:outline-none"
|
|
placeholder="Context, logs (redact IPs), PGP block optional…"
|
|
/>
|
|
</div>
|
|
<button
|
|
type="submit"
|
|
className="w-full rounded border-2 border-[#ff9a3c] bg-[#ff9a3c] py-3 font-mono text-sm font-black uppercase tracking-wider text-black hover:bg-[#ffcb8a]"
|
|
>
|
|
Publish
|
|
</button>
|
|
</form>
|
|
</div>
|
|
);
|
|
}
|