PageSourceSearch

https://studiojungle.ai/assets/Billing-Ta75PHq3.js

js studiojungle.ai collected 2026-10-05 14:20:12 UTC 16,390 bytes, 8 lines download raw bytes

1import{c as J,u as V,F as W,a as Q,s as C,v as S,j as e,l as U,T as X}from"./index-TQG2ztjm.js";import{r as o}from"./vendor-monaco-K2VEKovO.js";import{B as m}from"./button-DtOMgFYX.js";import{P as ee,a as se}from"./progress-B3zdPJWQ.js";import{A as te}from"./arrow-left-ItJqViyp.js";import{R as re}from"./refresh-cw-643fMIYJ.js";import{E as ae}from"./external-link-1cYqniwe.js";import{S as $}from"./sparkles-DXp1XtxN.js";import{L as y}from"./loader-circle-9UcafR3w.js";import{C as ne}from"./credit-card-_BGqL_0-.js";import{C as F}from"./check-DX1qY1zh.js";import{B as ie}from"./building-2-JQVWg13i.js";import{Z as le}from"./zap-p1HVi94e.js";import{S as oe}from"./shield-_9vMyv1d.js";import{C as ce}from"./crown-B3SdS7fn.js";import"./vendor-swagger-Bf7V8oR3.js";/**
2 * @license lucide-react v0.462.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 de=J("Coins",[["circle",{cx:"8",cy:"8",r:"6",key:"3yglwk"}],["path",{d:"M18.09 10.37A6 6 0 1 1 10.34 18",key:"t5s6rm"}],["path",{d:"M7 6h1v4",key:"1obek4"}],["path",{d:"m16.71 13.88.7.71-2.82 2.82",key:"1rbuyh"}]]),_=[{id:"starter",name:"Starter",price:25,monthlyCredits:100,description:"For solo builders shipping their first app.",icon:le,features:["100 AI credits / month","1 published cloud project","Cloud rollback","Top-up packs available"]},{id:"pro",name:"Pro",price:99,monthlyCredits:200,description:"For serious builders who need power and flexibility.",icon:oe,features:["200 AI credits / month","Premium reasoning unlocked","5 published cloud projects","Priority queue (faster compute)","Vercel + GitHub deploy"]},{id:"studio",name:"Studio",price:299,monthlyCredits:500,description:"For teams building production-grade apps at scale.",icon:ce,features:["500 AI credits / month","Premium reasoning by default","Unlimited cloud projects","Priority email support","Custom integrations on request"]}],me=[{id:"pack-50",credits:50,price:10},{id:"pack-150",credits:150,price:25},{id:"pack-500",credits:500,price:75}];function Pe(){const x=V(),[f]=W(),{user:c,loading:P}=Q(),[t,D]=o.useState(null),[L,w]=o.useState(!0),[u,b]=o.useState(null),[E,A]=o.useState(!1);o.useEffect(()=>{!P&&!c&&x("/auth?redirect=/studio/billing")},[P,c,x]);const v=o.useCallback(async s=>{if(!c)return;s!=null&&s.silent?A(!0):w(!0);const{data:a,error:r}=await C.from("user_credits").select("balance, monthly_grant, monthly_granted_at, total_consumed, total_purchased, plan, trial_ends_at").eq("user_id",c.id).maybeSingle();r&&(console.warn("[billing] fetch user_credits failed:",r.message),S({title:"Could not load credit balance",description:r.message})),D(a),w(!1),A(!1)},[c]);o.useEffect(()=>{if(!c)return;let s=!1;return w(!0),(async()=>await v())(),()=>{s=!0}},[c,v]);const I=f.get("checkout"),z=f.get("plan"),n=_.find(s=>s.id===z)??null,O=f.get("tier")??"0",M=f.get("billing")??"monthly",h=(t==null?void 0:t.plan)??"none",q=h==="starter"||h==="pro"||h==="studio",j=h==="trial",T=q?h:"none",i=_.find(s=>s.id===T)??null,R=I==="subscription_canceled"||I==="canceled",g=(t==null?void 0:t.balance)??0,d=(t==null?void 0:t.monthly_grant)??0,H=Math.min(g,d),G=Math.max(0,g-d),K=Math.max((t==null?void 0:t.total_consumed)??0,d>0?d-H:0),Y=d>0?Math.min(100,Math.round(g/d*100)):0,N=o.useMemo(()=>{if(!(t!=null&&t.monthly_granted_at))return null;const a=new Date(t.monthly_granted_at).getTime()+30*24*60*60*1e3,r=Math.ceil((a-Date.now())/(24*60*60*1e3));return Math.max(0,r)},[t==null?void 0:t.monthly_granted_at]),k=async s=>{const a=s.packId??s.planId??"checkout";b(a);try{const{data:r,error:l}=await C.functions.invoke("create-checkout",{body:s}),p=(r==null?void 0:r.error)||(l==null?void 0:l.message),B=r==null?void 0:r.hint;if(p)throw new Error(B?`${p}
7
8Hint: ${B}`:p);if(r!=null&&r.url){window.location.href=r.url;return}throw new Error("No checkout URL returned")}catch(r){const l=r instanceof Error?r.message:"Unknown error";S({title:"Checkout failed",description:l,variant:"destructive",duration:12e3}),b(null)}},Z=async()=>{b("portal");try{const{data:s,error:a}=await C.functions.invoke("customer-portal",{});if(a)throw new Error(a.message);if(s!=null&&s.error)throw new Error(s.error);if(s!=null&&s.url){window.location.href=s.url;return}throw new Error("No portal URL returned")}catch(s){const a=s instanceof Error?s.message:"Unknown error";S({title:"Could not open billing portal",description:a,variant:"destructive"}),b(null)}};return e.jsx("div",{className:"min-h-screen bg-background text-foreground",children:e.jsxs("div",{className:"max-w-6xl mx-auto px-4 sm:px-6 py-8",children:[e.jsxs("div",{className:"mb-8 rounded-2xl border bg-card/80 p-4 shadow-sm sm:p-5",children:[e.jsxs("div",{className:"mb-5 flex flex-wrap items-center justify-between gap-3",children:[e.jsxs("button",{onClick:()=>x("/studio"),className:"inline-flex items-center gap-2 rounded-lg border bg-background px-3 py-2 text-[13px] font-medium text-foreground shadow-sm transition-colors hover:bg-secondary/70",children:[e.jsx(te,{className:"h-3.5 w-3.5"}),"Back to Studio"]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs(m,{variant:"outline",size:"sm",onClick:()=>v({silent:!0}),disabled:E||L,className:"gap-1.5",children:[e.jsx(re,{className:U("h-3.5 w-3.5",E&&"animate-spin")}),"Refresh"]}),e.jsxs("a",{href:"https://docs.studiojungle.ai/",target:"_blank",rel:"noopener noreferrer",className:"inline-flex items-center gap-1.5 rounded-lg border bg-background px-3 py-2 text-[13px] font-medium text-muted-foreground shadow-sm transition-colors hover:bg-secondary/70 hover:text-foreground",children:[e.jsx(ae,{className:"h-3.5 w-3.5"})," Docs"]})]})]}),e.jsxs("div",{className:"flex flex-col gap-4 sm:flex-row sm:items-end sm:justify-between",children:[e.jsxs("div",{children:[e.jsxs("div",{className:"mb-2 inline-flex items-center gap-2 rounded-full bg-primary/10 px-2.5 py-1 text-[11px] font-semibold uppercase tracking-wide text-primary",children:[e.jsx($,{className:"h-3.5 w-3.5"}),"Account billing"]}),e.jsx("h1",{className:"text-2xl font-semibold tracking-tight sm:text-3xl",children:"Plans & credits"}),e.jsx("p",{className:"mt-1.5 max-w-xl text-sm text-muted-foreground",children:"Manage your subscription, credit balance, and monthly reset from one place."})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-2 sm:min-w-[260px]",children:[e.jsxs("div",{className:"rounded-xl border bg-secondary/30 px-3 py-2",children:[e.jsx("p",{className:"text-[11px] text-muted-foreground",children:"Current plan"}),e.jsx("p",{className:"text-sm font-semibold",children:i?i.name:j?"Trial":"No plan"})]}),e.jsxs("div",{className:"rounded-xl border bg-secondary/30 px-3 py-2",children:[e.jsx("p",{className:"text-[11px] text-muted-foreground",children:"Balance"}),e.jsxs("p",{className:"text-sm font-semibold tabular-nums",children:[g.toLocaleStr
8ing()," credits"]})]})]})]})]}),L?e.jsxs("div",{className:"flex items-center justify-center py-20 text-muted-foreground",children:[e.jsx(y,{className:"w-5 h-5 animate-spin mr-2"}),"Loading your plan…"]}):e.jsxs(e.Fragment,{children:[R&&!i&&e.jsx("div",{className:"mb-6 rounded-2xl border border-destructive/25 bg-destructive/5 p-4 shadow-sm",children:e.jsxs("div",{className:"flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between",children:[e.jsxs("div",{className:"flex gap-3",children:[e.jsx("div",{className:"flex h-10 w-10 shrink-0 items-center justify-center rounded-xl bg-destructive/10 text-destructive",children:e.jsx(X,{className:"h-5 w-5"})}),e.jsxs("div",{children:[e.jsx("h2",{className:"text-base font-semibold tracking-tight",children:"Payment was not completed"}),e.jsx("p",{className:"mt-1 max-w-2xl text-sm leading-6 text-muted-foreground",children:"Your Studio Jungle account is saved, but the subscription is not active yet. Finish checkout to unlock monthly credits, publishing, and paid plan features."}),n&&e.jsxs("p",{className:"mt-2 text-xs font-medium text-foreground/80",children:["Pending plan: ",n.name," · ",M]})]})]}),e.jsxs("div",{className:"flex shrink-0 flex-col gap-2 sm:min-w-[210px]",children:[e.jsxs(m,{onClick:()=>k({planId:(n==null?void 0:n.id)??"pro",tier:O,billingCycle:M}),disabled:u===((n==null?void 0:n.id)??"pro"),className:"gap-2",children:[u===((n==null?void 0:n.id)??"pro")?e.jsx(y,{className:"h-4 w-4 animate-spin"}):e.jsx(ne,{className:"h-4 w-4"}),"Finish payment"]}),e.jsx(m,{variant:"outline",onClick:()=>x("/pricing"),children:"Choose another plan"})]})]})}),j&&!i&&!R&&e.jsx("div",{className:"mb-6 rounded-2xl border border-primary/20 bg-primary/5 p-4 shadow-sm",children:e.jsxs("div",{className:"flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"text-base font-semibold tracking-tight",children:"Trial account"}),e.jsx("p",{className:"mt-1 text-sm text-muted-foreground",children:"Add a plan before the trial ends to keep builds, publishing, and monthly credits active."})]}),e.jsx(m,{onClick:()=>x("/pricing"),className:"shrink-0",children:"Pick a plan"})]})}),e.jsxs("div",{className:"grid grid-cols-1 lg:grid-cols-2 gap-4 mb-10",children:[e.jsxs("div",{className:"rounded-2xl border bg-secondary/30 p-5",children:[e.jsxs("div",{className:"flex items-start gap-3",children:[e.jsx("div",{className:"w-9 h-9 rounded-xl bg-primary/10 flex items-center justify-center shrink-0",children:e.jsx($,{className:"w-4 h-4 text-primary"})}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("p",{className:"text-[13px] text-muted-foreground",children:"You're on"}),e.jsx("h2",{className:"text-lg font-semibold tracking-tight",children:i?`${i.name} plan`:j?"Trial account":"No active plan"}),i&&e.jsx("p",{className:"text-[12px] text-muted-foreground mt-0.5",children:N!==null?`Renews in ${N} days`:"Active"}),j&&(t==null?void 0:t.trial_ends_at)&&e.jsxs("p",{className:"text-[12px] text-muted-foreground mt-0.5",children:["Trial ends ",new Date(t.trial_ends_at).toLocaleDateString(void 0,{month:"short",day:"numeric"})]})]})]}),i&&e.jsx("ul",{className:"mt-4 space-y-1.5",children:i.features.slice(0,3).map(s=>e.jsxs("li",{className:"flex items-center gap-2 text-[13px] text-foreground/85",children:[e.jsx(F,{className:"w-3.5 h-3.5 text-primary shrink-0"}),s]},s))}),e.jsx("div",{className:"mt-5 flex items-center gap-2",children:i?e.jsxs(m,{variant:"outline",size:"sm",onClick:Z,disabled:u==="portal",className:"gap-1.5",children:[u==="portal"?e.jsx(y,{className:"w-3.5 h-3.5 animate-spin"}):null,"Manage subscription"]}):e.jsx("p",{className:"text-[12px] text-muted-foreground",children:"Pick a plan below to start."})})]}),e.jsxs("div",{className:"rounded-2xl border bg-secondary/30 p-5",children:[e.jsxs("div",{className:"flex items-start justify-between gap-2 mb-2",children:[e.jsxs("div",{children:[e.jsx("p",{className:"text-[13px] text-muted-foreground",children:"Credits remaining"}),e.jsx("p",{className:"text-3xl font-semibold tabular-nums tracking-tight mt-0.5",children:g.toLocaleStr
8ing()})]}),e.jsx("div",{className:"w-9 h-9 rounded-xl bg-primary/10 flex items-center justify-center shrink-0",children:e.jsx(de,{className:"w-4 h-4 text-primary"})})]}),e.jsx(ee,{value:Y,className:"h-1.5 mt-2"}),e.jsxs("div",{className:"mt-4 grid grid-cols-2 gap-3 text-[12px] sm:grid-cols-4",children:[e.jsxs("div",{className:"rounded-xl border bg-background/70 p-3",children:[e.jsx("p",{className:"text-muted-foreground",children:"Used tracked"}),e.jsx("p",{className:"mt-1 text-lg font-semibold text-foreground tabular-nums",children:K.toLocaleString()})]}),e.jsxs("div",{className:"rounded-xl border bg-background/70 p-3",children:[e.jsx("p",{className:"text-muted-foreground",children:"Monthly included"}),e.jsx("p",{className:"mt-1 text-lg font-semibold text-foreground tabular-nums",children:d.toLocaleString()})]}),e.jsxs("div",{className:"rounded-xl border bg-background/70 p-3",children:[e.jsx("p",{className:"text-muted-foreground",children:"Extra credits"}),e.jsx("p",{className:"mt-1 text-lg font-semibold text-foreground tabular-nums",children:G.toLocaleString()})]}),e.jsxs("div",{className:"rounded-xl border bg-background/70 p-3",children:[e.jsx("p",{className:"text-muted-foreground",children:"Resets"}),e.jsx("p",{className:"mt-1 text-sm font-semibold text-foreground",children:N!==null?`in ${N} days`:"—"})]})]}),e.jsx("p",{className:"mt-3 text-[11px] leading-relaxed text-muted-foreground",children:"Extra/top-up credits are included in your balance and do not reset with the monthly plan grant."})]})]}),e.jsxs("section",{className:"mb-10",children:[e.jsx("div",{className:"flex items-center justify-between mb-3",children:e.jsxs("div",{children:[e.jsx("h3",{className:"text-[15px] font-semibold tracking-tight",children:"Top up credits"}),e.jsx("p",{className:"text-[12px] text-muted-foreground mt-0.5",children:"One-off packs for extra builds. Added immediately after Stripe confirms payment."})]})}),e.jsx("div",{className:"grid grid-cols-1 sm:grid-cols-3 gap-3",children:me.map(s=>e.jsxs("button",{type:"button",onClick:()=>k({packId:s.id}),disabled:u===s.id,className:"group text-left rounded-xl border bg-card p-4 hover:border-primary/30 hover:shadow-sm transition-all disabled:opacity-60",children:[e.jsxs("div",{className:"flex items-center justify-between mb-2",children:[e.jsxs("span",{className:"text-[20px] font-semibold tabular-nums tracking-tight",children:["+",s.credits.toLocaleString()]}),e.jsx(se,{className:"w-4 h-4 text-muted-foreground group-hover:text-primary transition-colors"})]}),e.jsx("p",{className:"text-[12px] text-muted-foreground mb-3",children:"credits"}),e.jsxs("p",{className:"text-[13px] font-medium",children:["$",s.price," ",e.jsx("span",{className:"text-muted-foreground font-normal",children:"one-time"})]})]},s.id))})]}),e.jsxs("section",{children:[e.jsxs("div",{className:"mb-3",children:[e.jsx("h3",{className:"text-[15px] font-semibold tracking-tight",children:i?"Switch or upgrade your plan":"Pick a plan"}),e.jsx("p",{className:"text-[12px] text-muted-foreground mt-0.5",children:"Subscriptions renew monthly. Cancel anytime from the Stripe portal."})]}),e.jsx("div",{className:"grid grid-cols-1 md:grid-cols-3 gap-4",children:_.map(s=>{const a=s.id===T,r=s.icon,l=u===s.id;return e.jsxs("div",{className:U("rounded-2xl border bg-card p-5 flex flex-col",a&&"ring-2 ring-primary/30 border-primary/40"),children:[e.jsxs("div",{className:"flex items-center gap-2 mb-1.5",children:[e.jsx(r,{className:"w-4 h-4 text-primary"}),e.jsx("h4",{className:"text-[15px] font-semibold tracking-tight",children:s.name}),a&&e.jsx("span",{className:"ml-auto text-[10px] font-semibold uppercase tracking-wider text-primary bg-primary/10 px-1.5 py-0.5 rounded",children:"Current"})]}),e.jsx("p",{className:"text-[12px] text-muted-foreground leading-snug mb-4",children:s.description}),e.jsxs("div",{className:"flex items-baseline gap-1 mb-4",children:[e.jsxs("span",{className:"text-2xl font-semibold tabular-nums tracking-tight",children:["$",s.price]}),e.jsx("span",{className:"text-[12px] text-muted-foreground",children:"/ month"})]}),e.jsx("ul",{className:"space-y-1.5 mb-5 flex-1",children:s.features.map(p=>e.jsxs("li",{className:"flex items-start gap-2 text-[12.5px] text-foreground
8/85",children:[e.jsx(F,{className:"w-3.5 h-3.5 text-primary shrink-0 mt-0.5"}),e.jsx("span",{children:p})]},p))}),e.jsxs(m,{variant:a?"outline":"default",size:"sm",onClick:()=>k({planId:s.id}),disabled:l||a,className:"w-full gap-1.5",children:[l&&e.jsx(y,{className:"w-3.5 h-3.5 animate-spin"}),a?"Current plan":`Upgrade to ${s.name}`]})]},s.id)})}),e.jsxs("div",{className:"mt-4 rounded-2xl border bg-card p-5 flex flex-col sm:flex-row items-start sm:items-center gap-3 justify-between",children:[e.jsxs("div",{className:"flex items-start gap-3",children:[e.jsx("div",{className:"w-9 h-9 rounded-xl bg-primary/10 flex items-center justify-center shrink-0",children:e.jsx(ie,{className:"w-4 h-4 text-primary"})}),e.jsxs("div",{children:[e.jsx("h4",{className:"text-[14px] font-semibold tracking-tight",children:"Enterprise"}),e.jsx("p",{className:"text-[12px] text-muted-foreground mt-0.5 max-w-xl",children:"Bring your own keys, database, and cloud. SOC 2, SSO, audit logs, dedicated support."})]})]}),e.jsx(m,{variant:"outline",size:"sm",onClick:()=>x("/sales"),className:"shrink-0",children:"Talk to sales"})]})]})]})]})})}export{Pe 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.