// ---- Root app ----

// แบนเนอร์ประกาศบนหน้าสมาชิก — ดึงประกาศที่ active จากตาราง announcements
// แสดงทีละอัน หมุนเปลี่ยนทุก 5 วินาที (carousel). ปิดได้ต่อ session โดยจำคีย์
// เป็น "รายการ id ของประกาศที่ active" → ถ้ามีประกาศใหม่/เปลี่ยน แบนเนอร์จะเด้งกลับมา
const AnnouncementBanner = () => {
  const [items, setItems] = React.useState([]);
  const [idx, setIdx] = React.useState(0);
  const [dismissed, setDismissed] = React.useState(false);
  const [lightbox, setLightbox] = React.useState(false);

  React.useEffect(() => {
    let alive = true;
    const load = async () => {
      const { data } = await sb.from("announcements")
        .select("*")
        .eq("active", true)
        .order("sort_order", { ascending: true })
        .order("created_at", { ascending: true });
      if (!alive) return;
      // ประกาศที่ตั้งเป็นป๊อบอัพ แสดงเฉพาะเป็นป๊อบอัพ ไม่ต้องโผล่ในแถบบน
      const rows = (data || []).filter(a => !a.popup);
      setItems(rows);
      setIdx(0);
      const key = `${window.TENANT.prefix}.announce.dismissed`;
      const sig = rows.map(r => r.id).join(",");
      setDismissed(rows.length > 0 && sessionStorage.getItem(key) === sig);
    };
    load();
    const timer = window.setInterval(load, 60000);
    return () => { alive = false; window.clearInterval(timer); };
  }, []);

  // หมุนเปลี่ยนประกาศทุก 5 วิ เมื่อมีมากกว่า 1 อัน
  React.useEffect(() => {
    if (items.length <= 1) return;
    const timer = window.setInterval(() => {
      setIdx(i => (i + 1) % items.length);
    }, 5000);
    return () => window.clearInterval(timer);
  }, [items.length]);

  const dismiss = (e) => {
    if (e) e.stopPropagation();
    const key = `${window.TENANT.prefix}.announce.dismissed`;
    sessionStorage.setItem(key, items.map(r => r.id).join(","));
    setDismissed(true);
  };

  if (dismissed || !items.length) return null;
  const cur = items[Math.min(idx, items.length - 1)];
  const img = announceImageSrc(cur.image_path);

  return (
    <>
      <div className="announce-banner" onClick={() => img && setLightbox(true)}>
        {img && <img src={img} className="announce-thumb" alt="ประกาศ" />}
        <div className="announce-text" key={cur.id}>
          {cur.tag && <span className="announce-tag">{cur.tag}</span>}
          {cur.message && <span className="announce-msg">{cur.message}</span>}
        </div>
        {items.length > 1 && (
          <div className="announce-dots" onClick={e => e.stopPropagation()}>
            {items.map((it, i) => (
              <button key={it.id} className={`announce-dot ${i === idx ? "on" : ""}`}
                onClick={() => setIdx(i)} aria-label={`ประกาศที่ ${i + 1}`} />
            ))}
          </div>
        )}
        <button className="announce-close" onClick={dismiss} aria-label="ปิด">✕</button>
      </div>

      {lightbox && img && (
        <div className="announce-lightbox" onClick={() => setLightbox(false)}>
          <img src={img} alt="ประกาศ" onClick={e => e.stopPropagation()} />
          <button className="announce-lb-close" onClick={() => setLightbox(false)}>✕</button>
        </div>
      )}
    </>
  );
};

