/* ============================================================= * Forge Dashboard — interactive Uganda map, member dashboard, progress * ============================================================= */ function ForgeDashboard() { const [groups, setGroups] = useState([]); const [goal, setGoal] = useState({ current: 82, target: 1000 }); const [selected, setSelected] = useState(null); const [filter, setFilter] = useState("all"); const [loaded, setLoaded] = useState(false); useEffect(() => { Promise.all([window.cms.getForgeGroups(), window.cms.getForgeGoal()]).then(([g, goal]) => { setGroups(g); setGoal(goal); setLoaded(true); }).catch(() => setLoaded(true)); }, []); const filtered = filter === "all" ? groups : groups.filter((g) => g.status === filter); const totalMembers = groups.reduce((s, g) => s + g.members, 0); return (
{/* Stat strip */}
{[ { label: "Active Forge groups", value: goal.current, suffix: "" }, { label: "Men meeting weekly", value: totalMembers, suffix: "" }, { label: "Districts engaged", value: 11, suffix: "" }, { label: "Goal", value: goal.target, suffix: "" }, ].map((s, i) => (
{s.suffix}
{s.label}
))}
{/* Map + side panel */}
Forge groups across Uganda
{[["all", "All"], ["active", "Active"], ["growing", "Growing"]].map(([k, l]) => ( ))}
); } function ForgeDetail({ group, onClose }) { // Rotate through real Forge photos by group id so each Forge feels unique const groupPhotos = [ "uploads/Forge 1-104.jpg", "uploads/forge meeting event section.jpg", "uploads/FATHERS ARISE MEETING-49 (1).jpg", "uploads/FATHERS ARISE MEETING-66.jpg", "uploads/FATHERS ARISE MEETING-79.jpg", "uploads/TRG_Father_sBreakfast125.jpg" ]; const photo = groupPhotos[(group.id?.charCodeAt(0) || 0) % groupPhotos.length]; return (
{`Forge
{group.region}

{group.name}

Members
{group.members} men
Meeting
Tue · 7pm
Status
{group.status}
Curriculum
Be a Man · wk 7
); } /* ----- Uganda map (placeholder polygon) ----- */ function UgandaMap({ groups, selected, onSelect, loaded }) { // Stylised Uganda outline. Hand-drawn approximation; a real map ships from the CMS. const ugandaPath = "M 22 18 Q 30 12 42 14 L 58 14 Q 68 18 72 22 L 80 22 L 84 28 L 82 36 L 86 44 Q 86 52 82 58 L 78 64 Q 76 70 72 74 L 64 82 Q 54 86 44 82 L 30 80 Q 22 74 18 66 L 16 56 Q 12 48 16 40 L 18 30 Q 18 22 22 18 Z"; return (
Uganda · Forge network {groups.length} groups shown
{/* graticule */} {/* Uganda body */} {/* Lake Victoria (south-east blob) */} Lake Victoria {/* Region label */} NORTHERN WESTERN EASTERN CENTRAL {/* Forge markers */} {loaded && groups.map((g, i) => { const isSel = selected?.id === g.id; return ( onSelect(g)} transform={`translate(${g.x} ${g.y})`}> {/* halo */} {isSel && ( {g.name} )} ); })} {/* Legend */}
Active Growing map · placeholder geometry
); } /* ----- Member dashboard ----- */ function MemberDashboard() { const [tab, setTab] = useState("login"); const [signedIn, setSignedIn] = useState(false); return (
{!signedIn ? (
{[["login", "Sign in"], ["join", "Join a Forge"]].map(([k, l]) => ( ))}
{tab === "login" ? (
{ e.preventDefault(); setSignedIn(true); }} className="p-6 space-y-4">
Forgot? Text FORGE to 8002.
) : ( setSignedIn(true)} /> )}
) : (
Joseph K.
Welcome
Joseph K.
Forge Wakiso · Be a Man · Week 7 of 12
)}
Next meeting
Tue · 7:00pm
Forge Wakiso · Pastor Mukasa's home
  • Week 8: Repentance as a daily practice
  • Bring: your journal & a story
); } function ProgressRing({ label, value, max, color }) { const pct = (value / max) || 0; const r = 44, c = 2 * Math.PI * r; const [ref, inView] = useInView(); return (
{value}/{max}
weeks
In progress
{label}
{Math.round(pct * 100)}% complete
); } function StepIndicator({ label, filled, total }) { return (
{label}
{Array.from({ length: total }).map((_, i) => ( {i < filled ? "✓" : i + 1} ))}
{filled} of {total} weeks attended
); } function JoinForgeForm({ onComplete }) { const [form, setForm] = useState({ name: "", phone: "", region: "", commit: false }); const [err, setErr] = useState({}); const submit = (e) => { e.preventDefault(); const errs = {}; if (!form.name.trim()) errs.name = "Required"; if (!/^[+0-9 -]{7,}$/.test(form.phone)) errs.phone = "Enter a valid phone"; if (!form.region) errs.region = "Pick a region"; if (!form.commit) errs.commit = "Confirm the weekly commitment"; setErr(errs); if (Object.keys(errs).length === 0) onComplete(); }; const set = (k) => (e) => setForm({ ...form, [k]: e.target.type === "checkbox" ? e.target.checked : e.target.value }); return (
); } window.ForgeDashboard = ForgeDashboard;