← back to Marketing Command Center

public/panels/engine.html

124 lines

<!-- Engine panel — daily AI-suggested social posts, grouped by product, with a
     per-channel approve → schedule → post flow. Markup only; engine.js drives it
     and registers window.MCC_PANELS['engine'] = { init(root) }. -->

<!-- 1 ── Header strip: scheduler dot + last tick · today's count chips · Generate + cost badge -->
<div class="card" id="eng-header">
  <div class="row" style="justify-content:space-between;align-items:center;row-gap:12px">
    <div class="row" style="align-items:center;gap:16px;row-gap:8px">
      <span class="eng-sched" id="eng-sched" title="scheduler status">
        <span class="dot" id="eng-sched-dot"></span><span id="eng-sched-txt">scheduler…</span>
      </span>
      <span class="muted" id="eng-tick" style="font-size:12px"></span>
      <span class="eng-chips" id="eng-chips"></span>
    </div>
    <div class="row" style="align-items:center;gap:10px">
      <span class="pill eng-cost" id="eng-cost" title="captions generated by local qwen3:14b — no API cost">$0 local</span>
      <button class="btn gold" id="eng-generate">⚡ Generate today</button>
    </div>
  </div>
  <div id="eng-banner" class="eng-banner" hidden></div>
</div>

<!-- 2 ── Today's Suggestions (grouped by product) -->
<div class="card">
  <div class="row" style="justify-content:space-between;align-items:baseline">
    <h2 style="margin:0">Today's Suggestions</h2>
    <span class="muted" id="eng-today-count" style="font-size:12.5px"></span>
  </div>
  <div id="eng-today" style="margin-top:14px">
    <div class="loading">Loading today's suggestions…</div>
  </div>
</div>

<!-- 3 ── Pipeline strip: last 7 days from /queue, horizontal scroll -->
<div class="card">
  <div class="row" style="justify-content:space-between;align-items:baseline">
    <h2 style="margin:0">Pipeline · last 7 days</h2>
    <span class="muted" id="eng-pipe-count" style="font-size:12.5px"></span>
  </div>
  <div id="eng-pipeline" class="eng-pipe" style="margin-top:12px">
    <div class="muted">Loading history…</div>
  </div>
</div>

