1import{r as u,c as R,j as e}from"./vendor-react-D47JvSX0.js";import{w as V,s as m,N as q,B as x,F as J,I as r,C as N}from"./index-CyolZPlc.js";import{C as W,a as z,c as G,d as K,b as Q}from"./card-DNf18MTj.js";import{L as i}from"./label-WUQZf4s-.js";import{S as X}from"./switch-rESC2rLj.js";import{T as Y}from"./textarea-BLdnKB6Y.js";import{S as w,a as S,b as k,c as D,d as l}from"./select-D9mWH3NW.js";import{D as Z,a as ee,b as se,c as ae,d as te,e as ne}from"./dialog-BDRJmGBt.js";import{T as de,a as ie,b as T,c as p,d as oe,e as h}from"./table-BcYpMvA9.js";import{B as re}from"./badge-CsxXKVYk.js";import{V as A,A as le,b8 as ce,as as ue,aR as me,al as xe}from"./vendor-icons-CpgEi55e.js";import"./vendor-supabase-BZ1YugtK.js";import"./vendor-ui-CcHuJjDu.js";import"./vendor-utils-Dd_H0aph.js";const j=[{id:"homepage",label:"Job Featured on Homepage"},{id:"newsletter",label:"Newsletter Spotlight"},{id:"social",label:"Social Media Promotion"},{id:"company_homepage",label:"Company Featured on Homepage"}],pe=()=>({code:"",discount_type:"percent",discount_value:100,free_addon_types:[],addon_discount_type:null,addon_discount_value:0,addon_discount_addon_ids:[],max_uses:null,max_uses_per_email:1,max_uses_per_company:1,expires_at:null,is_active:!0,notes:"",allowed_email:""});function Te(){const[P,$]=u.useState(!0),[F,E]=u.useState(!1),[y,I]=u.useState([]),[a,n]=u.useState(null),[b,C]=u.useState(!1),{toast:c}=V(),v=R();u.useEffect(()=>{L()},[]);const L=async()=>{const{data:{session:s}}=await m.auth.getSession();if(!s){v("/auth");return}const{data:t}=await m.rpc("has_role",{_user_id:s.user.id,_role:"admin"});if(!t){v("/");return}E(!0),await g(),$(!1)},g=async()=>{const{data:s,error:t}=await m.from("promo_codes").select("*").order("created_at",{ascending:!1});if(t){c({title:"Failed to load",description:t.message,variant:"destructive"});return}I(s||[])},O=async()=>{var d;if(!a)return;if(!((d=a.code)!=null&&d.trim())){c({title:"Code is required",variant:"destructive"});return}C(!0);const s={code:a.code.trim().toUpperCase(),discount_type:a.discount_type,discount_value:Number(a.discount_value)||0,free_addon_types:a.free_addon_types||[],addon_discount_type:a.addon_discount_type||null,addon_discount_value:Number(a.addon_discount_value)||0,addon_discount_addon_ids:a.addon_discount_addon_ids||[],max_uses:a.max_uses??null,max_uses_per_email:a.max_uses_per_email??null,max_uses_per_company:a.max_uses_per_company??null,expires_at:a.expires_at||null,is_active:!!a.is_active,notes:a.notes||null,allowed_email:a.allowed_email||null},t=a.id?m.from("promo_codes").update(s).eq("id",a.id):m.from("promo_codes").insert(s),{error:o}=await t;if(C(!1),o){c({title:"Save failed",description:o.message,variant:"destructive"});return}c({title:a.id?"Promo code updated":"Promo code created"}),n(null),await g()},H=async s=>{if(!confirm("Delete this promo code?"))return;const{error:t}=await m.from("promo_codes").delete().eq("id",s);if(t){c({title:"Delete failed",description:t.message,variant:"destructive"});return}await g()},B=s=>{navigator.clipboard.writeText(s),c({title:"Copied",description:s})},U=s=>{const t=[];if(s.discount_type==="percent")t.push(`${s.discount_value}% off everything`);else if(s.discount_type==="fixed")t.push(`$${s.discount_value} off`);else if(s.discount_type==="free_listing")t.push("Listing free");else if(s.discount_type==="free_addons"){const o=(s.free_addon_types||[]).map(d=>{var _;return((_=j.find(f=>f.id===d))==null?void 0:_.label)||d});t.push(`Free add-ons: ${o.join(", ")||"none"}`)}if(s.addon_discount_type){const o=s.addon_discount_addon_ids||[],d=o.length===0?"all add-ons":o.map(_=>{var f;return((f=j.find(M=>M.id===_))==null?void 0:f.label)||_}).join(", ");s.addon_discount_type==="free"?t.push(`+ ${d} free`):s.addon_discount_type==="percent"?t.push(`+ ${s.addon_discount_value}% off ${d}`):s.addon_discount_type==="fixed"&&t.push(`+ $${s.addon_discount_value} off ${d}`)}return t.join(" ")||"â"};return P?e.jsx("div",{className:"min-h-screen flex items-center justify-center",children:e.jsx(A,{className:"h-8 w-8 animate-spin text-primary"})}):F?e.jsxs("div",{className:"min-h-screen flex flex-col bg-background",children:[e.jsx(q,{}),e.jsxs("main",{className:"flex-1 container mx-auto px-4 py-8 max-w-6xl",children:[e.jsxs(x,{variant:"ghost",onClick:()=>v("/admin"),className:"mb-4",children:[e.jsx(le,{className:"mr-2 h-4 w-4"}),"Back to Admin"]}),e.jsxs(W,{children:[e.jsxs(z,{className:"flex flex-row items-center justify-between",children:[e.jsxs("div",{children:[e.jsxs(G,{className:"flex items-center gap-2",children:[e.jsx(ce,{className:"h-5 w-5"})," Promo Codes"]}),e.jsx(K,{children:"Create discount codes for the Post a Job page â percent off, fixed amount off, free listing, or free add-ons."})]}),e.jsxs(x,{onClick:()=>n(pe()),children:[e.jsx(ue,{className:"mr-2 h-4 w-4"})," New Code"]})]}),e.jsx(Q,{children:y.length===0?e.jsx("p",{className:"text-sm text-muted-foreground py-8 text-center",children:"No promo codes yet. Create one to share with companies."}):e.jsxs(de,{children:[e.jsx(ie,{children:e.jsxs(T,{children:[e.jsx(p,{children:"Code"}),e.jsx(p,{children:"Discount"}),e.jsx(p,{children:"Uses"}),e.jsx(p,{children:"Expires"}),e.jsx(p,{children:"Status"}),e.jsx(p,{className:"text-right",children:"Actions"})]})}),e.jsx(oe,{children:y.map(s=>e.jsxs(T,{children:[e.jsxs(h,{className:"font-mono font-semibold",children:[e.jsxs("button",{onClick:()=>B(s.code),className:"inline-flex items-center gap-1 hover:underline",children:[s.code," ",e.jsx(me,{className:"h-3 w-3 opacity-60"})]}),s.notes&&e.jsx("div",{className:"text-xs text-muted-foreground font-sans font-normal mt-1",children:s.notes})]}),e.jsx(h,{className:"text-sm",children:U(s)}),e.jsxs(h,{className:"text-sm",children:[s.uses_count,s.max_uses!=null?` / ${s.max_uses}`:""]}),e.jsx(h,{className:"text-sm",children:s.expires_at?new Date(s.expires_at).toLocaleDateString():"â"}),e.jsx(h,{children:e.jsx(re,{variant:s.is_active?"default":"secondary",children:s.is_active?"Active":"Inactive"})}),e.jsxs(h,{className:"text-right space-x-2",children:[e.jsx(x,{size:"sm",variant:"outline",onClick:()=>n(s),children:"Edit"}),e.jsx(x,{size:"sm",variant:"destructive",onClick:()=>H(s.id),children:e.jsx(xe,{className:"h-3 w-3"})})]})]},s.id))})]})})]})]}),e.jsx(J,{}),e.jsx(Z,{open:!!a,onOpenChange:s=>!s&&n(null),children:e.jsxs(ee,{className:"max-w-lg",children:[e.jsxs(se,{children:[e.jsx(ae,{children:a!=null&&a.id?"Edit Promo Code":"New Promo Code"}),e.jsx(te,{children:"Configure how this code discounts the Post a Job checkout."})]}),a&&e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{children:[e.jsx(i,{children:"Code"}),e.jsx(r,{value:a.code||"",onChange:s=>n({...a,code:s.target.value.toUpperCase()}),placeholder:"WELCOME50",className:"uppercase font-mono"})]}),e.jsxs("div",{children:[e.jsx(i,{children:"Discount Type"}),e.jsxs(w,{value:a.discount_type,onValueChange:s=>n({...a,discount_type:s}),children:[e.jsx(S,{children:e.jsx(k,{})}),e.jsxs(D,{children:[e.jsx(l,{value:"percent",children:"% off (entire order)"}),e.jsx(l,{value:"fixed",children:"Fixed $ off"}),e.jsx(l,{value:"free_listing",children:"First listing free (100% off base plan)"}),e.jsx(l,{value:"free_addons",children:"Free selected add-ons"})]})]})]}),(a.discount_type==="percent"||a.discount_type==="fixed")&&e.jsxs("div",{children:[e.jsx(i,{children:a.discount_type==="percent"?"Percent (1-100)":"Amount in $"}),e.jsx(r,{type:"number",min:0,max:a.discount_type==="percent"?100:void 0,value:a.discount_value??0,onChange:s=>n({...a,discount_value:Number(s.target.value)})})]}),a.discount_type==="free_addons"&&e.jsxs("div",{children:[e.jsx(i,{children:"Which add-ons are free?"}),e.jsx("div",{className:"space-y-2 mt-2",children:j.map(s=>
1{const t=(a.free_addon_types||[]).includes(s.id);return e.jsxs("label",{className:"flex items-center gap-2 text-sm",children:[e.jsx(N,{checked:t,onCheckedChange:o=>{const d=new Set(a.free_addon_types||[]);o?d.add(s.id):d.delete(s.id),n({...a,free_addon_types:Array.from(d)})}}),s.label]},s.id)})})]}),e.jsxs("div",{className:"border rounded-md p-3 space-y-3 bg-muted/30",children:[e.jsxs("div",{children:[e.jsx(i,{className:"text-sm font-semibold",children:"Add-on discount (optional, stacks on top)"}),e.jsx("p",{className:"text-xs text-muted-foreground mt-1",children:'Combine the listing discount above with a separate discount on add-ons. Example: "First listing free" + "50% off Homepage Featured".'})]}),e.jsxs(w,{value:a.addon_discount_type??"none",onValueChange:s=>n({...a,addon_discount_type:s==="none"?null:s}),children:[e.jsx(S,{children:e.jsx(k,{})}),e.jsxs(D,{children:[e.jsx(l,{value:"none",children:"No extra add-on discount"}),e.jsx(l,{value:"free",children:"Selected add-ons free"}),e.jsx(l,{value:"percent",children:"% off selected add-ons"}),e.jsx(l,{value:"fixed",children:"Fixed $ off selected add-ons"})]})]}),(a.addon_discount_type==="percent"||a.addon_discount_type==="fixed")&&e.jsxs("div",{children:[e.jsx(i,{children:a.addon_discount_type==="percent"?"Percent (1-100)":"Amount in $"}),e.jsx(r,{type:"number",min:0,max:a.addon_discount_type==="percent"?100:void 0,value:a.addon_discount_value??0,onChange:s=>n({...a,addon_discount_value:Number(s.target.value)})})]}),a.addon_discount_type&&e.jsxs("div",{children:[e.jsx(i,{children:"Which add-ons does this apply to?"}),e.jsx("p",{className:"text-xs text-muted-foreground mt-1 mb-2",children:"Leave all unchecked to apply to every add-on."}),e.jsx("div",{className:"space-y-2",children:j.map(s=>{const t=(a.addon_discount_addon_ids||[]).includes(s.id);return e.jsxs("label",{className:"flex items-center gap-2 text-sm",children:[e.jsx(N,{checked:t,onCheckedChange:o=>{const d=new Set(a.addon_discount_addon_ids||[]);o?d.add(s.id):d.delete(s.id),n({...a,addon_discount_addon_ids:Array.from(d)})}}),s.label]},s.id)})})]})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[e.jsxs("div",{children:[e.jsx(i,{children:"Max total uses (optional)"}),e.jsx(r,{type:"number",min:1,value:a.max_uses??"",onChange:s=>n({...a,max_uses:s.target.value?Number(s.target.value):null}),placeholder:"Unlimited"}),e.jsx("p",{className:"text-xs text-muted-foreground mt-1",children:"Across all users combined"})]}),e.jsxs("div",{children:[e.jsx(i,{children:"Max uses per email (optional)"}),e.jsx(r,{type:"number",min:1,value:a.max_uses_per_email??"",onChange:s=>n({...a,max_uses_per_email:s.target.value?Number(s.target.value):null}),placeholder:"Unlimited"}),e.jsx("p",{className:"text-xs text-muted-foreground mt-1",children:"Per individual email address"})]}),e.jsxs("div",{children:[e.jsx(i,{children:"Max uses per company (optional)"}),e.jsx(r,{type:"number",min:1,value:a.max_uses_per_company??"",onChange:s=>n({...a,max_uses_per_company:s.target.value?Number(s.target.value):null}),placeholder:"Unlimited"}),e.jsx("p",{className:"text-xs text-muted-foreground mt-1",children:"Per company name (across all users)"})]})]}),e.jsxs("div",{children:[e.jsx(i,{children:"Expires at (optional)"}),e.jsx(r,{type:"datetime-local",value:a.expires_at?new Date(a.expires_at).toISOString().slice(0,16):"",onChange:s=>n({...a,expires_at:s.target.value?new Date(s.target.value).toISOString():null})})]}),e.jsxs("div",{children:[e.jsx(i,{children:"Restrict to email (optional)"}),e.jsx(r,{type:"email",value:a.allowed_email||"",onChange:s=>n({...a,allowed_email:s.target.value}),placeholder:"[email protected]"})]}),e.jsxs("div",{children:[e.jsx(i,{children:"Internal notes"}),e.jsx(Y,{value:a.notes||"",onChange:s=>n({...a,notes:s.target.value}),placeholder:"Outreach to Acme Inc - first listing free"})]}),e.jsxs("div",{className:"flex items-center justify-between border rounded-md p-3",children:[e.jsx(i,{className:"m-0",children:"Active"}),e.jsx(X,{checked:!!a.is_active,onCheckedChange:s=>n({...a,is_active:s})})]})]}),e.jsxs(ne,{children:[e.jsx(x,{variant:"outline",onClick:()=>n(null),children:"Cancel"}),e.jsxs(x,{onClick:O,disabled:b,children:[b&&e.jsx(A,{className:"mr-2 h-4 w-4 animate-spin"}),"Save"]})]})]})})]}):null}export{Te 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.