1(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[3557],{81098:function(e,t,s){(window.__NEXT_P=window.__NEXT_P||[]).push(["/admin/coupons",function(){return s(80488)}])},43765:function(e,t,s){"use strict";s.d(t,{Z:function(){return a}});let a=(0,s(63759).Z)("AlertCircle",[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["line",{x1:"12",x2:"12",y1:"8",y2:"12",key:"1pkeuh"}],["line",{x1:"12",x2:"12.01",y1:"16",y2:"16",key:"4dfq90"}]])},60493:function(e,t,s){"use strict";s.d(t,{Z:function(){return a}});let a=(0,s(63759).Z)("CheckCircle",[["path",{d:"M22 11.08V12a10 10 0 1 1-5.93-9.14",key:"g774vq"}],["path",{d:"m9 11 3 3L22 4",key:"1pflzl"}]])},4270:function(e,t,s){"use strict";s.d(t,{Z:function(){return a}});let a=(0,s(63759).Z)("Plus",[["path",{d:"M5 12h14",key:"1ays0h"}],["path",{d:"M12 5v14",key:"s699le"}]])},44976:function(e,t,s){"use strict";s.d(t,{Z:function(){return a}});let a=(0,s(63759).Z)("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"}]])},21603:function(e,t,s){"use strict";s.d(t,{Z:function(){return a}});let a=(0,s(63759).Z)("Tag",[["path",{d:"M12 2H2v10l9.29 9.29c.94.94 2.48.94 3.42 0l6.58-6.58c.94-.94.94-2.48 0-3.42L12 2Z",key:"14b2ls"}],["path",{d:"M7 7h.01",key:"7u93v4"}]])},9475:function(e,t,s){"use strict";s.d(t,{Z:function(){return a}});let a=(0,s(63759).Z)("XCircle",[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"m15 9-6 6",key:"1uzhvr"}],["path",{d:"m9 9 6 6",key:"z0biqf"}]])},80488:function(e,t,s){"use strict";s.r(t),s.d(t,{default:function(){return y}});var a=s(85893),n=s(67294),l=s(9008),c=s.n(l),i=s(11163),r=s(85412),o=s(67694),d=s(92761),u=s(21603),p=s(44976),m=s(4270),x=s(43765),h=s(60493),b=s(9475);let g={code:"",name:"",description:"",discountType:"percent",discountValue:20,duration:"once",durationInMonths:3,validDays:30,maxRedemptions:"",userEligibility:"all_users",applicablePlans:[],isActive:!0};function y(){let{theme:e}=(0,o.F)(),t=(0,i.useRouter)(),s="dark"===e,[l,y]=(0,n.useState)(""),[f,j]=(0,n.useState)([]),[N,v]=(0,n.use
1State)(!0),[w,k]=(0,n.useState)(""),[C,S]=(0,n.useState)(""),[_,E]=(0,n.useState)(!1),[A,P]=(0,n.useState)(null),[Z,R]=(0,n.useState)(g),[T,M]=(0,n.useState)(!1),U=s?"bg-[#15171b] border border-white/10":"bg-white border border-gray-200 shadow-sm",F=s?"text-gray-100":"text-gray-900",D=s?"text-gray-400":"text-gray-500",V=s?"bg-[#1A1A1B] border-[#343536] text-white":"bg-white border-gray-300 text-gray-900",O=e=>({"Content-Type":"application/json","x-admin-key":e}),I=async e=>{v(!0);try{let t=await fetch("/api/admin/coupons",{headers:{"x-admin-key":e}});if(!t.ok)throw Error("Failed to load coupons");let s=await t.json();j(s.coupons||[]),k("")}catch(e){k(e.message||"Failed to load")}finally{v(!1)}};(0,n.useEffect)(()=>{let e=localStorage.getItem("admin_key");if(!e){t.replace("/admin");return}y(e),I(e)},[t]);let L=e=>{P(e._id),R({code:e.code,name:e.name,description:e.description||"",discountType:e.discountType,discountValue:(e.discountType,e.discountValue),duration:e.duration,durationInMonths:e.durationInMonths||3,validDays:Math.max(1,Math.ceil((new Date(e.validUntil).getTime()-Date.now())/864e5)),maxRedemptions:e.maxRedemptions?String(e.maxRedemptions):"",userEligibility:e.userEligibility||(e.firstTimeUserOnly?"new_users":"all_users"),applicablePlans:e.applicablePlans||[],isActive:e.isActive}),E(!0)},q=async()=>{if(l){M(!0),k(""),S("");try{let e={...Z,discountValue:Number(Z.discountValue),maxRedemptions:Z.maxRedemptions?Number(Z.maxRedemptions):void 0,...A?{id:A}:{}},t=await fetch("/api/admin/coupons",{method:A?"PUT":"POST",headers:O(l),body:JSON.stringify(e)}),s=await t.json();if(!t.ok)throw Error(s.error||s.message||"Save failed");S(A?"Coupon updated and synced to Stripe":"Coupon created and synced to Stripe"),E(!1),await I(l)}catch(e){k(e.message||"Save failed")}finally{M(!1)}}},z=async e=>{if(l)try{if(!(await fetch("/api/admin/coupons",{method:"PATCH",headers:O(l),body:JSON.stringify({id:e._id,isActive:!e.isActive})})).ok)throw Error("Update failed");await I(l)}catch(e){k(e.message)}},H=e=>"percent"===e.discountType?"".concat(e.discountValue,"%"):"$".concat((e.discountValue/100).toFixed(2));return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(c(),{children:(0,a.jsx)("title",{children:"Coupon Codes â Admin"})}),(0,a.jsx)(r.Z,{}),(0,a.jsx)("div",{className:"min-h-screen pt-20 pb-12 px-4 ".concat(s?"bg-[#0b0d10]":"bg-gray-50"),children:(0,a.jsxs)("div",{className:"max-w-6xl mx-auto",children:[(0,a.jsxs)("button",{onClick:()=>t.push("/admin"),className:"flex items-center gap-2 text-sm mb-4 ".concat(D," hover:underline"),children:[(0,a.jsx)(d.Z,{className:"w-4 h-4"})," Back to admin"]}),(0,a.jsxs)("div",{className:"flex flex-wrap items-center justify-between gap-4 mb-6",children:[(0,a.jsxs)("div",{children:[(0,a.jsxs)("h1",{className:"text-2xl font-bold flex items-center gap-2 ".concat(F),children:[(0,a.jsx)(u.Z,{className:"w-7 h-7 text-[#FF4500]"}),"Coupon codes"]}),(0,a.jsx)("p",{className:"text-sm mt-1 ".concat(D),children:"Configure offers here â synced to Stripe for checkout. Payments stay on Stripe."})]}),(0,a.jsxs)("div",{className:"flex gap-2",children:[(0,a.jsx)("button",{onClick:()=>l&&I(l),className:"p-2 rounded-lg border ".concat(U),title:"Refresh",children:(0,a.jsx)(p.Z,{className:"w-4 h-4"})}),(0,a.jsxs)("button",{onClick:()=>{P(null),R(g),E(!0)},className:"flex items-center gap-2 px-4 py-2 rounded-lg bg-[#FF4500] text-white font-semibold text-sm",children:[(0,a.jsx)(m.Z,{className:"w-4 h-4"})," New coupon"]})]})]}),(0,a.jsxs)("div",{className:"p-4 rounded-xl mb-6 text-sm ".concat(s?"bg-blue-900/20 border border-blue-800/40 text-blue-200":"bg-blue-50 border border-blue-200 text-blue-900"),children:[(0,a.jsx)("strong",{children:"Stripe + TrueResume:"})," Rules (who can use, plans, dates) are set here. Users apply codes in the upgrade modal (Apply â Upgrade). The Stripe payment page has ",(0,a.jsx)("strong",{children:"no promo code field"})," â the discount is pre-applied automatically."]}),w&&(0,a.jsxs)("div",{className:"mb-4 p-3 rounded-lg bg-red-500/10 border border-red-500/30 text-red-400 text-sm flex items-center gap-2",children:[(0,a.jsx)(x.Z,{className:"w-4 h-4 shrink-0"})," ",w]}),C&&(0,a.jsxs)("div",{className:"mb-4 p-3 rounded-lg bg-emerald-500/10 border border-emerald-500/30 text-emerald-400 text-sm flex items-center gap-2",children:[(0,a.jsx)(h.Z,{className:"w-4 h-4 shrink-0"})," ",C]}),_&&(0,a.jsxs)("div",{className:"p-6 rounded-2xl mb-6 ".concat(U),children:[(0,a.jsx)("h2",{className:"font-bold mb-4 ".concat(F),children:A?"Edit coupon":"Create coupon"}),(0,a.jsxs)("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-4",children:[(0,a.jsxs)("label",{className:"block",children:[(0,a.jsx)("span",{className:"text-xs font-semibold ".concat(D),children:"Code *"}),(0,a.jsx)("input",{className:"mt-1 w-full px-3 py-2 rounded-lg border text-sm ".concat(V),value:Z.code,onChange:e=>R({...Z,code:e.target.value.toUpperCase()}),placeholder:"LAUNCH20",disabled:!!A})]}),(0,a.jsxs)("label",{className:"block",children:[(0,a.jsx)("span",{className:"text-xs font-semibold ".concat(D),children:"Display name *"}),(0,a.jsx)("input",{className:"mt-1 w-full px-3 py-2 rounded-lg border text-sm ".concat(V),value:Z.name,onChange:e=>R({...Z,name:e.target.value})})]}),(0,a.jsxs)("label",{className:"block md:col-span-2",children:[(0,a.jsx)("span",{className:"text-xs font-semibold ".concat(D),children:"Description"}),(0,a.jsx)("input",{className:"mt-1 w-full px-3 py-2 rounded-lg border text-sm ".concat(V),value:Z.description,onChange:e=>R({...Z,description:e.target.value})})]}),(0,a.jsxs)("label",{className:"block",children:[(0,a.jsx)("span",{className:"text-xs font-semibold ".concat(D),children:"Discount type"}),(0,a.jsxs)("select",{className:"mt-1 w-full px-3 py-2 rounded-lg border text-sm ".concat(V),value:Z.discountType,onCh
1ange:e=>R({...Z,discountType:e.target.value}),children:[(0,a.jsx)("option",{value:"percent",children:"Percent off"}),(0,a.jsx)("option",{value:"amount",children:"Fixed amount (cents)"})]})]}),(0,a.jsxs)("label",{className:"block",children:[(0,a.jsx)("span",{className:"text-xs font-semibold ".concat(D),children:"percent"===Z.discountType?"Percent (1â100)":"Amount in cents"}),(0,a.jsx)("input",{type:"number",className:"mt-1 w-full px-3 py-2 rounded-lg border text-sm ".concat(V),value:Z.discountValue,onChange:e=>R({...Z,discountValue:Number(e.target.value)})})]}),(0,a.jsxs)("label",{className:"block",children:[(0,a.jsx)("span",{className:"text-xs font-semibold ".concat(D),children:"Valid for (days from now)"}),(0,a.jsx)("input",{type:"number",min:1,className:"mt-1 w-full px-3 py-2 rounded-lg border text-sm ".concat(V),value:Z.validDays,onChange:e=>R({...Z,validDays:Number(e.target.value)})})]}),(0,a.jsxs)("label",{className:"block",children:[(0,a.jsx)("span",{className:"text-xs font-semibold ".concat(D),children:"Max redemptions (optional)"}),(0,a.jsx)("input",{type:"number",min:1,className:"mt-1 w-full px-3 py-2 rounded-lg border text-sm ".concat(V),value:Z.maxRedemptions,onChange:e=>R({...Z,maxRedemptions:e.target.value}),placeholder:"Unlimited"})]}),(0,a.jsxs)("label",{className:"block",children:[(0,a.jsx)("span",{className:"text-xs font-semibold ".concat(D),children:"Duration"}),(0,a.jsxs)("select",{className:"mt-1 w-full px-3 py-2 rounded-lg border text-sm ".concat(V),value:Z.duration,onChange:e=>R({...Z,duration:e.target.value}),children:[(0,a.jsx)("option",{value:"once",children:"Once (first invoice)"}),(0,a.jsx)("option",{value:"repeating",children:"Repeating months"}),(0,a.jsx)("option",{value:"forever",children:"Forever"})]})]}),"repeating"===Z.duration&&(0,a.jsxs)("label",{className:"block",children:[(0,a.jsx)("span",{className:"text-xs font-semibold ".concat(D),children:"Months"}),(0,a.jsx)("input",{type:"number",min:1,max:36,className:"mt-1 w-full px-3 py-2 rounded-lg border text-sm ".concat(V),value:Z.durationInMonths,onChange:e=>R({...Z,durationInMonths:Number(e.target.value)})})]}),(0,a.jsxs)("label",{className:"block md:col-span-2",children:[(0,a.jsx)("span",{className:"text-xs font-semibold ".concat(D),children:"Who can use this coupon?"}),(0,a.jsxs)("select",{className:"mt-1 w-full px-3 py-2 rounded-lg border text-sm ".concat(V),value:Z.userEligibility,onChange:e=>R({...Z,userEligibility:e.target.value}),children:[(0,a.jsx)("option",{value:"all_users",children:"All users (new + returning) â Stripe page + upgrade modal"}),(0,a.jsx)("option",{value:"new_users",children:"New users only â never subscribed to Pro/Enterprise"}),(0,a.jsx)("option",{value:"returning_users",children:"Returning users only â previously had Pro/Enterprise"})]}),(0,a.jsxs)("p",{className:"mt-1 text-[11px] ".concat(D),children:["all_users"===Z.userEligibility&&"Anyone eligible. Users Apply in upgrade modal, then Upgrade â discount is pre-applied on Stripe.","new_users"===Z.userEligibility&&"Upgrade modal only. Free users with a Stripe customer id still qualify.","returning_users"===Z.userEligibility&&"Upgrade modal only. For win-back / loyalty offers."]})]}),(0,a.jsxs)("div",{className:"md:col-span-2",children:[(0,a.jsx)("span",{className:"text-xs font-semibold ".concat(D),children:"Applicable plans (empty = all paid)"}),(0,a.jsx)("div",{className:"flex gap-4 mt-2",children:["pro","enterprise"].map(e=>(0,a.jsxs)("label",{className:"flex items-center gap-2",children:[(0,a.jsx)("input",{type:"checkbox",checked:Z.applicablePlans.includes(e),onChange:t=>{let s=t.target.checked?[...Z.applicablePlans,e]:Z.applicablePlans.filter(t=>t!==e);R({...Z,applicablePlans:s})}}),(0,a.jsx)("span",{className:"text-sm capitalize ".concat(F),children:e})]},e))})]})]}),(0,a.jsxs)("div",{className:"flex gap-2 mt-6",children:[(0,a.jsx)("button",{onClick:q,disabled:T,className:"px-4 py-2 rounded-lg bg-[#FF4500] text-white font-semibold text-sm disabled:opacity-50",children:T?"Savingâ¦":"Save & sync to Stripe"}),(0,a.jsx)("button",{onClick:()=>E(!1),className:"px-4 py-2 rounded-lg border text-sm ".concat(U),children:"Cancel"})]})]}),(0,a.jsx)("div",{className:"rounded-2xl overflow-hidden ".concat(U),children:N?(0,a.jsx)("p",{className:"p-8 text-center ".concat(D),children:"Loadingâ¦"}):0===f.length?(0,a.jsx)("p",{className:"p-8 text-center ".concat(D),children:"No coupons yet. Create one to get started."}):(0,a.jsx)("div",{className:"overflow-x-auto",children:(0,a.jsxs)("table",{className:"w-full text-sm",children:[(0,a.jsx)("thead",{className:s?"bg-white/5":"bg-gray-50",children:(0,a.jsxs)("tr",{children:[(0,a.jsx)("th",{className:"text-left p-3 ".concat(D),children:"Code"}),(0,a.jsx)("th",{className:"text-left p-3 ".concat(D),children:"Discount"}),(0,a.jsx)("th",{className:"text-left p-3 ".concat(D),children:"Valid until"}),(0,a.jsx)("th",{className:"text-left p-3 ".concat(D),children:"Used"}),(0,a.jsx)("th",{className:"text-left p-3 ".concat(D),children:"Rules"}),(0,a.jsx)("th",{className:"text-left p-3 ".concat(D),children:"Stripe"}),(0,a.jsx)("th",{className:"text-left p-3 ".concat(D),children:"Status"}),(0,a.jsx)("th",{className:"text-left p-3 ".concat(D),children:"Actions"})]})}),(0,a.jsx)("tbody",{children:f.map(e=>{var t;return(0,a.jsxs)("tr",{className:s?"border-t border-white/10":"border-t border-gray-100",children:[(0,a.jsx)("td",{className:"p-3 font-mono font-semibold ".concat(F),children:e.code}),(0,a.jsx)("td",{className:"p-3 ".concat(F),children:H(e)}),(0,a.jsx)("td",{className:"p-3 ".concat(D),children:new Date(e.validUntil).toLocaleDateString()}),(0,a.jsxs)("td",{className:"p-3 ".concat(F),children:[e.redemptionCount,e.maxRedemptions?" / ".concat(e.maxRedemptions):""]}),(0,a.jsxs)("td",{className:"p-3 ".concat(D," text-xs"),children:[(0,a.jsxs)("div",{children:["Users:"," ","returning_users"===e.userEligibility?"Returning only":"new_users"===e.userEligibility||e.firstTimeUserOnly?"New only":"All users"]}),(null===(t=e.applicablePlans)||void 0===t?void 0:t.length)>0&&(0,a.jsxs)("div",{children:["Plans: ",e.applicablePlans.join(", ")
1]}),(0,a.jsx)("div",{children:"Upgrade modal only"})]}),(0,a.jsxs)("td",{className:"p-3",children:[e.stripeCouponId?(0,a.jsx)("span",{title:e.stripePromotionCodeId?"Stripe coupon + public code":"Stripe coupon (modal-only)",children:(0,a.jsx)(h.Z,{className:"w-4 h-4 text-emerald-500"})}):(0,a.jsx)(b.Z,{className:"w-4 h-4 text-red-500"}),e.syncError&&(0,a.jsx)("span",{className:"block text-[10px] text-red-400 mt-1",children:e.syncError})]}),(0,a.jsx)("td",{className:"p-3",children:(0,a.jsx)("span",{className:"px-2 py-0.5 rounded-full text-xs font-semibold ".concat(e.isActive?"bg-emerald-500/20 text-emerald-400":"bg-gray-500/20 text-gray-400"),children:e.isActive?"Active":"Off"})}),(0,a.jsx)("td",{className:"p-3",children:(0,a.jsxs)("div",{className:"flex gap-2",children:[(0,a.jsx)("button",{onClick:()=>L(e),className:"text-xs text-[#FF4500] hover:underline",children:"Edit"}),(0,a.jsx)("button",{onClick:()=>z(e),className:"text-xs text-gray-400 hover:underline",children:e.isActive?"Disable":"Enable"})]})})]},e._id)})})]})})})]})})]})}}},function(e){e.O(0,[4968,1296,5412,2888,9774,179],function(){return e(e.s=81098)}),_N_E=e.O()}]);
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.