"use client"; import { useState } from "react"; import { useRouter } from "next/navigation"; import { MANUAL_LANGUAGES, DEFAULT_MANUAL_LANGUAGE, type ManualLanguage } from "@tactical-media-broadcast-hub/core"; import { Button, Card, Input } from "../../../../components/ui/primitives"; import { api, errorMessage } from "../../../../lib/api-client"; import type { CollectiveNode } from "../../../../lib/api-types"; /** * Create a collective (operator reorder #3: the door from the no-collectives * home). Posts /collectives — the provisioner mints the room set, the founder * membership and the onboarding manual land in one transaction, then the user * is dropped on the tree. Bilingual by the same Spanish-first rule as the rest * of the product. */ export default function NewCollectivePage(): React.ReactElement { const router = useRouter(); const [name, setName] = useState(""); const [language, setLanguage] = useState(DEFAULT_MANUAL_LANGUAGE); const [description, setDescription] = useState(""); const [busy, setBusy] = useState(false); const [error, setError] = useState(null); const ready = name.trim().length >= 2; async function create(): Promise { setBusy(true); setError(null); try { const collective = await api.post("/collectives", { name: name.trim(), language, ...(description.trim() === "" ? {} : { description: description.trim() }), }); // Full navigation so the tree mounts with the new collective in place. router.push(`/streams?created=${encodeURIComponent(collective.name)}`); } catch (err) { setError(errorMessage(err)); setBusy(false); } } return (

Crear un colectivo

Se crean tres salas — abierta (pública, nunca cifrada), cerrada (cifrada desde su creación) y de acogida (con el manual de participación) — y quedas como fundador/a.

setName(e.target.value)} placeholder="Nombre del colectivo" autoFocus />