import { r as reactExports, j as jsxRuntimeExports } from "../index.js"; import { i as isValidAutomergeUrl } from "./fullfat_node-75TjwUrn.js"; import { u as useRepo, a as useDocument } from "./index-BSpyO9eA.js"; import { h as hasVoted, a as addOption, u as unvote, v as vote } from "./poll-R5-eIJ_b.js"; import "../__vite_rsc_assets_manifest.js"; import "node:async_hooks"; import "tty"; import "util"; import "os"; import "node:crypto"; import "crypto"; import "module"; import "fs"; const PEER_ID_KEY = "p2p-poll-peer-id"; function generateUUID() { return crypto.randomUUID(); } function getPeerId() { if (typeof globalThis.localStorage === "undefined") { return generateUUID(); } let id = localStorage.getItem(PEER_ID_KEY); if (!id) { id = generateUUID(); localStorage.setItem(PEER_ID_KEY, id); } return id; } function ConnectionStatus() { const repo = useRepo(); const [connected, setConnected] = reactExports.useState(false); const updateStatus = reactExports.useCallback(() => { setConnected(repo.peers.length > 0); }, [repo]); reactExports.useEffect(() => { updateStatus(); const onChange = () => updateStatus(); repo.networkSubsystem.on("peer", onChange); repo.networkSubsystem.on("peer-disconnected", onChange); return () => { repo.networkSubsystem.off("peer", onChange); repo.networkSubsystem.off("peer-disconnected", onChange); }; }, [repo, updateStatus]); return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2 text-xs text-gray-500", children: [ /* @__PURE__ */ jsxRuntimeExports.jsx( "span", { className: `inline-block h-2 w-2 rounded-full ${connected ? "bg-green-500" : "bg-yellow-500"}` } ), connected ? "Connected" : "Connecting..." ] }); } function PollView({ docUrl }) { const [doc, changeDoc] = useDocument(docUrl); const [newOption, setNewOption] = reactExports.useState(""); const [copied, setCopied] = reactExports.useState(false); const peerId = reactExports.useMemo(() => getPeerId(), []); if (!doc) { return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex items-center justify-center py-12", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-gray-500", children: "Loading poll..." }) }); } const totalVotes = doc.options.reduce((sum, o) => sum + o.votes.length, 0); const handleAddOption = () => { const text = newOption.trim(); if (!text) return; changeDoc((d) => addOption(d, text)); setNewOption(""); }; const handleVote = (optionId) => { if (hasVoted(doc, optionId, peerId)) { changeDoc((d) => unvote(d, optionId, peerId)); } else { changeDoc((d) => vote(d, optionId, peerId)); } }; const handleCopy = () => { const url = window.location.href; navigator.clipboard.writeText(url).then(() => { setCopied(true); setTimeout(() => setCopied(false), 2e3); }); }; return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-6", children: [ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start justify-between", children: [ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [ /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { className: "text-2xl font-bold", children: doc.title }), /* @__PURE__ */ jsxRuntimeExports.jsxs("p", { className: "mt-1 text-sm text-gray-500", children: [ totalVotes, " vote", totalVotes !== 1 ? "s" : "", " total" ] }) ] }), /* @__PURE__ */ jsxRuntimeExports.jsx(ConnectionStatus, {}) ] }), /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-3", children: [ doc.options.map((option) => { const voted = hasVoted(doc, option.id, peerId); const pct = totalVotes > 0 ? option.votes.length / totalVotes * 100 : 0; return /* @__PURE__ */ jsxRuntimeExports.jsxs( "div", { className: "relative overflow-hidden rounded-lg border border-gray-200 bg-white", children: [ /* @__PURE__ */ jsxRuntimeExports.jsx( "div", { className: "absolute inset-y-0 left-0 bg-blue-50 transition-all duration-300", style: { width: `${pct}%` } } ), /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "relative flex items-center justify-between px-4 py-3", children: [ /* @__PURE__ */ jsxRuntimeExports.jsxs( "button", { onClick: () => handleVote(option.id), className: `flex items-center gap-2 text-left text-sm font-medium ${voted ? "text-blue-600" : "text-gray-700 hover:text-blue-600"}`, children: [ /* @__PURE__ */ jsxRuntimeExports.jsx( "span", { className: `flex h-5 w-5 items-center justify-center rounded border text-xs ${voted ? "border-blue-600 bg-blue-600 text-white" : "border-gray-300"}`, children: voted ? "\u2713" : "" } ), option.text ] } ), /* @__PURE__ */ jsxRuntimeExports.jsxs("span", { className: "text-sm text-gray-500", children: [ option.votes.length, " (", pct.toFixed(0), "%)" ] }) ] }) ] }, option.id ); }), doc.options.length === 0 && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "py-4 text-center text-sm text-gray-400", children: "No options yet. Add one below!" }) ] }), /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex gap-2", children: [ /* @__PURE__ */ jsxRuntimeExports.jsx( "input", { type: "text", value: newOption, onChange: (e) => setNewOption(e.target.value), onKeyDown: (e) => e.key === "Enter" && handleAddOption(), placeholder: "Add an option...", className: "flex-1 rounded-md border border-gray-300 px-3 py-2 text-sm focus:border-blue-500 focus:outline-none focus:ring-1 focus:ring-blue-500" } ), /* @__PURE__ */ jsxRuntimeExports.jsx( "button", { onClick: handleAddOption, className: "rounded-md bg-blue-600 px-4 py-2 text-sm font-medium text-white hover:bg-blue-700", children: "Add" } ) ] }), /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "border-t border-gray-200 pt-4", children: /* @__PURE__ */ jsxRuntimeExports.jsx( "button", { onClick: handleCopy, className: "rounded-md border border-gray-300 px-3 py-1.5 text-sm text-gray-600 hover:bg-gray-50", children: copied ? "Copied!" : "Copy shareable link" } ) }) ] }); } function PollPageClient({ id }) { const automergeUrl = `automerge:${id}`; if (!isValidAutomergeUrl(automergeUrl)) { return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rounded-lg border border-red-200 bg-red-50 p-6 text-center", children: [ /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { className: "text-lg font-semibold text-red-800", children: "Invalid Poll ID" }), /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mt-2 text-sm text-red-600", children: "The poll ID in the URL is not valid." }), /* @__PURE__ */ jsxRuntimeExports.jsx("a", { href: "/", className: "mt-4 inline-block text-sm text-blue-600 hover:underline", children: "Go back home" }) ] }); } return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "rounded-lg border border-gray-200 bg-white p-6 shadow-sm", children: /* @__PURE__ */ jsxRuntimeExports.jsx(PollView, { docUrl: automergeUrl }) }); } const export_4af94835fa0f = { default: PollPageClient }; export { export_4af94835fa0f };