// ป๊อบอัพโปสเตอร์โฆษณาเต็มจอ — เปิดเฉพาะประกาศที่ตั้ง popup = true พร้อมช่วงเวลา
// [popup_start, popup_end] (ไม่บังคับ). เด้งครั้งเดียวต่อ session ของเบราว์เซอร์
const AdPopup = () => {
  const STORAGE_KEY = `${window.TENANT.prefix}.adpopup.dismissed`;
  const [items, setItems] = React.useState(null); // null = loading
  const [open, setOpen] = React.useState(false);

  React.useEffect(() => {
    let alive = true;
    const now = new Date().toISOString();
    sb.from("announcements")
      .select("*")
      .eq("active", true)
      .eq("popup", true)
      .order("sort_order", { ascending: true })
      .order("created_at", { ascending: true })
      .then(({ data, error }) => {
        if (!alive) return;
        const live = (error ? [] : (data || [])).filter(a =>
          (!a.popup_start || a.popup_start <= now) &&
          (!a.popup_end || a.popup_end >= now));
        setItems(live);
      });
    return () => { alive = false; };
  }, []);

  // จำการปิดผูกกับชุดป๊อบอัพที่ active → ถ้ามีป๊อบอัพใหม่จะเด้งใหม่รอบหน้า
  const signature = React.useMemo(() => (items || []).map(a => a.id).join(","), [items]);

  React.useEffect(() => {
    if (!items || !items.length) { setOpen(false); return; }
    setOpen(sessionStorage.getItem(STORAGE_KEY) !== signature);
  }, [signature, items]);

  const close = React.useCallback(() => {
    sessionStorage.setItem(STORAGE_KEY, signature);
    setOpen(false);
  }, [signature]);

  React.useEffect(() => {
    if (!open) return;
    const onKey = (e) => { if (e.key === "Escape") close(); };
    window.addEventListener("keydown", onKey);
    document.body.style.overflow = "hidden";
    return () => {
      window.removeEventListener("keydown", onKey);
      document.body.style.overflow = "";
    };
  }, [open, close]);

  if (!open || !items || !items.length) return null;

  const cur = items[0];
  const img = announceImageSrc(cur.image_path);

  return (
    <div className="ad-popup-overlay" onClick={close}>
      <div className="ad-popup-card" onClick={e => e.stopPropagation()}>
        <button className="ad-popup-close" onClick={close} aria-label="ปิด">✕</button>
        {img ? (
          // มีรูปโปสเตอร์ = โชว์รูปอย่างเดียว ไม่ต้องมีข้อความ
          <img src={img} className="ad-popup-img" alt="โฆษณา" />
        ) : (cur.tag || cur.message) && (
          // ไม่มีรูป = fallback เป็นการ์ดข้อความ
          <div className="ad-popup-text">
            {cur.tag && <span className="ad-popup-tag">{cur.tag}</span>}
            {cur.message && <span className="ad-popup-msg">{cur.message}</span>}
          </div>
        )}
      </div>
    </div>
  );
};

// Section ต่างๆ บนหน้า public ใช้สำหรับ scroll-spy + breadcrumb (ไม่ผูกกับเมนูทางลัด)
const SECTIONS = [
  { id: "overview",          label: "สรุปให้แล้ว" },
  { id: "ape-goal",          label: "เช็กเป้า" },
  { id: "training",          label: "คลับอัปสกิล" },
  { id: "daily-challenges",  label: "Daily challenges" },
];

