"use client";
import { useEffect, useState } from "react";
import Link from "next/link";
import { useRouter } from "next/navigation";
import {
MANUAL_INTRO,
MANUAL_PATHS_HEADING,
MANUAL_TITLE,
PARTICIPATION_MANUAL,
PARTICIPATION_PATHS,
isManualLanguage,
type ManualLanguage,
} from "@tactical-media-broadcast-hub/core";
import { Logo } from "../components/brand/logo";
import { AuthProvider, useAuth } from "../lib/auth-store";
/**
* Public participation-manual landing page (the app root).
*
* Design (docs/design/2026-10-12-collectives-architecture.md §"Participation
* manual"): the root explains the platform in plain language and offers the
* three participation paths — join a collective, start one, work on your own —
* before any auth wall. The copy is the SINGLE source in
* packages/core/src/participation-manual.ts: the provisioner posts the
* byte-identical text into onboarding rooms, so this page and the bot guide can
* never drift apart.
*
* Spanish is the primary language: the page opens in ES and the EN toggle is a
* one-tap switch, mirroring the bot's ES-first posting order.
*/
const STORAGE_KEY = "tmbh.manual.lang";
function readStoredLanguage(): ManualLanguage {
if (typeof window === "undefined") return "es";
try {
const stored = window.localStorage.getItem(STORAGE_KEY);
return isManualLanguage(stored) ? stored : "es";
} catch {
return "es";
}
}
/** Renders manual body text: blank-line paragraphs, "- " bullets. */
function ManualBody({ text }: { text: string }): React.ReactElement {
const blocks = text.split("\n\n");
return (
<>
{blocks.map((block, index) => {
const lines = block.split("\n");
return lines.every((line) => line.startsWith("- ")) ? (
{lines.map((line, i) => (
{line.slice(2)}
))}
) : (
{block}
);
})}
>
);
}
/**
* The root sits OUTSIDE the (main) route group, so its AuthProvider must be
* local: the (main) layout's provider does not wrap this page, and useAuth
* without a provider throws during prerender.
*/
export default function ManualLandingPage(): React.ReactElement {
return (
);
}
function ManualLanding(): React.ReactElement {
const { status, session } = useAuth();
const router = useRouter();
const [lang, setLang] = useState("es");
useEffect(() => setLang(readStoredLanguage()), []);
function switchLanguage(next: ManualLanguage): void {
setLang(next);
try {
window.localStorage.setItem(STORAGE_KEY, next);
} catch {
// Private-browsing refusal: the choice still holds for this view.
}
}
// Signed-in visitors go straight to the app; the manual stays reachable at /wiki.
useEffect(() => {
if (status === "authenticated") router.replace("/streams");
}, [status, router]);
const t = (text: T): string => text[lang];
return (
{/* The three participation paths — the core of the page. */}
{t(MANUAL_PATHS_HEADING)}
{PARTICIPATION_PATHS.map((path) => {
// All three land on /onboarding: that page holds the sign-in and
// create-account forms. A join link itself arrives from outside
// (the only /join route is /join/[token]); starting/solo need the
// same forms, so one destination is honest for all three.
const href = "/onboarding";
return (