Add implementation

This commit is contained in:
yannickschuchmann
2026-03-08 18:01:28 +00:00
parent cc5394c3db
commit b936095286
56 changed files with 68376 additions and 49 deletions

210
dist/public/assets/_id_-cxsEKuSj.js vendored Normal file
View File

@@ -0,0 +1,210 @@
import { r as a, j as e, __tla as __tla_0 } from "./index-I8cR0Dsm.js";
import { i as j, __tla as __tla_1 } from "./fullfat_bundler-C8o4MXnP.js";
import { u as v, a as N } from "./index-ChbWTil4.js";
import { h as p, a as w, u as C, v as k } from "./poll-BI_0HvZY.js";
let $;
let __tla = Promise.all([
(() => {
try {
return __tla_0;
} catch {
}
})(),
(() => {
try {
return __tla_1;
} catch {
}
})()
]).then(async () => {
const h = "p2p-poll-peer-id";
function g() {
return crypto.randomUUID();
}
function S() {
if (typeof globalThis.localStorage > "u") return g();
let s = localStorage.getItem(h);
return s || (s = g(), localStorage.setItem(h, s)), s;
}
function D() {
const s = v(), [r, d] = a.useState(false), l = a.useCallback(() => {
d(s.peers.length > 0);
}, [
s
]);
return a.useEffect(() => {
l();
const o = () => l();
return s.networkSubsystem.on("peer", o), s.networkSubsystem.on("peer-disconnected", o), () => {
s.networkSubsystem.off("peer", o), s.networkSubsystem.off("peer-disconnected", o);
};
}, [
s,
l
]), e.jsxs("div", {
className: "flex items-center gap-2 text-xs text-gray-500",
children: [
e.jsx("span", {
className: `inline-block h-2 w-2 rounded-full ${r ? "bg-green-500" : "bg-yellow-500"}`
}),
r ? "Connected" : "Connecting..."
]
});
}
function I({ docUrl: s }) {
const [r, d] = N(s), [l, o] = a.useState(""), [b, u] = a.useState(false), i = a.useMemo(() => S(), []);
if (!r) return e.jsx("div", {
className: "flex items-center justify-center py-12",
children: e.jsx("div", {
className: "text-gray-500",
children: "Loading poll..."
})
});
const c = r.options.reduce((t, n) => t + n.votes.length, 0), x = () => {
const t = l.trim();
t && (d((n) => w(n, t)), o(""));
}, f = (t) => {
p(r, t, i) ? d((n) => C(n, t, i)) : d((n) => k(n, t, i));
}, y = () => {
const t = window.location.href;
navigator.clipboard.writeText(t).then(() => {
u(true), setTimeout(() => u(false), 2e3);
});
};
return e.jsxs("div", {
className: "space-y-6",
children: [
e.jsxs("div", {
className: "flex items-start justify-between",
children: [
e.jsxs("div", {
children: [
e.jsx("h2", {
className: "text-2xl font-bold",
children: r.title
}),
e.jsxs("p", {
className: "mt-1 text-sm text-gray-500",
children: [
c,
" vote",
c !== 1 ? "s" : "",
" total"
]
})
]
}),
e.jsx(D, {})
]
}),
e.jsxs("div", {
className: "space-y-3",
children: [
r.options.map((t) => {
const n = p(r, t.id, i), m = c > 0 ? t.votes.length / c * 100 : 0;
return e.jsxs("div", {
className: "relative overflow-hidden rounded-lg border border-gray-200 bg-white",
children: [
e.jsx("div", {
className: "absolute inset-y-0 left-0 bg-blue-50 transition-all duration-300",
style: {
width: `${m}%`
}
}),
e.jsxs("div", {
className: "relative flex items-center justify-between px-4 py-3",
children: [
e.jsxs("button", {
onClick: () => f(t.id),
className: `flex items-center gap-2 text-left text-sm font-medium ${n ? "text-blue-600" : "text-gray-700 hover:text-blue-600"}`,
children: [
e.jsx("span", {
className: `flex h-5 w-5 items-center justify-center rounded border text-xs ${n ? "border-blue-600 bg-blue-600 text-white" : "border-gray-300"}`,
children: n ? "\u2713" : ""
}),
t.text
]
}),
e.jsxs("span", {
className: "text-sm text-gray-500",
children: [
t.votes.length,
" (",
m.toFixed(0),
"%)"
]
})
]
})
]
}, t.id);
}),
r.options.length === 0 && e.jsx("p", {
className: "py-4 text-center text-sm text-gray-400",
children: "No options yet. Add one below!"
})
]
}),
e.jsxs("div", {
className: "flex gap-2",
children: [
e.jsx("input", {
type: "text",
value: l,
onChange: (t) => o(t.target.value),
onKeyDown: (t) => t.key === "Enter" && x(),
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"
}),
e.jsx("button", {
onClick: x,
className: "rounded-md bg-blue-600 px-4 py-2 text-sm font-medium text-white hover:bg-blue-700",
children: "Add"
})
]
}),
e.jsx("div", {
className: "border-t border-gray-200 pt-4",
children: e.jsx("button", {
onClick: y,
className: "rounded-md border border-gray-300 px-3 py-1.5 text-sm text-gray-600 hover:bg-gray-50",
children: b ? "Copied!" : "Copy shareable link"
})
})
]
});
}
function U({ id: s }) {
const r = `automerge:${s}`;
return j(r) ? e.jsx("div", {
className: "rounded-lg border border-gray-200 bg-white p-6 shadow-sm",
children: e.jsx(I, {
docUrl: r
})
}) : e.jsxs("div", {
className: "rounded-lg border border-red-200 bg-red-50 p-6 text-center",
children: [
e.jsx("h2", {
className: "text-lg font-semibold text-red-800",
children: "Invalid Poll ID"
}),
e.jsx("p", {
className: "mt-2 text-sm text-red-600",
children: "The poll ID in the URL is not valid."
}),
e.jsx("a", {
href: "/",
className: "mt-4 inline-block text-sm text-blue-600 hover:underline",
children: "Go back home"
})
]
});
}
$ = {
default: U
};
});
export {
__tla,
$ as export_4af94835fa0f
};