<style>
  /* header */
  #eng-header .eng-sched{display:inline-flex;align-items:center;gap:6px;font-size:12.5px;font-weight:600;color:var(--ink)}
  #eng-header .eng-sched .dot::before{margin-right:6px}
  .eng-chips{display:inline-flex;gap:6px;flex-wrap:wrap}
  .eng-chips .pill{background:var(--cream);color:var(--accent)}
  .eng-chips .pill.on{background:#e3efe0;color:#3a6b3a}
  .eng-chips .pill.warn{background:#f3e9e9;color:#9a5a5a}
  .eng-chips .pill.blue{background:#eef3f8;color:#3a5a8a}
  .eng-cost{background:#eef3f8;color:#3a5a8a;cursor:default}
  .eng-cost.template{background:#f6f0e4;color:#7a5a2a}
  .eng-banner{margin-top:12px;background:#f3e9e9;border:1px solid #e2c9c9;color:#8a4a4a;border-radius:10px;padding:9px 13px;font-size:12.5px}
  .eng-banner.ok{background:#e9f3e9;border-color:#c9e2c9;color:#3a6b3a}

  /* product cards */
  .eng-prod{display:flex;gap:16px;border:1px solid var(--line);border-radius:12px;padding:14px;margin-bottom:14px;background:var(--paper)}
  .eng-prod .thumb{flex:none;width:104px;height:104px;border-radius:9px;overflow:hidden;background:var(--cream);border:1px solid var(--line)}
  .eng-prod .thumb a{display:block;width:100%;height:100%}
  .eng-prod .thumb img{width:100%;height:100%;object-fit:cover;display:block}
  .eng-prod .thumb .ph{width:100%;height:100%;display:grid;place-items:center;color:var(--mut);font-size:26px}
  .eng-prod .body{flex:1;min-width:0}
  .eng-prod .ptitle{font:600 15px/1.25 "Cormorant Garamond",Georgia,serif;margin:0}
  .eng-prod .ptitle a{color:var(--ink);text-decoration:none}
  .eng-prod .ptitle a:hover{text-decoration:underline}
  .eng-prod .pmeta{font-size:11.5px;color:var(--mut);margin:2px 0 3px}
  .eng-prod .pwhen{font-size:10.5px;color:var(--mut)}

  /* channel tabs */
  .eng-tabs{display:flex;gap:5px;flex-wrap:wrap;margin:10px 0 8px}
  .eng-tab{display:inline-flex;align-items:center;gap:5px;border:1px solid var(--line);background:#fff;border-radius:8px;
    padding:4px 9px;font-size:12px;font-weight:600;color:var(--ink);cursor:pointer;line-height:1.3}
  .eng-tab:hover{background:var(--cream)}
  .eng-tab.active{border-color:var(--ink);box-shadow:0 0 0 1px var(--ink) inset}
  .eng-tab .ic{font-size:13px}
  .eng-tab .st{font-size:9px;text-transform:uppercase;letter-spacing:.4px}
  /* status coloring */
  .eng-tab.s-approved{background:#eef3f8;border-color:#c3d4e8;color:#2f4f7a}
  .eng-tab.s-posted{background:#e9f3e9;border-color:#c9e2c9;color:#3a6b3a}
  .eng-tab.s-failed{background:#f6ecec;border-color:#e2c9c9;color:#9a4a4a}
  .eng-tab.s-skipped{color:var(--mut);text-decoration:line-through;opacity:.7}
  .eng-tab.s-gated{opacity:.5}
  .eng-tab.s-posting{animation:eng-pulse 1s ease-in-out infinite}
  @keyframes eng-pulse{0%,100%{opacity:1}50%{opacity:.45}}

  /* active channel detail */
  .eng-detail{border:1px solid var(--line);border-radius:10px;padding:12px;background:#fff}
  .eng-detail .cap{font-size:13px;line-height:1.5;white-space:pre-wrap;color:var(--ink)}
  .eng-detail .cap.muted{color:var(--mut)}
  .eng-detail textarea{margin-top:2px;min-height:88px}
  .eng-detail .tags{margin:8px 0 0;display:flex;gap:4px;flex-wrap:wrap}
  .eng-detail .slot{font-size:11.5px;color:var(--mut);margin:8px 0 6px}
  .eng-detail .slot b{color:var(--ink)}
  .eng-detail .gate{background:#f6f0e4;border:1px solid #e6d6b8;color:#7a5a2a;border-radius:8px;padding:7px 10px;font-size:12px;margin-bottom:8px}
  .eng-actions{display:flex;gap:7px;flex-wrap:wrap;align-items:center;margin-top:6px}
  .eng-actions .btn{padding:6px 12px;font-size:12.5px}
  .eng-actions .msg{font-size:11.5px;color:var(--mut)}
  .eng-sched-inline{display:flex;gap:6px;align-items:center;flex-wrap:wrap;margin-top:8px;padding:8px;background:var(--cream);border-radius:8px}
  .eng-sched-inline input,.eng-sched-inline select{width:auto;font-size:12px;padding:6px 8px}
  .eng-sched-inline label{margin:0;font-size:11px}

  /* pipeline strip */
  .eng-pipe{display:flex;gap:10px;overflow-x:auto;padding-bottom:6px}
  .eng-pipe::-webkit-scrollbar{height:8px}
  .eng-pipe::-webkit-scrollbar-thumb{background:var(--line);border-radius:8px}
  .eng-pc{flex:none;width:150px;border:1px solid var(--line);border-radius:10px;background:#fff;overflow:hidden}
  .eng-pc .pt{width:100%;height:82px;object-fit:cover;display:block;background:var(--cream)}
  .eng-pc .pt.ph{display:grid;place-items:center;color:var(--mut);font-size:22px}
  .eng-pc .meta{padding:7px 9px}
  .eng-pc .meta .ch{font-size:12px;font-weight:600}
  .eng-pc .meta .st{font-size:10px;margin-top:2px}
  .eng-pc .meta .st.s-posted{color:#3a6b3a}
  .eng-pc .meta .st.s-failed{color:#9a4a4a}
  .eng-pc .meta .st.s-approved{color:#2f4f7a}
  .eng-pc .meta .st.s-skipped{color:var(--mut);text-decoration:line-through}
  .eng-pc .meta .tm{font-size:10px;color:var(--mut);margin-top:1px}

  .eng-empty{color:var(--mut);text-align:center;padding:26px;font-size:13px}
  .eng-empty .btn{margin-top:12px}
</style>