← back to Marketing Command Center

public/dw-accounts.js

51 lines

// Shared canonical DW-owned Instagram accounts helper. Every social/account panel
// uses this so all owned accounts render everywhere (not just where a surface has
// data for them). Loaded once from index.html; the fetch is memoized so panels
// re-init cheaply.
//
//   const accts = await window.MCC_ACCOUNTS.load();   // [{handle, name, ig_user_id}]
//   window.MCC_ACCOUNTS.handles();                     // ['asseeninhotels', ...] (after load)
//   window.MCC_ACCOUNTS.byHandle('linenwallpaper');    // {handle,name,...} | undefined
//
// merge(dynamicRows, keyFn) unions the canonical accounts with a panel's dynamic
// data keyed by handle: every canonical account appears, annotated with its dynamic
// row when one exists (else null) — the one pattern every panel repeats.
(function () {
  // Always hit the bare origin — a page opened with embedded URL creds would make
  // a relative fetch throw "URL that includes credentials" (see app.js).
  const ORIGIN = location.origin;
  let cache = null;      // resolved [{handle,name,ig_user_id}]
  let inflight = null;   // de-dupe concurrent loads

  async function load() {
    if (cache) return cache;
    if (inflight) return inflight;
    inflight = fetch(ORIGIN + '/api/dw-accounts', { credentials: 'same-origin' })
      .then(r => r.ok ? r.json() : { accounts: [] })
      .then(d => { cache = (d && d.accounts) || []; inflight = null; return cache; })
      .catch(() => { inflight = null; return cache || []; });
    return inflight;
  }

  function handles() { return (cache || []).map(a => a.handle); }
  function byHandle(h) { return (cache || []).find(a => a.handle === h); }

  // Union canonical accounts with a panel's dynamic rows. keyFn(row) → handle.
  // Returns [{ ...account, data: <matching row | null> }] in canonical (sorted) order,
  // then any dynamic rows whose handle isn't a known canonical account (rare).
  function merge(rows, keyFn) {
    const list = cache || [];
    const byKey = new Map();
    (rows || []).forEach(r => { const k = keyFn ? keyFn(r) : r.handle; if (k != null) byKey.set(String(k), r); });
    const out = list.map(a => ({ ...a, data: byKey.get(a.handle) || null }));
    const known = new Set(list.map(a => a.handle));
    (rows || []).forEach(r => {
      const k = String(keyFn ? keyFn(r) : r.handle);
      if (k && !known.has(k)) out.push({ handle: k, name: k, ig_user_id: null, data: r });
    });
    return out;
  }

  window.MCC_ACCOUNTS = { load, handles, byHandle, merge };
})();