1import{r as o,j as t,S as M,L as E,e as P,F as $,s as b,a as c,A as O}from"./index-C9IJSwBm.js";import{A as B}from"./arrow-left-BLmjnVT9.js";import{S as F}from"./save-BEm5wWjW.js";import{T as U}from"./trash-eQ6puWi0.js";import{A as q}from"./arrow-up-BpgSnNLc.js";const N=["planned","drafted","published","paused"],H=["informational","commercial","transactional","navigational"],V={transactional:3,commercial:2.5,navigational:1.5,informational:1};function _(l){if(l.status==="published")return 0;const u=l.search_volume??10,h=Math.max(l.difficulty??30,1),m=V[l.intent??"informational"]??1;let n=u*m/h;return l.status==="drafted"&&(n*=.5),l.status==="paused"&&(n*=.3),Math.round(n*10)/10}function W(l){return l>=30?{label:"High",cls:"bg-emerald-500/15 text-emerald-400 border-emerald-500/30"}:l>=10?{label:"Med",cls:"bg-amber-500/15 text-amber-400 border-amber-500/30"}:l>0?{label:"Low",cls:"bg-slate-500/15 text-slate-400 border-slate-500/30"}:{label:"â",cls:"bg-muted text-muted-foreground border-border"}}function Y(){const[l,u]=o.useState([]),[h,m]=o.useState(!0),[n,k]=o.useState("all"),[x,S]=o.useState("all"),[p,C]=o.useState("score"),[g,j]=o.useState("desc"),f=async()=>{m(!0);const{data:e,error:s}=await b.from("keyword_map").select("*").order("cluster",{ascending:!0});s?c.error(s.message):u(e||[]),m(!1)};o.useEffect(()=>{f()},[]);const T=o.useMemo(()=>Array.from(new Set(l.map(e=>e.cluster).filter(Boolean))).sort(),[l]),v=o.useMemo(()=>{const e=l.filter(r=>(n==="all"||r.cluster===n)&&(x==="all"||r.status===x)),s=g==="asc"?1:-1,a=r=>{switch(p){case"score":return _(r);case"search_volume":return r.search_volume??-1;case"difficulty":return r.difficulty??999;case"cluster":return(r.cluster||"").toLowerCase();case"primary_keyword":return(r.primary_keyword||"").toLowerCase();case"intent":return r.intent||"";case"status":return r.status||""}};return[...e].sort((r,K)=>{const w=a(r),y=a(K);return typeof w=="number"&&typeof y=="number"?(w-y)*s:String(w).localeCompare(String(y))*s})},[l,n,x,p,g]),A=e=>{p===e?j(s=>s==="asc"?"desc":"asc"):(C(e),j(e==="cluster"||e==="primary_keyword"||e==="intent"||e==="status"?"asc":"desc"))},i=(e,s)=>{u(a=>a.map(r=>r.id===e?{...r,...s,_dirty:!0}:r))},D=()=>{u(e=>[{cluster:"",primary_keyword:"",search_volume:null,difficulty:null,intent:"informational",target_slug:null,destination_url:null,status:"planned",notes:null,priority:100,_dirty:!0,_new:!0},...e])},L=async e=>{if(!e.primary_keyword.trim()||!e.cluster.trim()){c.error("Cluster and primary keyword are required");return}const s={cluster:e.cluster.trim(),primary_keyword:e.primary_keyword.trim(),search_volume:e.search_volume,difficulty:e.difficulty,intent:e.intent,target_slug:e.target_slug,destination_url:e.destination_url,status:e.status,notes:e.notes,priority:e.priority};if(e._new||!e.id){const{error:a}=await b.from("keyword_map").insert(s);if(a){c.error(a.message);return}}else{const{error:a}=await b.from("keyword_map").update(s).eq("id",e.id);if(a){c.error(a.message);return}}c.success("Saved"),await f()},R=async e=>{if(!e.id){u(a=>a.filter(r=>r!==e));return}if(!confirm(`Delete "${e.primary_keyword}"?`))return;const{error:s}=await b.from("keyword_map").delete().eq("id",e.id);if(s){c.error(s.message);return}c.success("Deleted"),await f()},I=e=>{const s=new URLSearchParams({primary_keyword:e.primary_keyword,
1cluster:e.cluster,...e.target_slug?{slug:e.target_slug}:{},...e.destination_url?{stage3:e.destination_url}:{}});window.location.href=`/admin/blog/new?${s.toString()}`},d=({k:e,label:s,align:a="left"})=>t.jsx("th",{className:`p-2 ${a==="right"?"text-right":"text-left"}`,children:t.jsxs("button",{onClick:()=>A(e),className:"inline-flex items-center gap-1 hover:text-foreground transition",children:[s,p===e&&(g==="asc"?t.jsx(q,{className:"w-3 h-3"}):t.jsx(O,{className:"w-3 h-3"}))]})});return t.jsxs("div",{className:"max-w-7xl mx-auto px-4 py-8",children:[t.jsx(M,{title:"Keyword Map - Admin",description:"",robots:"noindex, nofollow"}),t.jsxs("div",{className:"flex items-center justify-between mb-6 gap-4 flex-wrap",children:[t.jsxs("div",{children:[t.jsxs(E,{to:"/admin",className:"inline-flex items-center gap-1 text-sm text-muted-foreground hover:text-foreground mb-2",children:[t.jsx(B,{className:"w-4 h-4"})," Back to admin"]}),t.jsx("h1",{className:"text-2xl font-bold text-foreground",children:"Keyword Map"}),t.jsxs("p",{className:"text-sm text-muted-foreground mt-1 max-w-3xl",children:["The master list of every primary keyword we plan to target â one row per post. Click a column header to sort. The ",t.jsx("strong",{children:"Score"})," column ranks opportunity using ",t.jsx("code",{className:"text-xs",children:"(Volume à Intent weight) ÷ KD"}),", with weights Transactional 3.0, Commercial 2.5, Navigational 1.5, Informational 1.0. Published rows score 0; drafted Ã0.5; paused Ã0.3. Work top-down."]})]}),t.jsxs("div",{className:"flex items-center gap-2",children:[t.jsxs("select",{value:n,onChange:e=>k(e.target.value),className:"rounded-full border border-border bg-background px-3 py-1.5 text-sm",children:[t.jsx("option",{value:"all",children:"All clusters"}),T.map(e=>t.jsx("option",{value:e,children:e},e))]}),t.jsxs("select",{value:x,onChange:e=>S(e.target.value),className:"rounded-full border border-border bg-background px-3 py-1.5 text-sm",children:[t.jsx("option",{value:"all",children:"All statuses"}),N.map(e=>t.jsx("option",{value:e,children:e},e))]}),t.jsxs("button",{onClick:D,className:"inline-flex items-center gap-1 px-3 py-1.5 rounded-full bg-primary text-white text-sm font-semibold hover:shadow-[0_0_20px_hsl(var(--primary)/0.4)] transition",children:[t.jsx(P,{className:"w-4 h-4"})," Add row"]})]})]}),h?t.jsx("p",{className:"text-sm text-muted-foreground",children:"Loading..."}):t.jsx("div",{className:"overflow-x-auto rounded-xl border border-border",children:t.jsxs("table",{className:"w-full text-sm",children:[t.jsx("thead",{className:"bg-muted/30 text-xs uppercase text-muted-foreground",children:t.jsxs("tr",{children:[t.jsx(d,{k:"score",label:"Score"}),t.jsx(d,{k:"cluster",label:"Cluster"}),t.jsx(d,{k:"primary_keyword",label:"Primary keyword"}),t.jsx(d,{k:"search_volume",label:"Vol"}),t.jsx(d,{k:"difficulty",label:"KD"}),t.jsx(d,{k:"intent",label:"Intent"}),t.jsx("th",{className:"text-left p-2",children:"Slug"}),t.jsx("th",{className:"text-left p-2",children:"Stage-3 URL"}),t.jsx(d,{k:"status",label:"Status"}),t.jsx("th",{className:"text-right p-2",children:"Actions"})]})}),t.jsxs("tbody",{children:[v.length===0&&t.jsx("tr",{children:t.jsx("td",{colSpan:10,className:"text-center text-muted-foreground p-6",children:"No keyword rows yet. Add one to get started."})}),v.map(e=>{const s=_(e),a=W(s);return t.jsxs("tr",{className:`border-t border-border ${e._dirty?"bg-amber-500/5":""}`,children:[t.jsx("td",{className:"p-1.5",children:t.jsxs("div",{className:"flex items-center gap-2",children:[t.jsx("span",{className:"font-mono text-xs tabular-nums w-10 text-right",children:s||"â"}),t.jsx("span",{className:`inline-block text-[10px] uppercase px-1.5 py-0.5 rounded border ${a.cls}`,children:a.label})]})}),t.jsx("td",{className:"p-1.5",children:t.jsx("input",{value:e.cluster,onChange:r=>i(e.id,{cluster:r.target.value}),className:"w-32 rounded border border-border bg-background px-2 py-1 text-xs"})}),t.jsx("td",{className:"p-1.5",children:t.jsx("input",{value:e.primary_keyword,onChange:r=>i(e.id,{primary_keyword:r.target.value}),className:"w-48 rounded border border-border bg-background px-2 py-1 text-xs"})}),t.jsx("td",{className:"p-1.5",children:t.jsx("input",{type:"number",value:e.search_volume??"",onChange:r=>i(e.id,{search_volume:r.target.value?Number(r.target.value):null}),className:"w-20 rounded border border-border bg-background px-2 py-1 text-xs"})}),t.jsx("td",{className:"p-1.5",children:t.jsx("input",{type:"number",value:e.difficulty??"",onChange:r=>i(e.id,{difficulty:r.target.value?Number(r.target.value):null}),className:"w-16 rounded border border-border bg-background px-2 py-1 text-xs"})}),t.jsx("td",{className:"p-1.5",children:t.jsxs("select",{value:e.intent??"",onChange:r=>i(e.id,{intent:r.target.value||null}),className:"rounded border border-border bg-background px-2 py-1 text-xs",children:[t.jsx("option",{value:"",children:"â"}),H.map(r=>
1t.jsx("option",{value:r,children:r},r))]})}),t.jsx("td",{className:"p-1.5",children:t.jsx("input",{value:e.target_slug??"",onChange:r=>i(e.id,{target_slug:r.target.value||null}),className:"w-40 rounded border border-border bg-background px-2 py-1 text-xs"})}),t.jsx("td",{className:"p-1.5",children:t.jsx("input",{value:e.destination_url??"",onChange:r=>i(e.id,{destination_url:r.target.value||null}),placeholder:"/features/...",className:"w-44 rounded border border-border bg-background px-2 py-1 text-xs"})}),t.jsx("td",{className:"p-1.5",children:t.jsx("select",{value:e.status,onChange:r=>i(e.id,{status:r.target.value}),className:"rounded border border-border bg-background px-2 py-1 text-xs",children:N.map(r=>t.jsx("option",{value:r,children:r},r))})}),t.jsxs("td",{className:"p-1.5 text-right whitespace-nowrap",children:[e._dirty&&t.jsxs("button",{onClick:()=>L(e),className:"inline-flex items-center gap-1 px-2 py-1 rounded text-xs bg-primary text-white hover:opacity-90",title:"Save",children:[t.jsx(F,{className:"w-3 h-3"})," Save"]}),!e._new&&e.primary_keyword&&t.jsxs("button",{onClick:()=>I(e),className:"ml-1 inline-flex items-center gap-1 px-2 py-1 rounded text-xs border border-border hover:bg-muted",title:"Start draft",children:[t.jsx($,{className:"w-3 h-3"})," Draft"]}),t.jsx("button",{onClick:()=>R(e),className:"ml-1 inline-flex items-center gap-1 px-2 py-1 rounded text-xs border border-border text-destructive hover:bg-destructive/10",title:"Delete",children:t.jsx(U,{className:"w-3 h-3"})})]})]},e.id??`new-${e.primary_keyword}`)})]})]})}),t.jsxs("p",{className:"mt-6 text-xs text-muted-foreground",children:["Tip: sort by ",t.jsx("strong",{children:"Score"}),' (default) and work top-down. Rows with missing Vol/KD use neutral fallbacks â fill them in to sharpen the ranking. The "Draft" button opens the blog editor pre-filled with this keyword.']})]})}export{Y as default};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.