PageSourceSearch

https://blisstherapy.ai/assets/admin.reviews-DeUg8Qaj.js

js blisstherapy.ai collected 2026-10-05 11:52:46 UTC 6,770 bytes, 1 lines download raw bytes

1import{r,b as S,j as e,I as R,B as o,f as k,g as P,t as b,T as A}from"./index-CwxMVMRT.js";import{o as T,p as w}from"./admin-fns-BVo-iKH0.js";import{P as $,C as q}from"./admin-list-toolbar-HOJAtrfi.js";import"./download-CNdfX1M-.js";const z=["all","private","pending","published","hidden","removed","historical"],N={all:"All",private:"Private",pending:"Pending approval",published:"Published",hidden:"Hidden",removed:"Removed",historical:"Historical"};function F(){const[s,h]=r.useState(""),[m,u]=r.useState(""),[n,x]=r.useState(""),[i,v]=r.useState("all"),[a,l]=r.useState(0),[c,C]=r.useState(50);r.useEffect(()=>{const t=setTimeout(()=>{u(s.trim()),l(0)},250);return()=>clearTimeout(t)},[s]);const d=S({queryKey:["admin-reviews",m,n,i,a,c],queryFn:()=>T({data:{q:m||void 0,therapistId:n||void 0,filter:i,page:a,pageSize:c}})}),g=d.data?.rows??[],p=d.data?.total??0,j=d.data?.therapists??[],f=j.filter(t=>!n||t.id===n).reduce((t,y)=>t+y.recommendations,0);return e.jsxs("section",{className:"space-y-5",children:[e.jsxs("header",{className:"flex flex-wrap items-end justify-between gap-4",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"font-serif text-3xl text-bliss-ink",children:"Reviews"}),e.jsx("p",{className:"mt-2 text-sm text-muted-foreground",children:d.isSuccess?`${p} ${p===1?"record":"records"} · ${f} active ${f===1?"recommendation":"recommendations"}${n?" for this therapist":" across therapists"}`:"Recommendations and private therapist feedback."})]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx($,{value:c,onChange:t=>{C(t),l(0)}}),e.jsx(q,{filename:"therapist-reviews.csv",rows:g.map(t=>({therapist:t.therapistName??"",patient:t.customerName??t.customerEmail??"",origin:t.origin,answer:t.recommendationCurrent?t.wouldRecommend?"Yes":"No":t.origin==="Old platform"&&t.rating===1?"Old-platform Yes":"Historical",rating:t.origin==="Old platform"?"":t.rating??"",consent:t.publicationConsent?"Yes":"No",status:t.removedAt?"Removed":t.commentStatus,comment:t.comment??""})),columns:[{key:"therapist",header:"Therapist"},{key:"patient",header:"Patient"},{key:"origin",header:"Origin"},{key:"answer",header:"Answer"},{key:"rating",header:"Historical rating"},{key:"consent",header:"Publication consent"},{key:"status",header:"Status"},{key:"comment",header:"Comment"}]})]})]}),e.jsxs("div",{className:"flex flex-wrap gap-3 rounded-xl border bg-white p-4",children:[e.jsx(R,{"aria-label":"Search reviews",value:s,onChange:t=>h(t.target.value),placeholder:"Search patient, therapist, or comment…",className:"max-w-sm"}),e.jsxs("select",{"aria-label":"Therapist",value:n,onChange:t=>{x(t.target.value),l(0)},className:"rounded-md border px-3 py-2 text-sm",children:[e.jsx("option",{value:"",children:"All therapists"}),j.map(t=>e.jsxs("option",{value:t.id,children:[t.name??"Therapist"," (",t.recommendations,")"]},t.id))]}),e.jsx("select",{"aria-label":"Review status",value:i,onChange:t=>{v(t.target.value),l(0)},className:"rounded-md border px-3 py-2 text-sm",children:z.map(t=>e.jsx("option",{value:t,children:N[t]},t))})]}),d.isPending?e.jsx("p",{children:"Loading reviews…"}):d.isError?e.jsxs("div",{children:[e.jsx("p",{children:"Couldn’t load reviews."}),e.jsx(o,{onClick:()=>d.refetch(),children:"Try again"})]}):g.length?g.map(t=>e.jsx(E,{row:t},`${t.id}-${t.updatedAt}`)):e.jsx("p",{className:"rounded-xl border border-dashed p-8 text-center",children:"No reviews match these filters."}),e.jsxs("div",{className:"flex items-center justify-center gap-3",children:[e.jsx(o,{variant:"outline",disabled:!a,onClick:()=>l(a-1),children:"Previous"}),e.jsxs("span",{className:"text-sm",children:["Page ",a+1," / ",Math.max(1,Math.ceil(p/c))]}),e.jsx(o,{variant:"outline",disabled:(a+1)*c>=p,onClick:()=>l(a+1),children:"Next"})]})]})}function E({row:s}){const h=k(),[m,u]=r.useState(!1),[n,x]=r.useState(""),i=P({mutationFn:a=>w({data:{id:s.id,expectedUpdatedAt:new Date(s.updatedAt).toISOString(),action:a,reason:a==="remove"?n.trim():void 0}}),onSuccess:()=>{b.success("Review updated."),u(!1),h.invalidateQueries({queryKey:["admin-reviews"]})},onError:a=>b.error(a.message||"Couldn’t update review.")}),v=s.removedAt?"Removed":N[s.commentStatus]??s.commentStatus;return e.jsxs("article",{className:"space-y-3 rounded-xl border bg-white p-5",children:[e.jsxs("div",{className:"flex flex-wrap items-start justify-between gap-3",children:[e.jsxs("div",{children:[e.jsxs("p",{className:"font-medium",children:[s.customerName??s.customerEmail??"Deleted patient"," ·"," ",s.therapistName??"Therapist unavailable"]}),e.jsxs("p",{className:"mt-1 text-xs text-muted-foreground",children:[new Date(s.createdAt).toLocaleStr
1ing()," · ",s.origin]})]}),e.jsx("span",{className:"rounded-full bg-muted px-3 py-1 text-xs",children:v})]}),e.jsx("p",{className:"text-sm",children:s.recommendationCurrent?s.wouldRecommend?"Yes — recommends this therapist":"No — does not add a recommendation":s.origin==="Old platform"?s.legacyRecommendationCounted?"Old-platform Yes — included in web recommendation count":"Old-platform feedback — not counted (hidden, removed, superseded, unlinked, or not Yes)":`Historical feedback${s.rating!==null?` · original rating: ${s.rating}/5`:""} · excluded from recommendation count`}),e.jsx("p",{className:"whitespace-pre-wrap break-words text-sm",children:s.comment||"No comment"}),s.comment&&e.jsx("p",{className:"text-xs text-muted-foreground",children:s.publicationConsent?"Patient permits publication with initials.":"Private — no permission to publish."}),s.removalReason&&e.jsxs("p",{className:"text-sm",children:["Removal reason: ",s.removalReason]}),e.jsxs("div",{className:"flex flex-wrap gap-2",children:[!s.removedAt&&s.recommendationCurrent&&s.publicationConsent&&s.comment&&s.commentStatus!=="published"&&e.jsx(o,{size:"sm",disabled:i.isPending,onClick:()=>i.mutate("approve"),children:"Approve comment"}),!s.removedAt&&s.publicationConsent&&s.comment&&s.commentStatus!=="hidden"&&e.jsx(o,{size:"sm",variant:"outline",disabled:i.isPending,onClick:()=>i.mutate("hide"),children:"Hide comment"}),s.removedAt?e.jsx(o,{size:"sm",variant:"outline",disabled:i.isPending,onClick:()=>i.mutate("restore"),children:"Restore review"}):e.jsx(o,{size:"sm",variant:"outline",disabled:i.isPending,onClick:()=>u(!m),children:"Remove entire review"})]}),m&&e.jsxs("div",{className:"space-y-2 rounded-lg border p-3",children:[e.jsx("p",{className:"text-sm",children:"Removes the comment and any Yes vote. This can be restored."}),e.jsx(A,{"aria-label":"Removal reason",placeholder:"Reason for removal (required)",value:n,maxLength:2e3,onChange:a=>x(a.target.value)}),e.jsx(o,{size:"sm",disabled:!n.trim()||i.isPending,onClick:()=>i.mutate("remove"),children:"Confirm removal"})]})]})}export{F as component};

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.