PageSourceSearch

https://crewops.lovable.app/assets/PromoDetail-GGSZEjmw.js

js crewops.lovable.app collected 2026-10-03 03:23:31 UTC 6,967 bytes, 1 lines download raw bytes

1import{b7 as V,u as z,r as y,ad as q,j as e,aq as E,B as P,b8 as Y,Q as S,$ as C,m as _,h as G,an as J,b9 as W,s as F,d as X,V as Z,Y as ee,U as se,aK as te,a1 as ae,K as $}from"./index-B01jGDSO.js";import{T as ne,a as re,b as B,d as ie,e as g,c as le}from"./table-B_s0nExu.js";import{u as oe}from"./useOrgQuery-JRPR4imB.js";import{L as R}from"./link-BNRasCVE.js";import{M as ce}from"./mouse-pointer-click-CAXhSaZh.js";import{A as de}from"./arrow-up-down-CydMclkM.js";function je(){const{id:n}=V(),x=z();oe();const[o,L]=y.useState(""),[a,M]=y.useState("sent_at"),[i,k]=y.useState("desc"),{data:U}=q({queryKey:["promo_campaign",n],queryFn:async()=>{if(!n)return null;const{data:s}=await $.from("promotional_campaigns").select("*").eq("id",n).single();return s},enabled:!!n}),{data:c=[]}=q({queryKey:["promo_recipients",n],queryFn:async()=>{if(!n)return[];const{data:s}=await $.from("promotional_campaign_recipients").select("*, clients(name, email)").eq("campaign_id",n).order("sent_at",{ascending:!1}).limit(500);return s??[]},enabled:!!n}),t=U,H=c.length,O=c.filter(s=>s.opened_at).length,A=c.filter(s=>s.clicked_at).length,I=t&&t.views>0?(t.bookings/t.views*100).toFixed(1):"0.0",v=t?t.original_price_cents/100:0,T=t?t.sale_price_cents/100:0,D=v>0?Math.round((v-T)/v*100):0,K=y.useMemo(()=>{let s=[...c];if(o.trim()){const r=o.toLowerCase();s=s.filter(l=>{var j,f,b,N;const d=((f=(j=l.clients)==null?void 0:j.name)==null?void 0:f.toLowerCase())||"",m=((N=(b=l.clients)==null?void 0:b.email)==null?void 0:N.toLowerCase())||"";return d.includes(r)||m.includes(r)})}return s.sort((r,l)=>{var j,f,b,N;let d,m;return a==="name"?(d=((j=r.clients)==null?void 0:j.name)||"",m=((f=l.clients)==null?void 0:f.name)||""):a==="email"?(d=((b=r.clients)==null?void 0:b.email)||"",m=((N=l.clients)==null?void 0:N.email)||""):(d=r[a]||"",m=l[a]||""),d<m?i==="asc"?-1:1:d>m?i==="asc"?1:-1:0}),s},[c,o,a,i]);function u(s){a===s?k(r=>r==="asc"?"desc":"asc"):(M(s),k("asc"))}function Q(s){return s?new Date(s).toLocaleDateString("en-US",{month:"short",day:"numeric",year:"numeric"}):"—"}function w(s){return s?new Date(s).toLocaleString("en-US",{month:"short",day:"numeric",hour:"numeric",minute:"2-digit"}):"—"}return t?e.jsx(E,{title:t.title,children:e.jsxs("div",{className:"space-y-6 max-w-5xl mx-auto",children:[e.jsxs(P,{variant:"ghost",onClick:()=>x("/marketing/promo-blast"),className:"gap-2",children:[e.jsx(Y,{className:"h-4 w-4"})," Back to Dashboard"]}),e.jsxs("div",{className:"grid md:grid-cols-[1fr_1.5fr] gap-6",children:[e.jsx(S,{children:e.jsxs(C,{className:"p-0",children:[t.promo_image_url&&e.jsx("img",{src:t.promo_image_url,alt:t.title,className:"w-full h-40 object-cover rounded-t-lg"}),e.jsxs("div",{className:"p-4 space-y-3",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("h3",{className:"font-bold text-lg",children:t.title}),e.jsx(_,{variant:t.status==="active"?"default":t.status==="ended"?"destructive":"outline",children:t.status})]}),t.description&&e.jsx("p",{className:"text-sm text-muted-foreground",children:t.description}),e.jsxs("div",{className:"flex items-baseline gap-3",children:[e.jsxs("span",{className:"text-2xl font-bold text-green-600",children:["$",T.toFixed(2)]}),e.jsxs("span",{className:"text-lg line-through text-muted-foreground",children:["$",v.toFixed(2)]}),D>0&&e.jsxs(_,{className:"bg-green-600 text-white",children:[D,"% OFF"]})]}),t.expires_at&&e.jsxs("p",{className:"text-xs text-muted-foreground flex items-center gap-1",children:[e.jsx(G,{className:"h-3.5 w-3.5"})," Expires ",Q(t.expires_at)]}),e.jsxs(P,{variant:"outline",size:"sm",className:"gap-1.5",onClick:()=>{navigator.clipboard.writeText(`${window.location.origin}/promo/${t.slug}`),J.success("Link copied!")},children:[e.jsx(R,{className:"h-3.5 w-3.5"})," Copy Link"]})]})]})}),e.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[e.jsx(h,{icon:W,label:"Page Views",value:t.views.toLocaleString()}),e.jsx(h,{icon:ce,label:"Bookings",value:t.bookings.toLocaleString()}),e.jsx(h,{icon:F,label:"Emails Sent",value:H.toLocaleString()}
1),e.jsx(h,{icon:F,label:"Emails Opened",value:O.toLocaleString()}),e.jsx(h,{icon:R,label:"Link Clicks",value:A.toLocaleString()}),e.jsx(h,{icon:X,label:"Conversion Rate",value:`${I}%`})]})]}),e.jsxs(S,{children:[e.jsx(Z,{className:"pb-3",children:e.jsxs("div",{className:"flex items-center justify-between flex-wrap gap-3",children:[e.jsxs(ee,{className:"text-base flex items-center gap-2",children:[e.jsx(se,{className:"h-4 w-4"})," Recipient Log (",c.length,")"]}),e.jsxs("div",{className:"relative w-64",children:[e.jsx(te,{className:"absolute left-2.5 top-2.5 h-4 w-4 text-muted-foreground"}),e.jsx(ae,{placeholder:"Search by name or email…",value:o,onChange:s=>L(s.target.value),className:"pl-9 h-9 text-sm"})]})]})}),e.jsx(C,{children:K.length===0?e.jsx("p",{className:"text-center py-8 text-sm text-muted-foreground",children:c.length===0?"No recipients yet.":"No results found."}):e.jsx("div",{className:"border rounded-md overflow-x-auto",children:e.jsxs(ne,{children:[e.jsx(re,{children:e.jsxs(B,{children:[e.jsx(p,{label:"Name",sortKey:"name",current:a,dir:i,onToggle:u}),e.jsx(p,{label:"Email",sortKey:"email",current:a,dir:i,onToggle:u}),e.jsx(p,{label:"Status",sortKey:"delivery_status",current:a,dir:i,onToggle:u}),e.jsx(p,{label:"Sent",sortKey:"sent_at",current:a,dir:i,onToggle:u}),e.jsx(p,{label:"Opened",sortKey:"opened_at",current:a,dir:i,onToggle:u}),e.jsx(p,{label:"Clicked",sortKey:"clicked_at",current:a,dir:i,onToggle:u})]})}),e.jsx(ie,{children:K.map(s=>{var r,l;return e.jsxs(B,{children:[e.jsx(g,{className:"font-medium",children:((r=s.clients)==null?void 0:r.name)||"—"}),e.jsx(g,{className:"text-muted-foreground",children:((l=s.clients)==null?void 0:l.email)||"—"}),e.jsx(g,{children:e.jsx(_,{variant:s.delivery_status==="sent"?"default":"outline",className:"text-xs",children:s.delivery_status})}),e.jsx(g,{className:"text-xs",children:w(s.sent_at)}),e.jsx(g,{className:"text-xs",children:w(s.opened_at)}),e.jsx(g,{className:"text-xs",children:w(s.clicked_at)})]},s.id)})})]})})})]})]})}):e.jsx(E,{title:"Promotion Details",children:e.jsx("div",{className:"flex items-center justify-center py-20 text-muted-foreground",children:"Loading…"})})}function h({icon:n,label:x,value:o}){return e.jsx(S,{children:e.jsxs(C,{className:"p-4 flex items-center gap-3",children:[e.jsx("div",{className:"p-2 rounded-lg bg-muted",children:e.jsx(n,{className:"h-4 w-4 text-primary"})}),e.jsxs("div",{children:[e.jsx("p",{className:"text-xs text-muted-foreground",children:x}),e.jsx("p",{className:"text-lg font-bold",children:o})]})]})})}function p({label:n,sortKey:x,current:o,dir:L,onToggle:a}){return e.jsx(le,{children:e.jsxs("button",{onClick:()=>a(x),className:"flex items-center gap-1 hover:text-foreground transition-colors text-xs",children:[n,e.jsx(de,{className:`h-3 w-3 ${o===x?"text-primary":"text-muted-foreground/50"}`})]})})}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.