49
dist/public/assets/_layout-C9jEQBWP.js vendored Normal file
View File

@@ -0,0 +1,49 @@
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/repo-CjvObF6Z.js","assets/fullfat_bundler-C8o4MXnP.js"])))=>i.map(i=>d[i]);
import { r as a, _ as l, j as i, __tla as __tla_0 } from "./index-I8cR0Dsm.js";
import { R as p } from "./index-ChbWTil4.js";
let v;
let __tla = Promise.all([
(() => {
try {
return __tla_0;
} catch {
}
})()
]).then(async () => {
function f({ children: c }) {
const [o, d] = a.useState(null);
return a.useEffect(() => {
let n, e;
return l(async () => {
const { getRepo: t, cleanupRepo: r } = await import("./repo-CjvObF6Z.js").then(async (m) => {
await m.__tla;
return m;
});
return {
getRepo: t,
cleanupRepo: r
};
}, __vite__mapDeps([0,1])).then(({ getRepo: t, cleanupRepo: r }) => {
const s = t();
d(s), n = r, e = () => {
s.networkSubsystem.adapters.forEach((u) => u.disconnect());
}, window.addEventListener("beforeunload", e);
}), () => {
e && window.removeEventListener("beforeunload", e), n == null ? void 0 : n();
};
}, []), o ? i.jsx(p.Provider, {
value: o,
children: c
}) : i.jsx("div", {
className: "flex min-h-screen items-center justify-center text-gray-400",
children: "Loading..."
});
}
v = {
default: f
};
});
export {
__tla,
v as export_125820ecd802
};

File diff suppressed because one or more lines are too long

