1import{j as t,B as h,K as y}from"./index-B0cTFD4s.js";import{r as l}from"./router-BvNiAcqA.js";import{S as ue}from"./Sidebar-CLJqG-KW.js";import{H as me}from"./Header-CU60gd0V.js";import{C}from"./card-BD-yHdhS.js";import{I as c}from"./input-DPLyZNju.js";import{S as _}from"./switch-C5C834aF.js";import{T as f}from"./textarea-B3c_8qKR.js";import{a as pe,b as he,e as ye,f as _e}from"./adminApi-DCQ_Penl.js";import"./layout-dashboard-C3WopaTg.js";import"./zap-BhxVQWmx.js";import"./credit-card-BRIDQY_J.js";import"./chevron-left-CzvR3Mam.js";import"./index-uNNyWAB_.js";function xe(o){try{return JSON.stringify(o??{},null,2)}catch{return"{}"}}function le(o){const p=(o??"").trim();if(!p)return{};try{return JSON.parse(p)}catch{throw new Error("Invalid JSON in features")}}function N(o){return(Number(o??0)/100).toFixed(2)}function j(o){const p=(o??"").trim(),x=Number(p===""?"0":p);if(!Number.isFinite(x)||x<0)throw new Error("Price must be a number >= 0");return Math.round(x*100)}const Je=()=>{const[o,p]=l.useState(!0),[x,S]=l.useState(!1),[w,g]=l.useState([]),[k,M]=l.useState(""),[D,P]=l.useState(""),[E,J]=l.useState(""),[U,Y]=l.useState("{}"),[A,O]=l.useState("0.00"),[F,$]=l.useState("0.00"),[z,T]=l.useState("0"),[H,R]=l.useState("0"),[q,I]=l.useState("0"),[B,L]=l.useState(!1),[K,V]=l.useState(""),[G,Q]=l.useState(""),[W,X]=l.useState(!0),[Z,ee]=l.useState(!1),[te,se]=l.useState("0"),[v,d]=l.useState({}),re=async()=>{S(!0);try{const e=await pe(o);g(e)}catch(e){y({title:"Failed to load plans",description:e!=null&&e.detail?JSON.stringify(e.detail):"Unknown error",variant:"destructive"})}finally{S(!1)}};l.useEffect(()=>{re()}
1,[o]);const b=l.useMemo(()=>[...w].sort((e,i)=>{const a=Number(e.sort_order??0),n=Number(i.sort_order??0);return a!==n?a-n:(e.slug??"").localeCompare(i.slug??"")}),[w]),ce=e=>{d(i=>({...i,[e.id]:{id:e.id,slug:e.slug??"",name:e.name??"",description:e.description??"",featuresJson:xe(e.features),monthly_price_usd:N(e.monthly_price_cents),yearly_price_usd:N(e.yearly_price_cents),monthly_credits:String(e.monthly_credits??0),yearly_credits:String(e.yearly_credits??0),discount_percent:String(e.discount_percent??0),is_popular:!!e.is_popular,stripe_price_id_monthly:e.stripe_price_id_monthly??"",stripe_price_id_yearly:e.stripe_price_id_yearly??"",is_active:!!e.is_active,is_default:!!e.is_default,sort_order:String(e.sort_order??0)}}))},ie=e=>{d(i=>{const a={...i};return delete a[e],a})},de=async e=>{const i=v[e];if(i)try{const a=le(i.featuresJson),n=Number(i.discount_percent);if(!Number.isFinite(n)||n<0||n>100)throw new Error("Discount must be a number between 0 and 100");const r={slug:i.slug.trim(),name:i.name.trim(),description:i.description.trim()||null,features:a,monthly_price_cents:j(i.monthly_price_usd),yearly_price_cents:j(i.yearly_price_usd),monthly_credits:Number(i.monthly_credits),yearly_credits:Number(i.yearly_credits),discount_percent:n,is_popular:i.is_popular,stripe_price_id_monthly:i.stripe_price_id_monthly.trim()||null,stripe_price_id_yearly:i.stripe_price_id_yearly.trim()||null,is_active:i.is_active,is_default:i.is_default,sort_order:Number(i.sort_order)};if(!r.slug)throw new Error("Slug is required");if(!r.name)throw new Error("Name is required");if([r.monthly_price_cents,r.yearly_price_cents,r.monthly_credits,r.yearly_credits,r.sort_order].some(m=>!Number.isFinite(m)||m<0))throw new Error("Prices/credits/sort_order must be numbers >= 0");const u=await ye(e,r);g(m=>m.map(ne=>ne.id===e?u:ne)),ie(e),y({title:"Updated plan",description:u.slug})}catch(a){y({title:"Update failed",description:(a==null?void 0:a.message)??(a!=null&&a.detail?JSON.stringify(a.detail):"Unknown error"),variant:"destructive"})}},oe=async()=>{try{const e=k.trim(),i=D.trim();if(!e)throw new Error("Slug is required");if(!i)throw new Error("Name is required");const a=le(U),n=Number(q);if(!Number.isFinite(n)||n<0||n>100)throw new Error("Discount must be a number between 0 and 100");const r={slug:e,name:i,description:E.trim()||null,features:a,monthly_price_cents:j(A),yearly_price_cents:j(F),monthly_credits:Number(z),yearly_credits:Number(H),discount_percent:n,is_popular:B,stripe_price_id_monthly:K.trim()||null,stripe_price_id_yearly:G.trim()||null,is_active:W,is_default:Z,sort_order:Number(te)};if([r.monthly_price_cents,r.yearly_price_cents,r.monthly_credits,r.yearly_credits,r.sort_order].some(m=>!Number.isFinite(m)||m<0))throw new Error("Prices/credits/sort_order must be numbers >= 0");const u=await he(r);g(m=>[...m,u]),M(""),P(""),J(""),Y("{}"),O("0.00"),$("0.00"),T("0"),R("0"),I("0"),L(!1),V(""),Q(""),X(!0),ee(!1),se("0"),y({title:"Created plan",description:u.slug})}catch(e){y({title:"Create failed",description:(e==null?void 0:e.message)??(e!=null&&e.detail?JSON.stringify(e.detail):"Unknown error"),variant:"destructive"})}},ae=async(e,i=!1)=>{const a=w.find(s=>s.id===e),n=(a==null?void 0:a.slug)??e;if(window.confirm(i?`Hard delete "${n}"? This cannot be undone.`:`Disable "${n}" (soft delete)? You can re-enable by editing and turning Active on.`))try{await _e(e,i),g(i?s=>s.filter(u=>u.id!==e):s=>s.map(u=>u.id===e?{...u,is_active:!1}:u)),y({title:i?"Hard deleted":"Disabled",description:n})}catch(s){y({title:"Delete failed",description:s!=null&&s.detail?JSON.stringify(s.detail):"Unknown error",variant:"destructive"})}};return t.jsxs("div",{className:"min-h-screen bg-background",children:[t.jsx("div",{className:"fixed left-0 top-0 h-screen w-64 border-r bg-background z-40",children:t.jsx(ue,{})}),t.jsxs("div",{className:"ml-64 flex min-h-screen flex-col",children:[t.jsx(me,{title:"Subscription Plans",subtitle:"View, add, update and delete subscription plans."}),t.jsxs("main",{className:"flex-1 overflow-y-auto p-6 space-y-6",children:[t.jsx(C,{className:"p-4",children:t.jsxs("div",{className:"flex items-center justify-between gap-4 flex-wrap",children:[t.jsxs("div",{className:"flex items-center gap-3",children:[t.jsx(_,{checked:o,onCheckedChange:p}),t.jsx("span",{className:"text-sm text-muted-foreground",children:"Include inactive"})]}),t.jsx(h,{variant:"secondary",onClick:re,disabled:x,children:x?"Refreshingâ¦":"Refresh"})]})}),t.jsxs(C,{className:"p-4 space-y-4",children:[t.jsx("h2",{className:"text-base font-semibold",children:"Add Plan"}),t.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-3 gap-3",children:[t.jsx(c,{placeholder:"slug (e.g. free, pro)",value:k,onChange:e=>M(e.target.value)}),t.jsx(c,{placeholder:"name",value:D,onChange:e=>P(e.target.value)}),t.jsx(c,{placeholder:"sort_order",inputMode:"numeric",value:te,onChange:e=>se(e.target.value)})]}),t.jsx(f,{placeholder:"description (optional)",value:E,onChange:e=>J(e.target.value),rows:2}),t.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-4 gap-3",children:[t.jsx(c,{placeholder:"Monthly price (USD) e.g. 9.99",inputMode:"decimal",value:A,onChange:e=>O(e.target.value)}),t.jsx(c,{placeholder:"Yearly price (USD) e.g. 99.99",inputMode:"decimal",value:F,onChange:e=>$(e.target.value)}),t.jsx(c,{placeholder:"monthly_credits",inputMode:"numeric",value:z,onChange:e=>T(e.target.value)}),t.jsx(c,{placeholder:"yearly_credits",inputMode:"numeric",value:H,onChange:e=>R(e.target.value)})]}),t.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-4 gap-3",children:[t.jsx(c,{placeholder:"discount_percent (0..100)",inputMode:"numeric",value:q,onChange:e=>I(e.target.value)}),t.jsxs("div",{className:"flex items-center gap-2",children:[t.jsx(_,{checked:B,onCheckedChange:L}),t.jsx("span",{className:"text-sm text-muted-foreground",children:"Popular"})]}),t.jsxs("div",{className:"flex items-center gap-2",children:[t.jsx(_,{checked:W,onCheckedChange:X}),t.jsx("span",{className:"text-sm text-muted-foreground",children:"Active"})]}),t.jsxs("div",{className:"flex items-center gap-2",children:[t.jsx(_,{checked:Z,onCheckedChange:ee}),t.jsx("span",{className:"text-sm text-muted-foreground",children:"Default"})]})]}),t.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-3",children:[t.jsx(c,{placeholder:"stripe_price_id_monthly (optional)",value:K,onChange:e=>V(e.target.value)}),t.jsx(c,{placeholder:"stripe_price_id_yearly (optional)",value:G,onChange:e=>Q(e.target.value)})]}),t.jsx(f,{placeholder:'features JSON (optional). Example: {"watermark":false,"support":"community"}',value:U,onChange:e=>Y(e.target.value),rows:6}),t.jsx("div",{className:"flex justify-end",children:t.jsx(h,{onClick:oe,children:"Create"})})]}),t.jsxs(C,{className:"p-4",children:[t.jsxs("div",{className:"flex items-center justify-between mb-4",children:[t.jsx("h2",{className:"text-base font-semibold",children:"Plans"}),t.jsxs("span",{className:"text-sm text-muted-foreground",children:[b.length," rows"]})]}),t.jsx("div",{className:"overflow-auto",children:t.jsxs("table",{className:"w-full text-sm",children:[t.jsx("thead",{className:"text-left text-muted-foreground",children:t.jsxs("tr",{className:"border-b",children:[t.jsx("th",{className:"py-2 pr-3",children:"Slug"}),t.jsx("th",{className:"py-2 pr-3",children:"Name"}),t.jsx("th",{className:"py-2 pr-3 w-24",children:"Default"}),t.jsx("th",{className:"py-2 pr-3 w-20",children:"Active"}),t.jsx("th",{className:"py-2 pr-3 w-24",children:"Popular"}),t.jsx("th",{className:"py-2 pr-3 w-28",children:"Discount"}),t.jsx("th",{className:"py-2 pr-3 w-28",children:"Monthly (USD)"}),t.jsx("th",{className:"py-2 pr-3 w-28",children:"Yearly (USD)"}),t.jsx("th",{className:"py-2 pr-3 w-40",children:"Credits (M/Y)"}),t.jsx("th",{className:"py-2 pr-3 w-56",children:"Updated"}),t.jsx("th",{className:"py-2 pr-3 w-64",children:"Actions"})]})}),t.jsxs("tbody",{children:[b.map(e=>{const i=!!v[e.id],a=v[e.id],n=e;return t.jsxs("tr",{className:"border-b align-top",children:[t.jsx("td",{className:"py-2 pr-3 font-medium",children:i?t.jsx(c,{value:a.slug,onChange:r=>d(s=>({...s,[e.id]:{...s[e.id],slug:r.target.value}}))}):n.slug}),t.jsx("td",{className:"py-2 pr-3",children:i?t.jsxs("div",{className:"space-y-2",children:[t.jsx(c,{value:a.name,onChange:r=>d(s=>({...s,[e.id]:{...s[e.id],name:r.target.value}}))}),t.jsx(f,{value:a.description,rows:2,onChange:r=>d(s=>({...s,[e.id]:{...s[e.id],description:r.target.value}})),placeholder:"description"}),t.jsx(f,{value:a.featuresJson,rows:6,onChange:r=>d(s=>({...s,[e.id]:{...s[e.id],featuresJson:r.target.value}})),placeholder:"features JSON"})]}):t.jsxs("div",{className:"space-y-1",children:[t.jsx("div",{className:"font-medium",children:n.name}),n.description&&t.jsx("div",{className:"text-xs text-muted-foreground",children:n.description})]})}),t.jsx("td",{className:"py-2 pr-3",children:i?t.jsx(_,{checked:a.is_default,onCheckedChange:r=>d(s=>({...s,[e.id]:{...s[e.id],is_default:r}}))}):t.jsx("span",{className:n.is_default?"text-foreground":"text-muted-foreground",children:n.is_default?"Yes":"No"})}),t.jsx("td",{className:"py-2 pr-3",children:i?t.jsx(_,{checked:a.is_active,onCheckedChange:r=>d(s=>({...s,[e.id]:{...s[e.id],is_active:r}}))}):t.jsx("span",{className:n.is_active?"text-foreground":"text-muted-foreground",children:n.is_active?"Yes":"No"})}),t.jsx("td",{className:"py-2 pr-3",children:i?t.jsx(_,{checked:a.is_popular,onCheckedChange:r=>d(s=>({...s,[e.id]:{...s[e.id],is_popular:r}}))}):t.jsx("span",{className:n.is_popular?"text-foreground":"text-muted-foreground",children:n.is_popular?"Yes":"No"})}),t.jsx("td",{className:"py-2 pr-3",children:i?t.jsx(c,{inputMode:"numeric",value:a.discount_percent,onChange:r=>d(s=>({...s,[e.id]:{...s[e.id],discount_percent:r.target.value}})),placeholder:"0..100"}):t.jsxs("span",{children:[Number(n.discount_percent??0),"%"]})}),t.jsx("td",{className:"py-2 pr-3",children:i?t.jsx(c,{inputMode:"decimal",value:a.monthly_price_usd,onChange:r=>d(s=>({...s,[e.id]:{...s[e.id],monthly_price_usd:r.target.value}})),placeholder:"e.g. 9.99"}):`$${N(n.monthly_price_cents)}`}),t.jsx("td",{className:"py-2 pr-3",children:i?t.jsx(c,{inputMode:"decimal",value:a.yearly_price_usd,onChange:r=>d(s=>({...s,[e.id]:{...s[e.id],yearly_price_usd:r.target.value}})),placeholder:"e.g. 99.99"}):`$${N(n.yearly_price_cents)}`}),t.jsx("td",{className:"py-2 pr-3",children:i?t.jsxs("div",{className:"grid grid-cols-2 gap-2",children:[t.jsx(c,{inputMode:"numeric",value:a.monthly_credits,onChange:r=>d(s=>({...s,[e.id]:{...s[e.id],monthly_credits:r.target.value}})),placeholder:"monthly"}),t.jsx(c,{inputMode:"numeric",value:a.yearly_credits,onChange:r=>d(s=>({...s,[e.id]:{...s[e.id],yearly_credits:r.target.value}})),placeholder:"yearly"}),t.jsx(c,{inputMode:"numeric",value:a.sort_order,onChange:r=>d(s=>({...s,[e.id]:{...s[e.id],sort_order:r.target.value}})),placeholder:"sort_order"}),t.jsx(c,{value:a.stripe_price_id_monthly,onChange:r=>d(s=>
1({...s,[e.id]:{...s[e.id],stripe_price_id_monthly:r.target.value}})),placeholder:"stripe monthly"}),t.jsx(c,{value:a.stripe_price_id_yearly,onChange:r=>d(s=>({...s,[e.id]:{...s[e.id],stripe_price_id_yearly:r.target.value}})),placeholder:"stripe yearly"})]}):`${n.monthly_credits}/${n.yearly_credits}`}),t.jsx("td",{className:"py-2 pr-3 text-muted-foreground",children:n.updated_at?new Date(n.updated_at).toLocaleString():"-"}),t.jsx("td",{className:"py-2 pr-3",children:t.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[i?t.jsxs(t.Fragment,{children:[t.jsx(h,{size:"sm",onClick:()=>de(e.id),children:"Save"}),t.jsx(h,{variant:"secondary",size:"sm",onClick:()=>ie(e.id),children:"Cancel"})]}):t.jsx(h,{variant:"secondary",size:"sm",onClick:()=>ce(e),children:"Edit"}),t.jsx(h,{variant:"outline",size:"sm",onClick:()=>ae(e.id,!1),children:"Disable"}),t.jsx(h,{variant:"destructive",size:"sm",onClick:()=>ae(e.id,!0),children:"Hard delete"})]})})]},e.id)}),b.length===0&&t.jsx("tr",{children:t.jsx("td",{colSpan:11,className:"py-6 text-center text-muted-foreground",children:"No plans found."})})]})]})})]})]})]})]})};export{Je as default};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.