var Z=window.location.origin;async function h(e,t){let s=await fetch(`${Z}${e}`,{...t,headers:{"Content-Type":"application/json",...t?.headers}});if(!s.ok){let r=await s.text();throw new Error(`API ${s.status}: ${r}`)}return s.json()}async function N(){return h("/api/me")}async function E(){return h("/api/config")}async function R(e){let t=e?.length?`?authors=${encodeURIComponent(e.join(","))}`:"";return h(`/api/prs${t}`)}async function D(e,t,s){return h(`/api/prs/${encodeURIComponent(e)}/${encodeURIComponent(t)}/${s}`)}async function O(){await h("/api/sync",{method:"POST"})}async function j(e){return h("/api/prs/merge",{method:"POST",body:JSON.stringify({targets:e})})}async function G(e){return h("/api/prs/close",{method:"POST",body:JSON.stringify({targets:e})})}function o(e){let t=document.createElement("span");return t.textContent=e,t.innerHTML}function b(e){let t=new Date(e),r=Math.floor((new Date().getTime()-t.getTime())/1e3);if(r<60)return"just now";let n=Math.floor(r/60);if(n<60)return`${n}m ago`;let a=Math.floor(n/60);if(a<24)return`${a}h ago`;let i=Math.floor(a/24);return i<30?`${i}d ago`:`${Math.floor(i/30)}mo ago`}function C(e){if(!e)return"";let t=e.toUpperCase();return t==="SUCCESS"?'<span class="badge badge-success">&#x2713; CI passed</span>':t==="FAILURE"||t==="ERROR"?'<span class="badge badge-failure">&#x2717; CI failed</span>':t==="PENDING"||t==="EXPECTED"?'<span class="badge badge-pending">&#x25cf; CI pending</span>':`<span class="badge badge-pending">${o(e)}</span>`}function w(e){if(!e)return"";let t=e.toUpperCase();return t==="MERGEABLE"?'<span class="badge badge-mergeable">&#x2713; No conflicts</span>':t==="CONFLICTING"?'<span class="badge badge-conflict">&#x2717; Conflicts</span>':t==="UNKNOWN"?'<span class="badge badge-pending">? Merge status unknown</span>':""}function P(e){if(!e)return"";let t=e.toUpperCase();return t==="APPROVED"?'<span class="badge badge-success">&#x2713; Approved</span>':t==="CHANGES_REQUESTED"?'<span class="badge badge-failure">&#x270e; Changes requested</span>':t==="REVIEW_REQUIRED"?'<span class="badge badge-review">&#x25cb; Review required</span>':""}function L(e){let t=`#${e.color}`,s=parseInt(e.color.substring(0,2),16),r=parseInt(e.color.substring(2,4),16),n=parseInt(e.color.substring(4,6),16),i=(.299*s+.587*r+.114*n)/255>.5?"#000":"#fff";return`<span class="label-tag" style="background:${t};color:${i}">${o(e.name)}</span>`}var F=[];function B(e,t){F.push({pattern:e,handler:t})}function v(e){window.location.hash=e}async function _(){let e=window.location.hash.replace(/^#/,"")||"/",t=document.getElementById("view-container");if(t){for(let s of F){let r=e.match(s.pattern);if(r){await s.handler(t,...r.slice(1));return}}v("/")}}var g=[],Y=null,$="",S=new Set,I=new Set,x=new Set,d=new Set,T="repo",M="number",y=!1,m=null;function V(e){return`${e.repo_owner}/${e.repo_name}#${e.number}`}function A(e,t,s,r,n){return`<div class="multi-select" id="${e}-ms"><button class="multi-select-btn" id="${e}-btn">${t}<span class="ms-count" id="${e}-count"></span> <span class="ms-caret">&#x25BE;</span></button><div class="multi-select-dropdown hidden" id="${e}-dropdown"></div></div>`}function H(e,t,s,r,n){let a=document.getElementById(`${e}-btn`),i=document.getElementById(`${e}-dropdown`),p=document.getElementById(`${e}-count`);i.innerHTML=t.map(c=>{let f=s.has(c)?"checked":"";return`<label class="ms-option"><input type="checkbox" value="${o(c)}" ${f} /> ${o(r(c))}</label>`}).join("");let u=()=>{p.textContent=s.size>0?` (${s.size})`:""};u(),a.addEventListener("click",c=>{c.stopPropagation(),document.querySelectorAll(".multi-select-dropdown").forEach(f=>{f!==i&&f.classList.add("hidden")}),i.classList.toggle("hidden")}),i.querySelectorAll("input[type=checkbox]").forEach(c=>{c.addEventListener("change",()=>{c.checked?s.add(c.value):s.delete(c.value),u(),n()})})}document.addEventListener("click",()=>{document.querySelectorAll(".multi-select-dropdown").forEach(e=>e.classList.add("hidden"))});async function J(e){e.innerHTML=`
    <div id="dashboard-stats" class="dashboard-stats"></div>
    <div class="filter-bar">
      <input id="filter-search" type="text" placeholder="Search PRs..." />
      <div id="ms-author-placeholder"></div>
      <div id="ms-repo-placeholder"></div>
      <div id="ms-ci-placeholder"></div>
      <select id="group-by">
        <option value="repo">Group by repo</option>
        <option value="author">Group by author</option>
        <option value="none">No grouping</option>
      </select>
    </div>
    <div id="batch-bar" class="batch-bar hidden">
      <span id="batch-count">0 selected</span>
      <button id="batch-merge" class="batch-btn batch-btn-merge" disabled>Merge selected</button>
      <button id="batch-close" class="batch-btn batch-btn-close">Close selected</button>
      <button id="batch-clear" class="batch-btn batch-btn-clear">Clear selection</button>
    </div>
    <div id="pr-table-container"></div>
  `;try{Y=await E(),g=await R()}catch(i){e.innerHTML=`<div class="empty-state"><h3>Failed to load</h3><p>${o(String(i))}</p></div>`;return}if(g.length===0){e.innerHTML='<div class="empty-state"><h3>No open PRs</h3><p>Waiting for background sync to complete. Try clicking the sync button.</p></div>';return}let t=[...new Set(g.map(i=>i.author))].sort(),s=[...new Set(g.map(i=>`${i.repo_owner}/${i.repo_name}`))].sort(),r=["SUCCESS","FAILURE","PENDING","NONE"],n={SUCCESS:"CI passing",FAILURE:"CI failing",PENDING:"CI pending",NONE:"No CI"};document.getElementById("ms-author-placeholder").outerHTML=A("ms-author","Authors",t,S,l),document.getElementById("ms-repo-placeholder").outerHTML=A("ms-repo","Repos",s,I,l),document.getElementById("ms-ci-placeholder").outerHTML=A("ms-ci","CI Status",r,x,l),H("ms-author",t,S,i=>i,l),H("ms-repo",s,I,i=>i,l),H("ms-ci",r,x,i=>n[i]||i,l);let a=document.getElementById("filter-search");a.addEventListener("input",()=>{$=a.value.toLowerCase(),l()}),document.getElementById("group-by").addEventListener("change",i=>{T=i.target.value,l()}),document.getElementById("batch-merge").addEventListener("click",se),document.getElementById("batch-close").addEventListener("click",ae),document.getElementById("batch-clear").addEventListener("click",()=>{d.clear(),l()}),d.clear(),l()}function K(e,t){switch(t){case"total":return!0;case"ready":return e.ci_status?.toUpperCase()==="SUCCESS"&&e.mergeable?.toUpperCase()==="MERGEABLE"&&!e.draft;case"pass":return e.ci_status?.toUpperCase()==="SUCCESS";case"fail":return e.ci_status?.toUpperCase()==="FAILURE"||e.ci_status?.toUpperCase()==="ERROR";case"pending":return e.ci_status?.toUpperCase()==="PENDING"||e.ci_status?.toUpperCase()==="EXPECTED";case"mergeable":return e.mergeable?.toUpperCase()==="MERGEABLE";case"conflicts":return e.mergeable?.toUpperCase()==="CONFLICTING";case"approved":return e.review_decision?.toUpperCase()==="APPROVED";case"drafts":return!!e.draft;default:return!0}}function ee(){let e=g;return m&&m!=="total"&&(e=e.filter(t=>K(t,m))),$&&(e=e.filter(t=>t.title.toLowerCase().includes($)||`${t.repo_owner}/${t.repo_name}`.toLowerCase().includes($)||t.author.toLowerCase().includes($))),S.size>0&&(e=e.filter(t=>S.has(t.author))),I.size>0&&(e=e.filter(t=>I.has(`${t.repo_owner}/${t.repo_name}`))),x.size>0&&(e=e.filter(t=>{let s=t.ci_status?.toUpperCase()||"NONE";for(let r of x)if(r==="NONE"&&!t.ci_status||s===r)return!0;return!1})),e}function z(e){let t=(r,n)=>{switch(M){case"number":return r.number-n.number;case"author":return r.author.localeCompare(n.author);case"created":return new Date(r.created_at).getTime()-new Date(n.created_at).getTime();case"updated":return new Date(r.updated_at).getTime()-new Date(n.updated_at).getTime();default:return 0}},s=[...e].sort(t);return y?s:s.reverse()}function te(){let e=document.getElementById("dashboard-stats");if(!e)return;let t=[{key:"total",cls:"stat-total",label:"Open PRs"},{key:"ready",cls:"stat-ready",label:"Ready to merge"},{key:"pass",cls:"stat-pass",label:"CI passing"},{key:"fail",cls:"stat-fail",label:"CI failing"},{key:"pending",cls:"stat-pending-stat",label:"CI pending"},{key:"mergeable",cls:"stat-mergeable",label:"No conflicts"},{key:"conflicts",cls:"stat-conflicts",label:"Conflicts"},{key:"approved",cls:"stat-approved",label:"Approved"},{key:"drafts",cls:"stat-drafts",label:"Drafts"}];e.innerHTML=t.map(s=>{let r=g.filter(a=>K(a,s.key)).length,n=m===s.key?" active":"";return`<div class="stat-card ${s.cls}${n}" data-stat="${s.key}"><div class="stat-value">${r}</div><div class="stat-label">${s.label}</div></div>`}).join(""),e.querySelectorAll(".stat-card").forEach(s=>{s.addEventListener("click",()=>{let r=s.dataset.stat;m=m===r?null:r,l()})})}function l(){let e=ee();te(),U();let t=document.getElementById("pr-table-container");if(t){if(e.length===0){t.innerHTML='<div class="empty-state"><p>No PRs match the current filters.</p></div>';return}if(T==="none")t.innerHTML=W(z(e),null);else{let s=new Map;for(let n of e){let a=T==="repo"?`${n.repo_owner}/${n.repo_name}`:n.author;s.has(a)||s.set(a,[]),s.get(a).push(n)}let r=[...s.entries()].sort((n,a)=>a[1].length-n[1].length);t.innerHTML=r.map(([n,a])=>W(z(a),n)).join("")}t.querySelectorAll(".pr-checkbox").forEach(s=>{s.checked=d.has(s.value),s.addEventListener("change",()=>{s.checked?d.add(s.value):d.delete(s.value),U(),ne(t)})}),t.querySelectorAll(".group-select-all").forEach(s=>{s.addEventListener("change",()=>{let r=s.getAttribute("data-group");t.querySelectorAll(`.pr-checkbox[data-group="${r}"]`).forEach(a=>{a.checked=s.checked,s.checked?d.add(a.value):d.delete(a.value)}),U()})}),t.querySelectorAll(".pr-row-link").forEach(s=>{s.addEventListener("click",()=>{v(`/pr/${s.dataset.owner}/${s.dataset.repo}/${s.dataset.number}`)})}),t.querySelectorAll(".sortable-th").forEach(s=>{s.addEventListener("click",()=>{let r=s.dataset.sort;M===r?y=!y:(M=r,y=r==="author"),l()})})}}function k(e){return M!==e?"":y?" &#x25B4;":" &#x25BE;"}function W(e,t){let s=t?t.replace(/[^a-zA-Z0-9]/g,"_"):"all",r=t?`<div class="group-header">
        <label class="group-select-label"><input type="checkbox" class="group-select-all" data-group="${o(s)}" /> </label>
        <span class="group-name">${o(t)}</span>
        <span class="group-count">${e.length}</span>
       </div>`:"",n=e.map(a=>{let i=V(a),p=d.has(i)?"checked":"",u=[];a.draft&&u.push('<span class="badge badge-draft">Draft</span>'),u.push(C(a.ci_status)),u.push(w(a.mergeable)),u.push(P(a.review_decision));let c=(a.labels||[]).map(L).join(" ");return`<tr class="pr-row ${a.ci_status?.toUpperCase()==="SUCCESS"&&a.mergeable?.toUpperCase()==="MERGEABLE"&&!a.draft?"pr-row-ready":""}">
      <td class="td-check"><input type="checkbox" class="pr-checkbox" value="${o(i)}" data-group="${o(s)}" data-owner="${o(a.repo_owner)}" data-repo="${o(a.repo_name)}" data-number="${a.number}" ${p} /></td>
      <td class="td-status">${u.filter(Boolean).join(" ")}</td>
      <td class="td-title">
        <span class="pr-row-link" data-owner="${o(a.repo_owner)}" data-repo="${o(a.repo_name)}" data-number="${a.number}">
          ${o(a.title)}
        </span>
        <span class="pr-row-ref">${T!=="repo"?o(`${a.repo_owner}/${a.repo_name}`)+" ":""}#${a.number} ${o(a.head_ref||"")} &rarr; ${o(a.base_ref||"")}</span>
        ${c?`<span class="pr-row-labels">${c}</span>`:""}
      </td>
      <td class="td-author">
        ${a.author_avatar?`<img class="avatar-sm" src="${o(a.author_avatar)}&s=32" alt="" />`:""}
        ${o(a.author)}
      </td>
      <td class="td-stats"><span class="stat-add">+${a.additions}</span> <span class="stat-del">-${a.deletions}</span></td>
      <td class="td-time" title="${o(a.created_at)}">${b(a.created_at)}</td>
      <td class="td-time" title="${o(a.updated_at)}">${b(a.updated_at)}</td>
    </tr>`}).join("");return`
    ${r}
    <table class="pr-table">
      <thead>
        <tr>
          <th class="th-check"></th>
          <th class="th-status">Status</th>
          <th class="th-title sortable-th" data-sort="number">PR${k("number")}</th>
          <th class="th-author sortable-th" data-sort="author">Author${k("author")}</th>
          <th class="th-stats">Changes</th>
          <th class="th-time sortable-th" data-sort="created">Created${k("created")}</th>
          <th class="th-time sortable-th" data-sort="updated">Updated${k("updated")}</th>
        </tr>
      </thead>
      <tbody>${n}</tbody>
    </table>
  `}function U(){let e=document.getElementById("batch-bar"),t=document.getElementById("batch-count");if(!(!e||!t))if(d.size>0){e.classList.remove("hidden"),t.textContent=`${d.size} selected`;let s=document.getElementById("batch-merge"),r=q().every(n=>n.ci_status?.toUpperCase()==="SUCCESS"&&n.mergeable?.toUpperCase()==="MERGEABLE"&&!n.draft);s.disabled=!r,s.title=r?"Merge all selected PRs":"Some selected PRs have failing CI, conflicts, or are drafts"}else e.classList.add("hidden")}function ne(e){e.querySelectorAll(".group-select-all").forEach(t=>{let s=t.getAttribute("data-group"),r=e.querySelectorAll(`.pr-checkbox[data-group="${s}"]`),n=r.length>0&&[...r].every(a=>a.checked);t.checked=n,t.indeterminate=!n&&[...r].some(a=>a.checked)})}function q(){return g.filter(e=>d.has(V(e)))}async function se(){let e=q();if(e.filter(n=>n.ci_status?.toUpperCase()!=="SUCCESS"||n.mergeable?.toUpperCase()!=="MERGEABLE"||n.draft).length>0)return;let s=e.map(n=>({owner:n.repo_owner,repo:n.repo_name,number:n.number})),r=document.getElementById("batch-bar");r.classList.add("batch-working");try{let n=await j(s),a=n.filter(i=>!i.success);a.length>0&&alert(`Merged ${n.length-a.length} PRs. ${a.length} failed:
${a.map(i=>i.error||"Unknown error").join(`
`)}`),d.clear(),g=await R(),l()}catch(n){alert(`Batch merge failed: ${n}`)}finally{r.classList.remove("batch-working")}}async function ae(){let t=q().map(r=>({owner:r.repo_owner,repo:r.repo_name,number:r.number})),s=document.getElementById("batch-bar");s.classList.add("batch-working");try{let r=await G(t),n=r.filter(a=>!a.success);n.length>0&&alert(`Closed ${r.length-n.length} PRs. ${n.length} failed:
${n.map(a=>a.error||"Unknown error").join(`
`)}`),d.clear(),g=await R(),l()}catch(r){alert(`Batch close failed: ${r}`)}finally{s.classList.remove("batch-working")}}async function Q(e,t,s,r){e.innerHTML='<div class="loading">Loading PR&hellip;</div>';let n;try{n=await D(t,s,r)}catch(p){e.innerHTML=`<div class="empty-state"><h3>Failed to load PR</h3><p>${o(String(p))}</p></div>`;return}let a=[];n.draft&&a.push('<span class="badge badge-draft">Draft</span>'),a.push(C(n.ci_status)),a.push(w(n.mergeable)),a.push(P(n.review_decision));let i=(n.labels||[]).map(L).join(" ");e.innerHTML=`
    <button class="pr-detail-back" id="back-btn">&larr; All PRs</button>

    <div class="pr-detail-header">
      <div class="pr-detail-title">${o(n.title)}</div>
      <div class="pr-detail-subtitle">
        ${o(t)}/${o(s)}#${r}
        &middot; ${o(n.head_ref||"")} &rarr; ${o(n.base_ref||"")}
        &middot; <span class="pr-author">
          ${n.author_avatar?`<img src="${o(n.author_avatar)}&s=32" alt="" />`:""}
          ${o(n.author)}
        </span>
        &middot; updated ${b(n.updated_at)}
        &middot; <a class="external-link" href="${o(n.url)}" target="_blank" rel="noopener">View on GitHub &nearr;</a>
      </div>
      <div class="pr-detail-badges">
        ${a.filter(Boolean).join(" ")} ${i}
      </div>
      <div class="pr-stats" style="margin-top:8px">
        <span class="stat-add">+${n.additions}</span>
        <span class="stat-del">-${n.deletions}</span>
        <span class="stat-files">${n.changed_files} file${n.changed_files!==1?"s":""}</span>
      </div>
    </div>

    ${re(n.checks)}
    ${oe(n.commits)}
    ${ie(n.files)}
  `,document.getElementById("back-btn")?.addEventListener("click",()=>v("/")),e.querySelectorAll(".file-header").forEach(p=>{p.addEventListener("click",()=>{let u=p.nextElementSibling;u&&u.classList.toggle("open")})})}function re(e){if(!e.length)return"";let t=e.filter(n=>n.conclusion==="success").length,s=e.filter(n=>n.conclusion==="failure"||n.conclusion==="action_required").length,r=e.filter(n=>!n.conclusion||n.conclusion==="neutral"||n.status==="in_progress"||n.status==="queued").length;return`
    <div class="section">
      <h3>Checks (${t} passed, ${s} failed, ${r} pending)</h3>
      <div class="check-list">
        ${e.map(n=>{let a="pending",i="&#x25cf;";return n.conclusion==="success"?(a="success",i="&#x2713;"):(n.conclusion==="failure"||n.conclusion==="action_required")&&(a="failure",i="&#x2717;"),`
            <div class="check-item">
              <span class="check-icon ${a}">${i}</span>
              <span class="check-name">${o(n.name)}</span>
              ${n.url?`<a class="external-link" href="${o(n.url)}" target="_blank" rel="noopener">&nearr;</a>`:""}
            </div>
          `}).join("")}
      </div>
    </div>
  `}function oe(e){return e.length?`
    <div class="section">
      <h3>Commits (${e.length})</h3>
      <div class="commit-list">
        ${e.map(t=>{let s=t.sha.substring(0,7),r=t.message.split(`
`)[0];return`
            <div class="commit-item">
              <span class="commit-sha">${t.url?`<a class="external-link" href="${o(t.url)}" target="_blank" rel="noopener">${s}</a>`:s}</span>
              <span class="commit-msg">${o(r)}</span>
              ${t.author?`<span class="commit-author">${o(t.author)}</span>`:""}
            </div>
          `}).join("")}
      </div>
    </div>
  `:""}function ie(e){return e.length?`
    <div class="section">
      <h3>Files changed (${e.length})</h3>
      <div class="file-list">
        ${e.map(t=>{let s=t.status?`file-status-${t.status}`:"",r=t.patch?le(t.patch):"<pre>(no diff available)</pre>";return`
            <div class="file-item">
              <div class="file-header">
                <span class="file-status ${s}">${o(t.status||"")}</span>
                <span class="file-name">${o(t.filename)}</span>
                <span class="file-stats">
                  <span class="stat-add">+${t.additions}</span>
                  <span class="stat-del">-${t.deletions}</span>
                </span>
              </div>
              <div class="file-patch">${r}</div>
            </div>
          `}).join("")}
      </div>
    </div>
  `:""}function le(e){return`<pre>${e.split(`
`).map(r=>{let n=o(r);return r.startsWith("@@")?`<span class="diff-hunk">${n}</span>`:r.startsWith("+")?`<span class="diff-add">${n}</span>`:r.startsWith("-")?`<span class="diff-del">${n}</span>`:n}).join(`
`)}</pre>`}B(/^\/$/,async e=>{await J(e)});B(/^\/pr\/([^/]+)\/([^/]+)\/(\d+)$/,async(e,t,s,r)=>{await Q(e,t,s,parseInt(r,10))});async function X(){let e=document.getElementById("loading");try{let n=await N(),a=document.getElementById("user-info");a&&(a.textContent=n.login)}catch{}let t=document.getElementById("sync-btn"),s=!1;async function r(){if(!s){s=!0,t?.classList.add("syncing");try{await O(),await _()}catch(n){console.error("Sync failed:",n)}finally{s=!1,t?.classList.remove("syncing")}}}t&&t.addEventListener("click",r);try{let a=(await E()).sync_interval_seconds;a&&a>0&&setInterval(r,a*1e3)}catch{}window.addEventListener("hashchange",()=>{_()}),e&&e.classList.add("hidden"),await _()}document.readyState==="loading"?document.addEventListener("DOMContentLoaded",X):X();
//# sourceMappingURL=index.js.map
