PageSourceSearch

https://myechoboard.com/assets/AdminReportsPanel-CaVqbLGt.js

js myechoboard.com collected 2026-09-24 13:51:02 UTC 15,547 bytes, 1 lines download raw bytes

1import{r as e,j as r}from"./vendor-react-C9yDzYQD.js";import{supabase as t}from"./supabase-client-_h80EYw_.js";import{S as s}from"./supabase-config-Bge368iX.js";import{B as a}from"./button-CcIRk75H.js";import{I as n}from"./input-CJADGzyX.js";import{T as i}from"./textarea-vEj0waFH.js";import{S as l,a as o,b as d,c,d as m}from"./select-BE1IGN5Z.js";import{D as p,a as u,b as x,c as g,d as f,e as h}from"./dialog-DHNNRuDw.js";import{S as v}from"./switch-CM-712rT.js";import{u as b}from"./useAuth-Dz3EPsxs.js";import{g as j}from"./shareUrls-BBmEIcFl.js";import{a as _}from"./runtime-utils-GN4cODRt.js";import{S as w}from"./star-PkyT3oQ1.js";import{R as N}from"./refresh-cw-Bjlnjg0v.js";import{L as y}from"./vendor-router-X7RJKav4.js";import{a as k}from"./vendor-date-D4HAbvGT.js";import{B as S}from"./bell-BfXb5drb.js";import{S as C}from"./send-A4X7gax7.js";import{L as M}from"./loader-circle-CWK_zhHB.js";const R={pending:"Pending",reviewed:"Reviewed",dismissed:"Dismissed"},L={spam:"Spam",inappropriate:"Inappropriate content",harassment:"Harassment or bullying",copyright:"Copyright violation",other:"Other"},D={rate_clicked:"Clicked Rate",dismissed:"Dismissed",maybe_later:"Maybe later",shown:"Seen",eligible_not_seen:"Eligible, not seen",not_tracked:"No tracking yet"},$={rate_clicked:"bg-green-500/15 text-green-600 dark:text-green-400",dismissed:"bg-rose-500/15 text-rose-600 dar
1k:text-rose-400",maybe_later:"bg-amber-500/15 text-amber-600 dark:text-amber-400",shown:"bg-blue-500/15 text-blue-600 dark:text-blue-400",eligible_not_seen:"bg-purple-500/15 text-purple-600 dark:text-purple-400",not_tracked:"bg-muted text-muted-foreground"},O=e=>{if(!e)return"—";try{return k(new Date(e),"MMM dd, HH:mm")}catch{return"—"}};function T(){const{toast:s}=b(),[i,p]=e.useState(null),[u,x]=e.useState(!0),[g,f]=e.useState(""),[h,v]=e.useState("all"),j=e.useCallback(async()=>{x(!0);const{data:e,error:r}=await t.rpc("admin_get_echo_review_prompt_overview");r?(s({title:"Failed to load rating prompt tracking",description:r.message,variant:"error"}),p(null)):p(e||{}),x(!1)},[s]);e.useEffect(()=>{j()},[j]);const _=(null==i?void 0:i.summary)||{},y=(null==i?void 0:i.users)||[],k=g.trim().toLowerCase(),S=y.filter(e=>("all"===h||e.status===h)&&(!k||[e.username,e.full_name,e.email,e.id].some(e=>(e||"").toLowerCase().includes(k)))),C=[{label:"Tracked users",value:_.tracked_users||0},{label:"Prompt shown",value:_.shown_users||0},{label:"Clicked Rate",value:_.rate_clicked_users||0},{label:"Maybe later",value:_.maybe_later_users||0},{label:"Dismissed",value:_.dismissed_users||0},{label:"No tracking yet",value:_.not_tracked_users||0}];return r.jsxs("div",{className:"space-y-6",children:[r.jsxs("div",{className:"flex flex-col gap-4 md:flex-row md:items-start md:justify-between",children:[r.jsxs("div",{className:"flex items-start gap-3",children:[r.jsx("div",{className:"p-2 rounded-xl bg-primary/10",children:r.jsx(w,{className:"w-5 h-5 text-primary"})}),r.jsxs("div",{children:[r.jsx("h3",{className:"text-sm font-bold uppercase tracking-widest text-foreground/80",children:"iOS Rating Prompt"}),r.jsx("p",{className:"mt-1 max-w-2xl text-sm text-muted-foreground",children:"Tracks future prompt eligibility, impressions, Rate clicks, Maybe later clicks, and dismissals. Older local-only prompt history cannot be recovered."})]})]}),r.jsxs(a,{type:"button",variant:"outline",className:"h-10 rounded-xl gap-2",onClick:()=>{j()},disabled:u,children:[r.jsx(N,{className:"w-4 h-4 "+(u?"animate-spin":"")}),"Refresh"]})]}),r.jsx("div",{className:"grid grid-cols-2 gap-3 lg:grid-cols-6",children:C.map(e=>r.jsxs("div",{className:"rounded-2xl border border-border/50 bg-muted/20 p-4",children:[r.jsx("div",{className:"text-2xl font-black text-foreground",children:e.value}),r.jsx("div",{className:"mt-1 text-[10px] font-bold uppercase tracking-widest text-muted-foreground",children:e.label})]},e.label))}),r.jsxs("div",{className:"flex flex-col gap-3 md:flex-row",children:[r.jsx(n,{value:g,onChange:e=>f(e.target.value),placeholder:"Search users...",className:"h-11 rounded-2xl bg-muted/30"}),r.jsxs(l,{value:h,onValueChange:e=>v(e),children:[r.jsx(o,{className:"h-11 rounded-2xl bg-muted/30 md:w-56",children:r.jsx(d,{placeholder:"Status"})}),r.jsxs(c,{children:[r.jsx(m,{value:"all",children:"All statuses"}),Object.entries(D).map(([e,t])=>r.jsx(m,{value:e,children:t},e))]})]})]}),u?r.jsx("div",{className:"py-12 text-center text-muted-foreground text-sm",children:"Loading rating prompt tracking…"}):0===S.length?r.jsx("div",{className:"py-12 text-center text-muted-foreground text-sm",children:"No users match this filter."}):r.jsxs("div",{className:"overflow-hidden rounded-2xl border border-border/50",children:[r.jsxs("div",{className:"grid grid-cols-[minmax(220px,1.3fr)_140px_100px_120px_120px_120px] gap-3 bg-muted/30 px-4 py-3 text-[10px] font-bold uppercase tracking-widest text-muted-foreground",children:[r.jsx("span",{children:"User"}),r.jsx("span",{children:"Status"}),r.jsx("span",{children:"Shown"}),r.jsx("span",{children:"Last seen"}),r.jsx("span",{children:"Rate click"}),r.jsx("span",{children:"Last active"})]}),r.jsx("div",{className:"max-h-[560px] overflow-y-auto custom-scrollbar",children:S.map(e=>r.jsxs("div",{className:"grid grid-cols-[minmax(220px,1.3fr)_140px_100px_120px_120px_120px] gap-3 border-t border-border/40 px-4 py-3 text-sm",children:[r.jsxs("div",{className:"min-w-0",children:[r.jsx("div",{className:"truncate font-bold text-foreground",children:e.username?`@${e.username}`:e.full_name||e.email||e.id.slice(0,8)}),r.jsx("div",{className:"truncate text-xs text-muted-foreground",children:e.email||e.id})]}),r.jsx("div",{children:r.jsx("span",{className:`inline-flex rounded-full px-2 py-1 text-[10px] font-bold uppercase tracking-wider ${$[e.status]}`,children:D[e.status]})}),r.jsx("div",{className:"font-semibold text-foreground",children:e.shown_count||0}),r.jsx("div",{className:"text-muted-foreground",children:O(e.last_shown_at)}),r.jsx("div",{className:"text-muted-foreground",children:O(e.rate_clicked_at)}),r.jsx("div",{className:"text-muted-foreground",children:O(e.last_active_at)})]},e.id))})]})]})}function U(){const{toast:n}=b(),[l,o]=e.useState([]),[d,c]=e.useState(!0),[m,w]=e.useState(null),[N,D]=e.useState(""),[$,O]=e.useState(!0),[T,U]=e.useState(!0),[z,A]=e.useState(!1),[E,H]=e.useState("pending"),I=async()=>{c(!0);try{const{data:e,error:r}
1=await t.rpc("get_admin_reports",{p_status:E});if(r)throw r;o(e||[])}catch(e){let r=t.from("reports").select("*, reporter:profiles(id, username, full_name, avatar_url)").order("created_at",{ascending:!1});"all"!==E&&(r=r.eq("status",E));const{data:s,error:a}=await r;a?(n({title:"Failed to load reports",description:a.message,variant:"error"}),o([])):o(await(async e=>{const r=e.filter(e=>"memory"===e.content_type&&e.content_id).map(e=>e.content_id);if(0===r.length)return e;const{data:s}=await t.from("memories").select("id, user_id").in("id",r),a=[...new Set((s||[]).map(e=>e.user_id).filter(Boolean))];let n=new Map;if(a.length>0){const{data:e}=await t.from("profiles").select("id, username").in("id",a);n=new Map((e||[]).filter(e=>e.username).map(e=>[e.id,e.username]))}const i=new Map((s||[]).map(e=>[e.id,n.get(e.user_id)||null]));return e.map(e=>({...e,echo_owner_username:"memory"===e.content_type&&i.get(e.content_id)||null}))})((s||[]).map(e=>{var r,t,s;return{...e,reporter_username:(null==(r=e.reporter)?void 0:r.username)||null,reporter_full_name:(null==(t=e.reporter)?void 0:t.full_name)||null,reporter_avatar_url:(null==(s=e.reporter)?void 0:s.avatar_url)||null}})))}c(!1)};e.useEffect(()=>{I()},[E]);const q=e=>{var r;if(!e)return"Something went wrong.";if("string"==typeof e)return e;const t=null==(r=null==e?void 0:e.context)?void 0:r.body;if(t)try{const e="string"==typeof t?JSON.parse(t):t;if((null==e?void 0:e.error_code)&&(null==e?void 0:e.error))return`${e.error_code}: ${e.error}`;if(null==e?void 0:e.error)return e.error;if(null==e?void 0:e.message)return e.message}catch{if("string"==typeof t)return t}return(null==e?void 0:e.message)||"Something went wrong."},B=l.filter(e=>"pending"===e.status).length;return r.jsxs("div",{className:"space-y-4",children:[r.jsx("div",{className:"flex gap-2",children:["pending","reviewed","dismissed","all"].map(e=>r.jsxs("button",{onClick:()=>H(e),className:"px-4 py-1.5 rounded-xl text-xs font-bold transition-all capitalize "+(E===e?"pending"===e?"bg-amber-500/20 text-amber-600 dark:text-amber-400":"bg-primary/10 text-primary":"text-muted-foreground hover:text-foreground"),children:["all"===e?"All":R[e],"pending"===e&&B>0&&"pending"!==E&&r.jsx("span",{className:"ml-1.5 px-1.5 py-0.5 rounded-full bg-amber-500 text-white text-[9px]",children:B})]},e))}),d?r.jsx("div",{className:"py-12 text-center text-muted-foreground text-sm",children:"Loading reports…"}):0===l.length?r.jsx("div",{className:"py-12 text-center text-muted-foreground text-sm",children:"No reports found."}):r.jsx("div",{className:"space-y-3 max-h-[600px] overflow-y-auto pr-1 custom-scrollbar",children:l.map(e=>{var s;const i=e.reporter_username?`@${e.reporter_username}`:e.reporter_full_name||e.reporter_email||(null==(s=e.reporter_id)?void 0:s.slice(0,8)),l=(e.reporter_username||e.reporter_full_name||e.reporter_email||"?").trim().charAt(0).toUpperCase(),o=e.reporter_username?`/u/${encodeURIComponent(e.reporter_username)}`:null;return r.jsxs("div",{className:"p-4 rounded-2xl bg-muted/20 border border-foreground
1/5 space-y-3",children:[r.jsxs("div",{className:"flex items-start justify-between gap-3",children:[r.jsxs("div",{className:"space-y-3 min-w-0",children:[r.jsxs("div",{className:"space-y-1",children:[r.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[r.jsx("span",{className:"px-2 py-0.5 rounded-full text-[10px] font-bold uppercase tracking-wider "+("pending"===e.status?"bg-amber-500/15 text-amber-600 dark:text-amber-400":"reviewed"===e.status?"bg-green-500/15 text-green-600 dark:text-green-400":"bg-muted text-muted-foreground"),children:R[e.status]||e.status}),r.jsx("span",{className:"px-2 py-0.5 rounded-full text-[10px] font-bold bg-primary/10 text-primary uppercase tracking-wider",children:e.content_type}),r.jsx("span",{className:"text-xs font-semibold text-foreground",children:L[e.reason]||e.reason})]}),r.jsxs("p",{className:"text-[10px] text-muted-foreground font-mono truncate max-w-[280px]",children:["ID: ",e.content_id]}),e.description&&r.jsxs("p",{className:"text-xs text-muted-foreground italic",children:['"',e.description,'"']})]}),r.jsxs("div",{className:"flex items-center gap-3 rounded-xl bg-background/50 border border-foreground
1/5 p-3",children:[r.jsx("div",{className:"h-10 w-10 rounded-full bg-foreground/10 overflow-hidden flex items-center justify-center text-xs font-black text-muted-foreground shrink-0",children:e.reporter_avatar_url?r.jsx("img",{src:e.reporter_avatar_url,alt:"",className:"h-full w-full object-cover"}):l}),r.jsxs("div",{className:"min-w-0",children:[r.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[o?r.jsx(y,{to:o,className:"text-sm font-bold text-foreground hover:text-primary",children:i}):r.jsx("span",{className:"text-sm font-bold text-foreground",children:i}),e.reporter_full_name&&e.reporter_username&&r.jsx("span",{className:"text-xs text-muted-foreground",children:e.reporter_full_name})]}),r.jsxs("p",{className:"text-[10px] text-muted-foreground truncate",children:[e.reporter_email||e.reporter_id," · ",k(new Date(e.created_at),"MMM dd, yyyy HH:mm")]})]})]}),e.review_message&&r.jsxs("div",{className:"rounded-xl bg-green-500/5 border border-green-500/10 p-3",children:[r.jsx("p",{className:"text-[10px] font-bold uppercase tracking-widest text-green-600 dark:text-green-400 mb-1",children:"Sent response"}),r.jsx("p",{className:"text-xs text-foreground",children:e.review_message})]})]}),r.jsx("div",{className:"flex flex-col gap-2 shrink-0",children:r.jsx(a,{size:"sm",variant:"outline",className:"h-7 rounded-xl text-[10px] font-bold gap-1",onClick:()=>{const r="memory"===e.content_type?j({id:e.content_id,ownerUsername:e.echo_owner_username}):`/boards/${e.content_id}`;window.open(r,"_blank")},children:"View"})})]}),"pending"===e.status&&r.jsxs("div",{className:"flex gap-2 pt-1 border-t border-foreground
1/5",children:[r.jsx(a,{size:"sm",variant:"outline",className:"h-8 rounded-xl text-[11px] font-bold flex-1 text-green-600 border-green-500/20 hover:bg-green-500/10",onClick:()=>(e=>{w(e),D(e.review_message||"Thanks for sending this report. We reviewed it and took the appropriate action."),O(!e.review_emailed_at),U(!e.review_notified_at)})(e),children:"Mark Reviewed"}),r.jsx(a,{size:"sm",variant:"ghost",className:"h-8 rounded-xl text-[11px] font-bold flex-1 text-muted-foreground hover:text-foreground",onClick:()=>(async e=>{const{error:r}=await t.from("reports").update({status:"dismissed",reviewed_at:(new Date).toISOString()}).eq("id",e);r?n({title:"Failed to update",description:r.message,variant:"error"}):(n({title:"Status updated"}),I())})(e.id),children:"Dismiss"})]})]},e.id)})}),r.jsx(p,{open:!!m,onOpenChange:e=>{e||z||(w(null),D(""))},children:r.jsxs(u,{className:"sm:max-w-[540px] rounded-2xl",children:[r.jsxs(x,{children:[r.jsx(g,{children:"Mark report reviewed"}),r.jsx(f,{children:"This message is sent to the reporter as an in-app notification and email."})]}),r.jsx(i,{value:N,onChange:e=>D(e.target.value),placeholder:"Write a short update for the reporter...",className:"min-h-[140px]"}),r.jsxs("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-2",children:[r.jsxs("div",{className:_("flex items-center justify-between rounded-xl border px-3 py-2 text-left transition-colors",T?"border-primary/30 bg-primary/10":"border-border/50 bg-muted/20"),children:[r.jsxs("span",{className:"flex items-center gap-2 text-xs font-bold",children:[r.jsx(S,{className:"h-4 w-4"}),"Notification"]}),r.jsx(v,{checked:T,onCheckedChange:U})]}),r.jsxs("div",{className:_("flex items-center justify-between rounded-xl border px-3 py-2 text-left transition-colors",$?"border-primary/30 bg-primary/10":"border-border/50 bg-muted/20"),children:[r.jsxs("span",{className:"flex items-center gap-2 text-xs font-bold",children:[r.jsx(C,{className:"h-4 w-4"}),"Email"]}),r.jsx(v,{checked:$,onCheckedChange:O})]})]}),r.jsxs(h,{className:"gap-2",children:[r.jsx(a,{variant:"outline",disabled:z,onClick:()=>{w(null),D("")},children:"Cancel"}),r.jsxs(a,{onClick:async()=>{var e;if(!m)return;const r=N.trim();if(r){A(!0);try{const a=await(async()=>{var e,r;const{data:s}=await t.auth.getSession();let a=null==(e=null==s?void 0:s.session)?void 0:e.access_token;if(!a){const{data:e}=await t.auth.refreshSession();a=null==(r=null==e?void 0:e.session)?void 0:r.access_token}return a})(),{data:i,error:l}=await t.functions.invoke("admin-report-review",{body:{report_id:m.id,message:r,send_email:$,send_notification:T},headers:{...a?{Authorization:`Bearer ${a}`}:{},apikey:s}});if(l)throw l;(null==(e=null==i?void 0:i.sent)?void 0:e.email_error)?n({title:"Email skipped",description:i.sent.email_error,variant:"warning"}):n({title:"Report reviewed",description:"The reporter was notified."}),w(null),D(""),await I()}catch(a){n({title:"Review failed",description:q(a),variant:"error"})}finally{A(!1)}}else n({title:"Message required",description:"Write the message the reporter should receive.",variant:"error"})},disabled:z,children:[z?r.jsx(M,{className:"mr-2 h-4 w-4 animate-spin"}):null,"Send and Review"]})]})]})})]})}export{T as AdminRatingsPanel,U as AdminReportsPanel};

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.