// ---- "มีอะไรใหม่" (ป๊อปอัพ changelog) — สร้างอัตโนมัติจาก commit log ----
// window.APP_CHANGELOG มาจาก changelog.js ที่ pre-commit hook เขียนใหม่ทุก commit
const CHANGELOG_TYPE = {
  feat:     { tag: "ใหม่",     color: "#3F7A54" },
  fix:      { tag: "แก้ไข",    color: "#E2AA4C" },
  style:    { tag: "ปรับปรุง", color: "#6D98C7" },
  refactor: { tag: "ปรับปรุง", color: "#6D98C7" },
  perf:     { tag: "ปรับปรุง", color: "#6D98C7" },
};
const CHANGELOG_HIDE = ["chore", "docs", "test", "ci", "build"]; // งานภายใน ไม่ต้องโชว์ผู้ใช้
// คำแปลเป็นภาษาผู้ใช้ของ commit เก่าที่ยังอยู่ในช่วง 7 วัน (null = ซ่อน ไม่เกี่ยวกับผู้ใช้)
// รายการเหล่านี้หมดอายุไปเองเมื่อพ้นช่วง — commit ใหม่ๆ เขียนส่วนหน้า " — " เป็นภาษาผู้ใช้อยู่แล้ว
const CHANGELOG_FRIENDLY = {
  "feat(landing): เพิ่ม section กิจกรรมล่าสุด (5 รายการ) บนหน้า home + export TH_MONTHS ขึ้น window (port จาก 83G30M 3b13161+3c42fcd)": "หน้าแรกมีส่วน \"กิจกรรมล่าสุด\" กดดูโปสเตอร์เต็มได้",
  "feat(sales): แยกยอด \"นำส่ง\" กับ \"อนุมัติ\" + เช็คลิสต์อนุมัติ (port จาก 83G30M, คงดีไซน์การ์ดเดิม)": "แยกยอด \"นำส่ง\" กับ \"อนุมัติ\" พร้อมเช็คลิสต์อนุมัติในหน้าดีล",
  "feat(landing): manager โผล่ในฟีด \"ใครเพิ่งขาย & ชวนตัวแทน\" ของหน้า public landing ด้วย": "หัวหน้าทีมแสดงในฟีด \"ใครเพิ่งขาย & ชวนตัวแทน\" หน้าแรกด้วย",
  "feat(manager): manager นับเป็นผู้เล่นใน Members panel/My Money Need, ไม่นับใน ตัวตึง (leaderboard)": "หัวหน้าทีมร่วมเป็นผู้เล่นในระบบเป้าหมาย แต่ไม่นับใน \"ตัวตึง\"",
  "feat(recruiting): manager มีแท็บ \"ของฉัน\" ใน Recruiting สรรหาตัวแทนของตัวเองได้เหมือนตัวแทน": "หัวหน้าทีมมีแท็บ \"ของฉัน\" ใน Recruiting สรรหาตัวแทนเองได้",
  "feat(prospecting): manager มีแท็บ \"ของฉัน\" ใน Prospecting ทำดีลของตัวเองได้เหมือนตัวแทน": "หัวหน้าทีมมีแท็บ \"ของฉัน\" ใน Prospecting ทำดีลเองได้",
  "fix(sales): เพิ่ม TH_MONTHS copy ใน components.jsx กัน ReferenceError บน admin/manager panel": null,
  "refactor(sales): ย้าย SalesTab/RecruitTab ไปไว้ components.jsx เพื่อใช้ซ้ำฝั่ง manager panel": null,
  "fix(perf): ตัด backdrop-filter blur เต็มจอออกจาก modal/overlay แก้จอกระตุกบน iPad Safari": "แก้อาการหน้าจอกระตุกบน iPad",
  "feat(admin): ปุ่มพิมพ์/PDF + print layout รายงาน A4 ใน 6 หน้า admin (port จาก 83G30M)": "เพิ่มปุ่มพิมพ์/บันทึก PDF ในหน้ารายงานแอดมิน",
  "feat(team-competition): เพิ่มแท็บตัวแทน + โชว์ผู้แข่งขันรายบุคคล": "ตัวแทนมีแท็บดูตัวเลขผลงานของตัวเองในหน้าแข่งขัน",
  "feat(team-competition): admin panel รองรับ 2-6 ทีม + manager ดูอย่างเดียว": "จัดแข่งได้ 2-6 ทีม · หัวหน้าทีมดูผลได้อย่างเดียว",
  "style(team-competition): CSS leaderboard bars + ผู้แข่งขัน + ฟอร์มหลายทีม": "ปรับหน้าตาตารางคะแนนและรายชื่อผู้แข่งขันให้อ่านง่ายขึ้น",
  "feat(team-competition): public landing ใช้ shared hook + โชว์ผู้แข่งขันรายบุคคล": "หน้าแรกแสดงรายชื่อผู้แข่งขันของแต่ละทีมด้วย",
  "feat(team-competition): พอร์ต logic 2-6 ทีม + ผู้แข่งขันรายบุคคล + shared hook": "รองรับการแข่งขัน 2-6 ทีม พร้อมผลงานรายบุคคล",
  "feat(team-competition): widen side check constraint to support 2-6 teams": null,
  "feat(point-rules): พอร์ตกติกาการรับคะแนนที่แก้ได้จากแอดมินมาจาก 83G30M": "แอดมินแก้กติกาการรับคะแนนได้เอง",
  "feat(club-schedule): เพิ่มกรอบโปสเตอร์ 3:2/2:3 อัตโนมัติตามสัดส่วนภาพจริงในหน้าคลับอัปสกิล": "โปสเตอร์คลับอัปสกิลไม่ถูกตัดขอบอีกต่อไป",
};
const changelogItems = () => {
  const items = (window.APP_CHANGELOG || [])
    .map(c => {
      const m = c.msg.match(/^(\w+)(\([^)]*\))?!?:\s*(.*)$/);
      const type = m ? m[1] : "";
      if (CHANGELOG_HIDE.includes(type)) return null;
      const info = CHANGELOG_TYPE[type] || { tag: "อื่นๆ", color: "#8E7AE6" };
      // ข้อความที่ผู้ใช้เห็น: ใช้คำแปลจาก CHANGELOG_FRIENDLY ก่อน (null = ซ่อน)
      // ถ้าไม่มีในตาราง ให้ตัดรายละเอียดเชิงเทคนิคหลัง " — " ออก
      let text;
      if (Object.prototype.hasOwnProperty.call(CHANGELOG_FRIENDLY, c.msg)) {
        text = CHANGELOG_FRIENDLY[c.msg];
        if (!text) return null;
      } else {
        text = (m ? m[3] : c.msg).split(" — ")[0].trim();
        if (text.length < 4) return null; // กัน commit ขยะ
      }
      return { date: c.date, text, tag: info.tag, color: info.color };
    })
    .filter(Boolean);
  // เอาเฉพาะ 7 วันล่าสุด — ถ้าช่วงนั้นไม่มี commit เลย fallback เป็น 10 รายการล่าสุดแทน
  const cutoff = new Date(getNow().getTime() - 7 * 24 * 60 * 60 * 1000).toLocaleDateString("sv-SE");
  const recent = items.filter(i => i.date >= cutoff);
  return recent.length ? recent : items.slice(0, 10);
};

