// community.jsx — Q&A community and the activity feed. // Loaded from index.html as an ordered `text/babel` classic script (position 6 of 8). // Classic scripts share one global scope — see docs/engineering/Patterns.md §9. // ─── Community Page ───────────────────────────────────────────────────────── function CommunityPage() { const [tab, setTab] = useState("faq"); const [questions, setQuestions] = useState([]); const [features, setFeatures] = useState([]); const [selectedQ, setSelectedQ] = useState(null); const [answers, setAnswers] = useState([]); const [showAsk, setShowAsk] = useState(false); const [askTitle, setAskTitle] = useState(""); const [askBody, setAskBody] = useState(""); const [answerBody, setAnswerBody] = useState(""); const isLoggedIn = !!localStorage.getItem("zs_token"); const loadQuestions = (cat) => { fetch(`${API_BASE}/community/questions?category=${cat}&limit=50`) .then(r => { if (!r.ok) throw new Error(r.status); return r.json(); }).then(d => setQuestions(d.questions || [])); }; const loadFeatures = () => { fetch(`${API_BASE}/community/features`) .then(r => { if (!r.ok) throw new Error(r.status); return r.json(); }).then(d => setFeatures(d.features || [])); }; useEffect(() => { if (tab === "features") loadFeatures(); else loadQuestions(tab); }, [tab]); const openQuestion = (q) => { setSelectedQ(q); fetch(`${API_BASE}/community/questions/${q.id}/answers`) .then(r => { if (!r.ok) throw new Error(r.status); return r.json(); }).then(d => setAnswers(d.answers || [])); }; const submitQuestion = async () => { if (!askTitle || !askBody) return; try { await apiCall("/community/questions", { method: "POST", body: JSON.stringify({ title: askTitle, body: askBody }), }); setShowAsk(false); setAskTitle(""); setAskBody(""); loadQuestions(tab); } catch (e) { alert(e.message); } }; const submitAnswer = async () => { if (!answerBody || !selectedQ) return; try { await apiCall(`/community/questions/${selectedQ.id}/answers`, { method: "POST", body: JSON.stringify({ body: answerBody }), }); setAnswerBody(""); openQuestion(selectedQ); } catch (e) { alert(e.message); } }; const vote = async (featureId, dir) => { try { await apiCall(`/community/features/${featureId}/vote`, { method: "POST", body: JSON.stringify({ direction: dir }), }); loadFeatures(); } catch (e) { alert(e.message); } }; const tabStyle = (t) => ({ padding: "10px 20px", fontSize: 14, fontWeight: tab === t ? 600 : 400, color: tab === t ? "#22c55e" : "#666", border: "none", borderBottom: tab === t ? "2px solid #22c55e" : "2px solid transparent", background: "none", cursor: "pointer", fontFamily: "'DM Sans', sans-serif", }); const statusColor = { open: "#22c55e", planned: "#3b82f6", in_progress: "#f59e0b", shipped: "#d97706", declined: "#6e6e6e" }; return (
Get help, share knowledge, and vote on what we build next.
{f.description}
}No feature requests yet.
}{selectedQ.body}
{a.body}
Sign in as a customer to post answers.
)}Sign in as a customer to ask questions.
)} {questions.map(q => ({q.body}
No {tab === "faq" ? "FAQs" : "questions"} yet.
}Product updates, announcements, and tips from the ZenSys team.
{posts.map(p => ({p.body}
{p.admin_name &&No updates yet. Check back soon!
}