1import{c as R,W as Se,a0 as Xe,r as m,j as e,d as de,B as h,a1 as c,a2 as Z,a3 as ke,a4 as J,a5 as ws,l as Ie,a6 as es,T as ss,U as ts,a7 as as,a8 as ns,a9 as is,aa as rs,x as he,ab as os,F as ce,ac as Cs,I as A,Y as X,u as ls,v as L,ad as ne,ae as ie,af as re,ag as oe,ah as le,ai as q,aj as Q,ak as We,p as cs,al as Ss,am as ks,an as Ne,m as H,ao as Is,ap as Ps,C as Us,aq as Pe,ar as me,as as Ue,X as Oe,H as As}from"./index-DrAEDOWO.js";import{C as P}from"./card-tjKlq1tq.js";import{B as Ye}from"./badge-BJD2Z0uZ.js";import{L as N}from"./label-O1ybTSDS.js";import{D as Fs}from"./duda-DJj_FJrt.js";import{p as D,a as Es}from"./platformService-Cl7tAPru.js";import{W as Ts,S as Ke,G as Ls,a as Ds,B as Rs,b as Bs,c as Ms,d as $s,e as qs,f as He}from"./Icons-DDkdSM7U.js";import{c as zs,d as _s,e as Gs}from"./useContentPlanner-5fc17g5G.js";import{L as V}from"./loader-circle-jYO-yoyj.js";import{S as Ws}from"./settings-axDot6x9.js";/** 2 * @license lucide-react v0.453.0 - ISC 3 * 4 * This source code is licensed under the ISC license. 5 * See the LICENSE file in the root directory of this source tree. 6 */const Os=R("Bell",[["path",{d:"M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9",key:"1qo2s2"}],["path",{d:"M10.3 21a1.94 1.94 0 0 0 3.4 0",key:"qgo35s"}]]);/** 7 * @license lucide-react v0.453.0 - ISC 8 * 9 * This source code is licensed under the ISC license. 10 * See the LICENSE file in the root directory of this source tree. 11 */const Y=R("ExternalLink",[["path",{d:"M15 3h6v6",key:"1q9fwt"}],["path",{d:"M10 14 21 3",key:"gplh6r"}],["path",{d:"M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6",key:"a6xqqp"}]]);/** 12 * @license lucide-react v0.453.0 - ISC 13 * 14 * This source code is licensed under the ISC license. 15 * See the LICENSE file in the root directory of this source tree. 16 */const Ys=R("Heart",[["path",{d:"M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z",key:"c3ymky"}]]);/** 17 * @license lucide-react v0.453.0 - ISC 18 * 19 * This source code is licensed under the ISC license. 20 * See the LICENSE file in the root directory of this source tree. 21 */const Ks=R("Layers",[["path",{d:"m12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83Z",key:"8b97xw"}],["path",{d:"m22 17.65-9.17 4.16a2 2 0 0 1-1.66 0L2 17.65",key:"dd6zsq"}],["path",{d:"m22 12.65-9.17 4.16a2 2 0 0 1-1.66 0L2 12.65",key:"ep9fru"}]]);/** 22 * @license lucide-react v0.453.0 - ISC 23 * 24 * This source code is licensed under the ISC license. 25 * See the LICENSE file in the root directory of this source tree. 26 */const Hs=R("LayoutGrid",[["rect",{width:"7",height:"7",x:"3",y:"3",rx:"1",key:"1g98yp"}],["rect",{width:"7",height:"7",x:"14",y:"3",rx:"1",key:"6d4xhi"}],["rect",{width:"7",height:"7",x:"14",y:"14",rx:"1",key:"nxv5o0"}],["rect",{width:"7",height:"7",x:"3",y:"14",rx:"1",key:"1bb6yr"}]]);/** 27 * @license lucide-react v0.453.0 - ISC 28 * 29 * This source code is licensed under the ISC license. 30 * See the LICENSE file in the root directory of this source tree. 31 */const Vs=R("Mail",[["rect",{width:"20",height:"16",x:"2",y:"4",rx:"2",key:"18n3k1"}],["path",{d:"m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7",key:"1ocrg3"}]]);/** 32 * @license lucide-react v0.453.0 - ISC 33 * 34 * This source code is licensed under the ISC license. 35 * See the LICENSE file in the root directory of this source tree. 36 */const Qs=R("Mic",[["path",{d:"M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3Z",key:"131961"}],["path",{d:"M19 10v2a7 7 0 0 1-14 0v-2",key:"1vc78b"}],["line",{x1:"12",x2:"12",y1:"19",y2:"22",key:"x3vr5v"}]]);/** 37 * @license lucide-react v0.453.0 - ISC 38 * 39 * This source code is licensed under the ISC license. 40 * See the LICENSE file in the root directory of this source tree. 41 */const Zs=R("RefreshCw",[["path",{d:"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8",key:"v9h5vc"}],["path",{d:"M21 3v5h-5",key:"1q7to0"}],["path",{d:"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16",key:"3uifl3"}],["path",{d:"M8 16H3v5",key:"1cv678"}]]);/** 42 * @license lucide-react v0.453.0 - ISC 43 * 44 * This source code is licensed under the ISC license. 45 * See the LICENSE file in the root directory of this source tree. 46 */const Js=R("Shield",[["path",{d:"M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z",ke
46y:"oel41y"}]]);/** 47 * @license lucide-react v0.453.0 - ISC 48 * 49 * This source code is licensed under the ISC license. 50 * See the LICENSE file in the root directory of this source tree. 51 */const Xs=R("Users",[["path",{d:"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2",key:"1yyitq"}],["circle",{cx:"9",cy:"7",r:"4",key:"nufk8"}],["path",{d:"M22 21v-2a4 4 0 0 0-3-3.87",key:"kshegd"}],["path",{d:"M16 3.13a4 4 0 0 1 0 7.75",key:"1da9ce"}]]);/** 52 * @license lucide-react v0.453.0 - ISC 53 * 54 * This source code is licensed under the ISC license. 55 * See the LICENSE file in the root directory of this source tree. 56 */const et=R("Webhook",[["path",{d:"M18 16.98h-5.99c-1.1 0-1.95.94-2.48 1.9A4 4 0 0 1 2 17c.01-.7.2-1.4.57-2",key:"q3hayz"}],["path",{d:"m6 17 3.13-5.78c.53-.97.1-2.18-.5-3.1a4 4 0 1 1 6.89-4.06",key:"1go1hn"}],["path",{d:"m12 6 3.13 5.73C15.66 12.7 16.9 13 18 13a4 4 0 0 1 0 8",key:"qlwsc0"}]]),st=[{id:0,label:"Sunday",short:"Sun"},{id:1,label:"Monday",short:"Mon"},{id:2,label:"Tuesday",short:"Tue"},{id:3,label:"Wednesday",short:"Wed"},{id:4,label:"Thursday",short:"Thu"},{id:5,label:"Friday",short:"Fri"},{id:6,label:"Saturday",short:"Sat"}],tt=()=>{const{data:t,refetch:r}=Se(),n=Xe(),[i,d]=m.useState(!0),[a,u]=m.useState([0,1,2,3,4,5,6]);m.useEffect(()=>{t&&(t.automationEnabled!=null&&d(t.automationEnabled),t.automationDays&&u(t.automationDays))},[t]);const f=x=>{u(g=>g.includes(x)?g.filter(b=>b!==x):[...g,x].sort((b,C)=>b-C))},p=()=>{n.mutate({automationEnabled:i,automationDays:a},{onSuccess:()=>c.success("Automation settings updated successfully"),onError:({message:x})=>c.error(x||"Failed to update automation settings"),onSettled:()=>void r()})};return e.jsxs(P,{className:"border-gray-200 p-6",children:[e.jsx("h3",{className:"mb-6 text-lg font-semibold",children:"Content Automation"}),e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{className:"flex items-center justify-between rounded-xl bg-gray-50 p-4",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-sm font-medium",children:"Enable Automation"}),e.jsx("div",{className:"text-xs text-gray-600",children:"Automatically generate and publish content based on your schedule."})]}),e.jsxs("label",{className:"relative inline-flex cursor-pointer items-center",children:[e.jsx("input",{type:"checkbox",className:"peer sr-only",checked:i,onChange:()=>d(x=>!x),disabled:n.isPending}),e.jsx("div",{className:"peer h-6 w-11 rounded-full bg-gray-200 peer-checked:bg-blue after:absolute after:top-0.5 after:left-0.5 after:h-5 after:w-5 after:rounded-full after:border after:border-gray-300 after:bg-white after:transition-all after:content-[''] peer-checked:after:translate-x-full peer-checked:after:border-white"})]})]}),e.jsxs("div",{className:"flex items-center justify-between rounded-xl bg-gray-50 p-4",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-sm font-medium",children:"Automation Schedule"}),e.jsx("div",{className:"text-xs text-gray-600",children:"Select the days you want content to be automatically generated and published (at 9:00 AM)."})]}),e.jsx("div",{className:"flex flex-wrap gap-2",children:st.map(x=>e.jsx("button",{onClick:()=>f(x.id),className:de("flex size-12 items-center justify-center rounded-xl border text-sm font-medium transition-all",a.includes(x.id)?"border-blue bg-blue text-white shadow-lg shadow-blue-100":"border-gray-200 bg-white text-gray-600 hover:border-gray-300"),title:x.label,children:x.short},x.id))})]}),e.jsx("div",{className:"flex justify-end gap-3",children:e.jsx(h,{className:"h-12 p-6 text-sm",onClick:p,disabled:n.isPending,children:n.isPending?"Saving...":"Save Changes"})})]})]})},at=(t,r)=>{try{return new Intl.NumberFormat(void 0,{style:"currency",currency:(r||"usd").toUpperCase()}).format((t||0)/100)}catch{return`$${((t||0)/100).toFixed(2)}`}},nt=({language:t,open:r,onOpenChange:n})=>{const[i,d]=m.useState(null),{activeWebsite:a}=Z(),{activeLanguage:u,setActiveLanguage:f,languages:p}=ke(),x=J(),g=ws(),b=(t==null?void 0:t.status)==="failed",C=Ie({queryKey:["languages","preview-remove",a==null?void 0:a.id,t==null?void 0:t.id],queryFn:()=>Cs.previewRemove(a.id,t.id),enabled:r&&!!(a!=null&&a.id)&&!!(t!=null&&t.id)&&!b,staleTime:0,retry:!1}),E=b||C.isSuccess&&!!C.data,y=async()=>
56{if(!(!a||!t)){d(null);try{if(await g.mutateAsync({websiteId:a.id,languageId:t.id}),x.invalidateQueries({queryKey:["languages",a.id]}),(u==null?void 0:u.id)===t.id){const F=p.find(U=>U.id!==t.id);F&&f(F.id)}n(!1)}catch(F){d(F instanceof ce?F.message:"Could not remove this language. Please try again.")}}},S=t?es[t.languageCode]:null;return e.jsx(ss,{open:r,onOpenChange:n,children:e.jsxs(ts,{className:"sm:max-w-md",children:[e.jsxs(as,{children:[e.jsxs(ns,{className:"flex items-center gap-2",children:["Remove ",e.jsx(is,{country:S==null?void 0:S.country})," ",(S==null?void 0:S.label)??(t==null?void 0:t.languageCode),"?"]}),e.jsx(rs,{children:b?"This language setup didn't finish and will be cleared from your account.":C.isLoading?"Calculating your updated plan amount...":C.data?e.jsxs(e.Fragment,{children:["Are you sure you want to remove this language? Your plan will update to"," ",e.jsxs("strong",{className:"text-gray-900",children:[at(C.data.nextRecurringAmount,C.data.currency),"/mo"]})," ","for this website starting"," ",C.data.periodEnd?new Date(C.data.periodEnd).toLocaleDateString():"next renewal","."]}):"Are you sure you want to remove this language from this website?"})]}),C.isLoading&&e.jsxs("div",{className:"flex items-center justify-center py-4 text-sm text-gray-500",children:[e.jsx(he,{className:"size-4 mr-2"})," Loading updated plan detailsâ¦"]}),C.isError&&!b&&e.jsxs("div",{className:"flex items-center justify-between gap-3 rounded-xl border border-gray-200 p-3 text-sm",children:[e.jsx("span",{className:"text-red-600",children:"Couldn't load plan update."}),e.jsx(h,{variant:"outline",size:"sm",onClick:()=>C.refetch(),children:"Retry"})]}),i&&e.jsx("p",{className:"text-sm text-red-600",children:i}),e.jsxs(os,{className:"mt-2",children:[e.jsx(h,{variant:"outline",onClick:()=>n(!1),disabled:g.isPending,children:"Cancel"}),e.jsx(h,{onClick:y,disabled:!E||g.isPending,className:"bg-red-600 hover:bg-red-700",children:g.isPending?e.jsx(he,{className:"size-4"}):"Remove Language"})]})]})})},it=["Technology","E-commerce","Healthcare","Finance","Education"],rt=["UTC-08:00 Pacific Time","UTC-05:00 Eastern Time","UTC+00:00 London","UTC+01:00 Paris"],Ve={companyName:"",websiteUrl:"",industry:"",timezone:""},ot=()=>{const{activeWebsite:t}=Z(),{languages:r}=ke(),{isTeamContext:n}=X(),[i,d]=m.useState(null);return!t||r.length===0?null:e.jsxs(P,{className:"border-gray-200 p-6",children:[e.jsx("h3",{className:"mb-1 text-lg font-semibold",children:"Languages"}),e.jsxs("p",{className:"mb-6 text-sm text-gray-500",children:["Each language has its own independent content calendar for ",t.name||t.domain,"."]}),e.jsx("ul",{className:"divide-y divide-gray-100 rounded-xl border border-gray-200",children:r.map(a=>{const u=es[a.languageCode];return e.jsxs("li",{className:"flex items-center justify-between gap-3 px-4 py-3",children:[e.jsxs("span",{className:"flex items-center gap-2 text-sm",children:[e.jsx(is,{country:u==null?void 0:u.country}),e.jsx("span",{className:"font-medium",children:(u==null?void 0:u.label)??a.languageCode}),a.isDefault&&e.jsx(Ye,{variant:"secondary",children:"Default"}),a.status==="failed"&&e.jsx(Ye,{variant:"destructive",children:"Setup failed"})]}),!a.isDefault&&!n&&e.jsx(h,{variant:"outline",size:"sm",onClick:()=>d(a),children:"Remove"})]},a.id)})}),e.jsx(nt,{language:i,open:!!i,onOpenChange:a=>!a&&d(null)})]})},lt=()=>{const{data:t,refetch:r}=Se(),n=Xe(),[i,d]=m.useState(Ve);m.useEffect(()=>{t&&d({companyName:t.companyName??"",websiteUrl:t.websiteUrl??"",industry:t.industry??"",timezone:t.timezone??""})},[t]);const a=p=>x=>{d(g=>({...g,[p]:x.target.value}))},u=()=>{if(!t){d(Ve);return}d({companyName:t.companyName??"",websiteUrl:t.websiteUrl??"",industry:t.industry??"",timezone:t.timezone??""})},f=()=>{n.mutate(i,{onSuccess:()=>c.success("General settings updated"),onError:({message:p})=>c.error(p||"Failed to update settings"),onSettled:()=>void r()})};return e.jsxs("div",{className:"space-y-6",children:[e.jsxs(P,{className:"border-gray-200 p-6",children:[e.jsx("h3",{className:"mb-6 text-lg font-semibold",children:"General Settings"}),e.jsxs("div",{className:"space-y-6",children:[e.jsxs("div",{children:[e.jsx(N,{className:"mb-2 block text-sm font-medium text-gray-700",children:"Company Name"}),e.jsx(A,{placeholder:"Enter company name",value:i.companyName,onChange:a("companyName")})]}),e.jsxs("div",{children:[e.jsx(N,{className:"mb-2 block text-sm font-medium text-gray-700",children:"Website URL"}),e.jsx(A,{placeholder:"https://example.com",value:i.websiteUrl,onChange:a("websiteUrl")})]}),e.jsxs("div",{children:[e.jsx(N,{className:"mb-2 block text-sm font-medium text-gray-700",children:"Industry"}),e.jsxs("select",{value:i.industry,onChange:a("industry"),className:"flex h-12 w-full rounded-xl border border-gray-200 bg-white px-4 py-3 text-sm r
56ing-offset-white focus-visible:ring-2 focus-visible:ring-blue focus-visible:outline-none",children:[e.jsx("option",{value:"",children:"Select industry"}),it.map(p=>e.jsx("option",{value:p,children:p},p))]})]}),e.jsxs("div",{children:[e.jsx(N,{className:"mb-2 block text-sm font-medium text-gray-700",children:"Time Zone"}),e.jsxs("select",{value:i.timezone,onChange:a("timezone"),className:"flex h-12 w-full rounded-xl border border-gray-200 bg-white px-4 py-3 text-sm ring-offset-white focus-visible:ring-2 focus-visible:ring-blue focus-visible:outline-none",children:[e.jsx("option",{value:"",children:"Select time zone"}),rt.map(p=>e.jsx("option",{value:p,children:p},p))]})]}),e.jsxs("div",{className:"flex justify-end gap-3",children:[e.jsx(h,{variant:"outline",className:"h-12 p-6 text-sm",onClick:u,disabled:n.isPending,children:"Cancel"}),e.jsx(h,{className:"h-12 p-6 text-sm",onClick:f,disabled:n.isPending,children:n.isPending?"Saving...":"Save Changes"})]})]})]}),e.jsx(ot,{})]})},ct=[{id:"wordpress",name:"WordPress",status:"disconnected",description:"Connect your WordPress site for automated content publishing and SEO optimization",lastSync:"Never",supportsConfig:!0,icon:e.jsx(Ts,{className:"h-8 w-8 text-[#21759B]"})},{id:"shopify",name:"Shopify",status:"disconnected",description:"Connect your Shopify store for automated content publishing and SEO optimization",lastSync:"Never",supportsConfig:!0,icon:e.jsx(Ke,{className:"h-8 w-8 text-[#7AB55C]"})},{id:"shopify-app",name:"Shopify Plugin",status:"disconnected",description:"Install the official Rankpilot Shopify app â no credentials to manage.",lastSync:"Never",supportsConfig:!0,icon:e.jsx(Ke,{className:"h-8 w-8 text-[#7AB55C]"})},{id:"google-analytics",name:"Google Analytics",status:"disconnected",description:"Track website performance and user behavior",lastSync:"Never",supportsConfig:!0,icon:e.jsx(Ls,{className:"h-8 w-8 text-[#E37400]"})},{id:"search-console",name:"Google Search Console",status:"disconnected",description:"Monitor search performance and indexing",lastSync:"Never",supportsConfig:!0,icon:e.jsx(Ds,{className:"h-8 w-8 text-[#458CF5]"})},{id:"blogger",name:"Google Blogger",status:"disconnected",description:"Connect your Blogger account for automated content publishing",lastSync:"Never",supportsConfig:!0,icon:e.jsx(Rs,{className:"h-8 w-8 text-[#FF5722]"})},{id:"sanity",name:"Sanity.io",status:"disconnected",description:"Connect your Sanity project for automated content publishing as Portable Text",lastSync:"Never",supportsConfig:!0,icon:e.jsx(Bs,{className:"h-8 w-8 text-[#F03E2F]"})},{id:"duda",name:"Duda",status:"disconnected",description:"Publish straight to your Duda site's blog",lastSync:"Never",supportsConfig:!0,icon:e.jsx("img",{src:Fs,alt:"Duda",className:"h-8 w-auto"})},{id:"webflow",name:"Webflow",status:"disconnected",description:"Connect your Webflow site for automated content publishing",lastSync:"Never",supportsConfig:!0,icon:e.jsx(Ms,{className:"h-8 w-8 text-[#146EF5]"})},{id:"wix",name:"Wix",status:"disconnected",description:"Connect your Wix site for automated blog post publishing",lastSync:"Never",supportsConfig:!0,icon:e.jsx($s,{className:"h-8 w-8 text-black"})},{id:"ghost",name:"Ghost",status:"disconnected",description:"Connect your Ghost site for automated content publishing",lastSync:"Never",supportsConfig:!0,icon:e.jsx(qs,{className:"h-8 w-8 text-black"})},{id:"base44",name:"Base44",status:"disconnected",description:"Connect your Base44 app for automated content publishing via a signed webhook",lastSync:"Never",supportsConfig:!0,icon:e.jsx(Ks,{className:"h-8 w-8 text-[#6D5CFF]"})},{id:"lovable",name:"Lovable",status:"disconnected",description:"Connect your Lovable app for automated content publishing via a signed webhook",lastSync:"Never",supportsConfig:!0,icon:e.jsx(Ys,{className:"h-8 w-8 text-[#FF5B7F]"})},{id:"webhook",name:"Webhook / API",status:"disconnected",description:"Connect any custom app or backend via a signed webhook for automated content publishing",lastSync:"Never",supportsConfig:!0,icon:e.jsx(et,{className:"h-8 w-8 text-[#4B5563]"})}],ve=({idPrefix:t,config:r,onChange:n})=>{const i=()=>{const a=new Uint8Array(24);window.crypto.getRandomValues(a);const u=Array.from(a,f=>f.toString(16).padStart(2,"0")).join("");n({...r,webhookSecret:u})},d=async()=>{r.webhookSecret&&(await navigator.clipboard.writeText(r.webhookSecret),c.success("Secret
56copied"))};return e.jsxs("div",{className:"grid gap-6",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{htmlFor:`${t}-url`,children:"Webhook URL"}),e.jsx(A,{id:`${t}-url`,placeholder:"https://your-app.example.com/api/rankpilot-webhook",value:r.webhookUrl,onChange:a=>n({...r,webhookUrl:a.target.value})}),e.jsx("p",{className:"text-xs text-gray-500",children:"Must be HTTPS. This is the endpoint we'll POST content to."})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{htmlFor:`${t}-secret`,children:"Webhook Secret"}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(L,{id:`${t}-secret`,placeholder:"A long random string, at least 16 characters",value:r.webhookSecret,onChange:a=>n({...r,webhookSecret:a.target.value})}),e.jsx(h,{type:"button",variant:"outline",onClick:i,children:"Generate"}),e.jsx(h,{type:"button",variant:"outline",size:"icon",onClick:d,disabled:!r.webhookSecret,children:e.jsx(Q,{className:"size-4"})})]}),e.jsx("p",{className:"text-xs text-gray-500",children:"Use this exact value in your endpoint's signature verification code (see below). We store it encrypted and it won't be shown again after you leave this page â copy it now."})]})]})},dt=({tabs:t})=>{var a;const[r,n]=m.useState((a=t[0])==null?void 0:a.id),i=t.find(u=>u.id===r)??t[0],d=async()=>{await navigator.clipboard.writeText(i.code),c.success("Code copied")};return e.jsxs("div",{className:"mt-2",children:[e.jsx("div",{className:"flex flex-wrap gap-1",children:t.map(u=>e.jsx("button",{type:"button",onClick:()=>n(u.id),className:`rounded-t-md px-3 py-1.5 text-xs font-medium transition-colors ${u.id===i.id?"bg-gray-900 text-white":"bg-gray-200 text-gray-600 hover:bg-gray-300"}`,children:u.label},u.id))}),e.jsxs("div",{className:"relative",children:[e.jsx("pre",{className:"max-h-72 overflow-auto rounded-b-md rounded-tr-md bg-gray-900 p-3 text-xs text-gray-100",children:i.code}),e.jsx(h,{type:"button",variant:"outline",size:"icon",className:"absolute top-2 right-2",onClick:d,children:e.jsx(Q,{className:"size-4"})})]})]})},Ae=({children:t})=>e.jsxs("div",{className:"flex items-start gap-2 rounded-lg border border-blue-100 bg-blue-50 p-3 text-xs text-blue-900",children:[e.jsx(cs,{className:"mt-0.5 size-4 shrink-0"}),e.jsxs("p",{children:[t," ",e.jsx("a",{href:"mailto:[email protected]",className:"font-medium underline",children:"Email support"})," ","and we'll help you get connected."]})]}),ht=[{id:"node",label:"Node.js",code:`const crypto = require("crypto"); 57 58function isValid(rawBody, header, secret) { 59 const [tPart, vPart] = header.split(","); 60 const timestamp = tPart.split("=")[1]; 61 const signature = vPart.split("=")[1]; 62 63 const expected = crypto 64 .createHmac("sha256", secret) 65 .update(\`\${timestamp}.\${rawBody}\`) 66 .digest("hex"); 67 68 const fresh = Math.abs(Date.now() / 1000 - Number(timestamp)) < 300; 69 return fresh && crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected)); 70}`},{id:"python",label:"Python",code:`import hashlib 71import hmac 72import time 73 74def is_valid(raw_body: bytes, header: str, secret: str) -> bool: 75 t_part, v_part = header.split(",") 76 timestamp = t_part.split("=")[1] 77 signature = v_part.split("=")[1] 78 79 payload = f"{timestamp}.{raw_body.decode()}".encode() 80 expected = hmac.new(secret.encode(), payload, hashlib.sha256).hexdigest() 81 82 fresh = abs(time.time() - int(timestamp)) < 300 83 return fresh and hmac.compare_digest(signature, expected)`},{id:"php",label:"PHP",code:`<?php 84 85function is_valid(string $rawBody, string $header, string $secret): bool { 86 [$tPart, $vPart] = explode(",", $header); 87 $timestamp = explode("=", $tPart)[1]; 88 $signature = explode("=", $vPart)[1]; 89 90 $expected = hash_hmac("sha256", "{$timestamp}.{$rawBody}", $secret); 91 92 $fresh = abs(time() - (int) $timestamp) < 300; 93 return $fresh && hash_equals($expected, $signature); 94}`},{id:"ruby",label:"Ruby",code:`require "openssl" 95 96def valid?(raw_body, header, secret) 97 t_part, v_part = header.split(",") 98 timestamp = t_part.split("=")[1] 99 signature = v_part.split("=")[1] 100 101 expected = OpenSSL::HMAC.hexdigest("SHA256", secret, "#{timestamp}.#{raw_body}") 102 fresh = (Time.now.to_i - timestamp.to_i).abs < 300 103 104 fresh && OpenSSL.fixed_length_secure_compare(signature, expected) 105end`},{id:"go",label:"Go",code:`package main 106 107import ( 108 "crypto/hmac" 109 "crypto/sha256" 110 "encoding/hex" 111 "fmt" 112 "math" 113 "strconv" 114 "strings" 115 "time" 116) 117 118func isValid(rawBody []byte, header, secret string) bool { 119 parts := strings.Split(header, ",") 120 timestamp := strings.Split(parts[0], "=")[1] 121 signature := strings.Split(parts[1], "=")[1] 122 123 mac := hmac.New(sha256.New, []byte(secret)) 124 mac.Write([]byte(fmt.Sprintf("%s.%s", timestamp, rawBody))) 125 expected := hex.EncodeToString(mac.Sum(nil)) 126 127 ts, _ := strconv.ParseInt(timestamp, 10, 64) 128 fresh := math.Abs(float64(time.Now().Unix()-ts)) < 300 129 130 return fresh && hmac.Equal([]byte(signature), []byte(expected)) 131}`}],we=()=>e.jsxs("div",{className:"space-y-4 rounded-lg border border-gray-200 bg-gray-50 p-4 text-sm",children:[e.jsx("h4",{className:"font-semibold",children:"How to set up your endpoint"}),e.jsxs("ol",{className:"list-decimal space-y-3 pl-5 text-gray-700",children:[e.jsxs("li",{children:["Create an endpoint on your app that accepts ",e.jsx("code",{className:"rounded bg-gray-200 px-1",children:"POST"})," requests with a JSON body â that's the only method we ever send."]}),e.jsxs("li",{children:["Every request includes these headers:",e.jsx("pre",{className:"mt-2 overflow-x-auto rounded bg-gray-900 p-3 text-xs text-gray-100",children:`X-RankPilot-Event: content.publish | integration.test 132X-RankPilot-Signature: t=<unix_timestamp>,v1=<hmac_sha256_hex>`})]}),e.jsxs("li",{children:["Verify the signature before trusting the payload. Compute HMAC-SHA256 over"," ",e.jsx("code",{className:"rounded bg-gray-200 px-1",children:"`${timestamp}.${rawRequestBody}`"})," using your secret, and compare it to the ",e.jsx("code",{className:"rounded bg-gray-200 px-1",children:"v1"})," value. Use the raw request body exactly as received â parsing and re-serializing the JSON before verifying will break the signature. Reject requests where the timestamp is more than 5 minutes old. Pick your language below â the logic is identical in each:",e.jsx(dt,{tabs:ht})]}),e.jsxs("li",{children:["When you click ",e.jsx("strong",{children:"Save Configuration"}),", we immediately send a test ping:",e.jsx("pre",{className:"mt-2 overflow-x-auto rounded bg-gray-900 p-3 text-xs text-gray-100",children:`{ 133 "event": "integration.test", 134 "timestamp": "2026-07-17T12:00:00.000Z", 135 "payload": { "message": "Test ping from RankPilot" } 136}`}),"Any response from your endpoint â including a 4xx/5xx if it doesn't recognize the test payload â counts as a successful connection, since it proves the endpoint is reachable. Only a timeout, connection refused, or DNS failure fails verification. We use the same check afterward to detect if your endpoint goes down, and will auto-disconnect the integration and notify you if it becomes unreachable."]}),e.jsxs("li",{children:["Real content is sent the same way, with ",e.jsx("code",{className:"rounded bg-gray-200 px-1",children:'event: "content.publish"'}),":",e.jsx("pre",{className:"mt-2 overflow-x-auto rounded bg-gray-900 p-3 text-xs text-gray-100",children:`{ 137 "event": "content.publish", 138 "contentItemId": "...", 139 "title": "...", 140 "html": "...", 141 "metaDescription": "...", 142 "keywords": ["..."], 143 "mainImage": "https://...", 144 "type": "blog", 145 "author": "...", 146 "status": "publish" 147}`}),e.jsx("p",{className:"mt-2 text-gray-700",children:"Field reference for the body above:"}),e.jsx("div",{className:"mt-2 overflow-x-auto rounded border border-gray-200",children:e.jsxs("table",{className:"w-full text-left text-xs",children:[e.jsx("thead",{className:"bg-gray-100 text-gray-600",children:e.jsxs("tr",{children:[e.jsx("th",{className:"px-2 py-1.5 font-medium",children:"Field"}),e.jsx("th",{className:"px-2 py-1.5 font-medium",children:"Type"}),e.jsx("th",{className:"px-2 py-1.5 font-medium",children:"Always present"}),e.jsx("th",{className:"px-2 py-1.5 font-medium",children:"Notes"})]})}),e.jsxs("tbody",{className:"divide-y divide-gray-200 text-gray-700",children:[e.jsxs("tr",{children:[e.jsx("td",{className:"px-2 py-1.5 font-mono",children:"event"}),e.jsx("td",{className:"px-2 py-1.5 font-mono",children:'"content.publish"'}),e.jsx("td",{className:"px-2 py-1.5",children:"Yes"}),e.jsx("td",{className:"px-2 py-1.5",children:'Constant for real publishes ("integration.test" for the connect-time ping)'})]}),e.jsxs("tr",{children:[e.jsx("td",{className:"px-2 py-1.5 font-mono",children:"contentItemId"}),e.jsx("td",{className:"px-2 py-1.5 font-mono",children:"string"}),e.jsx("td",{className:"px-2 py-1.5",children:"No"}),e.jsx("td",{className:"px-2 py-1.5",children:"RankPilot's internal
147content ID, omitted if not tracked as a content item"})]}),e.jsxs("tr",{children:[e.jsx("td",{className:"px-2 py-1.5 font-mono",children:"title"}),e.jsx("td",{className:"px-2 py-1.5 font-mono",children:"string"}),e.jsx("td",{className:"px-2 py-1.5",children:"Yes"}),e.jsx("td",{className:"px-2 py-1.5",children:"Post/article title"})]}),e.jsxs("tr",{children:[e.jsx("td",{className:"px-2 py-1.5 font-mono",children:"html"}),e.jsx("td",{className:"px-2 py-1.5 font-mono",children:"string"}),e.jsx("td",{className:"px-2 py-1.5",children:"Yes"}),e.jsx("td",{className:"px-2 py-1.5",children:"Full article body as sanitized HTML"})]}),e.jsxs("tr",{children:[e.jsx("td",{className:"px-2 py-1.5 font-mono",children:"metaDescription"}),e.jsx("td",{className:"px-2 py-1.5 font-mono",children:"string | undefined"}),e.jsx("td",{className:"px-2 py-1.5",children:"No"}),e.jsx("td",{className:"px-2 py-1.5",children:"SEO meta description, may be missing"})]}),e.jsxs("tr",{children:[e.jsx("td",{className:"px-2 py-1.5 font-mono",children:"keywords"}),e.jsx("td",{className:"px-2 py-1.5 font-mono",children:"string[]"}),e.jsx("td",{className:"px-2 py-1.5",children:"Yes"}),e.jsx("td",{className:"px-2 py-1.5",children:"Defaults to an empty array"})]}),e.jsxs("tr",{children:[e.jsx("td",{className:"px-2 py-1.5 font-mono",children:"mainImage"}),e.jsx("td",{className:"px-2 py-1.5 font-mono",children:"string | undefined"}),e.jsx("td",{className:"px-2 py-1.5",children:"No"}),e.jsx("td",{className:"px-2 py-1.5",children:"Featured image URL, may be missing"})]}),e.jsxs("tr",{children:[e.jsx("td",{className:"px-2 py-1.5 font-mono",children:"type"}),e.jsx("td",{className:"px-2 py-1.5 font-mono",children:"string"}),e.jsx("td",{className:"px-2 py-1.5",children:"Yes"}),e.jsx("td",{className:"px-2 py-1.5",children:'Content type, currently always "blog"'})]}),e.jsxs("tr",{children:[e.jsx("td",{className:"px-2 py-1.5 font-mono",children:"author"}),e.jsx("td",{className:"px-2 py-1.5 font-mono",children:"string | undefined"}),e.jsx("td",{className:"px-2 py-1.5",children:"No"}),e.jsx("td",{className:"px-2 py-1.5",children:"Author name, may be missing"})]}),e.jsxs("tr",{children:[e.jsx("td",{className:"px-2 py-1.5 font-mono",children:"status"}),e.jsx("td",{className:"px-2 py-1.5 font-mono",children:'"draft" | "publish"'}),e.jsx("td",{className:"px-2 py-1.5",children:"Yes"}),e.jsx("td",{className:"px-2 py-1.5",children:"Whether this should go live immediately or save as a draft on your side"})]})]})]})})]}),e.jsxs("li",{children:["Respond with a ",e.jsx("code",{className:"rounded bg-gray-200 px-1",children:"2xx"})," status and, if available, a JSON body so we can track the published URL:",e.jsx("pre",{className:"mt-2 overflow-x-auto rounded bg-gray-900 p-3 text-xs text-gray-100",children:'{ "id": "your-internal-id", "url": "https://your-site.com/post-slug" }'}),e.jsx("div",{className:"mt-2 overflow-x-auto rounded border border-gray-200",children:e.jsxs("table",{className:"w-full text-left text-xs",children:[e.jsx("thead",{className:"bg-gray-100 text-gray-600",children:e.jsxs("tr",{children:[e.jsx("th",{className:"px-2 py-1.5 font-medium",children:"Field"}),e.jsx("th",{className:"px-2 py-1.5 font-medium",children:"Type"}),e.jsx("th",{className:"px-2 py-1.5 font-medium",children:"Required"}),e.jsx("th",{className:"px-2 py-1.5 font-medium",children:"Notes"})]})}),e.jsxs("tbody",{className:"divide-y divide-gray-200 text-gray-700",children:[e.jsxs("tr",{children:[e.jsx("td",{className:"px-2 py-1.5 font-mono",children:"id"}),e.jsx("td",{className:"px-2 py-1.5 font-mono",children:"string | undefined"}),e.jsx("td",{className:"px-2 py-1.5",children:"No"}),e.jsx("td",{className:"px-2 py-1.5",children:"Your internal ID for the published item, stored for reference"})]}),e.jsxs("tr",{children:[e.jsx("td",{className:"px-2 py-1.5 font-mono",children:"url"}),e.jsx("td",{className:"px-2 py-1.5 font-mono",children:"string | undefined"}),e.jsx("td",{className:"px-2 py-1.5",children:"No"}),e.jsx("td",{className:"px-2 py-1.5",children:"Public URL of the published item, shown in your content history"})]})]})]})}),"An empty body is fine too â a bare ",e.jsx("code",{className:"rounded bg-gray-200 px-1",children:"2xx"}
147)," status is enough to mark the publish as successful. A non-2xx response marks that specific publish as failed (visible in your content history) without disconnecting the integration â we only disconnect on repeated unreachability, not on rejected content."]})]}),e.jsxs(Ae,{children:["Don't see your language above? The verification logic is the same everywhere â compute HMAC-SHA256 over"," ",e.jsx("code",{className:"rounded bg-blue-100 px-1",children:"`${timestamp}.${rawBody}`"}),", constant-time compare it to the signature, and reject anything older than 5 minutes. Paste one of the examples above into an AI assistant like Claude or ChatGPT and ask it to translate it into your language/framework."]})]}),Qe=`import { defineField, defineType } from "sanity"; 148 149export const rankpilotPost = defineType({ 150 name: "rankpilotPost", 151 title: "RankPilot Post", 152 type: "document", 153 fields: [ 154 defineField({ name: "title", title: "Title", type: "string", validation: (Rule) => Rule.required() }), 155 defineField({ name: "slug", title: "Slug", type: "slug", options: { source: "title", maxLength: 96 }, validation: (Rule) => Rule.required() }), 156 defineField({ name: "externalId", title: "RankPilot content ID", type: "string", readOnly: true }), 157 defineField({ name: "excerpt", title: "Excerpt / meta description", type: "text", rows: 3 }), 158 defineField({ name: "language", title: "Language", type: "string", readOnly: true }), 159 defineField({ name: "coverImage", title: "Cover image", type: "image", options: { hotspot: true } }), 160 defineField({ name: "body", title: "Body", type: "array", of: [{ type: "block" }, { type: "image", options: { hotspot: true } }] }), 161 defineField({ name: "keywords", title: "Keywords", type: "array", of: [{ type: "string" }] }), 162 defineField({ name: "author", title: "Author", type: "string" }), 163 defineField({ name: "status", title: "Status", type: "string", options: { list: ["draft", "published"] }, initialValue: "draft" }), 164 defineField({ name: "publishedAt", title: "Published at", type: "datetime" }), 165 ], 166}); 167`,mt=()=>{const t=async()=>{await navigator.clipboard.writeText(Qe),c.success("Schema code copied")};return e.jsxs("div",{className:"space-y-4 rounded-lg border border-gray-200 bg-gray-50 p-4 text-sm",children:[e.jsx("h4",{className:"font-semibold",children:"How to connect your Sanity project"}),e.jsxs("ol",{className:"list-decimal space-y-3 pl-5 text-gray-700",children:[e.jsxs("li",{children:["Add a new file ",e.jsx("code",{className:"rounded bg-gray-200 px-1",children:"schemaTypes/rankpilotPost.ts"})," to your Sanity Studio project with this content â RankPilot publishes into this document type, so the type name and field names must stay exactly as shown:",e.jsxs("div",{className:"relative mt-2",children:[e.jsx("pre",{className:"max-h-64 overflow-auto rounded bg-gray-900 p-3 text-xs text-gray-100",children:Qe}),e.jsx(h,{type:"button",variant:"outline",size:"icon",className:"absolute top-2 right-2",onClick:t,children:e.jsx(Q,{className:"size-4"})})]})]}),e.jsxs("li",{children:["Register it in your Studio's ",e.jsx("code",{className:"rounded bg-gray-200 px-1",children:"schema.ts"})," (or"," ",e.jsx("code",{className:"rounded bg-gray-200 px-1",children:"schemaTypes/index.ts"}),"):",e.jsx("pre",{className:"mt-2 overflow-x-auto rounded bg-gray-900 p-3 text-xs text-gray-100",children:`import { rankpilotPost } from "./rankpilotPost"; 168 169export const schemaTypes = [ 170 // ...your existing types 171 rankpilotPost, 172];`})]}),e.jsxs("li",{children:["Deploy your Studio (",e.jsx("code",{className:"rounded bg-gray-200 px-1",children:"npx sanity deploy"}),", or your usual deploy flow) so the new document type is live."]}),e.jsxs("li",{children:["Generate an API token: go to"," ",e.jsx("a",{href:"https://manage.sanity.io",target:"_blank",rel:"noopener noreferrer",className:"font-medium text-blue-600 hover:underline",children:"manage.sanity.io"})," ","â your project â ",e.jsx("strong",{children:"API"})," â ",e.jsx("strong",{children:"Tokens"})," â ",e.jsx("strong",{children:"Add API token"}),", with"," ",e.jsx("strong",{children:"Editor"})," permissions (read + write). It's shown once â copy it and paste it below."]}),e.jsxs("li",{children:["Your ",e.jsx("strong",{children:"Project ID"}
172)," is in your Studio's ",e.jsx("code",{className:"rounded bg-gray-200 px-1",children:"sanity.config.ts"})," ","or on manage.sanity.io. ",e.jsx("strong",{children:"Dataset"})," is usually ",e.jsx("code",{className:"rounded bg-gray-200 px-1",children:"production"}),". Enter both, plus the token from the step above, then hit ",e.jsx("strong",{children:"Save Configuration"})," below."]}),e.jsxs("li",{children:["When you click ",e.jsx("strong",{children:"Save Configuration"}),", we immediately verify the connection: a"," ",e.jsx("code",{className:"rounded bg-gray-200 px-1",children:"count(*)"})," query against your dataset (confirms the project ID, dataset name, and token are all valid) and a query for"," ",e.jsx("code",{className:"rounded bg-gray-200 px-1",children:'*[_type == "rankpilotPost"][0]'})," (confirms that document type is queryable). If either fails with an auth error, we'll tell you the token is invalid or lacks permissions; if the dataset itself can't be found, we'll tell you to double-check the project ID and dataset name. We use the same check afterward to detect if the token is revoked or the project is removed, and will auto-disconnect the integration and notify you if that happens."]}),e.jsxs("li",{children:["Each time RankPilot publishes, your article is converted into a"," ",e.jsx("code",{className:"rounded bg-gray-200 px-1",children:"rankpilotPost"})," document and written with a stable ID derived from the article, so editing and republishing the same article updates that document instead of creating a duplicate. Field mapping:",e.jsx("div",{className:"mt-2 overflow-x-auto rounded border border-gray-200",children:e.jsxs("table",{className:"w-full text-left text-xs",children:[e.jsx("thead",{className:"bg-gray-100 text-gray-600",children:e.jsxs("tr",{children:[e.jsx("th",{className:"px-2 py-1.5 font-medium",children:"Sanity field"}),e.jsx("th",{className:"px-2 py-1.5 font-medium",children:"Type"}),e.jsx("th",{className:"px-2 py-1.5 font-medium",children:"Source"}),e.jsx("th",{className:"px-2 py-1.5 font-medium",children:"Notes"})]})}),e.jsxs("tbody",{className:"divide-y divide-gray-200 text-gray-700",children:[e.jsxs("tr",{children:[e.jsx("td",{className:"px-2 py-1.5 font-mono",children:"title"}),e.jsx("td",{className:"px-2 py-1.5 font-mono",children:"string"}),e.jsx("td",{className:"px-2 py-1.5",children:"Article title"}),e.jsx("td",{className:"px-2 py-1.5",children:"â"})]}),e.jsxs("tr",{children:[e.jsx("td",{className:"px-2 py-1.5 font-mono",children:"slug"}),e.jsx("td",{className:"px-2 py-1.5 font-mono",children:"slug"}),e.jsx("td",{className:"px-2 py-1.5",children:"Generated from title"}),e.jsx("td",{className:"px-2 py-1.5",children:"â"})]}),e.jsxs("tr",{children:[e.jsx("td",{className:"px-2 py-1.5 font-mono",children:"body"}),e.jsx("td",{className:"px-2 py-1.5 font-mono",children:"Portable Text"}),e.jsx("td",{className:"px-2 py-1.5",children:"Article HTML"}),e.jsx("td",{className:"px-2 py-1.5",children:"Headings, bold/italic, links, lists, blockquotes, and inline images are converted automatically. Tables are flattened to one paragraph per row with the first cell in bold, so they render without you adding a schema type or a custom renderer. Iframes, videos, and other embeds aren't supported yet â they're dropped from the body rather than breaking the publish (logged on our side so we can prioritize support for them)."})]}),e.jsxs("tr",{children:[e.jsx("td",{className:"px-2 py-1.5 font-mono",children:"coverImage"}),e.jsx("td",{className:"px-2 py-1.5 font-mono",children:"image"}),e.jsx("td",{className:"px-2 py-1.5",children:"Featured image"}),e.jsx("td",{className:"px-2 py-1.5",children:"Uploaded to your project's Sanity asset library automatically"})]}),e.jsxs("tr",{children:[e.jsx("td",{className:"px-2 py-1.5 font-mono",children:"excerpt"}),e.jsx("td",{className:"px-2 py-1.5 font-mono",children:"text"}),e.jsx("td",{className:"px-2 py-1.5",children:"Meta description"}),e.jsx("td",{className:"px-2 py-1.5",children:"May be empty"})]}),e.jsxs("tr",{children:[e.jsx("td",{className:"px-2 py-1.5 font-mono",children:"keywords"}),e.jsx("td",{className:"px-2 py-1.5 font-mono",children:"string[]"}),e.jsx("td",{className:"px-2 py-1.5",children:"Keywords"}),e.jsx("td",{className:"px-2 py-1.5",children:"Defaults to an empty array"})]}),e.jsxs("tr",{children:[e.jsx("td",{className:"px-2 py-1.5 font-mono",children:"language"}),e.jsx("td",{className:"px-2 py-1.5 font-mono",children:"string"}),e.jsx("td",{className:"px-2 py-1.5",children:"Your content language"}),e.jsx("td",{className:"px-2 py-1.5",children:"Two-letter code (en, nl, â¦). Filter on this field if your site serves more than one language."})]}),e.jsxs("tr",{children:[e.jsx("td",{className:"px-2 py-1.5 font-mono",children:"author"}),e.jsx("td",{className:"px-2 py-1.5 font-mono",children:"string"}),e.jsx("td",{className:"px-2 py-1.5",children:"Author name"}),e.jsx("td",{className:"px-2 py-1.5",children:"May be empty"})]}),e.jsxs("tr",{children:[e.jsx("td",{className:"px-2 py-1.5 font-mono",children:"status"}),e.jsx("td",{className:"px-2 py-1.5 font-mono",children:'"draft" | "published"'}),e.jsx("td",{className:"px-2 py-1.5",children:"Publish status"}),e.jsx("td",{className:"px-2 py-1.5",children:"â"})]}),e.jsxs("tr",{children:[e.jsx("td",{className:"px-2 py-1.5 font-mono",children:"externalId"}),e.jsx("td",{className:"px-2 py-1.5 font-mono",children:"string"}),e.jsx("td",{className:"px-2 py-1.5",children:"RankPilot's internal
172content ID"}),e.jsx("td",{className:"px-2 py-1.5",children:"Used to detect updates vs. new posts â don't edit it in the Studio"})]}),e.jsxs("tr",{children:[e.jsx("td",{className:"px-2 py-1.5 font-mono",children:"publishedAt"}),e.jsx("td",{className:"px-2 py-1.5 font-mono",children:"datetime"}),e.jsx("td",{className:"px-2 py-1.5",children:"Set automatically"}),e.jsx("td",{className:"px-2 py-1.5",children:"â"})]})]})]})})]}),e.jsx("li",{children:"After a publish, RankPilot shows a link to the document in your Sanity Studio for editorial review. This link depends on your Studio's structure configuration, so treat it as a convenience shortcut â if it 404s, open your Studio directly and search for the article by title."})]}),e.jsxs(Ae,{children:[`Not comfortable editing your Studio's schema files yourself? Paste the schema code above into an AI assistant like Claude or ChatGPT along with "add this document type to my Sanity schema and register it" â it can usually do the whole thing for you, including finding your `,e.jsx("code",{className:"rounded bg-blue-100 px-1",children:"schema.ts"}),"."]})]})},ut=()=>e.jsxs("div",{className:"space-y-4 rounded-lg border border-gray-200 bg-gray-50 p-4 text-sm",children:[e.jsx("h4",{className:"font-semibold",children:"How to connect your Duda site"}),e.jsxs("ol",{className:"list-decimal space-y-3 pl-5 text-gray-700",children:[e.jsxs("li",{children:["In Duda, open ",e.jsx("strong",{children:"Business tools â API access"})," and copy the API username and password. If you don't see that section, API access isn't enabled on the account yet â Duda enables it on request, and if an agency built your site, it's their account that holds it."]}),e.jsxs("li",{children:["Find your ",e.jsx("strong",{children:"Site ID"}),": open the site in your Duda dashboard and copy the site identifier from the address bar (a short code like ",e.jsx("code",{className:"rounded bg-gray-200 px-1",children:"a1b2c3d4"}),") â not your domain name."]}),e.jsxs("li",{children:["Make sure the site already has a ",e.jsx("strong",{children:"Blog"})," section added in the Duda editor. Duda needs an existing blog and post layout before anything can be published into it."]}),e.jsxs("li",{children:["Fill in the fields below and click ",e.jsx("strong",{children:"Load layouts"}),". We check the credentials against Duda and list the post layouts on your blog â pick the one new articles should use, then save."]}),e.jsx("li",{children:"From then on, articles are pushed into your blog and published automatically. Re-publishing an article replaces the post we created for it last time at the same URL, so edits you make in the Duda editor to a RankPilot post will be overwritten."})]}),e.jsx(Ae,{children:"Not sure whether your Duda account has API access?"})]}),xt=({dudaConnected:t})=>{const{isTeamContext:r}=X(),{activeWebsite:n}=Z(),{languages:i,activeLanguage:d}=ke(),{data:a,isLoading:u}=zs(),f=_s(),p=Gs(),[x,g]=m.useState("");m.useEffect(()=>{g((a==null?void 0:a.feedPostBaseUrl)??"")},[a==null?void 0:a.feedPostBaseUrl,n==null?void 0:n.id]);const b=i.length>1,C=We[(d==null?void 0:d.languageCode)??""]??"en",E=a!=null&&a.feedUrl?`${a.feedUrl}?lang=${C}`:"",y=async()=>{a!=null&&a.feedUrl&&(await navigator.clipboard.writeText(a.feedUrl),c.success("Feed URL copied"))},S=async()=>{if(r){c.error("Integrations are managed by the team owner.");return}try{await f.mutateAsync(),c.success("Feed URL regenerated â the old link will stop working")}catch(U){q(U,{context:"regenerateFeedUrl"}),c.error(U.message||"Failed to regenerate feed URL")}},F=async()=>{if(r){c.error("Integrations are managed by the team owner.");return}try{await p.mutateAsync({feedPostBaseUrl:x.trim()}),c.success("Blog URL saved")}catch(U){q(U,{context:"updateFeedSettings"}),c.error(U instanceof Error?U.message:"Failed to save blog URL")}};return e.jsxs(P,{className:"border-gray-200 p-6",children:[e.jsx("h3",{className:"mb-2 text-lg font-semibold",children:"Blog RSS Feed"}),e.jsx("p",{className:"mb-4 text-sm text-gray-600",children:"A WordPress-style RSS feed of your posts, for site builders (e.g. Luxury Presence, Squarespace) that import
172content by polling a feed URL instead of a direct integration. Each post includes its full HTML and image."}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{htmlFor:"rss-feed-url",children:"Feed URL"}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(A,{id:"rss-feed-url",readOnly:!0,value:u?"Loading...":(a==null?void 0:a.feedUrl)??""}),e.jsx(h,{type:"button",variant:"outline",size:"icon",onClick:y,disabled:!(a!=null&&a.feedUrl),children:e.jsx(Q,{className:"size-4"})}),e.jsxs(h,{type:"button",variant:"outline",onClick:S,disabled:f.isPending,children:[f.isPending?e.jsx(V,{className:"size-4 animate-spin"}):e.jsx(Zs,{className:"size-4"}),"Regenerate"]})]}),e.jsx("p",{className:"text-xs text-gray-500",children:"Regenerating invalidates the current URL â anywhere it's already been submitted (e.g. to a site builder) will need the new one."})]}),e.jsxs("div",{className:"mt-4 space-y-2",children:[e.jsx(N,{htmlFor:"rss-post-base-url",children:"Blog URL (optional)"}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(A,{id:"rss-post-base-url",placeholder:`https://${(n==null?void 0:n.domain)??"yoursite.com"}/blog`,value:x,onChange:U=>g(U.target.value)}),e.jsxs(h,{type:"button",variant:"outline",onClick:F,disabled:p.isPending||x.trim()===((a==null?void 0:a.feedPostBaseUrl)??""),children:[p.isPending&&e.jsx(V,{className:"size-4 animate-spin"}),"Save"]})]}),e.jsxs("p",{className:"text-xs text-gray-500",children:["Some site builders (e.g. Duda) require every post in the feed to have its own unique link. Enter the address of your blog so those links match where your posts will live. If left empty, we use"," ",(n==null?void 0:n.domain)??"yoursite.com","/blog."]}),t&&e.jsx("p",{className:"rounded-md border border-amber-200 bg-amber-50 p-3 text-xs text-amber-800",children:"This website already publishes to Duda through the Duda integration. Don't import this feed into the same Duda site â articles the integration already published would be imported again as duplicates."})]}),e.jsxs("div",{className:"mt-6 space-y-4 rounded-lg border border-gray-200 bg-gray-50 p-4 text-sm text-gray-600",children:[e.jsxs("div",{children:[e.jsx("h4",{className:"mb-1 font-medium text-gray-900",children:"What the feed contains"}),e.jsxs("p",{children:["The 50 most recent published posts for"," ",e.jsx("span",{className:"font-medium",children:(n==null?void 0:n.domain)??"this website"}),", newest first."]}),e.jsx("p",{className:"mt-1",children:"Future and currently generating posts are excluded until they are published."})]}),e.jsxs("div",{children:[e.jsx("h4",{className:"mb-1 font-medium text-gray-900",children:"Language"}),b?e.jsxs(e.Fragment,{children:[e.jsxs("p",{children:["The feed uses your default language. Add ",e.jsx("code",{children:"?lang="})," for a specific language."]}),e.jsx("div",{className:"mt-2 flex flex-wrap gap-2",children:i.map(U=>{const _=We[U.languageCode]??"en";return e.jsxs(h,{type:"button",variant:"outline",size:"sm",disabled:!(a!=null&&a.feedUrl),onClick:()=>{navigator.clipboard.writeText(`${a==null?void 0:a.feedUrl}?lang=${_}`),c.success(`${U.languageCode} feed URL copied`)},children:[e.jsx(Q,{className:"size-3"}),U.languageCode]},U.id)})})]}):e.jsxs("p",{children:["This feed publishes in ",(d==null?void 0:d.languageCode)??"English",". If you add languages, use ",e.jsxs("code",{children:["?lang=",C]})," to select one."]})]}),e.jsxs("div",{children:[e.jsx("h4",{className:"mb-1 font-medium text-gray-900",children:"Setting it up"}),e.jsx("p",{children:"Copy the feed URL, paste it into your site's RSS importer, and run the import. Most builders automatically check for new posts."}),e.jsxs("p",{className:"mt-2",children:["If the URL is rejected, validate it with"," ",e.jsxs("a",{className:"font-medium underline",href:`https://validator.w3.org/feed/check.cgi?url=${encodeURIComponent(b?E:(a==null?void 0:a.feedUrl)??"")}`,target:"_blank",rel:"noopener noreferrer",children:["W3C Feed Validation",e.jsx(Y,{className:"ml-1 inline size-3"})]}),"."]})]})]})]})},pt=()=>{var Ge;const{activeWebsite:t}=Z(),{isTeamContext:r}=X(),[n,i]=m.useState(!1),[d,a]=m.useState(!0),[u,f]=m.useState(ct),[p,x]=m.useState(null),[g,b]=m.useState(null),[C,E]=m.useState({siteUrl:"",pluginKey:""}),[y,S]=m.useState({storeName:"",clientId:"",clientSecret:"",author:""}),[F,U]=m.useState(""),[_,xe]=m.useState(""),[M,G]=m.useState({apiToken:"",siteId:"",collectionId:""}),[$,w]=m.useState({siteId:"",accountId:"",apiKey:""}),[I,k]=m.useState({apiUrl:"",adminApiKey:""}),[W,Fe]=m.useState({webhookUrl:"",webhookSecret:""}),[Ee,Te]=m.useState({webhookUrl:"",webhookSecret:""}),[Le,De]=m.useState({webhookUrl:"",webhookSecret:""}),[z,ee]=m.useState({projectId:"",dataset:"production",apiToken:""}),[T,O]=m.useState({apiUsername:"",apiPassword:"",siteId:"",blogLayoutId:""}),[pe,ds]=m.useState([]),[Re,Be]=m.useState(!1),hs=J(),[Me]=ls(),[$e,ms]=m.useState(!1),[us,xs]=m.useState([]),[ps,gs]=m.useState([]),[se,ge]=m.useState(""),[te,ye]=m.useState(""),[ys,fs]=m.useState([]),[ae,fe]=m.useState(""),K=async()=>{try{a(!0);const s=await D.getConnections();
172s.forEach(j=>{const v=j.credentials;if(!(!v||typeof v!="object"))if(j.platform==="wordpress")E(l=>({...l,siteUrl:v.siteUrl??l.siteUrl,pluginKey:v.pluginKey??l.pluginKey}));else if(j.platform==="shopify")S(l=>({...l,storeName:v.storeName??l.storeName,clientId:v.clientId??l.clientId,clientSecret:v.clientSecret??l.clientSecret,author:v.author??l.author}));else if(j.platform==="shopify-app"){const l=v.storeName||"";xe(l),U(be=>l||be)}else if(j.platform==="webflow")G(l=>({...l,apiToken:v.apiToken??l.apiToken,siteId:v.siteId??l.siteId,collectionId:v.collectionId??l.collectionId}));else if(j.platform==="google-analytics"){const l=v.propertyId||"";l&&ge(l)}else if(j.platform==="search-console"){const l=v.siteUrl||"";l&&ye(l)}else if(j.platform==="blogger"){const l=v.blogId||"";l&&fe(l)}else j.platform==="wix"?w(l=>({...l,apiKey:v.apiKey??l.apiKey,siteId:v.siteId??l.siteId,accountId:v.accountId??l.accountId})):j.platform==="ghost"?k(l=>({...l,apiUrl:v.apiUrl??l.apiUrl,adminApiKey:v.adminApiKey??l.adminApiKey})):j.platform==="base44"?Fe(l=>({...l,webhookUrl:v.webhookUrl??l.webhookUrl,webhookSecret:v.webhookSecret??l.webhookSecret})):j.platform==="lovable"?Te(l=>({...l,webhookUrl:v.webhookUrl??l.webhookUrl,webhookSecret:v.webhookSecret??l.webhookSecret})):j.platform==="webhook"?De(l=>({...l,webhookUrl:v.webhookUrl??l.webhookUrl,webhookSecret:v.webhookSecret??l.webhookSecret})):j.platform==="sanity"?ee(l=>({...l,projectId:v.projectId??l.projectId,dataset:v.dataset??l.dataset})):j.platform==="duda"&&O(l=>({...l,apiUsername:v.apiUsername??l.apiUsername,siteId:v.siteId??l.siteId,blogLayoutId:v.blogLayoutId??l.blogLayoutId}))});const o=new Map(s.map(j=>[String(j.platform).toLowerCase(),j]));f(j=>j.map(v=>{const l=o.get(v.id.toLowerCase());return l?{...v,status:"connected",lastSync:l.lastUsed?new Date(l.lastUsed).toLocaleString():"Recently"}:{...v,status:"disconnected",lastSync:"Never"}}))}catch(s){console.error("Failed to fetch connections:",s),q(s,{context:"fetchConnections"}),c.error("Failed to load integrations. Please refresh the page.")}finally{a(!1)}};m.useEffect(()=>{a(!0),K()},[t==null?void 0:t.id,r]);const bs=async()=>{var s;try{Be(!0);const o=await D.getDudaLayouts({apiUsername:T.apiUsername||void 0,apiPassword:T.apiPassword||void 0,siteId:T.siteId||void 0});ds(o.layouts??[]),O(j=>({...j,blogLayoutId:j.blogLayoutId||o.defaultLayoutId||""})),c.success(`Found ${((s=o.layouts)==null?void 0:s.length)??0} blog layout(s)`)}catch(o){q(o,{context:"loadDudaLayouts"}),c.error(o.message||"Could not reach Duda with those details")}finally{Be(!1)}},B=async s=>{if(r){c.error("Integrations are managed by the team owner.");return}const o={wordpress:C,shopify:y,webflow:M,wix:$,ghost:I,base44:W,lovable:Ee,webhook:Le,sanity:z,duda:T}[s],j=Es[s].safeParse(o);if(!j.success){c.error(j.error.issues[0].message);return}const v=j.data;try{i(!0);const l=await D.connect({platform:s,credentials:v});l.success?(f(be=>be.map(je=>je.id===s?{...je,status:"connected",lastSync:"Recently"}:je)),c.success(`${s.charAt(0).toUpperCase()+s.slice(1)} connected successfully`),await K(),b(null)):c.error(l.message||l.error||`Failed to connect ${s}`)}catch(l){console.error(`Failed to connect ${s}`,l),q(l,{context:"handleIntegrationSave",platform:s}),c.error(l.message||`Failed to connect ${s}`)}finally{i(!1)}},js=async(s,o)=>{if(r){c.error("Integrations are managed by the team owner.");return}if(o==="connected")try{x(s),(await D.disconnect(s)).success&&(c.success(`${s.charAt(0).toUpperCase()+s.slice(1)} disconnected`),await K())}catch(j){q(j,{context:"handleToggleConnection",platform:s}),c.error(`Failed to disconnect ${s}`)}finally{x(null)}},qe=async s=>{if(r){c.error("Integrations are managed by the team owner.");return}try{if(x(s),s==="search-console"){const o=await D.getSearchConsoleAuthUrl("/dashboard/settings?tab=integrations&configure=search-console");if(o!=null&&o.url){window.location.href=o.url;return}}if(s==="google-analytics"){const o=await D.getGoogleAnalyticsAuthUrl("/dashboard/settings?tab=integrations&configure=google-analytics");if(o!=null&&o.url){window.location.href=o.url;return}}if(s==="blogger"){const o=await D.getBloggerAuthUrl("/dashboard/settings?tab=integrations&configure=blogger");if(o!=null&&o.url){window.location.href=o.url;return}}c.error(`Unable to connect ${s}`)}catch(o){console.error(`Failed to connect ${s}`,o),q(o,{context:"handleOAuthConnect",platform:s}),c.error(o.message||`Failed to connect ${s}`)}finally{x(null)}},Ns=async()=>
172{if(r){c.error("Integrations are managed by the team owner.");return}if(!F.trim()){c.error("Enter your Shopify store domain first");return}try{i(!0);const s=await D.getShopifyAppInstallUrl(F.trim(),"/dashboard/settings?tab=integrations");if(s!=null&&s.url){window.location.href=s.url;return}c.error((s==null?void 0:s.message)||"Unable to start Shopify connection")}catch(s){console.error("Failed to start Shopify app connection",s),q(s,{context:"handleShopifyAppConnect"}),c.error(s.message||"Unable to start Shopify connection")}finally{i(!1)}},ze=s=>{if(r){c.error("Integrations are managed by the team owner.");return}b(s),s==="google-analytics"?He.getProperties().then(o=>{xs(o.properties||[]);const j=o.selectedPropertyId||se||"";ge(j)}).catch(o=>{c.error(o.message||"Failed to load properties")}):s==="search-console"?He.getSearchConsoleSites().then(o=>{gs(o||[]),!te&&(o==null?void 0:o.length)>0&&ye(o[0].siteUrl)}).catch(o=>{c.error(o.message||"Failed to load sites")}):s==="blogger"&&D.getBloggerBlogs().then(o=>{fs(o.blogs||[]);const j=o.selectedBlogId||ae||"";fe(j)}).catch(o=>{c.error(o.message||"Failed to load blogs")})},vs=async()=>{if(r){c.error("Integrations are managed by the team owner.");return}try{i(!0);const s=await D.updateConfig("blogger",{blogId:ae});s.success?(c.success(s.message||"Configuration saved"),await K(),b(null)):c.error(s.message||"Failed to save configuration")}catch(s){c.error(s.message||"Failed to save configuration")}finally{i(!1)}},_e=async s=>{if(r){c.error("Integrations are managed by the team owner.");return}try{i(!0);const o=s==="google-analytics"?{propertyId:se}:{siteUrl:te},j=await D.updateConfig(s,o);j.success?(c.success(j.message||"Configuration saved"),hs.invalidateQueries({queryKey:["analytics"]}),await K(),b(null)):c.error(j.message||"Failed to save configuration")}catch(o){c.error(o.message||"Failed to save configuration")}finally{i(!1)}};if(m.useEffect(()=>{const s=Me.get("configure");if(s&&!d&&!$e){const o=u.find(j=>j.id===s);(o==null?void 0:o.status)==="connected"&&(ze(s),ms(!0))}},[Me,d,u,$e]),d&&u.every(s=>s.status==="disconnected"))return e.jsx("div",{className:"flex items-center justify-center p-12",children:e.jsx(he,{className:"size-8"})});if(g==="shopify-app"){const s=((Ge=u.find(o=>o.id==="shopify-app"))==null?void 0:Ge.status)==="connected";return e.jsxs("div",{className:"space-y-6",children:[e.jsx("div",{className:"flex items-center gap-4",children:e.jsxs("div",{children:[e.jsx("h3",{className:"text-xl font-semibold",children:"Shopify Plugin"}),e.jsx("p",{className:"text-sm text-gray-600",children:"Connect via the official Rankpilot Shopify app"})]})}),e.jsx(P,{className:"border-gray-200",children:e.jsxs("div",{className:"space-y-6 p-6",children:[s?e.jsxs("div",{className:"space-y-3",children:[e.jsxs("p",{className:"text-sm text-gray-700",children:["Connected to ",e.jsx("span",{className:"font-medium",children:_||"your Shopify store"}),"."]}),e.jsx("p",{className:"text-xs text-gray-500",children:"Manage the target blog, visibility, and author name from inside the Rankpilot app in your Shopify admin (Apps â Rankpilot)."})]}):e.jsx("div",{className:"grid gap-6 md:grid-cols-2",children:e.jsxs("div",{className:"space-y-2 md:col-span-2",children:[e.jsx(N,{htmlFor:"shopify-app-domain",children:"Store domain"}),e.jsx(A,{id:"shopify-app-domain",placeholder:"your-store.myshopify.com",value:F,onChange:o=>U(o.target.value)}),e.jsx("p",{className:"text-xs text-gray-500",children:"You'll be redirected to Shopify to install the Rankpilot app and approve access."})]})}),e.jsxs("div",{className:"flex justify-end gap-3",children:[e.jsx(h,{variant:"outline",className:"h-12 p-6 text-sm",onClick:()=>b(null),disabled:n,children:"Close"}),!s&&e.jsx(h,{className:"h-12 p-6 text-sm",onClick:Ns,disabled:n,children:n?"Redirecting...":"Continue to Shopify"})]})]})})]})}if(g==="shopify")return e.jsxs("div",{className:"space-y-6",children:[e.jsx("div",{className:"flex items-center gap-4",children:e.jsxs("div",{children:[e.jsx("h3",{className:"text-xl font-semibold",children:"Shopify Configuration"}),e.jsx("p",{className:"text-sm text-gray-600",children:"Connect your Shopify store for automated SEO optimization"})]})}),e.jsx(P,{className:"border-gray-200",children:e.jsxs("div",{className:"space-y-6 p-6",children:[e.jsxs("div",{className:"flex items-center gap-2 text-blue-600",children:[e.jsx(Y,{className:"size-4"}),e.jsx("a",{href:"https://www.youtube.com/watch?v=KQ7pJsS6k98",target:"_blank",rel:"noopener noreferrer",className:"text-sm font-medium",children:"Watch tutorial on how to connect"})]}),e.jsxs("div",{className:"grid gap-6 md:grid-cols-2",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{htmlFor:"shopify-store",children:"Store Name"}),e.jsx(A,{id:"shopify-store",placeholder:"https://store-name.myshopify.com",value:y.storeName,onChange:s=>S({...y,storeName:s.target.value})})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{htmlFor:"shopify-author",children:"Author"}),e.jsx(A,{id:"shopify-author",placeholder:"Author name",value:y.author,onChange:s=>S({...y,author:s.target.value})})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{htmlFor:"shopify-client-id",children:"Client ID"}),e.jsx(A,{id:"shopify-client-id",placeholder:"Your Shopify Client ID",value:y.clientId,onChange:s=>S({...y,clientId:s.target.value})})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{htmlFor:"shopify-client-secret",children:"Client Secret"}),e.jsx(L,{id:"shopify-client-secret",placeholder:"Your Shopify Client Secret",value:y.clientSecret,onChange:s=>S({...y,clientSecret:s.target.value})})]})]}),e.jsxs("div",{className:"flex justify-end gap-3",children:[e.jsx(h,{variant:"outline",className:"h-12 p-6 text-sm",onClick:()=>b(null),disabled:n,children:"Cancel"}),e.jsx(h,{className:"h-12 p-6 text-sm",onClick:()=>B("shopify"),disabled:n,children:n?"Saving...":"Save Configuration"})]})]})})]});if(g==="webflow")return e.jsxs("div",{className:"space-y-6",children:[e.jsx("div",{className:"flex items-center gap-4",children:e.jsxs("div",{children:[e.jsx("h3",{className:"text-xl font-semibold",children:"Webflow Configuration"}),e.jsx("p",{className:"text-sm text-gray-600",children:"Connect your Webflow site for automated content publishing"})]})}),e.jsx(P,{className:"border-gray-200",children:e.jsxs("div",{className:"space-y-6 p-6",children:[e.jsxs("div",{className:"flex items-center gap-2 text-blue-600",children:[e.jsx(Y,{className:"size-4"}),e.jsx("a",{href:"https://www.youtube.com/watch?v=yQ_3NNhm3-s",target:"_blank",rel:"noopener noreferrer",className:"text-sm font-medium",children:"Watch tutorial on how to connect"})]}),e.jsxs("div",{className:"grid gap-6 md:grid-cols-2",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{htmlFor:"webflow-site",children:"Webflow Site ID"}),e.jsx(A,{id:"webflow-site",placeholder:"Your Webflow site ID",value:M.siteId,onChange:s=>G({...M,siteId:s.target.value})})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{htmlFor:"webflow-collection",children:"Collection ID"}),e.jsx(A,{id:"webflow-collection",placeholder:"Your collection ID",value:M.collectionId,onChange:s=>G({...M,collectionId:s.target.value})})]}),e.jsxs("div",{className:"space-y-2 md:col-span-2",children:[e.jsx(N,{htmlFor:"webflow-token",children:"API Token"}),e.jsx(L,{id:"webflow-token",placeholder:"Your Webflow API token",value:M.apiToken,onChange:s=>G({...M,apiToken:s.target.value})})]})]}),e.jsxs("div",{className:"flex justify-end gap-3",children:[e.jsx(h,{variant:"outline",className:"h-12 p-6 text-sm",onClick:()=>b(null),disabled:n,children:"Cancel"}),e.jsx(h,{className:"h-12 p-6 text-sm",onClick:()=>B("webflow"),disabled:n,children:n?"Saving...":"Save Configuration"})]})]})})]});if(g==="wix")return e.jsxs("div",{className:"space-y-6",children:[e.jsx("div",{className:"flex items-center gap-4",children:e.jsxs("div",{children:[e.jsx("h3",{className:"text-xl font-semibold",children:"Wix Configuration"}),e.jsx("p",{className:"text-sm text-gray-600",children:"Connect your Wix site for automated content publishing"})]})}),e.jsx(P,{className:"border-gray-200",children:e.jsxs("div",{className:"space-y-6 p-6",children:[e.jsxs("div",{className:"flex items-center gap-2 text-blue-600",children:[e.jsx(Y,{className:"size-4"}),e.jsx("a",{href:"https://youtu.be/F7UvikrhLg0",target:"_blank",rel:"noopener noreferrer",className:"text-sm font-medium",children:"Watch tutorial on how to connect"})]}),e.jsxs("div",{className:"grid gap-6 md:grid-cols-2",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{htmlFor:"wix-site-id",children:"Site ID"}),e.jsx(A,{id:"wix-site-id",placeholder:"Your Wix site ID",value:$.siteId,onChange:s=>w({...$,siteId:s.target.value})})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{htmlFor:"wix-account-id",children:"Account ID"}),e.jsx(A,{id:"wix-account-id",placeholder:"Your Wix account ID",value:$.accountId,onChange:s=>w({...$,accountId:s.target.value})})]}),e.jsxs("div",{className:"space-y-2 md:col-span-2",children:[e.jsx(N,{htmlFor:"wix-api-key",children:"API Key"}),e.jsx(L,{id:"wix-api-key",placeholder:"Your Wix API key",value:$.apiKey,onChange:s=>w({...$,apiKey:s.target.value})})]})]}),e.jsxs("div",{className:"flex justify-end gap-3",children:[e.jsx(h,{variant:"outline",className:"h-12 p-6 text-sm",onClick:()=>b(null),disabled:n,children:"Cancel"}),e.jsx(h,{className:"h-12 p-6 text-sm",onClick:()=>B("wix"),disabled:n,children:n?"Saving...":"Save Configuration"})]})]})})]});if(g==="ghost")return e.jsxs("div",{className:"space-y-6",children:[e.jsx("div",{className:"flex items-center gap-4",children:e.jsxs("div",{children:[e.jsx("h3",{className:"text-xl font-semibold",children:"Ghost Configuration"}),e.jsx("p",{className:"text-sm text-gray-600",children:"Connect your Ghost site for automated content publishing"})]})}),e.jsx(P,{className:"border-gray-200",children:e.jsxs("div",{className:"space-y-6 p-6",children:[e.jsxs("div",{className:"grid gap-6 md:grid-cols-2",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{htmlFor:"ghost-url",children:"Ghost Admin API URL"}),e.jsx(A,{id:"ghost-url",placeholder:"https://yourblog.ghost.io",value:I.apiUrl,onChange:s=>k({...I,apiUrl:s.target.value})})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{htmlFor:"ghost-admin-key",children:"Admin API Key"}),e.jsx(L,{id:"ghost-admin-key",placeholder:"id:secret",value:I.adminApiKey,onChange:s=>k({...I,adminApiKey:s.target.value})}),e.jsx("p",{className:"text-xs text-gray-500",children:"Create a Custom Integration in Ghost Admin â Settings â Integrations to get this key."})]})]}),e.jsxs("div",{className:"flex justify-end gap-3",children:[e.jsx(h,{variant:"outline",className:"h-12 p-6 text-sm",onClick:()=>b(null),disabled:n,children:"Cancel"}),e.jsx(h,{className:"h-12 p-6 text-sm",onClick:()=>B("ghost"),disabled:n,children:n?"Saving...":"Save Configuration"})]})]})})]});if(g==="sanity")return e.jsxs("div",{className:"space-y-6",children:[e.jsx("div",{className:"flex items-center gap-4",children:e.jsxs("div",{children:[e.jsx("h3",{className:"text-xl font-semibold",children:"Sanity.io Configuration"}),e.jsx("p",{className:"text-sm text-gray-600",children:"Connect your Sanity project for automated content publishing"})]})}),e.jsx(P,{className:"border-gray-200",children:e.jsxs("div",{className:"space-y-6 p-6",children:[e.jsx(mt,{}),e.jsxs("div",{className:"grid gap-6 md:grid-cols-2",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{htmlFor:"sanity-project-id",children:"Project ID"}),e.jsx(A,{id:"sanity-project-id",placeholder:"e.g. abc123xy",value:z.projectId,onChange:s=>ee({...z,projectId:s.target.value})})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{htmlFor:"sanity-dataset",children:"Dataset"}),e.jsx(A,{id:"sanity-dataset",placeholder:"production",value:z.dataset,onChange:s=>ee({...z,dataset:s.target.value})})]}),e.jsxs("div",{className:"space-y-2 md:col-span-2",children:[e.jsx(N,{htmlFor:"sanity-api-token",children:"API Token"}),e.jsx(L,{id:"sanity-api-token",placeholder:"Your Sanity API token (Editor permissions)",value:z.apiToken,onChange:s=>ee({...z,apiToken:s.target.value})}),e.jsx("p",{className:"text-xs text-gray-500",children:"Create one at manage.sanity.io â your project â API â Tokens, with Editor permissions."})]})]}),e.jsxs("div",{className:"flex justify-end gap-3",children:[e.jsx(h,{variant:"outline",className:"h-12 p-6 text-sm",onClick:()=>b(null),disabled:n,children:"Cancel"}),e.jsx(h,{className:"h-12 p-6 text-sm",onClick:()=>B("sanity"),disabled:n,children:n?"Saving...":"Save Configuration"})]})]})})]});if(g==="duda")return e.jsxs("div",{className:"space-y-6",children:[e.jsx("div",{className:"flex items-center gap-4",children:e.jsxs("div",{children:[e.jsx("h3",{className:"text-xl font-semibold",children:"Duda Configuration"}),e.jsx("p",{className:"text-sm text-gray-600",children:"Publish straight to your Duda site's blog"})]})}),e.jsx(P,{className:"border-gray-200",children:e.jsxs("div",{className:"space-y-6 p-6",children:[e.jsx(ut,{}),e.jsxs("div",{className:"grid gap-6 md:grid-cols-2",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{htmlFor:"duda-username",children:"API Username"}),e.jsx(A,{id:"duda-username",placeholder:"From Business tools â API access",value:T.apiUsername,onChange:s=>O({...T,apiUsername:s.target.value})})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{htmlFor:"duda-password",children:"API Password"}),e.jsx(L,{id:"duda-password",placeholder:"From Business tools â API access",value:T.apiPassword,onChange:s=>O({...T,apiPassword:s.target.value})})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{htmlFor:"duda-site-id",children:"Site ID"}),e.jsx(A,{id:"duda-site-id",placeholder:"e.g. a1b2c3d4",value:T.siteId,onChange:s=>O({...T,siteId:s.target.value})}),e.jsx("p",{className:"text-xs text-gray-500",children:"The site identifier from your Duda dashboard, not your domain."})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{htmlFor:"duda-layout",children:"Blog post layout"}),e.jsxs("div",{className:"flex gap-2",children:[e.jsxs(ne,{value:T.blogLayoutId,onValueChange:s=>O({...T,blogLayoutId:s}),disabled:pe.length===0,children:[e.jsx(ie,{id:"duda-layout",className:"flex-1",children:e.jsx(re,{placeholder:pe.length?"Choose a layout":"Load layouts first"})}),e.jsx(oe,{children:pe.map(s=>e.jsxs(le,{value:s.id,children:[s.name,s.default?" (default)":""]},s.id))})]}),e.jsx(h,{type:"button",variant:"outline",onClick:bs,disabled:Re,children:Re?e.jsx(V,{className:"size-4 animate-spin"}):"Load layouts"})]})]})]}),e.jsxs("div",{className:"flex justify-end gap-3",children:[e.jsx(h,{variant:"outline",className:"h-12 p-6 text-sm",onClick:()=>b(null),disabled:n,children:"Cancel"}),e.jsx(h,{className:"h-12 p-6 text-sm",onClick:()=>B("duda"),disabled:n||!T.blogLayoutId,children:n?"Saving...":"Save Configuration"})]})]})})]});if(g==="base44")return e.jsxs("div",{className:"space-y-6",children:[e.jsx("div",{className:"flex items-center gap-4",children:e.jsxs("div",{children:[e.jsx("h3",{className:"text-xl font-semibold",children:"Base44 Configuration"}),e.jsx("p",{className:"text-sm text-gray-600",children:"Connect your Base44 app â we'll POST new content to a webhook endpoint you expose from a Base44 backend function."})]})}),e.jsx(P,{className:"border-gray-200",children:e.jsxs("div",{className:"space-y-6 p-6",children:[e.jsx(ve,{idPrefix:"base44",config:W,onChange:Fe}),e.jsx(we,{}),e.jsxs("div",{className:"flex justify-end gap-3",children:[e.jsx(h,{variant:"outline",className:"h-12 p-6 text-sm",onClick:()=>b(null),disabled:n,children:"Cancel"}),e.jsx(h,{className:"h-12 p-6 text-sm",onClick:()=>B("base44"),disabled:n,children:n?"Saving...":"Save Configuration"})]})]})})]});if(g==="lovable")return e.jsxs("div",{className:"space-y-6",children:[e.jsx("div",{className:"flex items-center gap-4",children:e.jsxs("div",{children:[e.jsx("h3",{className:"text-xl font-semibold",children:"Lovable Configuration"}),e.jsx("p",{className:"text-sm text-gray-600",children:"Connect your Lovable app â most Lovable apps run on Supabase, so this is usually a Supabase Edge Function that receives our webhook."})]})}),e.jsx(P,{className:"border-gray-200",children:e.jsxs("div",{className:"space-y-6 p-6",children:[e.jsx(
172ve,{idPrefix:"lovable",config:Ee,onChange:Te}),e.jsx(we,{}),e.jsxs("div",{className:"flex justify-end gap-3",children:[e.jsx(h,{variant:"outline",className:"h-12 p-6 text-sm",onClick:()=>b(null),disabled:n,children:"Cancel"}),e.jsx(h,{className:"h-12 p-6 text-sm",onClick:()=>B("lovable"),disabled:n,children:n?"Saving...":"Save Configuration"})]})]})})]});if(g==="webhook")return e.jsxs("div",{className:"space-y-6",children:[e.jsx("div",{className:"flex items-center gap-4",children:e.jsxs("div",{children:[e.jsx("h3",{className:"text-xl font-semibold",children:"Webhook / API Configuration"}),e.jsx("p",{className:"text-sm text-gray-600",children:"Connect any custom app or backend â we'll POST new content to a webhook endpoint you host and control."})]})}),e.jsx(P,{className:"border-gray-200",children:e.jsxs("div",{className:"space-y-6 p-6",children:[e.jsx(ve,{idPrefix:"webhook",config:Le,onChange:De}),e.jsx(we,{}),e.jsxs("div",{className:"flex justify-end gap-3",children:[e.jsx(h,{variant:"outline",className:"h-12 p-6 text-sm",onClick:()=>b(null),disabled:n,children:"Cancel"}),e.jsx(h,{className:"h-12 p-6 text-sm",onClick:()=>B("webhook"),disabled:n,children:n?"Saving...":"Save Configuration"})]})]})})]});if(g==="wordpress")return e.jsxs("div",{className:"space-y-6",children:[e.jsx("div",{className:"flex items-center gap-4",children:e.jsxs("div",{children:[e.jsx("h3",{className:"text-xl font-semibold",children:"WordPress Configuration"}),e.jsx("p",{className:"text-sm text-gray-600",children:"Connect your WordPress site for automated content publishing"})]})}),e.jsx(P,{className:"border-gray-200",children:e.jsxs("div",{className:"space-y-6 p-6",children:[e.jsxs("div",{className:"flex flex-col gap-3 md:flex-row md:items-center md:justify-between",children:[e.jsxs("div",{className:"flex items-center gap-2 text-blue-600",children:[e.jsx(Y,{className:"size-4"}),e.jsx("a",{href:"https://youtu.be/-Lza-uHy_bM",target:"_blank",rel:"noopener noreferrer",className:"text-sm font-medium hover:underline",children:"Watch tutorial on how to connect"})]}),e.jsx(h,{variant:"outline",size:"sm",className:"bg-gray-100",asChild:!0,children:e.jsxs("a",{href:"https://wordpress.org/plugins/rankpilot/",target:"_blank",rel:"noopener noreferrer",children:[e.jsx(Y,{}),"View WordPress Plugin"]})})]}),e.jsxs("div",{className:"grid gap-6 md:grid-cols-2",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{htmlFor:"wp-url",children:"WordPress URL"}),e.jsx(A,{id:"wp-url",placeholder:"https://yourdomain.com",value:C.siteUrl,onChange:s=>E({...C,siteUrl:s.target.value})}),e.jsx("p",{className:"text-xs text-gray-500",children:"Include https:// and do not include /wp-admin at the end."})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{htmlFor:"wp-plugin-key",children:"Rankpilot API Key"}),e.jsx(L,{id:"wp-plugin-key",placeholder:"rp_...",value:C.pluginKey,onChange:s=>E({...C,pluginKey:s.target.value})}),e.jsx("p",{className:"text-xs text-gray-500",children:"Install the free Rankpilot plugin from WordPress.org on your site to get this key."})]})]}),e.jsxs("div",{className:"flex justify-end gap-3",children:[e.jsx(h,{variant:"outline",className:"h-12 p-6 text-sm",onClick:()=>b(null),disabled:n,children:"Cancel"}),e.jsx(h,{className:"h-12 p-6 text-sm",onClick:()=>B("wordpress"),disabled:n,children:n?"Saving...":"Save Configuration"})]})]})})]});if(g==="google-analytics")return e.jsxs("div",{className:"space-y-6",children:[e.jsx("div",{className:"flex items-center gap-4",children:e.jsxs("div",{children:[e.jsx("h3",{className:"text-xl font-semibold",children:"Google Analytics Configuration"}),e.jsx("p",{className:"text-sm text-gray-600",children:"Select the property you want to track across Rankpilot"})]})}),e.jsx(P,{className:"border-gray-200",children:e.jsxs("div",{className:"space-y-6 p-6",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{htmlFor:"ga-property",children:"Analytics Property"}),e.jsx("div",{className:"grid grid-cols-1 md:grid-cols-2",children:e.jsxs(ne,{value:se,onValueChange:ge,children:[e.jsx(ie,{className:"h-10 text-sm",children:e.jsx(re,{placeholder:"Select a property"})}),e.jsx(oe,{children:us.map(s=>e.jsx(le,{value:s.propertyId,children:s.displayName},s.propertyId))})]})}),e.jsx("p",{className:"text-xs text-gray-500",children:"This property will be used for analytics data across the dashboard and analytics pages."})]}),e.jsxs("div",{className:"flex justify-end gap-3",children:[e.jsx(h,{variant:"outline",className:"h-12 p-6 text-sm",onClick:()=>b(null),disabled:n,children:"Cancel"}),e.jsx(h,{className:"h-12 p-6 text-sm",onClick:()=>_e("google-analytics"),disabled:n||!se,children:n?"Saving...":"Save Configuration"})]})]})})]});if(g==="search-console"){const s=o=>o.startsWith("sc-domain:")?o.replace("sc-domain:",""):o.replace(/^https?:\/\//,"").replace(/\/$/,"");return e.jsxs("div",{className:"space-y-6",children:[e.jsx("div",{className:"flex items-center gap-4",children:e.jsxs("div",{children:[e.jsx("h3",{className:"text-xl font-semibold",children:"Search Console Configuration"}),e.jsx("p",{className:"text-sm text-gray-600",children:"Select the site you want to track across Rankpilot"})]})}),e.jsx(P,{className:"border-gray-200",children:e.jsxs("div",{className:"space-y-6 p-6",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{htmlFor:"sc-site",children:"Search Console Site"}),e.jsx("div",{className:"grid grid-cols-1 md:grid-cols-2",children:e.jsxs(ne,{value:te,onValueChange:ye,children:[e.jsx(ie,{className:"h-10 text-sm",children:e.jsx(re,{placeholder:"Select a site"})}),e.jsx(oe,{children:ps.map(o=>e.jsx(le,{value:o.siteUrl,children:s(o.siteUrl)},o.siteUrl))})]})}),e.jsx("p",{className:"text-xs text-gray-500",children:"This site will be used for keyword and search data across the dashboard and analytics pages."})]}),e.jsxs("div",{className:"flex justify-end gap-3",children:[e.jsx(h,{variant:"outline",className:"h-12 p-6 text-sm",onClick:()=>b(null),disabled:n,children:"Cancel"}),e.jsx(h,{className:"h-12 p-6 text-sm",onClick:()=>_e("search-console"),disabled:n||!te,children:n?"Saving...":"Save Configuration"})]})]})})]})}return g==="blogger"?e.jsxs("div",{className:"space-y-6",children:[e.jsx("div",{className:"flex items-center gap-4",children:e.jsxs("div",{children:[e.jsx("h3",{className:"text-xl font-semibold",children:"Google Blogger Configuration"}),e.jsx("p",{className:"text-sm text-gray-600",children:"Select the blog you want to publish content to"})]})}),e.jsx(P,{className:"border-gray-200",children:e.jsxs("div",{className:"space-y-6 p-6",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(N,{htmlFor:"blogger-blog",children:"Blog"}),e.jsx("div",{className:"grid grid-cols-1 md:grid-cols-2",children:e.jsxs(ne,{value:ae,onValueChange:fe,children:[e.jsx(ie,{className:"h-10 text-sm",children:e.jsx(re,{placeholder:"Select a blog"})}),e.jsx(oe,{children:ys.map(s=>
172e.jsxs(le,{value:s.id,children:[s.name," (",s.url,")"]},s.id))})]})}),e.jsx("p",{className:"text-xs text-gray-500",children:"This blog will be used as the publish target for new content."})]}),e.jsxs("div",{className:"flex justify-end gap-3",children:[e.jsx(h,{variant:"outline",className:"h-12 p-6 text-sm",onClick:()=>b(null),disabled:n,children:"Cancel"}),e.jsx(h,{className:"h-12 p-6 text-sm",onClick:vs,disabled:n||!ae,children:n?"Saving...":"Save Configuration"})]})]})})]}):e.jsxs("div",{className:"space-y-6",children:[r&&e.jsx("div",{className:"rounded-lg border border-amber-200 bg-amber-50 px-4 py-3 text-sm text-amber-800",children:"Integrations are managed by the team owner. You can view connection status, but connecting, disconnecting, and configuration are done by the owner."}),e.jsxs(P,{className:"border-gray-200 p-6",children:[e.jsx("h3",{className:"text-lg font-semibold",children:"Connected Integrations"}),e.jsxs("p",{className:"mb-6 mt-1 text-sm text-gray-600",children:["These connections apply to"," ",e.jsx("span",{className:"font-medium text-gray-900",children:(t==null?void 0:t.name)||(t==null?void 0:t.domain)||"your active website"}),". Switch websites in the site selector to manage another site's integrations."]}),e.jsxs("div",{className:"space-y-4",children:[r&&u.filter(s=>s.status==="connected").length===0&&e.jsx("div",{className:"rounded-xl border border-dashed border-gray-200 p-6 text-center text-sm text-gray-500",children:"The team owner hasn't connected any integrations yet."}),(r?u.filter(s=>s.status==="connected"):u).map(s=>
172e.jsxs("div",{className:"flex flex-col gap-4 rounded-xl border border-gray-200 p-4 md:flex-row md:items-center md:justify-between",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"flex size-14 items-center justify-center rounded-lg bg-gray-100 *:size-1/2",children:s.icon}),e.jsxs("div",{children:[e.jsx("div",{className:"flex items-center gap-2 text-base font-semibold",children:s.name}),e.jsx("div",{className:"text-sm text-gray-600",children:s.description})]})]}),e.jsx("div",{className:"flex items-center gap-2",children:r?e.jsxs("span",{className:"inline-flex items-center gap-2 rounded-full bg-green-50 px-3 py-1 text-sm font-medium text-green-700",children:[e.jsx("span",{className:"h-2 w-2 rounded-full bg-green-500"})," Connected"]}):e.jsxs(e.Fragment,{children:[s.status==="connected"&&s.supportsConfig&&e.jsx(h,{variant:"outline",disabled:d||p===s.id,onClick:()=>{s.id==="google-analytics"||s.id==="search-console"||s.id==="blogger"?ze(s.id):b(s.id)},children:"Configure"}),e.jsx(h,{variant:s.status==="disconnected"?"primary":"destructive",disabled:d&&s.status==="connected"||p===s.id,onClick:()=>{if(s.status==="disconnected"&&s.supportsConfig){s.id==="search-console"||s.id==="google-analytics"||s.id==="blogger"?qe(s.id):b(s.id);return}if(s.status==="disconnected"&&(s.id==="search-console"||s.id==="google-analytics"||s.id==="blogger")){qe(s.id);return}js(s.id,s.status)},children:d&&s.status==="connected"?e.jsx(V,{className:"h-4 w-4 animate-spin"}):p===s.id?e.jsx(V,{className:"h-4 w-4 animate-spin"}):s.status==="connected"?"Disconnect":"Connect"})]})})]},s.id))]})]}),!r&&e.jsx(xt,{dudaConnected:u.some(s=>s.id==="duda"&&s.status==="connected")})]})},gt=()=>{const t=[{key:"email",title:"Email Notifications",description:"Receive email updates about your account activity"},{key:"keywordChanges",title:"Keyword Ranking Changes",description:"Get notified when your keyword positions change"},{key:"weeklyReports",title:"Weekly Reports",description:"Receive weekly performance reports"},{key:"monthlyReports",title:"Monthly Digest",description:"Get a monthly summary of your SEO performance"},{key:"productUpdates",title:"New Features",description:"Be the first to know about new features and updates"},{key:"billing",title:"Billing Alerts",description:"Get notified about payments, renewals, and trial status"},{key:"security",title:"Security Alerts",description:"Get notified about logins and account security changes"},{key:"content",title:"Content Updates",description:"Get notified when content generation completes"},{key:"backlinks",title:"Backlink Updates",description:"Get notified about new or lost backlinks"}],{data:r,isLoading:n}=Ss(),i=ks(),[d,a]=m.useState(Ne);m.useEffect(()=>{r&&a({...Ne,...r})},[r]);const u=x=>{a(g=>({...g,[x]:!g[x]}))},f=()=>{a({...Ne,...r||{}})},p=()=>{i.mutate(d)};return e.jsxs(P,{className:"border-gray-200 p-6",children:[e.jsx("h3",{className:"mb-6 text-lg font-semibold",children:"Notification Preferences"}),e.jsxs("div",{className:"space-y-4",children:[t.map(x=>e.jsxs("div",{className:"flex items-center justify-between rounded-xl bg-gray-50 p-4",children:[e.jsxs("div",{children:[e.jsx("div",{className:"text-sm font-medium",children:x.title}),e.jsx("div",{className:"text-xs text-gray-600",children:x.description})]}),e.jsxs("label",{className:"relative inline-flex cursor-pointer items-center",children:[e.jsx("input",{type:"checkbox",className:"peer sr-only",checked:!!d[x.key],onChange:()=>u(x.key),disabled:n}),e.jsx("div",{className:"peer h-6 w-11 rounded-full bg-gray-200 peer-checked:bg-blue after:absolute after:top-[2px] after:left-[2px] after:h-5 after:w-5 after:rounded-full after:border after:border-gray-300 after:bg-white after:transition-all after:content-[''] peer-checked:after:translate-x-full peer-checked:after:border-white"})]})]},x.key)),e.jsxs("div",{className:"flex justify-end gap-3",children:[e.jsx(h,{variant:"outline",className:"h-12 p-6 text-sm",onClick:f,disabled:n||i.isPending,children:"Cancel"}),e.jsx(h,{className:"h-12 p-6 text-sm",onClick:p,disabled:n||i.isPending,children:"Save Preferences"})]})]})]})},yt=5e3,ft=()=>{const t=w=>!!(w!=null&&w.pendingEmail&&(!w.pendingEmailExpires||new Date(w.pendingEmailExpires).getTime()>Date.now())),{data:r,refetch:n}=Ie({queryKey:["auth","me"],queryFn:()=>H.getMe(),staleTime:3e5,retry:!1,refetchInterval:w=>{var I;return t((I=w.state.data)==null?void 0:I.user)?yt:!1}}),i=r==null?void 0:r.user,d=!!(i!=null&&i.passwordIsGenerated),a=!!(i!=null&&i.pendingEmail)&&!t(i),[u,f]=m.useState(!1),[p,x]=m.useState({currentPassword:"",newPassword:"",confirmPassword:""}),[g,b]=m.useState(!1),[C,E]=m.useState(!1),[y,S]=m.useState({newEmail:"",currentPassword:""}),[F,U]=m.useState(!1),_=m.useRef(null);m.useEffect(()=>{const w=(i==null?void 0:i.pendingEmail)??null,I=_.current;I&&!w&&(i==null?void 0:i.email)===I&&U(!0),_.current=w},[i==null?void 0:i.pendingEmail,i==null?void 0:i.email]);const xe=async w=>{var I;if(w.preventDefault(),p.newPassword!==p.confirmPassword){c.error("New passwords do not match");return}if(p.newPassword.length<8){c.error("New password must be at least 8 characters long");return}f(!0);try{const k=await H.changePassword(d?{...p,currentPassword:void 0}:p);c.success((k==null?void 0:k.message)||"Password updated successfully!"),x({currentPassword:"",newPassword:"",confirmPassword:""}),d&&n()}catch(k){const W=((I=k==null?void 0:k.data)==null?void 0:I.message)||(k==null?void 0:k.message)||"Failed to update password";c.error(W)}finally{f(!1)}},M=async w=>{var I;w.preventDefault(),b(!0);try{const k=await H.changeEmail(d?{...y,currentPassword:void 0}:y);c.success((k==null?void 0:k.message)||`Verification email sent to ${y.newEmail}.`),S({newEmail:"",currentPassword:""}),n()}catch(k){const W=((I=k==null?void 0:k.data)==null?void 0:I.message)||(k==null?void 0:k.message)||"Failed to change email";c.error(W)}finally{b(!1)}},G=async()=>{var w;E(!0);try{await H.cancelEmailChange(),c.success("Email change request cancelled"),n()}catch(I){const k=((w=I==null?void 0:I.data)==null?void 0:w.message)||(I==null?void 0:I.message)||"Failed to cancel email change";c.error(k)}finally{E(!1)}},$=async()=>{try{await H.logout()}finally{window.location.href="/login"}};return e.jsxs("div",{className:"space-y-6",children:[e.jsxs(P,{className:"border-gray-200 p-6",children:[e.jsx("h3",{className:"mb-6 text-lg font-semibold",children:"Email Address"}),e.jsxs("form",{onSubmit:M,className:"space-y-6",children:[i!=null&&i.pendingEmail?e.jsxs("div",{className:"flex items-start justify-between gap-4 roun
172ded-lg bg-gray-50 p-4",children:[e.jsx("p",{className:"text-sm text-gray-600",children:a?e.jsxs(e.Fragment,{children:["The verification link sent to ",e.jsx("span",{className:"font-medium",children:i.pendingEmail})," has expired. Submit the form below to try again."]}):e.jsxs(e.Fragment,{children:["A verification email was sent to ",e.jsx("span",{className:"font-medium",children:i.pendingEmail}),". Click the link in that email to confirm the change."]})}),e.jsx(h,{type:"button",variant:"outline",size:"sm",onClick:G,disabled:C,children:C?"Cancelling...":"Cancel"})]}):null,e.jsxs("div",{children:[e.jsx(N,{className:"mb-2 block text-sm font-medium text-gray-700",children:"Current Email"}),e.jsx(A,{value:(i==null?void 0:i.email)||"",disabled:!0})]}),e.jsxs("div",{children:[e.jsx(N,{className:"mb-2 block text-sm font-medium text-gray-700",children:"New Email"}),e.jsx(A,{type:"email",placeholder:"Enter new email address",value:y.newEmail,onChange:w=>S({...y,newEmail:w.target.value}),required:!0})]}),d?null:e.jsxs("div",{children:[e.jsx(N,{className:"mb-2 block text-sm font-medium text-gray-700",children:"Current Password"}),e.jsx(L,{placeholder:"Enter current password to confirm",value:y.currentPassword,onChange:w=>S({...y,currentPassword:w.target.value}),required:!0})]}),e.jsx("div",{className:"flex justify-end gap-3",children:e.jsx(h,{type:"submit",className:"h-12 p-6 text-sm",disabled:g,children:g?"Sending...":"Change Email"})})]})]}),e.jsxs(P,{className:"border-gray-200 p-6",children:[e.jsx("h3",{className:"mb-6 text-lg font-semibold",children:"Security Settings"}),e.jsxs("form",{onSubmit:xe,className:"space-y-6",children:[d?e.jsx("p",{className:"text-sm text-gray-600",children:"Your account doesn't have a password yet. Set one here to be able to log in at rankpilot.dev directly."}):e.jsxs("div",{children:[e.jsx(N,{className:"mb-2 block text-sm font-medium text-gray-700",children:"Current Password"}),e.jsx(L,{placeholder:"Enter current password",value:p.currentPassword,onChange:w=>x({...p,currentPassword:w.target.value}),required:!0})]}),e.jsxs("div",{children:[e.jsx(N,{className:"mb-2 block text-sm font-medium text-gray-700",children:d?"Password":"New Password"}),e.jsx(L,{placeholder:"Enter new password",value:p.newPassword,onChange:w=>x({...p,newPassword:w.target.value}),required:!0})]}),e.jsxs("div",{children:[e.jsx(N,{className:"mb-2 block text-sm font-medium text-gray-700",children:d?"Confirm Password":"Confirm New Password"}),e.jsx(L,{placeholder:"Confirm new password",value:p.confirmPassword,onChange:w=>x({...p,confirmPassword:w.target.value}),required:!0})]}),e.jsxs("div",{className:"flex justify-end gap-3",children:[e.jsx(h,{type:"button",variant:"outline",className:"h-12 p-6 text-sm",onClick:()=>x({currentPassword:"",newPassword:"",confirmPassword:""}),disabled:u,children:"Cancel"}),e.jsx(h,{type:"submit",className:"h-12 p-6 text-sm",disabled:u,children:u?"Saving...":d?"Set Password":"Update Password"})]})]})]}),e.jsx(ss,{open:F,onOpenChange:()=>{},children:e.jsxs(ts,{className:"max-w-md",children:[e.jsxs(as,{children:[e.jsx(ns,{children:"Email verified"}),e.jsx(rs,{children:"Your email address has been changed and verified. You'll need to sign in again with your new email."})]}),e.jsx(os,{children:e.jsx(h,{onClick:$,children:"OK"})})]})})]})},bt=[{id:"friendly",label:"Friendly",blurb:"Warm and helpful, like a good neighbor.",sample:"Grocery bills sneaking up on you? Same. A few small habits can shave 20% off, without giving up the stuff you love."},{id:"professional",label:"Professional",blurb:"Polished and clear, like a business report.",sample:"Grocery costs have risen roughly 25% in three years. A few smart shopping habits can offset most of that, without changing what you eat."},{id:"casual",label:"Casual",blurb:"Relaxed, like a chat over coffee.",sample:"Grocery prices are wild right now. Here are the shopping tricks I actually use every week, no coupon binder required."},{id:"confident",label:"Confident",blurb:"Direct and sure, no hedging.",sample:"Your grocery bill is bigger than it needs to be. Three habits f
172ix that, starting on your next trip to the store."},{id:"playful",label:"Playful",blurb:"Light and fun, with a bit of personality.",sample:"If your receipt is longer than a CVS one, we need to talk. Here's how to cut it in half, without cutting the snacks."},{id:"expert",label:"Expert",blurb:"In-depth and precise, for a technical reader.",sample:"Unit pricing, price cycles, and loss-leader identification are the three habits behind most 20-30% grocery savings. Here's how to use them."}],jt=()=>{const{activeWebsite:t}=Z(),{isTeamContext:r}=X(),n=(t==null?void 0:t.id)??null,{data:i}=Is(n),d=Ps(n),[a,u]=m.useState(null),[f,p]=m.useState("");m.useEffect(()=>{u((i==null?void 0:i.voiceTone)??null),p((i==null?void 0:i.customVoiceNotes)??"")},[i==null?void 0:i.websiteId,i==null?void 0:i.voiceTone,i==null?void 0:i.customVoiceNotes]);const x=()=>{if(r){c.error("Voice is managed by the team owner.");return}d.mutate({voiceTone:a,customVoiceNotes:f.trim()},{onSuccess:()=>c.success("Voice saved. New articles for this website will use it."),onError:({message:g})=>c.error(g||"Failed to save voice")})};return e.jsxs("div",{className:"space-y-6",children:[r&&e.jsx("div",{className:"rounded-lg border border-amber-200 bg-amber-50 px-4 py-3 text-sm text-amber-800",children:"Voice is managed by the team owner. You can see the voice their articles use, but changing it is done by the owner. Switch to your own profile to edit your websites' voice."}),e.jsxs(P,{className:"border-gray-200 p-6",children:[e.jsxs("div",{className:"mb-6",children:[e.jsx("h3",{className:"text-2xl font-bold text-gray-900",children:r?"How these articles sound":"How should your articles sound?"}),e.jsxs("p",{className:"mt-2 text-base text-gray-700",children:[r?"The voice used for ":"Pick a voice for ",e.jsx("span",{className:"font-medium text-gray-900",children:(t==null?void 0:t.name)||(t==null?void 0:t.domain)||"this website"}),". Each website has its own voice",r?".":" â change it anytime, new articles will use it."]})]}),e.jsx("div",{className:"grid gap-3 sm:grid-cols-2 lg:grid-cols-3",children:bt.map(g=>{const b=a===g.id;return e.jsxs("button",{type:"button",onClick:()=>u(C=>C===g.id?null:g.id),"aria-pressed":b,disabled:r,className:de("group relative flex h-full flex-col rounded-xl border p-4 text-left transition-all","focus:outline-none focus-visible:ring-2 focus-visible:ring-blue","disabled:cursor-not-allowed disabled:opacity-70",b?"border-blue bg-blue-50/50 shadow-sm ring-1 ring-blue":"border-gray-200 bg-white hover:border-gray-300 hover:shadow-sm"),children:[e.jsxs("div",{className:"mb-2 flex items-center justify-between",children:[e.jsx("span",{className:de("text-lg font-bold",b?"text-blue":"text-gray-900"),children:g.label}),b&&e.jsx("span",{className:"flex size-6 items-center justify-center rounded-full bg-blue",children:e.jsx(Us,{className:"size-4 text-white",strokeWidth:3})})]}),e.jsx("p",{className:"mb-4 text-sm text-gray-700",children:g.blurb}),e.jsxs("div",{className:"mt-auto rounded-lg bg-gray-50 p-3",children:[e.jsx("div",{className:"mb-1.5 text-xs font-bold uppercase tracking-wide text-gray-600",children:"Sample"}),e.jsxs("p",{className:"text-sm italic leading-relaxed text-gray-800",children:['"',g.sample,'"']})]})]},g.id)})}),e.jsxs("div",{className:"mt-8 border-t border-gray-200 pt-6",children:[e.jsxs("div",{className:"mb-2 flex items-baseline justify-between",children:[e.jsx("label",{htmlFor:"custom-voice-notes",className:"text-lg font-bold text-gray-900",children:"Want to tweak it?"}),e.jsx("span",{className:"text-sm font-medium text-gray-600",children:"Optional"})]}),e.jsx("p",{className:"mb-3 text-base text-gray-700",children:"Add anything the writer should know about your brand."}),e.jsx("textarea",{id:"custom-voice-notes",value:f,onChange:g=>p(g.target.value),rows:3,maxLength:500,disabled:r,placeholder:'e.g. "Use bullet points when listing steps" or "Never use the word synergy"',className:"w-full rounded-xl border border-gray-200 bg-white px-4 py-3 text-base leading-relaxed text-gray-900 placeholder:text-gray-500 focus-visible:ring-2 focus-visible:ring-blue focus-visible:outline-none disabled:cursor-not-allowed disabled:bg-gray-50 disabled:text-gray-600"}),e.jsxs("div",{className:"mt-1.5 text-right text-sm font-medium text-gray-600",children:[f.length,"/500"]})]}),!r&&e.jsx("div",{className:"mt-6 flex justify-end",children:e.jsx(h,{className:"h-12 p-6 text-base font-semibold",onClick:x,disabled:d.isPending||!n,children:d.isPending?"Saving...":"Save Voice"})})]})]})},ue=["team","snapshot"],Nt=()=>Ie({queryKey:ue,queryFn:()=>me.getTeam(),retry:!1,staleTime:60*1e3}),vt=()=>{const t=J();return Pe({mutationFn:r=>me.invite(r),onSuccess:r=>{t.setQueryData(ue,r),t.invalidateQueries({queryKey:Ue})}})},wt=()=>{const t=J();return Pe({mutationFn:r=>me.cancelInvite(r),onSuccess:r=>{t.setQueryData(ue,r),t.invalidateQueries({queryKey:Ue})}})},Ct=()=>{const t=J();return Pe({mutationFn:r=>me.removeMember(r),onSuccess:r=>{t.setQueryData(ue,r),t.invalidateQueries({queryKey:Ue})}})},Ce=(t,r)=>{var d,a;const i=(t&&t!=="You"?t:r).replace(/@.*$/,"").split(/[\s._-]+/).filter(
172Boolean);return((((d=i[0])==null?void 0:d[0])??"")+(((a=i[1])==null?void 0:a[0])??"")).toUpperCase()||"?"},St=()=>{const{data:t}=Se(),{data:r,isLoading:n}=Nt(),i=vt(),d=wt(),a=Ct(),[u,f]=m.useState(""),p=r==null?void 0:r.seats,x=!!p&&p.remaining>0,g=async y=>{y.preventDefault();const S=u.trim().toLowerCase();if(!S||!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(S)){c.error("Enter a valid email address");return}try{await i.mutateAsync(S),f(""),c.success(`Invite sent to ${S}`)}catch(F){const U=F instanceof ce?F.message:"Could not send the invite";c.error(U)}},b=async y=>{try{await a.mutateAsync(y),c.success("Removed from team")}catch(S){const F=S instanceof ce?S.message:"Could not remove member";c.error(F)}},C=async y=>{try{await d.mutateAsync(y),c.success("Invite canceled")}catch(S){const F=S instanceof ce?S.message:"Could not cancel invite";c.error(F)}},E=`${(t==null?void 0:t.firstName)??""} ${(t==null?void 0:t.lastName)??""}`.trim()||"You";return e.jsxs(P,{className:"border-gray-200 p-6",children:[e.jsxs("div",{className:"mb-6 flex items-start justify-between gap-4",children:[e.jsxs("div",{children:[e.jsx("h3",{className:"text-2xl font-bold text-gray-900",children:"Your team"}),e.jsx("p",{className:"mt-2 text-base text-gray-700",children:"Invite people to work with you."})]}),p&&e.jsxs("div",{className:"shrink-0 rounded-full border border-gray-200 bg-gray-50 px-3 py-1.5 text-sm font-semibold text-gray-700",children:[p.used," of ",p.limit," seats"]})]}),e.jsxs("form",{onSubmit:g,className:"flex flex-col gap-3 sm:flex-row",children:[e.jsx(A,{type:"email",value:u,onChange:y=>f(y.target.value),placeholder:"[email protected]",className:"flex-1 text-base",disabled:!x||i.isPending}),e.jsxs(h,{type:"submit",className:"h-12 px-6 text-base font-semibold",disabled:!x||!u.trim()||i.isPending,children:[e.jsx(Vs,{className:"mr-2 size-4"}),i.isPending?"Sendingâ¦":"Send invite"]})]}),p&&!x&&e.jsx("p",{className:"mt-3 text-sm font-medium text-amber-700",children:"You've used all your seats. Remove a member or cancel an invite to free one up."}),e.jsxs("div",{className:"mt-8",children:[e.jsx("div",{className:"mb-3 text-sm font-semibold uppercase tracking-wide text-gray-600",children:"On your team"}),n?e.jsx("div",{className:"flex justify-center py-8",children:e.jsx(he,{})}):e.jsxs("ul",{className:"divide-y divide-gray-200 rounded-xl border border-gray-200",children:[e.jsxs("li",{className:"flex items-center gap-4 px-4 py-3 first:rounded-t-xl hover:bg-gray-50",children:[e.jsx("div",{className:"bg-blue flex size-10 shrink-0 items-center justify-center rounded-full text-sm font-bold text-white",children:Ce(E,(t==null?void 0:t.email)??"")}),e.jsx("div",{className:"min-w-0 flex-1",children:e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"truncate text-base font-semibold text-gray-900",children:E}),e.jsx("span",{className:"bg-blue-50 text-blue rounded-full px-2 py-0.5 text-xs font-semibold",children:"You"})]})})]}),r==null?void 0:r.members.map(y=>e.jsxs("li",{className:"group flex items-center gap-4 px-4 py-3 hover:bg-gray-50",children:[e.jsx("div",{className:"flex size-10 shrink-0 items-center justify-center rounded-full bg-emerald-100 text-sm font-bold text-emerald-800",children:Ce(y.name,y.email)}),e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsx("span",{className:"truncate text-base font-semibold text-gray-900",children:y.name||y.email}),y.name&&e.jsx("div",{className:"truncate text-sm text-gray-600",children:y.email})]}),e.jsx("button",{type:"button",onClick:()=>b(y.memberUserId),disabled:a.isPending,"aria-label":`Remove ${y.name||y.email}`,className:"rounded-lg p-2 text-gray-400 opacity-0 transition hover:bg-red-50 hover:text-red-600 focus-visible:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-red-300 group-hover:opacity-100",children:e.jsx(Oe,{className:"size-4"})})]},y.id)),r==null?void 0:r.invites.map(y=>e.jsxs("li",{className:de("group flex items-center gap-4 px-4 py-3 last:rounded-b-xl hover:bg-gray-50"),children:[e.jsx("div",{className:"flex size-10 shrink-0 items-center justify-center rounded-full bg-gray-100 text-sm font-bold text-gray-500",children:Ce("",y.email)}),e.jsx("div",{className:"min-w-0 flex-1",children:e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{className:"truncate text-base font-semibold text-gray-900",children:y.email}),e.jsx("span",{className:"rounded-full bg-amber-50 px-2 py-0.5 text-xs font-semibold text-amber-700",children:"Invite sent"})]})}),e.jsx("button",{type:"button",onClick:()=>C(y.id),disabled:d.isPending,"aria-label":`Cancel invite to ${y.email}`,className:"rounded-lg p-2 text-gray-400 opacity-0 transition hover:bg-red-50 hover:text-red-600 focus-visible:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-red-300 group-hover:opacity-100",children:e.jsx(Oe,{className:"size-4"})})]},y.id))]})]})]})},Ze=[{id:"general",label:"General",icon:Ws},{id:"voice",label:"Voice",icon:Qs},{id:"security",label:"Security",icon:Js},{id:"notifications",label:"Notifications",icon:Os},{id:"automation",label:"Automation",icon:cs},{id:"integrations",label:"Integrations",icon:Hs}],kt={id:"team",label:"Team",icon:Xs},Je="general",Bt=()=>{const[t,r]=ls(),{isTeamContext:n}=X(),i=n?Ze:[...Ze,kt],d=new Set(i.map(f=>f.id)),[a,u]=m.useState(()=>{const f=t.get("tab");return f&&d.has(f)?f:Je});return m.useEffect(()=>{const f=t.get("tab");u(f&&d.has(f)?f:Je)},[t,n]),e.jsxs("div",{className:"max-w-5xl space-y-6",children:[e.jsx(As,{children:e.jsx("title",{children:"Settings | Rankpilot"})}),e.jsx("div",{role:"tablist",className:"flex gap-4 border-b border-gray-200 pb-4",children:i.map(f=>{const p=f.icon;return e.jsxs("button",{role:"tab","aria-selected":a===f.id,"aria-controls":`tabpanel-${f.id}`,onClick:()=>{u(f.id);const x=new URLSearchParams(t);x.set("tab",f.id),r(x,{replace:!0})},className:`flex items-center gap-2 rounded-lg px-4 py-2 transition-colors ${a===f.id?"bg-blue text-white":"text-gray-600 hover:bg-gray-100"}`,children:[e.jsx(p,{className:"h-5 w-5"}),e.jsx("span",{className:"text-sm font-medium",children:f.label})]},f.id)})}),e.jsxs("div",{children:[a==="general"&&e.jsx(lt,{}),a==="voice"&&e.jsx(jt,{}),a==="security"&&e.jsx(ft,{}),a==="notifications"&&e.jsx(gt,{}),a==="automation"&&e.jsx(tt,{}),a==="integrations"&&e.jsx(pt,{}),a==="team"&&!n&&e.jsx(St,{})]})]})};export{Bt as Settings};
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.