// ปุ่ม "มีอะไรใหม่" ล่าง sidebar + ป๊อปอัพรายการอัปเดต — จุดแดงหายเมื่อเปิดดูรุ่นล่าสุดแล้ว
const WhatsNewNavButton = () => {
  const SEEN_KEY = `${window.TENANT.prefix}.whatsnew.seen`;
  const updates = React.useMemo(changelogItems, []);
  // ลายเซ็นของรุ่นล่าสุด — commit ใหม่เข้ามาเมื่อไหร่ จุดแดงกลับมาเอง
  const latest = updates.length ? `${updates[0].date}|${updates[0].text}` : "";
  const [open, setOpen] = React.useState(false);
  const [seen, setSeen] = React.useState(() => localStorage.getItem(SEEN_KEY) === latest);

  const show = () => {
    localStorage.setItem(SEEN_KEY, latest);
    setSeen(true);
    setOpen(true);
  };
  const close = React.useCallback(() => setOpen(false), []);

  const cardRef = React.useRef(null);
  useModalA11y(open, close, cardRef);

  const todayKey = getNow().toLocaleDateString("sv-SE");
  const fmtDate = (d) => {
    const [y, m, day] = d.split("-").map(Number);
    return `${day} ${TH_MONTHS[m - 1]} ${y + 543}`;
  };
  // จัดกลุ่มตามวัน (รายการเรียงใหม่→เก่าอยู่แล้วตาม git log)
  const days = [];
  updates.forEach(u => {
    const last = days[days.length - 1];
    if (last && last.date === u.date) last.items.push(u);
    else days.push({ date: u.date, items: [u] });
  });

  if (!updates.length) return null;
  return (
    <React.Fragment>
      <button className="nav-item whatsnew-btn" onClick={show} title="มีอะไรใหม่">
        <NavIcon><path d="m12 3 1.9 4.6 4.6 1.4-4.6 1.4L12 15l-1.9-4.6L5.5 9l4.6-1.4L12 3Z" /><path d="M19 14l.9 2.1 2.1.9-2.1.9L19 20l-.9-2.1-2.1-.9 2.1-.9L19 14Z" /></NavIcon>
        <span className="nav-text">มีอะไรใหม่</span>
        {!seen && <span className="whatsnew-dot" aria-label="มีอัปเดตใหม่" />}
      </button>
      {/* portal ไป body — ถ้า render ใน sidebar จะติด stacking context (sidebar z ต่ำกว่า main) ทำให้ป๊อปอัพโดนเนื้อหาบังจนมองไม่เห็น */}
      {open && ReactDOM.createPortal(
        <div className="ad-popup-overlay" onClick={close}>
          <div className="whatsnew-card" ref={cardRef} role="dialog" aria-modal="true" aria-label="มีอะไรใหม่" tabIndex={-1} onClick={e => e.stopPropagation()}>
            <div className="whatsnew-head">
              <span className="whatsnew-badge">
                <NavIcon><path d="m12 3 1.9 4.6 4.6 1.4-4.6 1.4L12 15l-1.9-4.6L5.5 9l4.6-1.4L12 3Z" /></NavIcon>
              </span>
              <div>
                <h2>มีอะไรใหม่</h2>
                <p>สิ่งที่เปลี่ยนแปลงในช่วง 7 วันล่าสุด</p>
              </div>
              <button type="button" className="whatsnew-close" onClick={close} aria-label="ปิด">✕</button>
            </div>
            <div className="whatsnew-body">
              {days.map(day => (
                <React.Fragment key={day.date}>
                  <div className="whatsnew-day">{day.date === todayKey ? `วันนี้ · ${fmtDate(day.date)}` : fmtDate(day.date)}</div>
                  {day.items.map((u, i) => (
                    <div key={`${day.date}-${i}`} className="whatsnew-item" style={{ "--upd": u.color }}>
                      <h3><span className="whatsnew-tag">{u.tag}</span>{u.text}</h3>
                    </div>
                  ))}
                </React.Fragment>
              ))}
            </div>
            <div className="whatsnew-foot">
              <button type="button" className="whatsnew-ok" onClick={close}>รับทราบ</button>
            </div>
          </div>
        </div>,
        document.body
      )}
    </React.Fragment>
  );
};

