PageSourceSearch

https://rubpage.com/assets/ModerationPage-Ckgf2Wje.js

js rubpage.com collected 2026-10-02 19:37:35 UTC 19,156 bytes, 1 lines download raw bytes

1import{a as oe,j as e}from"./vendor-query-nkyHp8gL.js";import{r as h,f as ce,L as me}from"./vendor-react-BNT0nzvx.js";import{D as xe,c as ue}from"./DashboardLayout-BwqfxABs.js";import{n as he,o as pe,p as fe,q as ge,r as je,j as ve}from"./use-admin-DyDskQ2r.js";import{i as Ne,O as ye,B as l,X as G,n as be,y as H,G as we,x as w,r as Z,o as _e,s as g}from"./index-UlqsakHc.js";import{c as Ce}from"./country-flag-S6YMbNwt.js";import{A as P,h as L,a as I,b as T,c as B,d as q,e as U,f as F,g as M}from"./alert-dialog-Cot7QkN9.js";import{D as ke,b as Se,c as De,d as Ae}from"./dialog-DV4xISIc.js";import{C as R}from"./checkbox-D_YIIhgX.js";import{S}from"./shield-check-D_dnqQxv.js";import{C as Ee}from"./chevron-up-DVkSX4kh.js";import{E as $e}from"./eye-Ca0Gb1H3.js";import{T as ze}from"./trash-2-omFn8pi_.js";import{P as Pe}from"./phone-CROm9Gxj.js";import{M as Le}from"./mail-bMhm6fVu.js";import{G as Ie}from"./globe-D5yIUDNO.js";import{C as Te}from"./calendar-BFyvQri4.js";import{Z as Be}from"./zap-BAJFvq0y.js";import{E as qe}from"./external-link-BXpInyWx.js";import"./input-otp-zCOwu37W.js";import"./shield-DMA6z9Kg.js";import"./chevron-right-Cm0QdkHJ.js";import"./mail-check-B9b1HxOk.js";import"./users-C1fVyj3Z.js";import"./newspaper-DDM9CgLF.js";import"./crown-DVNd9quJ.js";import"./target-nBqdJqET.js";import"./list-CEIXZF2y.js";import"./flag-CwDWn1bT.js";import"./vendor-ui-DPPUfW-O.js";import"./vendor-charts-B_MCcq71.js";import"./vendor-supabase-BRDBMtg7.js";import"./index-DcdyMenS.js";import"./check-7w7r-eFz.js";const Ue=[{key:"",label:"All"},{key:"live",label:"Live"},{key:"draft",label:"Draft"},{key:"featured",label:"Featured"},{key:"expired",label:"Expired"}],V=o=>o?new Date(o).toLocaleDateString():"—",Fe=50,Me=({email:o})=>{const[f,j]=h.useState(null);return h.useEffect(()=>{o&&g.from("competitor_leads").select("source_domain, status").eq("email",o).limit(1).maybeSingle().then(({data:v})=>{v?.source_domain&&j(v.source_domain)})},[o]),f?e.jsx("p",{className:"text-xs mt-1",children:e.jsxs("span",{className:"inline-flex items-center gap-1 px-2 py-0.5 rounded-full bg-primary/10 text-primary font-medium",children:["Converted from ",f]})}):null},Ve=({advertiserId:o})=>{const[f,j]=h.useState(null);return h.useEffect(()=>{o&&g.from("wallets").select("balance, total_spent").eq("user_id",o).maybeSingle().then(({data:v})=>{v&&j(v)})},[o]),o?f?e.jsxs("div",{className:"space-y-1 text-xs",children:[e.jsxs("p",{className:"text-muted-foreground",children:["Balance: ",e.jsxs("span",{className:"text-foreground font-medium",children:["$",f.balance.toFixed(2)]})]}),e.jsxs("p",{className:"text-muted-foreground",children:["Total spent: ",e.jsxs("span",{className:"text-foreground font-medium",children:["$",f.total_spent.toFixed(2)]})]})]}):e.jsx("p",{className:"text-xs text-muted-foreground",children:"Loading..."}):e.jsx("p",{className:"text-xs text-muted-foreground italic",children:"No owner"})},ws=()=>{const[o,f]=h.useState(""),[j,v]=h.useState(""),[_,C]=h.useState(0),[x,N]=h.useState(new Set),{data:m,isLoading:W}=he(o||void 0,j||void 0,_),{data:D}=pe(o||void 0,j||void 0),Q=fe(),A=ge(),E=je(),X=ve(),{toast:n}=Ne(),y=oe(),Y=ce(),[p,$]=h.useState(null),[J,ee]=h.useState(null),z=Math.ceil((D??0)/Fe),se=s=>{N(t=>{const r=new Set(t);return r.has(s)?r.delete(s):r.add(s),r})},te=()=>{if(!m)return;const s=m.map(r=>r.id),t=s.every(r=>x.has(r));N(t?new Set:new Set(s))},re=async()=>{const s=Array.from(x);try{for(const t of s)await Q.mutateAsync(t);n({title:`${s.length} listings deleted`}),N(new Set)}catch(t){n({title:"Error",description:t.message,variant:"destructive"})}},ae=async()=>{if(!m)return;const s=[...new Set(m.filter(t=>x.has(t.id)&&t.advertiser_id).map(t=>t.advertiser_id))];try{for(const t of s)await X.mutateAsync(t);n({title:`${s.length} user(s) permanently banned and all data deleted`}),N(new Set)}catch(t){n({title:"Error",description:t.message,variant:"destructive"})}},O=async()=>{await Promise.all([y.invalidateQueries({queryKey:["admin-users"]}),y.invalidateQueries({queryKey:["admin-user-count"]}),y.invalidateQueries({queryKey:["admin-listings"]}),y.invalidateQueries({queryKey:["admin-listing-count"]}),y.invalidateQueries({queryKey:["admin-user-listings"]})])},k=async(s,t)=>{const r=Array.from(x);try{if(s==="verified"&&m){const a=[...new Set(m.filter(u=>r.includes(u.id)&&u.advertiser_id).map(u=>u.advertiser_id))];if(a.length===0){n({title:"No advertiser found for selected listings",variant:"destructive"});return}const i=new Date().toISOString(),[{error:c},{error:d}]=await Promise.all([g.from("profiles").update({verified:t,updated_at:i}).in("id",a),g.from("listings").update({verified:t,updated_at:i}).in("advertiser_id",a)]);if(c)throw c;if(d)throw d;await O()}else for(const a of r){const i={[s]:t};s==="published"&&t===!1&&(i.featured=!1),await A.mutateAsync({listingId:a,updates:i})}n({title:`${r.length} listings updated`}),N(new Set)}catch(a){n({title:"Error",description:a.message,variant:"destructive"})}},b=async(s,t,r,a)=>{try{if(t==="verified"&&a?.advertiser_id){const i=!r,c=new Date().toISOString(),[{error:d},{error:u}]=await Promise.all([g.from("profiles").update({verified:i,updated_at:c}).eq("id",a.advertiser_id),g.from("listings").update({verified:i,updated_at:c}).eq("advertiser_id",a.advertiser_id)]);if(d)throw d;if(u)throw u;await O(),i?(n({title:`✅ "${w(a.title)}" advertiser verified`}),g.functions.invoke("send-email",{body:{action:"listing-verified",userId:a.advertiser_id,listingTitle:a.title,listingSlug:a.slug}}).catch(le=>console.error("Failed to send verified email:",le))):n({title:"Verification removed"})}else{const i={[t]:!r};t==="published"&&r===!0&&(i.featured=!1),await A.mutateAsync({listingId:s,updates:i}),n({title:`${t} toggled`})}}catch(i){n({title:"Error",description:i.message,variant:"destructive"})}},K=async(s,t)=>{try{await E.mutateAsync({listingId:s,days:t}),n({title:`Expiry extended by ${t} days`})}catch(r){n({title:"Error",description:r.message,variant:"destructive"})}},ie=async(s,t)=>{const r=[...s.images??[]],a=r.splice(t,1);try{if(a[0]?.includes("listing-images")){const i=a[0].split("listing-images/")[1];i&&await g.storage.from("listing-images").remove([i])}await A.mutateAsync({listingId:s.id,updates:{images:r}}),$({...s,images:r}),n({title:"Photo removed"})}catch(i){n({title:"Error",description:i.message,variant:"destructive"})}},ne=async s=>{try{await Q.mutateAsync(s),n({title:"Listing deleted"})}catch(t){n({title:"Error",description:t.message,variant:"destructive"})}},de=m&&m.length>0&&m.every(s=>x.has(s.id));return e.jsxs(xe,{children:[e.jsxs("h1",{className:"text-xl font-medium text-foreground mb-4",children:["Listing Moderation (",D??0,")"]}),e.jsxs("div",{className:"flex flex-col sm:flex-row gap-3 mb-4",children:[e.jsxs("div",{className:"relative max-w-sm flex-1",children:[e.jsx(ye,{className:"absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground"}),e.jsx("input",{value:o,onChange:s=>{f(s.target.value),C(0)},placeholder:"Search title, email, name...",className:"w-full pl-9 pr-3 py-2 rounded-lg border border-border bg-background text-sm"})]}),e.jsx("div",{className:"flex gap-1",children:Ue.map(s=>e.jsx("button",{onClick:()=>{v(s.key),C(0)},className:`px-3 py-1.5 rounded-md text-xs font-medium transition-colors ${j===s.key?"bg-foreground text-background":"bg-secondary text-muted-foreground hover:text-foreground"}`,children:s.label},s.key))})]}),x.size>0&&e.jsxs("div",{className:"flex items-center gap-2 mb-3 p-2 bg-secondary/50 rounded-lg border border-border",children:[e.jsxs("span",{className:"text-xs font-medium text-foreground",children:[x.size," selected"]}),e.jsx(l,{variant:"outline",size:"sm",className:"text-xs h-7",onClick:()=>k("published",!0),children:"Publish"}),e.jsx(l,{variant:"outline",size:"sm",className:"text-xs h-7",onClick:()=>k("published",!1),children:"Unpublish"}),e.jsx(l,{variant:"outline",size:"sm",className:"text-xs h-7",onClick:()=>k("featured",!0),children:"Feature"}),e.jsxs(l,{variant:"outline",size:"sm",className:"text-xs h-7",onClick:()=>k("verified",!0),children:[e.jsx(S,{className:"w-3 h-3 mr-1"})," Verify"]}),e.jsxs(P,{children:[e.jsx(L,{asChild:!0,children:e.jsxs(l,{variant:"destructive",size:"sm",className:"text-xs h-7",children:["Delete ",x.size]})}),e.jsxs(I,{children:[e.jsxs(T,{children:[e.jsxs(B,{children:["Delete ",x.size," listings?"]}),e.jsx(q,{children:"This action cannot be undone."})]}),e.jsxs(U,{children:[e.jsx(F,{children:"Cancel"}),e.jsx(M,{onClick:re,children:"Delete All"})]})]})]}),e.jsxs(P,{children:[e.jsx(L,{asChild:!0,children:e.jsx(l,{size:"sm",className:"text-xs h-7 bg-foreground text-background hover:bg-foreground
1/90",children:"BAN"})}),e.jsxs(I,{children:[e.jsxs(T,{children:[e.jsx(B,{children:"Ban and delete users?"}),e.jsx(q,{children:"This will permanently BAN the selected users (blocking re-registration) and delete all their listings, images, and wallet data. This cannot be undone."})]}),e.jsxs(U,{children:[e.jsx(F,{children:"Cancel"}),e.jsx(M,{onClick:ae,children:"Ban Users"})]})]})]}),e.jsxs(l,{variant:"ghost",size:"sm",className:"text-xs h-7 ml-auto",onClick:()=>N(new Set),children:[e.jsx(G,{className:"w-3 h-3 mr-1"})," Clear"]})]}),W?e.jsx("div",{className:"flex justify-center py-16",children:e.jsx(be,{className:"w-5 h-5 animate-spin text-muted-foreground"})}):e.jsx("div",{className:"border border-border rounded-lg overflow-hidden flex-1 flex flex-col min-h-0",children:e.jsxs("div",{className:"flex-1 overflow-auto",children:[e.jsxs("div",{className:"grid grid-cols-[28px_28px_40px_1fr_120px_100px_40px_40px_32px_32px_80px_80px_76px] gap-1.5 px-3 py-2.5 bg-secondary border-b border-border text-sm font-medium text-muted-foreground sticky top-0 z-10 min-w-[900px]",children:[e.jsx("span",{className:"flex items-center",children:e.jsx(R,{checked:de,onCheckedChange:te})}),e.jsx("span",{}),e.jsx("span",{}),e.jsx("span",{children:"Title"}),e.jsx("span",{children:"Advertiser"}),e.jsx("span",{children:"City"}),e.jsx("span",{className:"text-center",children:"Pub"}),e.jsx("span",{className:"text-center",children:e.jsx(S,{className:"w-3.5 h-3.5 inline"})}),e.jsx("span",{className:"text-center",children:"★"}),e.jsx("span",{className:"text-center",children:"🚩"}),e.jsx("span",{children:"Created"}),e.jsx("span",{children:"Expires"}),e.jsx("span",{children:"Actions"})]}),e.jsx("div",{className:"divide-y divide-border",children:m?.map(s=>{const t=J===s.id,r=s.advertiser?.display_name||s.advertiser?.email||"—",a=s.advertiser?.email??"",i=H(s.images?.[0]),c=s.advertiser?.verified??s.verified??!1;return e.jsxs("div",{children:[e.jsxs("div",{className:"grid grid-cols-[28px_28px_40px_1fr_120px_100px_40px_40px_32px_32px_80px_80px_76px] gap-1.5 px-3 py-2 text-sm items-center hover:bg-secondary/20 transition-colors min-w-[900px]",children:[e.jsx("span",{className:"flex items-center",children:e.jsx(R,{checked:x.has(s.id),onCheckedChange:()=>se(s.id)})}),e.jsx("button",{onClick:()=>ee(t?null:s.id),className:"text-muted-foreground hover:text-foreground",children:t?e.jsx(Ee,{className:"w-4 h-4"}):e.jsx(we,{className:"w-4 h-4"})}),e.jsx("div",{className:"w-8 h-8 rounded overflow-hidden bg-secondary",children:s.images?.[0]?e.jsx("img",{src:i,alt:`${w(s.title)} thumbnail`,className:"w-full h-full object-cover",onError:d=>{d.target.style.display="none"}}):e.jsx("div",{className:"w-full h-full"})}),e.jsx("p",{className:"text-foreground truncate text-sm font-medium",children:w(s.title)}),e.jsx("div",{className:"min-w-0",children:a?e.jsx("button",{onClick:()=>Y(`/dashboard/users?search=${encodeURIComponent(a)}`),className:"text-xs text-primary hover:underline truncate block",title:a,children:r}):e.jsx("span",{className:"text-xs text-muted-foreground",children:"No owner"})}),e.jsx("p",{className:"text-sm text-muted-foreground truncate",children:s.city?.name??"—"}),e.jsx("button",{onClick:()=>b(s.id,"published",s.published),className:"flex items-center justify-center",title:s.published?"Unpublish":"Publish",children:e.jsx("span",{className:`w-2.5 h-2.5 rounded-full ${s.published?"bg-[hsl(142,76%,36%)]":"bg-destructive/60"}`})}),e.jsx("button",{onClick:()=>b(s.id,"verified",c,s),className:"flex items-center justify-center",title:c?"Unverify":"Verify",children:e.jsx(S,{className:`w-4 h-4 ${c?"text-primary fill-primary":"text-muted-foreground/30"}`})}),e.jsx("button",{onClick:()=>b(s.id,"featured",s.featured),className:"flex items-center justify-center",children:s.featured?e.jsx(Z,{className:"w-4 h-4 text-primary fill-primary"}):e.jsx(Z,{className:"w-4 h-4 text-muted-foreground/30"})}),e.jsx("span",{className:`text-xs font-medium text-center ${s.report_count>0?"text-destructive":"text-muted-foreground/30"}`,children:s.report_count??0}),e.jsx("span",{className:"text-xs text-muted-foreground",children:V(s.created_at)}),e.jsx("span",{className:`text-xs ${s.expires_at&&new Date(s.expires_at)<new Date?"text-destructive":"text-muted-foreground"}`,children:V(s.expires_at)}),e.jsxs("div",{className:"flex items-center gap-0.5",children:[e.jsx(l,{variant:"ghost",size:"sm",onClick:()=>$(s),title:"Photos",className:"h-7 w-7 p-0",children:e.jsx(ue,{className:"w-3.5 h-3.5"})}),e.jsx(l,{variant:"ghost",size:"sm",asChild:!0,className:"h-7 w-7 p-0",children:e.jsx(me,{to:`/dashboard/admin-listings/${s.id}/edit`,children:e.jsx($e,{className:"w-3.5 h-3.5"})})}),e.jsxs(P,{children:[e.jsx(L,{asChild:!0,children:e.jsx(l,{variant:"ghost",size:"sm",className:"h-7 w-7 p-0",children:e.jsx(ze,{className:"w-3.5 h-3.5 text-destructive"})})}),e.jsxs(I,{children:[e.jsxs(T,{children:[e.jsx(B,{children:"Delete listing?"}),e.jsx(q,{children:"This action cannot be undone."})]}),e.jsxs(U,{children:[e.jsx(F,{children:"Cancel"}),e.jsx(M,{onClick:()=>ne(s.id),children:"Delete"})]})]})]})]})]}),t&&e.jsx("div",{className:"bg-secondary/10 border-t border-border px-6 py-4 space-y-4",children:e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-3 gap-4",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx("h4",{className:"text-xs font-semibold text-foreground uppercase tracking-wider",children:"Contact"}),e.jsxs("div",{className:"space-y-1 text-xs text-muted-foreground",children:[s.phone&&e.jsxs("p",{className:"flex items-center gap-1.5",children:[e.jsx(Pe,{className:"w-3 h-3"})," ",s.phone]}),s.email&&e.jsxs("p",{className:"flex items-center gap-1.5",children:[e.jsx(Le,{className:"w-3 h-3"})," ",s.email]}),s.website&&e.jsxs("p",{className:"flex items-center gap-1.5",children:[e.jsx(Ie,{className:"w-3 h-3"})," ",e.jsx("a",{href:s.website,target:"_blank",className:"text-primary hover:underline truncate",children:s.website})]}),s.social_links&&Object.keys(s.social_links).length>0&&e.jsx("div",{className:"flex flex-wrap gap-1 mt-1",children:Object.entries(s.social_links).map(([d,u])=>u?e.jsxs("span",{className:"bg-secondary px-1.5 py-0.5 rounded text-[10px]",children:[d,": ",String(u)]},d):null)}),!s.phone&&!s.email&&!s.website&&e.jsx("p",{className:"italic",children:"No contact info"})]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx("h4",{className:"text-xs font-semibold text-foreground uppercase tracking-wider",children:"Financials"}),e.jsx(Ve,{advertiserId:s.advertiser_id}),e.jsxs("div",{className:"space-y-1 text-xs text-muted-foreground mt-2",children:[e.jsxs("p",{children:["Activated: ",e.jsx("span",{className:s.activated?"text-primary font-medium":"text-destructive",children:s.activated?"Yes":"No"})]}),e.jsxs("p",{children:["Expires: ",e.jsx("span",{className:s.expires_at&&new Date(s.expires_at)<new Date?"text-destructive font-medium":"text-foreground",children:s.expires_at?V(s.expires_at):"No expiry"})]}),s.expires_at&&e.jsx("p",{className:`text-[10px] ${new Date(s.expires_at)<new Date?"text-destructive":"text-muted-foreground"}`,children:(()=>{const d=Math.round((new Date(s.expires_at).getTime()-Date.now())/864e5);return d>0?`in ${d} day${d!==1?"s":""}`:d===0?"today":`${Math.abs(d)} day${Math.abs(d)!==1?"s":""} ago`})()})]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx("h4",{className:"text-xs font-semibold text-foreground uppercase tracking-wider",children:"Qu
1ick Actions"}),e.jsxs("div",{className:"flex flex-wrap gap-2",children:[e.jsxs(l,{variant:"outline",size:"sm",onClick:()=>K(s.id,7),disabled:E.isPending,children:[e.jsx(_e,{className:"w-3 h-3 mr-1"})," +7 days"]}),e.jsxs(l,{variant:"outline",size:"sm",onClick:()=>K(s.id,30),disabled:E.isPending,children:[e.jsx(Te,{className:"w-3 h-3 mr-1"})," +30 days"]}),e.jsxs(l,{variant:"outline",size:"sm",onClick:()=>b(s.id,"activated",s.activated??!1),children:[e.jsx(Be,{className:"w-3 h-3 mr-1"})," ",s.activated?"Deactivate":"Activate"]}),e.jsxs(l,{variant:c?"default":"outline",size:"sm",onClick:()=>b(s.id,"verified",c,s),children:[e.jsx(S,{className:"w-3 h-3 mr-1"})," ",c?"Unverify":"Verify"]}),s.slug&&e.jsx(l,{variant:"outline",size:"sm",asChild:!0,children:e.jsxs("a",{href:`https://rubpage.com/${s.slug}`,target:"_blank",rel:"noopener noreferrer",children:[e.jsx(qe,{className:"w-3 h-3 mr-1"})," View on site"]})})]}),a&&e.jsxs("div",{className:"mt-2 p-2 rounded-lg bg-secondary/50 text-xs",children:[e.jsxs("p",{className:"text-muted-foreground",children:["Advertiser: ",e.jsx("span",{className:"text-foreground font-medium",children:r})]}),e.jsx("p",{className:"text-muted-foreground",children:a}),(s.advertiser?.last_city||s.advertiser?.last_country)&&e.jsxs("p",{className:"text-muted-foreground",children:[Ce(s.advertiser?.last_country)," ",[s.advertiser.last_city,s.advertiser.last_country].filter(Boolean).join(", ")]}),s.advertiser?.last_ip&&e.jsxs("p",{className:"text-muted-foreground/70 font-mono",children:["IP: ",s.advertiser.last_ip]}),e.jsx(Me,{email:a})]})]})]})})]},s.id)})})]})}),z>1&&e.jsxs("div",{className:"flex items-center justify-between mt-4",children:[e.jsxs("p",{className:"text-xs text-muted-foreground",children:["Page ",_+1," of ",z," · Showing ",m?.length??0," of ",D??0]}),e.jsxs("div",{className:"flex gap-1",children:[e.jsx(l,{variant:"outline",size:"sm",disabled:_===0,onClick:()=>{C(s=>s-1),window.scrollTo({top:0,behavior:"instant"})},className:"text-xs h-7",children:"Previous"}),e.jsx(l,{variant:"outline",size:"sm",disabled:_>=z-1,onClick:()=>{C(s=>s+1),window.scrollTo({top:0,behavior:"instant"})},className:"text-xs h-7",children:"Next"})]})]}),e.jsx(ke,{open:!!p,onOpenChange:()=>$(null),children:e.jsxs(Se,{className:"max-w-lg",children:[e.jsx(De,{children:e.jsxs(Ae,{children:["Photos — ",p&&w(p.title)]})}),e.jsx("div",{className:"grid grid-cols-3 gap-2",children:p?.images?.map((s,t)=>e.jsxs("div",{className:"relative aspect-square rounded-lg overflow-hidden border border-border",children:[e.jsx("img",{src:H(s),alt:`${p?w(p.title):"Listing"} photo ${t+1}`,className:"w-full h-full object-cover"}),e.jsx("button",{onClick:()=>ie(p,t),className:"absolute top-1 right-1 bg-background/80 rounded-full p-1 hover:bg-destructive hover:text-destructive-foreground transition-colors",children:e.jsx(G,{className:"w-3 h-3"})})]},t))}),(!p?.images||p.images.length===0)&&e.jsx("p",{className:"text-sm text-muted-foreground text-center py-4",children:"No photos"})]})})]})};export{ws 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.