1import{cD as R,a8 as z,j as t,L as T,c as $,B as b,P as U,d9 as q,da as M,db as B,dc as D,dd as K,de as G,J as Q}from"./index-Bv3S47RD.js";import{u as w}from"./useMutation-DVVZtBR8.js";import{a as p}from"./minimax-localized-C7lF3KGy.js";import{t as y}from"./index-CJgmUuJ4.js";import{A as V}from"./admin-page-DuYbKQGA.js";import{B as P}from"./badge-DCBFLPrm.js";import{C as W,b as H,c as J,a as X}from"./card-Ce8YpCZv.js";import{C as Y,g as N}from"./error-message-CtdP4L9c.js";import{I as Z}from"./input-C67SbsrX.js";import{L as ee}from"./label-Dio5mB61.js";import{N as te,a as ae}from"./native-select-BzOItyyR.js";import{S as se}from"./switch-BpuhWW5C.js";import{T as re}from"./textarea-Cb-ma63q.js";import{I as ie}from"./IconPhoto-DN_ZE_ml.js";import{I as le}from"./IconUpload-D7OQE_vY.js";import{I as oe}from"./IconTrash-Bx4kxMNt.js";import"./dashboard-header-VSIWAcCX.js";import"./useFocus-BDpvPN3E.js";import"./useRender-B_Tg7mgV.js";import"./separator-CdrmIJef.js";import"./Separator-DMkZJVdp.js";import"./sidebar-D4vbg_cJ.js";import"./DialogTitle-DUdvhjof.js";import"./useControlled-BisvYZ-V.js";import"./useRegisterFieldControl-DmKA02dB.js";import"./useAriaLabelledBy-Bv8z3wRJ.js";import"./IconSelector-C1ywg_Ns.js";const ne=[{key:"general",label:"General"},{key:"auth",label:"Auth"},{key:"payment",label:"Payment"},{key:"email",label:"Email"},{key:"storage",label:"Storage"},{key:"ai",label:"AI"},{key:"analytics",label:"Analytics"},{key:"ads",label:"Ads"},{key:"affiliate",label:"Affiliate"},{key:"customer_service",label:"Customer Service"}],de={general:[{title:"App Info",description:"Customize your app information.",keys:["app_name","app_description","app_logo","app_preview_image"]},{title:"User Role",description:"Customize initial user role settings.",keys:["initial_role_enabled","initial_role_name"]},{title:"Credit",description:"Customize initial credit settings.",keys:["initial_credits_enabled","initial_credits_amount","initial_credits_valid_days","initial_credits_description"]}],auth:[{title:"Email Auth",description:"Customize your email authentication settings.",keys:["credential_login_enabled","email_verification_enabled"]},{title:"Google Auth",description:"Customize your Google authentication settings.",keys:["google_login_enabled","google_client_id","google_client_secret"]}],payment:[{title:"Basic Payment",description:"Customize your basic payment settings.",keys:["select_payment_enabled","payment_provider"]}
1,{title:"Stripe",description:"Customize your Stripe settings.",keys:["stripe_enabled","stripe_publishable_key","stripe_secret_key","stripe_webhook_secret","stripe_payment_methods","stripe_promotion_codes","stripe_allow_promotion_codes"]},{title:"Creem",description:"Customize your Creem settings.",keys:["creem_enabled","creem_debug","creem_api_key","creem_webhook_secret","creem_product_ids"]},{title:"Waffo",description:"Customize your Waffo settings.",keys:["waffo_enabled","waffo_debug","waffo_merchant_id","waffo_private_key"]},{title:"PayPal",description:"ShipAny includes a PayPal provider adapter.",keys:[],notice:"PayPal is not yet installed in this TanStarter payment layer. Its credential fields are intentionally not accepted until checkout, webhook verification, refunds, and billing history are implemented end to end."}],email:[{title:"Email Delivery",description:"Customize email delivery settings.",keys:["mail_enabled","mail_provider","mail_from","resend_api_key"]},{title:"Newsletter",description:"Customize newsletter settings.",keys:["newsletter_enabled","newsletter_provider","beehiiv_api_key","beehiiv_publication_id"]}],storage:[{title:"Cloudflare R2 - Users",description:"Private bucket for user uploads, avatars, and AI generation outputs.",keys:["storage_provider","cloudflare_account_id","storage_user_binding","storage_user_access_key_mode","storage_user_secret_key_mode","storage_user_bucket_name","storage_upload_path","storage_user_endpoint","storage_user_domain","storage_max_file_size_mb","storage_allowed_types"]},{title:"Cloudflare R2 - Assets",description:"Shared bucket for source examples, gallery covers, template videos, and site assets.",keys:["cloudflare_account_id","storage_asset_binding","storage_asset_access_key_mode","storage_asset_secret_key_mode","storage_asset_bucket_name","storage_asset_upload_path","storage_asset_endpoint","storage_asset_domain","storage_asset_access"]}],ai:[{title:"Fal",description:"Customize your Fal settings.",keys:["fal_key"]},{title:"Cloudflare AI",description:"Customize your Cloudflare AI settings.",keys:["cloudflare_account_id","cloudflare_api_token"]}],analytics:[{title:"Google Analytics",description:"Customize your Google Analytics settings.",keys:["google_analytics_id"]},{title:"Clarity",description:"Customize your Microsoft Clarity settings.",keys:["clarity_project_id"]},{title:"Plausible",description:"Customize your Plausible settings.",keys:["plausible_script"]},{title:"Umami",description:"Customize your Umami settings.",keys:["umami_website_id","umami_script"]}],ads:[{title:"AdSense",description:"Customize your AdSense settings.",keys:["adsense_code"]}
1],affiliate:[{title:"Affonso",description:"Customize your Affonso settings.",keys:["affonso_enabled","affonso_id","affonso_cookie_duration"]},{title:"PromoteKit",description:"Customize your PromoteKit settings.",keys:["promotekit_enabled","promotekit_id"]}],customer_service:[{title:"Crisp",description:"Customize your Crisp settings.",keys:["crisp_website_id"]},{title:"Notifications",description:"Customize operational notification settings.",keys:["notification_enabled","notification_provider","discord_webhook_url","feishu_webhook_url"]}]},ce={initial_role_name:[{label:"Viewer",value:"viewer"},{label:"Editor",value:"editor"},{label:"Admin",value:"admin"},{label:"Super Admin",value:"super_admin"}],payment_provider:[{label:"Not configured",value:""},{label:"Stripe",value:"stripe"},{label:"Creem",value:"creem"},{label:"Waffo",value:"waffo"}],mail_provider:[{label:"Cloudflare",value:"cloudflare"},{label:"Resend",value:"resend"}],newsletter_provider:[{label:"Resend",value:"resend"},{label:"Beehiiv",value:"beehiiv"}],notification_provider:[{label:"Discord",value:"discord"},{label:"Feishu",value:"feishu"}]};function ue(r){try{const o=JSON.parse(r);return Array.isArray(o)?o.filter(l=>typeof l=="string"):[]}catch{return[]}}function me(r){return r.secret?"*".repeat(r.secretLength):""}function pe({fieldKey:r,label:o,value:l,disabled:c,uploading:u,onSelect:m,onClear:x}){return t.jsxs("div",{className:"space-y-3",children:[l?t.jsx("div",{className:"flex min-h-28 items-center justify-center overflow-hidden rounded-lg border bg-muted/30 p-3",children:t.jsx("img",{src:l,alt:`${o} preview`,"data-testid":`config-${r}-preview`,className:"max-h-40 max-w-full rounded-md object-contain"})}):t.jsx("div",{"data-testid":`config-${r}-empty`,className:"flex min-h-28 items-center justify-center rounded-lg border border-dashed bg-muted/20 text-muted-foreground",children:t.jsx(ie,{className:"size-8","aria-hidden":"true"})}),t.jsxs("div",{className:"flex flex-wrap gap-2",children:[t.jsxs("label",{className:$(U({variant:"outline",size:"sm"}),"cursor-pointer",(c||u)&&"pointer-events-none opacity-50"),children:[t.jsx(le,{"aria-hidden":"true"}),u?"Uploadingâ¦":l?"Upload a new image to replace":"Upload image",t.jsx("input",{id:`config-${r}`,"data-testid":`config-${r}`,type:"file",accept:"image/jpeg,image/png,image/webp,image/gif",className:"sr-only",disabled:c||u,onChange:g=>{const f=g.currentTarget.files?.[0];f&&m(f),g.currentTarget.value=""}})]}),l?t.jsxs(b,{type:"button",variant:"outline",size:"sm","aria-label":`Remove ${o}`,disabled:c||u,onClick:x,children:[t.jsx(oe,{"aria-hidden":"true"}),"Remove image"]}):null]})]})}function ye({group:r}){const o=R(),l=z({queryKey:["admin","runtime-config"],queryFn:()=>D()}),[c,u]=p.useState({}),[m,x]=p.useState(null),[g,f]=p.useState(null),v=z({queryKey:["admin","runtime-config","revisions",m],queryFn:()=>K({data:{key:m}}),enabled:!!m});p.useEffect(()=>{l.data&&u(Object.fromEntries(l.data.map(a=>[a.key,{value:a.secret?me(a):a.value,secretAction:"keep"}])))},[l.data]);const A=p.useMemo(()=>new Map(l.data?.map(a=>[a.key,a])??[]),[l.data]),O=p.useMemo(()=>de[r].map(a=>({...a,items:a.keys.map(e=>A.get(e)).filter(e=>!!e)})).filter(a=>a.items.length>0||a.notice),[r,A]),n=(a,e)=>{u(i=>({...i,[a]:{value:i[a]?.value??"",secretAction:i[a]?.secretAction??"keep",...e}}))},h=w({onMutate:()=>f(null),mutationFn:a=>B({data:{updates:a.filter(e=>!e.readOnly).map(e=>({key:e.key,value:c[e.key]?.value??"",secretAction:e.secret?c[e.key]?.secretAction??"keep":void 0}))}}),onSuccess:async()=>{await Promise.all([o.invalidateQueries({queryKey:["admin","runtime-config"]}),o.invalidateQueries({queryKey:["public-runtime-config"]})]),y.success("Settings updated")},onError:a=>{const e=N(a);f(e),y.error(e)}}),S=w({mutationFn:a=>M({data:{revisionId:a}}),onSuccess:async()=>{await Promise.all([o.invalidateQueries({queryKey:["admin","runtime-config"]}),o.invalidateQueries({queryKey:["admin","runtime-config","revisions"]})]),y.success("Revision restored")},onError:a=>y.error(N(a))}),k=w({mutationFn:async({key:a,file:e})=>{const i=new FormData;i.append("file",e);const C=await q({data:i});return{key:a,url:C.url}},onSuccess:({key:a,url:e})=>{n(a,{value:e}),y.success("Image uploaded")},onError:a=>y.error(N(a))});return t.jsxs(V,{title:"Settings",children:[t.jsx("div",{className:"flex gap-2 overflow-x-auto border-b",children:ne.map(a=>t.jsx(T,{to:"/admin/settings/$tab",params:{tab:a.key},className:$("whitespace-nowrap border-b-2 border-transparent px-3 py-2 text-sm text-muted-foreground",a.key===r&&"border-primary font-medium text-foreground"),children:a.label},a.key))}),l.isLoading?t.jsx("div",{className:"max-w-xl rounded-xl border py-12 text-center text-muted-foreground",children:"Loadingâ¦"}):null,O.map(a=>t.jsxs(W,{className:"max-w-xl rounded-xl shadow-sm",children:[t.jsxs(H,{
1children:[t.jsx(J,{children:a.title}),t.jsx("p",{className:"text-sm text-muted-foreground",children:a.description})]}),t.jsxs(X,{className:"space-y-6",children:[a.items.map(e=>{const i=c[e.key]??{value:"",secretAction:"keep"},C=!e.secret&&["true","false"].includes(e.value),_=e.options?.length?[...e.options]:ce[e.key],d=e.fieldType??(C?"switch":_?"select":"text"),j=d==="checkbox"?ue(i.value):[];return t.jsxs("div",{className:"grid gap-2",children:[t.jsxs("div",{className:"flex items-center gap-2",children:[t.jsx(ee,{htmlFor:`config-${e.key}`,children:e.label}),e.secret?t.jsx(P,{variant:"secondary",className:"text-[10px]",children:"secret"}):null,e.readOnly?t.jsx(P,{variant:"outline",className:"text-[10px]",children:"managed"}):null]}),d==="switch"?t.jsx("div",{className:"flex min-h-9 items-center",children:t.jsx(se,{id:`config-${e.key}`,"data-testid":`config-${e.key}`,checked:i.value==="true",disabled:e.readOnly,onCheckedChange:s=>n(e.key,{value:s?"true":"false"})})}):d==="checkbox"&&_?t.jsx("div",{className:"flex flex-wrap gap-x-6 gap-y-3",children:_.map(s=>{const I=j.includes(s.value);return t.jsxs("label",{htmlFor:`config-${e.key}-${s.value}`,className:"flex items-center gap-2 text-sm",children:[t.jsx(Y,{id:`config-${e.key}-${s.value}`,"data-testid":`config-${e.key}-${s.value}`,checked:I,disabled:e.readOnly,onCheckedChange:L=>{const E=L?[...j,s.value]:j.filter(F=>F!==s.value);n(e.key,{value:JSON.stringify(E)})}}),s.label]},s.value)})}):d==="upload_image"?t.jsx(pe,{fieldKey:e.key,label:e.label,value:i.value,disabled:e.readOnly,uploading:k.isPending&&k.variables?.key===e.key,onSelect:s=>k.mutate({key:e.key,file:s}),onClear:()=>n(e.key,{value:""})}):d==="textarea"?t.jsx(re,{id:`config-${e.key}`,"data-testid":`config-${e.key}`,autoComplete:"off",value:i.value,placeholder:e.placeholder,rows:e.rows??4,readOnly:e.readOnly,disabled:e.readOnly,onChange:s=>n(e.key,{value:s.target.value})}):d==="select"&&_?t.jsx(te,{id:`config-${e.key}`,className:"w-full",value:i.value,disabled:e.readOnly,onChange:s=>n(e.key,{value:s.target.value}),children:_.map(s=>t.jsx(ae,{value:s.value,children:s.label},s.value||"empty"))}):t.jsxs("div",{className:"flex gap-2",children:[t.jsx(Z,{id:`config-${e.key}`,"data-testid":`config-${e.key}`,autoComplete:"off",value:i.value,type:d==="number"?"number":d,placeholder:e.placeholder,readOnly:e.readOnly,disabled:e.readOnly,onFocus:s=>{e.secret&&s.currentTarget.select()},onChange:s=>n(e.key,{value:s.target.value,secretAction:e.secret?"replace":"keep"})}),e.secret?t.jsx(b,{type:"button",variant:"outline",onClick:()=>n(e.key,{value:"",secretAction:"clear"}),children:"Clear"}):null]}),e.description?t.jsx("p",{className:"text-xs text-muted-foreground",children:e.description}):null,e.sourceLabel?t.jsxs("p",{className:"text-xs text-muted-foreground",children:["Source: ",e.sourceLabel]}):null,e.secret&&i.secretAction==="keep"?t.jsx("p",{className:"text-xs text-muted-foreground",children:e.configured?`Configured · ${e.secretLength} characters · unchanged when saved`:"Not configured"}):null,e.secret&&i.secretAction==="clear"?t.jsx("p",{className:"text-xs text-amber-600",children:"The D1 override will be removed and the Worker Secret fallback restored."}):null,e.readOnly?null:t.jsx(b,{type:"button",variant:"ghost",size:"sm",className:"w-fit px-0 text-xs text-muted-foreground","data-testid":`config-history-${e.key}`,onClick:()=>x(s=>s===e.key?null:e.key),children:m===e.key?"Hide history":"View history"}),m===e.key?t.jsxs("div",{className:"space-y-2 rounded-lg border bg-muted/30 p-3",children:[v.isLoading?t.jsx("p",{className:"text-xs text-muted-foreground",children:"Loading historyâ¦"}):null,v.data?.length===0?t.jsx("p",{className:"text-xs text-muted-foreground",children:"No database revisions yet."}):null,v.data?.map(s=>t.jsxs("div",{className:"flex items-center justify-between gap-3 border-b pb-2 text-xs last:border-0 last:pb-0",children:[t.jsxs("div",{className:"min-w-0",children:[t.jsxs("div",{className:"font-medium",children:["Revision ",s.revision]}),t.jsx("div",{className:"truncate text-muted-foreground",children:s.deleted?"Override cleared":s.secret?"*".repeat(s.secretLength??0):s.value??""}),t.jsx("div",{className:"text-muted-foreground",children:new Date(s.createdAt).toLocaleStr
1ing()})]}),t.jsx(b,{type:"button",size:"sm",variant:"outline","data-testid":`config-rollback-${s.revision}`,disabled:S.isPending,onClick:()=>S.mutate(s.id),children:"Restore"})]},s.id))]}):null]},e.key)}),a.notice?t.jsx("div",{className:"rounded-lg border border-amber-500/30 bg-amber-500/5 p-4 text-sm text-muted-foreground",children:a.notice}):null,a.items.some(e=>!e.readOnly)?t.jsxs("div",{className:"flex justify-end pt-2",children:[g?t.jsx("p",{"data-testid":"runtime-config-error",className:"mr-auto text-sm text-destructive",children:g}):null,t.jsx(b,{"data-testid":`save-runtime-config-${a.title.toLowerCase().replaceAll(" ","-")}`,disabled:h.isPending||l.isLoading,onClick:()=>h.mutate(a.items),children:h.isPending?"Savingâ¦":"Save"})]}):null]})]},a.title))]})}const ge=["general","auth","payment","email","storage","ai","analytics","ads","affiliate","customer_service"];function De(){const{tab:r}=G.useParams();if(!ge.includes(r))throw Q();return t.jsx(ye,{group:r})}export{De as component};
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.