Binary file not shown.

6
dist/public/assets/client-CsOmnPdF.js vendored Normal file
View File

@@ -0,0 +1,6 @@
import { I as r, E as o, S as e, C as t } from "./index-I8cR0Dsm.js";
const n = { Children: t, Slot: e }, s = { ErrorBoundary: o, INTERNAL_ServerRouter: r };
export {
s as export_6d786e16fc6b,
n as export_847a2b1045ef
};

File diff suppressed because it is too large Load Diff

21
dist/public/assets/index-BQZM9uZj.js vendored Normal file
View File

@@ -0,0 +1,21 @@
import { r as i, j as t } from "./index-I8cR0Dsm.js";
import { u as m } from "./index-ChbWTil4.js";
import { c as x } from "./poll-BI_0HvZY.js";
function p() {
const [o, d] = i.useState(""), [r, c] = i.useState(""), u = m(), s = () => {
if (!o.trim()) return;
const e = u.create();
e.change((l) => {
const a = x(o.trim());
l.title = a.title, l.options = a.options;
}), window.location.href = `/poll/${e.documentId}`;
}, n = () => {
const e = r.trim();
e && (window.location.href = `/poll/${e}`);
};
return t.jsxs("div", { className: "space-y-8", children: [t.jsx("title", { children: "P2P Poll" }), t.jsxs("section", { className: "rounded-lg border border-gray-200 bg-white p-6 shadow-sm", children: [t.jsx("h2", { className: "mb-4 text-lg font-semibold", children: "Create a New Poll" }), t.jsxs("div", { className: "flex gap-2", children: [t.jsx("input", { type: "text", value: o, onChange: (e) => d(e.target.value), onKeyDown: (e) => e.key === "Enter" && s(), placeholder: "Enter poll title...", 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" }), t.jsx("button", { onClick: s, className: "rounded-md bg-blue-600 px-4 py-2 text-sm font-medium text-white hover:bg-blue-700", children: "Create" })] })] }), t.jsxs("section", { className: "rounded-lg border border-gray-200 bg-white p-6 shadow-sm", children: [t.jsx("h2", { className: "mb-4 text-lg font-semibold", children: "Join an Existing Poll" }), t.jsxs("div", { className: "flex gap-2", children: [t.jsx("input", { type: "text", value: r, onChange: (e) => c(e.target.value), onKeyDown: (e) => e.key === "Enter" && n(), placeholder: "Paste poll ID or link...", 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" }), t.jsx("button", { onClick: n, className: "rounded-md bg-gray-600 px-4 py-2 text-sm font-medium text-white hover:bg-gray-700", children: "Join" })] })] })] });
}
const f = { default: p };
export {
f as export_5ce7e027532e
};

2543
dist/public/assets/index-ChbWTil4.js vendored Normal file

File diff suppressed because it is too large Load Diff

10668
dist/public/assets/index-I8cR0Dsm.js vendored Normal file

File diff suppressed because it is too large Load Diff

27
dist/public/assets/poll-BI_0HvZY.js vendored Normal file
View File

@@ -0,0 +1,27 @@
function u(n) {
return { title: n, options: [] };
}
function c(n, t) {
n.options.push({ id: crypto.randomUUID(), text: t, votes: [] });
}
function f(n, t, i) {
const o = n.options.find((s) => s.id === t);
return o ? o.votes.includes(i) : false;
}
function r(n, t, i) {
const o = n.options.find((s) => s.id === t);
o && (o.votes.includes(i) || o.votes.push(i));
}
function d(n, t, i) {
const o = n.options.find((e) => e.id === t);
if (!o) return;
const s = o.votes.indexOf(i);
s !== -1 && o.votes.splice(s, 1);
}
export {
c as a,
u as c,
f as h,
d as u,
r as v
};

1254
dist/public/assets/repo-CjvObF6Z.js vendored Normal file

File diff suppressed because it is too large Load Diff