const App = () => {
  const { logoUrl } = useBranding();
  const [active, setActive] = React.useState("overview");
  const [menuOpen, setMenuOpen] = React.useState(false);
  const [liveSales, setLiveSales] = React.useState(null);
  const [loggedIn, setLoggedIn] = React.useState(() => !!localStorage.getItem("agentSession"));
  const [adminAuth, setAdminAuth] = React.useState(() => {
    try { return JSON.parse(localStorage.getItem(`${window.TENANT.prefix}.admin.user`) || "null"); } catch { return null; }
  });
  const isAdmin = !!adminAuth;
  const adminPanelLabel = adminAuth?.role === "admin" ? "Admin Panel" : "Manager Panel";
  const adminPanelUrl = adminAuth?.role === "admin" ? "admin.html" : "manager.html";

  const handleLogout = () => {
    localStorage.removeItem("agentSession");
    localStorage.removeItem(`${window.TENANT.prefix}.admin.user`);
    setLoggedIn(false);
    setAdminAuth(null);
  };

  React.useEffect(() => {
    const sync = () => setLoggedIn(!!localStorage.getItem("agentSession"));
    window.addEventListener("storage", sync);
    return () => window.removeEventListener("storage", sync);
  }, []);

  // เป้าหมายใหญ่ (แผน active จากเมนูแอดมิน) — undefined = กำลังโหลด, null = ไม่มีแผน (ใช้ค่า config เดิม)
  const [orgGoal, setOrgGoal] = React.useState(undefined);

  const liveSalesFingerprint = React.useRef(null);
  React.useEffect(() => {
    let seasonStart = SEASON_START;
    const fetchSales = async () => {
      const [salesRes, recruitRes] = await Promise.all([
        // ต่างจาก 83G30M: GA83F ยังมีแถว recruit_count ใน agent_ape_sales (ข้อมูลเก่าที่กรอกมือ)
        // ซึ่ง OverviewSection/ApeGoalSection ใช้รวมยอด Recruit — ต้องคงคอลัมน์นี้ไว้
        sb.from("agent_ape_sales").select("date, amount, recruit_count").gte("date", seasonStart),
        sb.from("agent_activities").select("date").in("name", ["Recruit", "ตัวแทนชวนตัวแทน"]).gte("date", seasonStart),
      ]);
      const recruitRows = (recruitRes.data || []).map(r => ({
        date: r.date,
        amount: 0,
        recruit_count: 1,
      }));
      const combined = [...(salesRes.data || []), ...recruitRows];
      // ข้อมูลชุดนี้เล็ก (แค่ date+amount+recruit_count) เทียบตรงๆ เป็น string ได้ถูกและแม่นยำ
      // กว่าเทียบแค่ผลรวม/จำนวนแถว — กัน re-render ทั้งหน้าทุก 30 วิเมื่อไม่มีอะไรเปลี่ยนจริง
      const fingerprint = JSON.stringify(combined);
      if (fingerprint === liveSalesFingerprint.current) return;
      liveSalesFingerprint.current = fingerprint;
      setLiveSales(combined);
    };
    // โหลดแผน active ก่อน เพื่อให้ตัวกรองยอดขายเริ่มนับจากเดือนเริ่มแผน (ไม่มีแผน → SEASON_START เดิม)
    const boot = async () => {
      const goal = await loadActiveOrgGoal(sb);
      if (goal?.start_month) seasonStart = `${goal.start_month}-01`;
      setOrgGoal(goal);
      fetchSales();
    };
    boot();
    const timer = window.setInterval(fetchSales, 30000);
    return () => window.clearInterval(timer);
  }, []);

  React.useEffect(() => {
    const sections = SECTIONS.map(n => document.getElementById(n.id)).filter(Boolean);
    const obs = new IntersectionObserver((entries) => {
      entries.forEach(en => {
        if (en.isIntersecting) setActive(en.target.id);
      });
    }, { rootMargin: "-30% 0px -60% 0px", threshold: 0 });
    sections.forEach(s => obs.observe(s));
    return () => obs.disconnect();
  }, []);

  React.useEffect(() => {
    document.body.style.overflow = menuOpen ? "hidden" : "";
    return () => { document.body.style.overflow = ""; };
  }, [menuOpen]);

  const scrollTo = (id) => {
    const el = document.getElementById(id);
    if (el) {
      const main = el.closest(".main");
      if (main && main.scrollHeight > main.clientHeight + 1) {
        main.scrollTo({ top: el.offsetTop - 60, behavior: "smooth" });
      } else {
        window.scrollTo({ top: el.offsetTop - 60, behavior: "smooth" });
      }
    }
    setMenuOpen(false);
  };

  return (
    <div className="app public-app app-shell">
      <AdPopup />
      {menuOpen && <div className="mobile-overlay" onClick={() => setMenuOpen(false)} />}

      <aside className={`sidebar ${menuOpen ? "open" : ""}`}>
        <div className="brand">
          {logoUrl && <img src={logoUrl} className="brand-logo" alt="โลโก้" />}
        </div>

        <nav className="nav">
          <div className="nav-label">MENU</div>
          {NAV.map(n => (
            <button
              key={n.id}
              className={`nav-item ${active===n.id?"active":""}`}
              onClick={() => n.id === "login" && isAdmin ? (setMenuOpen(false), window.location.href = adminPanelUrl) : n.href ? (setMenuOpen(false), window.location.href = n.href) : scrollTo(n.id)}
              title={n.id === "login" ? (isAdmin ? adminPanelLabel : loggedIn ? "Agent Panel" : n.label) : n.label}
            >
              {n.icon}
              <span className="nav-num">{n.num}</span>
              <span className="nav-text">{n.id === "login" ? (isAdmin ? adminPanelLabel : loggedIn ? "Agent Panel" : n.label) : n.label}</span>
            </button>
          ))}
        </nav>

        <WhatsNewNavButton />

        {(loggedIn || isAdmin) && (
          <div className="sidebar-foot">
            <button className="logout-btn" onClick={handleLogout} title="ออกจากระบบ">
              {NAV_ICONS.logout}
              <span className="nav-text">ออกจากระบบ</span>
            </button>
          </div>
        )}

      </aside>

      <main className="main">
        <AnnouncementBanner />
        <div className="topbar">
          <button className={`menu-btn ${menuOpen ? "open" : ""}`} onClick={() => setMenuOpen(o => !o)} aria-label="เมนู">
            <span /><span /><span />
          </button>
          <div className="crumbs">
            <strong>แผนผู้บริหาร 83F</strong> &nbsp;›&nbsp; ปี 2026 &nbsp;›&nbsp; {SECTIONS.find(n=>n.id===active)?.label}
          </div>
          <div className="topbar-meta">
            <span>{(typeof window !== 'undefined' && window.APP_VERSION) || 'v0.1'} · {new Date().toLocaleDateString('th-TH', {day:'numeric', month:'short', year:'numeric'})}</span>
          </div>
        </div>

        <OverviewSection liveSales={liveSales} orgGoal={orgGoal} />
        <CompetitionPublicSection />
        <SalesFeedSection />
        <ApeGoalSection liveSales={liveSales} orgGoal={orgGoal} />
        <TrainingSection />
        <ActivitiesPublicSection />
        <DailyChallengesPublicSection />
        <footer className="app-footer">Application by 83F</footer>
      </main>
    </div>
  );
};

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
