PageSourceSearch

https://eventpulse.ng/assets/CouponManagement-EISAbIKT.js

js eventpulse.ng collected 2026-10-04 01:48:19 UTC 31,015 bytes, 517 lines download raw bytes

1import{u as X,a as Z,j as e,O as ee,F as z,C as I,h as re,k as se,s as te}from"./index-CsSXqz7N.js";import{r as x}from"./vendor-react-DPmWmpvI.js";import{P as q,J as R,d as $,o as ae,av as V,S as ie,a$ as ne,aP as oe,ax as le,aI as M,C as de,m as ce,aR as me,T as pe,ap as ue}from"./vendor-ui-DBK2XfYL.js";import"./vendor-canvas-B-q-NmKy.js";import"./vendor-pdf-xZJ_zfOo.js";const he=({coupon:t,usedCount:u,revenue:N,onEdit:n,onDelete:v,onCopy:C,onCopyLink:k})=>{const a=u!==void 0?u:Number(t.usedCount||0),b=N!==void 0?N:Number(t.revenue||0),c=t.usageLimit!==void 0&&t.usageLimit!==null&&t.usageLimit!==""?Number(t.usageLimit):null,T=c?Math.min(100,a/c*100):0,f=t.status==="expired",s=c?a>=c:!1;return e.jsxs("div",{className:`coupon-card ${f?"expired":""}`,children:[e.jsxs("div",{className:"coupon-header",children:[e.jsx("div",{className:"coupon-type-badge",children:t.type==="percentage"?e.jsxs(e.Fragment,{children:[e.jsx(ne,{size:14}),e.jsxs("span",{children:[t.value,"% OFF"]})]}):e.jsxs(e.Fragment,{children:[e.jsx(V,{size:14}),e.jsxs("span",{children:["₦",t.value," OFF"]})]})}),e.jsx("button",{className:"btn-icon",onClick:()=>{},children:e.jsx(oe,{size:16})})]}),e.jsxs("div",{className:"coupon-code-section",children:[e.jsx("code",{className:"coupon-code",children:t.code}),e.jsxs("div",{style:{display:"flex",gap:"0.35rem",alignItems:"center"},children:[e.jsx("button",{className:"btn-copy",onClick:()=>C(t.code),title:"Copy Code",style:{display:"inline-flex",alignItems:"center",justifyContent:"center"},children:e.jsx(le,{size:14})}),e.jsx("button",{className:"btn-copy",onClick:()=>k(t),title:"Copy Unique Discount Link (Auto-applies for attendees)",style:{display:"inline-flex",alignItems:"center",justifyContent:"center",color:"hsl(var(--primary))",background:"hsl(var(--primary) / 0.12)"},children:e.jsx(M,{size:14})})]})]}),e.jsx("p",{className:"coupon-description",children:t.description}),t.eventName&&e.jsxs("div",{style:{marginBottom:"1rem",fontSize:"0.85rem",color:"hsl(var(--primary))",background:"hsl(var(--primary)/0.1)",padding:"0.25rem 0.5rem",borderRadius:"4px",display:"inline-block"},children:["Applies to: ",e.jsx("strong",{children:t.eventName})]}),e.jsxs("div",{className:"coupon-stats",children:[e.jsxs("div",{className:"stat-row",children:[e.jsx("span",{className:"stat-label",children:"Usage"}),e.jsxs("span",{className:"stat-value",children:[a," / ",t.usageLimit||"∞"]})]}),e.jsx("div",{className:"progress-bar",children:e.jsx("div",{className:"progress-fill",style:{width:`${T}%`,background:s?"hsl(var(--error))":"hsl(var(--primary))"}})})]}),e.jsxs("div",{className:"coupon-meta",children:[e.jsxs("div",{className:"meta-item",children:[e.jsx(de,{size:14}),e.jsxs("span",{children:["Valid until ",new Date(t.validUntil).toLocaleDateString()]})]}),e.jsxs("div",{className:"meta-item",children:[e.jsx(ce,{size:14}),e.jsxs("span",{children:["₦",b?.toLocaleString()||0," revenue"]})]})]}),e.jsxs("div",{className:"coupon-actions",children:[e.jsxs("button",{className:"btn btn-sm btn-outline",onClick:()=>k(t),style:{flex:1.2,display:"inline-flex",alignItems:"center",justifyContent:"center",gap:"0.35rem",color:"hsl(var(--primary))",borderColor:"hsl(var(--primary) / 0.4)"},title:"Copy Unique Discount Link",children:[e.jsx(M,{size:14}),e.jsx("span",{children:"Copy Link"})]}),e.jsxs("button",{className:"btn btn-sm btn-outline",onClick:()=>n(t),children:[e.jsx(me,{size:14}),e.jsx("span",{children:"Edit"})]}),e.jsxs("button",{className:"btn btn-sm btn-outline danger",onClick:()=>v(t.id),children:[e.jsx(pe,{size:14}),e.jsx("span",{children:"Delete"})]})]}),f&&e.jsx("div",{className:"expired-overlay",children:e.jsx("span",{children:"Expired"})}),s&&!f&&e.jsxs("div",{className:"fully-used-badge",children:[e.jsx($,{size:14}),e.jsx("span",{children:"Fully Used"})]})]})},ge=({isOpen:t,onClose:u,onSave:N,initialData:n,events:v=[]})=>{const[C,k]=x.useState([]),[a,b]=x.useState({code:"",type:"percentage",value:"",description:"",usageLimit:"",validFrom:"",validUntil:"",eventId:"",eventName:"",applicableTicketIds:[],requiresTicketIds:[],autoApply:!1});x.useEffect(()=>{if(t)if(n){if(b({...n,validFrom:n.validFrom?n.validFrom.split("T")[0]:"",validUntil:n.validUntil?n.validUntil.split("T")[0]:"",applicableTicketIds:n.applicableTicketIds||[]}),n.eventId){const s=v.find(o=>o.id===n.eventId);k(s&&s.tickets||[])}}else k([]),b({code:"",type:"percentage",value:"",description:"",usageLimit:"",validFrom:"",validUntil:"",eventId:"",eventName:"",applicableTicketIds:[],requiresTicketIds:[],autoApply:!1})},[n,t]);const c=s=>{const{name:o,value:m}=s.target;if(o==="eventId"){const d=v.find(p=>p.id===m);k(d&&d.tickets||[]),b(p=>({...p,eventId:m,eventName:d?d.title:"",applicableTicketIds:[]}));return}b(d=>({...d,[o]:o==="code"?m.toUpperCase():m}))},T=s=>{s.preventDefault(),N(a),u()};if(!t)return null;const f=new Date().toISOString().split("T")[0];return e.jsx("div",{className:"modal-overlay",onClick:u,children:e.jsxs("div",{className:"modal-content",onClick:s=>s.stopPropagation(),children:[e.jsxs("div",{className:"modal-header",children:[e.jsx("h2",{children:n?"Edit Coupon":"Create New Coupon"}),e.jsx("button",{className:"btn-icon",onClick:u,children:e.jsx(ue,{size:20})})]}),e.jsxs("form",{onSubmit:T,className:"coupon-form",children:[e.jsxs("div",{className:"form-group",children:[e.jsx("label",{children:"Coupon Code"}),e.jsx("input",{type:"text",name:"code",value:a.code,onChange:c,placeholder:"e.g., SUMMER2025",required:!0,disabled:!!n,style:{textTransform:"uppercase"}}),e.jsx("span",{className:"form-hint",children:"Use uppercase letters and numbers"})]}),e.jsxs("div",{className:"form-row",children:[e.jsxs("div",{className:"form-group",children:[e.jsx("label",{children:"Discount Type"}
1),e.jsxs("select",{name:"type",value:a.type,onChange:c,children:[e.jsx("option",{value:"percentage",children:"Percentage (%)"}),e.jsx("option",{value:"fixed",children:"Fixed Amount (₦)"})]})]}),e.jsxs("div",{className:"form-group",children:[e.jsx("label",{children:"Discount Value"}),e.jsx("input",{type:"number",name:"value",value:a.value,onChange:c,placeholder:a.type==="percentage"?"20":"50",required:!0,min:"1",max:a.type==="percentage"?"100":void 0})]})]}),e.jsxs("div",{className:"form-group",children:[e.jsx("label",{children:"Description"}),e.jsx("textarea",{name:"description",value:a.description,onChange:c,placeholder:"Describe when and how this coupon should be used...",rows:3})]}),e.jsxs("div",{className:"form-group",children:[e.jsx("label",{children:"Usage Limit"}),e.jsx("input",{type:"number",name:"usageLimit",value:a.usageLimit,onChange:c,placeholder:"100",required:!0,min:"1"}),e.jsx("span",{className:"form-hint",children:"Maximum number of times this coupon can be used"})]}),e.jsxs("div",{className:"form-group",children:[e.jsx("label",{children:"Applicable Event (Optional)"}),e.jsxs("select",{name:"eventId",value:a.eventId||"",onChange:c,children:[e.jsx("option",{value:"",children:"All Events (Global)"}),v.map(s=>e.jsx("option",{value:s.id,children:s.title},s.id))]}),e.jsx("span",{className:"form-hint",children:"Limit this coupon to a specific event"})]}),C.length>0&&e.jsxs("div",{className:"form-group",children:[e.jsx("label",{children:"Applicable Ticket Types"}),e.jsx("div",{style:{display:"flex",flexWrap:"wrap",gap:"0.5rem",marginTop:"0.4rem"},children:C.map(s=>{const o=(a.applicableTicketIds||[]).includes(String(s.id));return e.jsx("button",{type:"button",onClick:()=>{const m=String(s.id),d=a.applicableTicketIds||[];b(p=>({...p,applicableTicketIds:d.includes(m)?d.filter(S=>S!==m):[...d,m]}))},style:{padding:"4px 12px",borderRadius:"20px",border:"1px solid",borderColor:o?"hsl(var(--primary))":"hsl(var(--border-color))",background:o?"hsl(var(--primary))":"transparent",color:o?"white":"hsl(var(--text-main))",fontSize:"0.8rem",cursor:"pointer",transition:"all 0.15s"},children:s.name||s.title||"Ticket #"+s.id},s.id)})}),e.jsx("span",{className:"form-hint",children:(a.applicableTicketIds||[]).length===0?"No selection = applies to all ticket types":(a.applicableTicketIds||[]).length+" ticket type(s) selected"})]}),C.length>0&&e.jsxs("div",{className:"form-group",children:[e.jsxs("label",{children:["Require Ticket Combination ",e.jsx("span",{style:{fontWeight:400,color:"hsl(var(--text-dim))"},children:"(Optional — bundle deal)"})]}),e.jsx("div",{style:{display:"flex",flexWrap:"wrap",gap:"0.5rem",marginTop:"0.4rem"},children:C.map(s=>{const o=(a.requiresTicketIds||[]).includes(String(s.id));return e.jsx("button",{type:"button",onClick:()=>{const m=String(s.id),d=a.requiresTicketIds||[];b(p=>({...p,requiresTicketIds:d.includes(m)?d.filter(S=>S!==m):[...d,m]}))},style:{padding:"4px 12px",borderRadius:"20px",border:"1px solid",borderColor:o?"hsl(var(--primary))":"hsl(var(--border-color))",background:o?"hsl(var(--primary))":"transparent",color:o?"white":"hsl(var(--text-main))",fontSize:"0.8rem",cursor:"pointer",transition:"all 0.15s"},children:s.name||s.title||"Ticket #"+s.id},s.id)})}),e.jsx("span",{className:"form-hint",children:(a.requiresTicketIds||[]).length===0?"Leave empty for a normal coupon. Select the ticket types that must be bought together (e.g. Tour + Event) for a bundle discount.":"Only valid when the cart contains all "+(a.requiresTicketIds||[]).length+" selected type(s)."}),(a.requiresTicketIds||[]).length>0&&e.jsxs("div",{style:{marginTop:"0.6rem",display:"flex",alignItems:"flex-start",gap:"0.5rem"},children:[e.jsx("input",{type:"checkbox",id:"coupon-auto-apply",checked:a.autoApply===!0,onChange:s=>b(o=>({...o,autoApply:s.target.checked}
1)),style:{cursor:"pointer",width:"1rem",height:"1rem",marginTop:"0.15rem"}}),e.jsxs("label",{htmlFor:"coupon-auto-apply",style:{fontSize:"0.82rem",color:"hsl(var(--text-dim))",cursor:"pointer",lineHeight:1.4},children:[e.jsx("strong",{style:{color:"hsl(var(--text-main))"},children:"Auto-apply"})," — discount is applied automatically at checkout when the required combination is in the cart (buyer doesn't type a code)."]})]})]}),e.jsxs("div",{className:"form-row",children:[e.jsxs("div",{className:"form-group",children:[e.jsx("label",{children:"Valid From"}),e.jsx("input",{type:"date",name:"validFrom",value:a.validFrom,onChange:c,required:!0,min:f,style:{cursor:"pointer"},onClick:s=>{try{s.target.showPicker&&s.target.showPicker()}catch{}}})]}),e.jsxs("div",{className:"form-group",children:[e.jsx("label",{children:"Valid Until"}),e.jsx("input",{type:"date",name:"validUntil",value:a.validUntil,onChange:c,required:!0,min:a.validFrom||f,style:{cursor:"pointer"},onClick:s=>{try{s.target.showPicker&&s.target.showPicker()}catch{}}})]})]}),e.jsxs("div",{className:"modal-actions",children:[e.jsx("button",{type:"button",className:"btn btn-outline",onClick:u,children:"Cancel"}),e.jsx("button",{type:"submit",className:"btn btn-primary",children:n?"Save Changes":"Create Coupon"})]})]})]})})},je=()=>{const{user:t}=X(),{success:u,error:N}=Z(),[n,v]=x.useState([]),[C,k]=x.useState([]),[a,b]=x.useState({}),[c,T]=x.useState(!0),[f,s]=x.useState(""),[o,m]=x.useState("all"),[d,p]=x.useState(!1),[S,L]=x.useState(null);x.useEffect(()=>{(async()=>{if(t){T(!0);try{const i=t.role==="team_member"?t.organizerId:t.uid,l=[{field:"organizerId",operator:"==",value:i}],{data:h,error:g}=await z.getAll(I.COUPONS,l);g||v(h||[]);const w=await z.getAll(I.EVENTS,l),y=w.data||[];if(w.error||k(y),y.length>0){const j={};await Promise.all(y.map(async E=>{const U=await z.getAll(I.TICKETS,[{field:"eventId",operator:"==",value:E.id}]);U.data&&U.data.forEach(O=>{const H=(O.status||"").toLowerCase().trim(),J=["valid","confirmed","paid","checked-in","used"].includes(H),F=(O.couponCode||O.promoCode||"").trim().toUpperCase();F&&J&&(j[F]||(j[F]={usedCount:0,revenue:0}),j[F].usedCount+=1,j[F].revenue+=Number(O.price)||0)})})),b(j)}try{const E=await re(se(),"syncCouponStats")({organizerId:i});if(E.data?.updatedCouponsCount>0||E.data?.rescuedTicketsCount>0){const{data:U}=await z.getAll(I.COUPONS,l);U&&v(U)}}catch(j){console.warn("Background coupon sync error:",j)}}catch(i){console.error("Error fetching coupons:",i)}finally{T(!1)}}})()},[t]);const P=r=>{const i=(r.code||"").trim().toUpperCase(),l=a[i],h=l!==void 0?l.usedCount:Number(r.usedCount||0),g=l!==void 0?l.revenue:Number(r.revenue||0);return{usedCount:h,revenue:g}},A=n.filter(r=>{const i=r.code.toLowerCase().includes(f.toLowerCase())||r.description.toLowerCase().includes(f.toLowerCase()),l=o==="all"||r.status===o;return i&&l}),B=n.filter(r=>r.status==="active").length,D=n.reduce((r,i)=>r+P(i).revenue,0),G=n.reduce((r,i)=>r+P(i).usedCount,0),W=r=>{navigator.clipboard.writeText(r),u(`Copied code: ${r}`)},Y=r=>{const i=window.location.origin;let l="";const h=C.find(w=>w.id===r.eventId||w.slug===r.eventId),g=h?.slug||h?.id||r.eventSlug||r.eventId;g?l=`${i}/events/${g}?coupon=${encodeURIComponent(r.code)}`:l=`${i}/events?coupon=${encodeURIComponent(r.code)}`,navigator.clipboard.writeText(l),u(`Copied unique discount link for ${r.code}!`)},K=r=>{L(r),p(!0)},Q=async r=>{if(await te("Are you sure you want to delete this coupon?")){const{error:i}=await z.delete(I.COUPONS,r);i?N("Failed to delete coupon"):(v(l=>l.filter(h=>h.id!==r)),u("Coupon deleted successfully"))}},_=async r=>{if(!t)return;const i=r.usageLimit!==void 0&&r.usageLimit!==null&&r.usageLimit!==""?Number(r.usageLimit):null,l=Number(r.value||0);if(S){const h={...r,usageLimit:i,value:l},{error:g}=await z.update(I.COUPONS,S.id,h);g?N("Failed to update coupon: "+g):(v(w=>w.map(y=>y.id===S.id?{...y,...h}:y)),u("Coupon updated successfully"),p(!1),L(null))}else{const h=t.role==="team_member"?t.organizerId:t.uid,g={...r,usageLimit:i,value:l,organizerId:h,usedCount:0,status:"active",revenue:0,createdAt:new Date().toISOString()},{id:w,error:y}=await z.add(I.COUPONS,g);y?N("Failed to create coupon: "+y):(v(j=>[{...g,id:w},...j]),u("Coupon created successfully"),p(!1))}};return c?e.jsx(ee,{message:"Loading coupons..."}):e.jsxs("div",{className:"coupon-management",children:[e.jsxs("div",{className:"page-header-premium",children:[e.jsxs("div",{className:"header-text",children:[e.jsx("h1",{className:"title-premium",children:"Discounts"}),e.jsx("p",{className:"subtitle-premium hide-mobile",children:"Create and manage promotional codes for your events"})]}),e.jsx("div",{className:"header-actions-premium",children:e.jsxs("button",{className:"btn-premium-action",onClick:()=>{L(null),p(!0)},children:[e.jsx(q,{size:18}),e.jsx("span",{children:"Create Coupon"})]})})]}),e.jsxs("div",{className:"stats-grid-premium",children:[e.jsxs("div",{className:"stat-card-premium",children:[e.jsx("div",{className:"stat-icon-wrapper-premium",children:e.jsx(R,{size:20})}),e.jsxs("div",{className:"stat-info-premium",children:[e.jsx("span",{className:"stat-value-premium",children:n.length}),e.jsx("span",{className:"stat-label-premium",children:"Total Coupons"})]})]}),e.jsxs("div",{className:"stat-card-premium",children:[e.jsx("div",{className:"stat-icon-wrapper-premium success",children:e.jsx($,{size:20})}),e.jsxs("div",{className:"stat-info-premium",children:[e.jsx("span",{className:"stat-value-premium",children:B}),e.jsx("span",{className:"stat-label-premium",children:"Active"})]})]}),e.jsxs("div",{className:"stat-card-premium",children:[e.jsx("div",{className:"stat-icon-wrapper-premium primary",children:e.jsx(ae,{size:20})}),e.jsxs("div",{className:"stat-info-premium",children:[e.jsx("span",{className:"stat-value-premium",children:G}),e.jsx("span",{className:"stat-label-premium",children:"Total Uses"})]})]}),e.jsxs("div",{className:"stat-card-premium",children:[e.jsx("div",{className:"stat-icon-wrapper-premium warning",children:e.jsx(V,{size:20})}),e.jsxs("div",{className:"stat-info-premium",children:[e.jsxs("span",{className:"stat-value-premium",children:["₦",D.toLocaleStr
1ing()]}),e.jsx("span",{className:"stat-label-premium",children:"Revenue"})]})]})]}),e.jsxs("div",{className:"toolbar-premium",children:[e.jsxs("div",{className:"search-bar-premium",children:[e.jsx(ie,{size:18,className:"search-icon-premium"}),e.jsx("input",{type:"text",placeholder:"Search coupons...",value:f,onChange:r=>s(r.target.value)})]}),e.jsx("div",{className:"filter-group-premium",children:e.jsxs("select",{className:"filter-select-premium",value:o,onChange:r=>m(r.target.value),children:[e.jsx("option",{value:"all",children:"All Status"}),e.jsx("option",{value:"active",children:"Active"}),e.jsx("option",{value:"expired",children:"Expired"})]})})]}),e.jsx("div",{className:"coupons-grid",children:A.map(r=>{const{usedCount:i,revenue:l}=P(r);return e.jsx(he,{coupon:r,usedCount:i,revenue:l,onEdit:K,onDelete:Q,onCopy:W,onCopyLink:Y},r.id)})}),A.length===0&&e.jsxs("div",{className:"empty-state-premium",children:[e.jsx("div",{className:"empty-icon-wrapper",children:e.jsx(R,{size:48})}),e.jsx("h3",{children:"No coupons found"}),e.jsx("p",{children:"Create your first coupon to start offering discounts to your attendees"}),e.jsxs("button",{className:"btn-premium-action",onClick:()=>{L(null),p(!0)},children:[e.jsx(q,{size:18}),e.jsx("span",{children:"Create Coupon"})]})]}),e.jsx(ge,{isOpen:d,onClose:()=>{p(!1),L(null)},onSave:_,initialData:S,events:C}),e.jsx("style",{children:`
2        .coupon-management {
3          max-width: 1400px;
4          margin: 0 auto;
5        }
6
7        .page-header-premium {
8          display: flex;
9          justify-content: space-between;
10          align-items: center;
11          margin-bottom: 2.5rem;
12          gap: 1.5rem;
13        }
14
15        .title-premium {
16          font-size: 2.5rem;
17          font-weight: 800;
18          color: hsl(var(--text-main));
19          margin: 0;
20          letter-spacing: -0.02em;
21          background: linear-gradient(to right, hsl(var(--text-main)), hsl(var(--text-dim)));
22          -webkit-background-clip: text;
23          -webkit-text-fill-color: transparent;
24        }
25
26        .subtitle-premium {
27          color: hsl(var(--text-dim));
28          font-size: 1.1rem;
29          margin: 0.5rem 0 0 0;
30          font-weight: 500;
31        }
32
33        .btn-premium-action {
34          display: inline-flex;
35          align-items: center;
36          gap: 0.75rem;
37          background: hsl(var(--primary));
38          color: #fff;
39          border: none;
40          padding: 0.85rem 1.75rem;
41          border-radius: 16px;
42          font-weight: 800;
43          font-size: 1rem;
44          cursor: pointer;
45          transition: all 0.3s cubic-bezier(0.16, 1, 0.3, 1);
46          box-shadow: 0 8px 25px hsl(var(--primary) / 0.3);
47        }
48
49        .btn-premium-action:hover {
50          transform: translateY(-2px);
51          box-shadow: 0 12px 35px hsl(var(--primary) / 0.4);
52        }
53
54        /* Stats Grid Premium */
55        .stats-grid-premium {
56          display: grid;
57          grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
58          gap: 1.5rem;
59          margin-bottom: 3rem;
60        }
61
62        .stat-card-premium {
63          background: hsl(var(--bg-card));
64          border: 1px solid hsl(var(--border-color));
65          border-radius: 24px;
66          padding: 1.5rem;
67          display: flex;
68          align-items: center;
69          gap: 1.25rem;
70          transition: all 0.3s ease;
71        }
72
73        .stat-card-premium:hover {
74          border-color: hsl(var(--primary) / 0.3);
75          transform: translateY(-2px);
76        }
77
78        .stat-icon-wrapper-premium {
79          width: 54px;
80          height: 54px;
81          border-radius: 18px;
82          background: hsl(var(--bg-dark));
83          display: flex;
84          align-items: center;
85          justify-content: center;
86          color: hsl(var(--text-dim));
87        }
88
89        .stat-icon-wrapper-premium.success { color: hsl(var(--success)); background: hsl(var(--success) / 0.1); }
90        .stat-icon-wrapper-premium.primary { color: hsl(var(--primary)); background: hsl(var(--primary) / 0.1); }
91        .stat-icon-wrapper-premium.warning { color: hsl(var(--warning)); background: hsl(var(--warning) / 0.1); }
92
93        .stat-value-premium {
94          display: block;
95          font-size: 1.75rem;
96          font-weight: 800;
97          color: hsl(var(--text-main));
98          line-height: 1.1;
99        }
100
101        .stat-label-premium {
102          display: block;
103          font-size: 0.85rem;
104          font-weight: 600;
105          color: hsl(var(--text-dim));
106          margin-top: 0.25rem;
107        }
108
109        /* Toolbar Premium */
110        .toolbar-premium {
111          display: flex;
112          gap: 1rem;
113          margin-bottom: 2rem;
114          align-items: center;
115        }
116
117        .search-bar-premium {
118          flex: 1;
119          display: flex;
120          align-items: center;
121          background: hsl(var(--bg-card));
122          border: 1px solid hsl(var(--border-color));
123          border-radius: 16px;
124          padding: 0 1.25rem;
125          transition: all 0.2s;
126        }
127
128        .search-bar-premium:focus-within {
129          border-color: hsl(var(--primary));
130          box-shadow: 0 0 0 3px hsl(var(--primary) / 0.1);
131        }
132
133        .search-icon-premium {
134          color: hsl(var(--text-dim));
135          margin-right: 0.75rem;
136        }
137
138        .search-bar-premium input {
139          background: transparent;
140          border: none;
141          color: hsl(var(--text-main));
142          height: 48px;
143          width: 100%;
144          outline: none;
145          font-size: 0.95rem;
146        }
147
148        .filter-select-premium {
149          height: 48px;
150          padding: 0 1.25rem;
151          background: hsl(var(--bg-card));
152          border: 1px solid hsl(var(--border-color));
153          border-radius: 16px;
154          color: hsl(var(--text-main));
155          font-weight: 600;
156          cursor: pointer;
157          outline: none;
158        }
159
160        .filter-select-premium:focus {
161          border-color: hsl(var(--primary));
162        }
163
164        /* Coupons Grid */
165        .coupons-grid {
166          display: grid;
167          grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
168          gap: 1.5rem;
169          margin-bottom: 3rem;
170        }
171
172        .coupon-card {
173          background: hsl(var(--bg-card));
174          border: 1px solid hsl(var(--border-color));
175          border-radius: var(--radius-lg);
176          padding: 1.5rem;
177          position: relative;
178          transition: all 0.2s;
179        }
180
181        .coupon-card:hover {
182          transform: translateY(-2px);
183          box-shadow: var(--shadow-md);
184        }
185
186        .coupon-card.expired {
187          opacity: 0.6;
188        }
189
190        .coupon-header {
191          display: flex;
192          justify-content: space-between;
193          align-items: center;
194          margin-bottom: 1rem;
195        }
196
197        .coupon-type-badge {
198          display: inline-flex;
199          align-items: center;
200          gap: 0.375rem;
201          background: hsl(var(--primary) / 0.1);
202          color: hsl(var(--primary));
203          padding: 0.375rem 0.75rem;
204          border-radius: var(--radius-sm);
205          font-size: 0.875rem;
206          font-weight: 600;
207        }
208
209        .coupon-code-section {
210          display: flex;
211          align-items: center;
212          gap: 0.75rem;
213          margin-bottom: 1rem;
214        }
215
216        .coupon-code {
217          flex: 1;
218          background: hsl(var(--bg-dark));
219          border: 1px dashed hsl(var(--border-color));
220          padding: 0.75rem 1rem;
221          border-radius: var(--radius-md);
222          font-family: monospace;
223          font-size: 1.1rem;
224          font-weight: 700;
225          color: hsl(var(--primary));
226          letter-spacing: 0.05em;
227        }
228
229        .btn-copy {
230          background: hsl(var(--bg-hover));
231          border: 1px solid hsl(var(--border-color));
232          color: hsl(var(--text-muted));
233          width: 36px;
234          height: 36px;
235          border-radius: var(--radius-sm);
236          display: flex;
237          align-items: center;
238          justify-content: center;
239          cursor: pointer;
240          transition: all 0.2s;
241        }
242
243        .btn-copy:hover {
244          background: hsl(var(--primary) / 0.1);
245          border-color: hsl(var(--primary));
246          color: hsl(var(--primary));
247        }
248
249        .coupon-description {
250          color: hsl(var(--text-muted));
251          font-size: 0.9rem;
252          margin: 0 0 1.25rem 0;
253          line-height: 1.5;
254        }
255
256        .coupon-stats {
257          margin-bottom: 1.25rem;
258        }
259
260        .stat-row {
261          display: flex;
262          justify-content: space-between;
263          margin-bottom: 0.5rem;
264          font-size: 0.875rem;
265        }
266
267        .stat-row .stat-label {
268          color: hsl(var(--text-muted));
269        }
270
271        .stat-row .stat-value {
272          font-weight: 600;
273          font-size: 0.875rem;
274        }
275
276        .progress-bar {
277          height: 6px;
278          background: hsl(var(--bg-hover));
279          border-radius: var(--radius-sm);
280          overflow: hidden;
281        }
282
283        .progress-fill {
284          height: 100%;
285          background: hsl(var(--primary));
286          transition: width 0.3s ease;
287        }
288
289        .coupon-meta {
290          display: flex;
291          flex-direction: column;
292          gap: 0.5rem;
293          margin-bottom: 1.25rem;
294          padding-top: 1.25rem;
295          border-top: 1px solid hsl(var(--border-color));
296        }
297
298        .meta-item {
299          display: flex;
300          align-items: center;
301          gap: 0.5rem;
302          font-size: 0.85rem;
303          color: hsl(var(--text-muted));
304        }
305
306        .coupon-actions {
307          display: flex;
308          gap: 0.75rem;
309        }
310
311        .coupon-actions .btn {
312          flex: 1;
313        }
314
315        .btn.danger {
316          color: hsl(var(--error));
317          border-color: hsl(var(--error) / 0.3);
318        }
319
320        .btn.danger:hover {
321          background: hsl(var(--error) / 0.1);
322          border-color: hsl(var(--error));
323        }
324
325        .expired-overlay {
326          position: absolute;
327          top: 1rem;
328          right: 1rem;
329          background: hsl(var(--error));
330          color: white;
331          padding: 0.25rem 0.75rem;
332          border-radius: var(--radius-sm);
333          font-size: 0.75rem;
334          font-weight: 600;
335          text-transform: uppercase;
336        }
337
338        .fully-used-badge {
339          position: absolute;
340          top: 1rem;
341          right: 1rem;
342          background: hsl(var(--success));
343          color: white;
344          padding: 0.25rem 0.75rem;
345          border-radius: var(--radius-sm);
346          font-size: 0.75rem;
347          font-weight: 600;
348          display: flex;
349          align-items: center;
350          gap: 0.25rem;
351        }
352
353        /* Modal */
354        .modal-overlay {
355          position: fixed;
356          inset: 0;
357          background: rgba(0, 0, 0, 0.5);
358          display: flex;
359          align-items: center;
360          justify-content: center;
361          z-index: 1000;
362          padding: 1rem;
363        }
364
365        .modal-content {
366          background: hsl(var(--bg-card));
367          border: 1px solid hsl(var(--border-color));
368          border-radius: var(--radius-lg);
369          max-width: 600px;
370          width: 100%;
371          max-height: 90vh;
372          overflow-y: auto;
373        }
374
375        .modal-header {
376          display: flex;
377          justify-content: space-between;
378          align-items: center;
379          padding: 1.5rem;
380          border-bottom: 1px solid hsl(var(--border-color));
381        }
382
383        .modal-header h2 {
384          margin: 0;
385          font-size: 1.5rem;
386          font-weight: 700;
387        }
388
389        .coupon-form {
390          padding: 1.5rem;
391        }
392
393        .form-group {
394          margin-bottom: 1.25rem;
395        }
396
397        .form-group label {
398          display: block;
399          font-size: 0.9rem;
400          font-weight: 500;
401          margin-bottom: 0.5rem;
402          color: hsl(var(--text-muted));
403        }
404
405        .form-group input,
406        .form-group select,
407        .form-group textarea {
408          width: 100%;
409          background: hsl(var(--bg-dark));
410          border: 1px solid hsl(var(--border-color));
411          border-radius: var(--radius-md);
412          padding: 0.75rem;
413          color: hsl(var(--text-main));
414          font-size: 0.95rem;
415          transition: border-color 0.2s;
416        }
417
418        .form-group input:focus,
419        .form-group select:focus,
420        .form-group textarea:focus {
421          outline: none;
422          border-color: hsl(var(--primary));
423        }
424
425        .form-hint {
426          display: block;
427          font-size: 0.8rem;
428          color: hsl(var(--text-dim));
429          margin-top: 0.25rem;
430        }
431
432        .form-row {
433          display: grid;
434          grid-template-columns: 1fr 1fr;
435          gap: 1rem;
436        }
437
438        .modal-actions {
439          display: flex;
440          gap: 1rem;
441          justify-content: flex-end;
442          padding-top: 1.5rem;
443          border-top: 1px solid hsl(var(--border-color));
444        }
445
446        /* Empty State Premium */
447        .empty-state-premium {
448          text-align: center;
449          padding: 5rem 2rem;
450          background: hsl(var(--bg-card));
451          border: 2px dashed hsl(var(--border-color));
452          border-radius: 32px;
453          margin: 2rem 0;
454        }
455
456        .empty-icon-wrapper {
457          width: 100px;
458          height: 100px;
459          background: hsl(var(--bg-hover));
460          border-radius: 50%;
461          display: flex;
462          align-items: center;
463          justify-content: center;
464          margin: 0 auto 1.5rem;
465          color: hsl(var(--text-dim));
466        }
467
468        .empty-state-premium h3 {
469          font-size: 1.5rem;
470          font-weight: 800;
471          margin-bottom: 0.5rem;
472        }
473
474        .empty-state-premium p {
475          color: hsl(var(--text-dim));
476          margin-bottom: 2rem;
477          max-width: 400px;
478          margin-left: auto;
479          margin-right: auto;
480        }
481
482        @media (max-width: 900px) {
483          .page-header-premium {
484            flex-direction: column;
485            align-items: flex-start;
486            gap: 1.25rem;
487          }
488          .title-premium { font-size: 2.1rem; }
489          .btn-premium-action { width: 100%; justify-content: center; }
490          
491          .toolbar-premium { flex-direction: column; align-items: stretch; }
492          
493          .stats-grid-premium {
494            grid-template-columns: 1fr 1fr;
495            gap: 1rem;
496          }
497          .stat-card-premium { padding: 1.25rem; flex-direction: column; align-items: flex-start; text-align: left; }
498          .stat-icon-wrapper-premium { width: 44px; height: 44px; }
499          .stat-value-premium { font-size: 1.4rem; }
500        }
501
502        @media (max-width: 600px) {
503          .hide-mobile { display: none; }
504          .stats-grid-premium { grid-template-columns: 1fr 1fr; }
505          .stat-card-premium { padding: 1rem; }
506        }
507
508        @media (max-width: 768px) {
509          .coupons-grid {
510            grid-template-columns: 1fr;
511          }
512
513          .form-row {
514            grid-template-columns: 1fr;
515          }
516        }
517      `})]})};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.