PageSourceSearch

https://app.janavaidya.com/assets/pricing-analysis-qOCd5hrk.js

js janavaidya.com collected 2026-10-02 01:34:10 UTC 14,649 bytes, 1 lines download raw bytes

1import{r as x,j as e}from"./react-core-ZGhOPDd5.js";import{c as Y,z as K,b as U,B as g,n as L,d as $}from"./index-B1RmW2iz.js";import{u as B,a as Q,b as R}from"./tanstack-dB9xAWBZ.js";import{a as V,ac as J,U as W,i as H,C as G,a7 as X,M as Z}from"./AppShell-BJbqryi5.js";import{C as d,a as m}from"./card-BDV-GJ6y.js";import{I as ee}from"./input-KgcadZjB.js";import{S as se}from"./skeleton-BiO_-9PB.js";import{D as ae,a as te,b as re,c as ne,j as ie}from"./dialog-BWGRs1UA.js";import{R as oe}from"./refresh-cw-rAsdZmIK.js";import{I as q}from"./info-BKxTQRLq.js";import{C as F}from"./chevron-up-C8WQRj-l.js";import{C as M}from"./chevron-down-Dlk9jhEJ.js";import{T as le}from"./trending-up-_eaKYqXK.js";import{T as ce}from"./trending-down-CcQ20i0y.js";import"./shared-helpers-D8lIdaSv.js";import"./index-Cip49JTN.js";import"./scroll-area-B7kuf1xS.js";import"./LanguageToggle-CvQUaDOW.js";import"./JANAVAIDYA_new_final_Logo_1779194409565-Doc7Imxs.js";import"./search-BNFm_9S1.js";import"./phone-CaciiwaS.js";import"./tslib.es6-DjMk01cD.js";const de=[["path",{d:"M7 7h10v10",key:"1tivn9"}],["path",{d:"M7 17 17 7",key:"1vkiza"}]],E=Y("arrow-up-right",de),me={radius_overlap:"doctors whose service area overlaps yours",district:"doctors in your district",state:"doctors in your state",india:"doctors across JanaVaidya"};function y(t){return t==null?"—":`₹${Number(t).toLocaleString("en-IN")}`}function pe({c:t}){const p={strong:{label:"Strong signal",cls:"bg-emerald-100 text-emerald-800 border-emerald-200"},directional:{label:"Directional",cls:"bg-amber-100 text-amber-800 border-amber-200"},signal:{label:"Just a signal",cls:"bg-muted text-muted-foreground border-border"},none:{label:"No data",cls:"bg-muted text-muted-foreground border-border"}}[t];return e.jsx("span",{className:`text-[10px] font-medium px-1.5 py-0.5 rounded border ${p.cls}`,children:p.label})}function ue({d:t}){const n="h-4 w-4";return t==="raise"?e.jsx(le,{className:`${n} text-emerald-600`}):t==="lower"?e.jsx(ce,{className:`${n} text-amber-600`}):t==="widen"?e.jsx(Z,{className:`${n} text-primary`}):t==="enable"?e.jsx(E,{className:`${n} text-primary`}):t==="adjust"?e.jsx(E,{className:`${n} text-primary`}):e.jsx(q,{className:`${n} text-muted-foreground`})}const xe={Reach:"bg-blue-50 text-blue-700 border-blue-200",Availability:"bg-violet-50 text-violet-700 border-violet-200",Channels:"bg-teal-50 text-teal-700 border-teal-200",Pricing:"bg-emerald-50 text-emerald-700 border-emerald-200",Revenue:"bg-amber-50 text-amber-700 border-amber-200",Loyalty:"bg-rose-50 text-rose-700 border-rose-200"};function he({l:t}){return e.jsx("span",{className:`text-[10px] font-medium px-1.5 py-0.5 rounded border ${xe[t]}`,children:t})}const fe={opportunity:"text-amber-700",watch:"text-rose-600",good:"text-emerald-700",neutral:"text-muted-foreground"};function ge({groups:t}){const[n,p]=x.useState(!0);return t.length?e.jsxs(d,{children:[e.jsxs("button",{className:"w-full flex items-center justify-between p-3 text-sm font-semibold",onClick:()=>p(o=>!o),children:[e.jsx("span",{children:"Where you stand"}),n?e.jsx(F,{className:"h-4 w-4"}):e.jsx(M,{className:"h-4 w-4"})]}),n&&e.jsx(m,{className:"p-0 border-t space-y-3 pb-3",children:t.map(o=>e.jsxs("div",{children:[e.jsx("p",{className:"text-[11px] font-medium uppercase tracking-wide text-muted-foreground px-3 pt-2 pb-1",children:o.group}),e.jsx("div",{className:"divide-y divide-border/50",children:o.rows.map(l=>e.jsxs("div",{className:"px-3 py-2 flex items-center justify-between gap-2",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("p",{className:"text-sm font-medium truncate",children:l.label}),e.jsxs("p",{className:"text-[11px] text-muted-foreground",children:["You: ",e.jsx("span",{className:"text-foreground font-medium",children:l.your})," · Market: ",l.market]})]}),e.jsx("span",{className:`text-[11px] font-semibold shrink-0 ${fe[l.tone]}`,children:l.standing})]},l.key))})]},o.group))})]}):null}function Oe(){const{toast:t}=K(),n=B(),[,p]=U(),[o,l]=x.useState(!0),[u,b]=x.useState({}),[j,k]=x.useState({}),[D,N]=x.useState(!1),{data:I,isLoading:A}=Q({queryKey:["pricing-analysis"],queryFn:()=>$("/api/doctor/pricing-analysis",{}),staleTime:6e4}),w=R({mutationFn:()=>$("/api/doctor/pricing-analysis",{method:"POST"}),onSuccess:()=>{b({}),k({}),n.invalidateQueries({queryKey:["pricing-analysis"]}),t({title:"Analysis ready",description:"Your pricing has been compared against nearby doctors."})},onError:s=>t({title:"Couldn't run the analysis",description:s?.message??"Please try again.",variant:"destructive"})}),v=R({mutationFn:s=>$("/api/doctor/profile",{method:"PUT",body:JSON.stringify(s)}),onSuccess:()=>{b({}),k({}),n.invalidateQueries({queryKey:["pricing-analysis"]}),n.invalidateQueries({queryKey:["/api/doctor/profile"]}
1),t({title:"Applied to your profile",description:"Your pricing has been updated. It affects future bookings only."})},onError:s=>t({title:"Couldn't apply the changes",description:s?.message??"Please try again.",variant:"destructive"})}),a=I?.latest??null,_=!!a?.is_org_managed,S=a?.recommendations??[],i=_?[]:S.filter(s=>s.applyType==="profile_field"),O=x.useMemo(()=>{const s={};for(const r of i){if(!u[r.id]||!r.applyPayload)continue;const c={...r.applyPayload},f=j[r.id];if(f!=null&&f!==""&&(r.field==="consultation_fee"||r.field==="base_radius_km"||r.field==="min_lead_minutes")){const C=parseInt(f,10);Number.isFinite(C)&&(c[r.field]=C)}Object.assign(s,c)}return s},[i,u,j]),h=i.filter(s=>u[s.id]).length;function z(s){const r={};for(const c of i)r[c.id]=s;b(r)}return e.jsxs(V,{title:"Pricing & Practice Analysis",subtitle:"See how your pricing, coverage, surcharges and availability compare with nearby doctors — and act on it.",children:[e.jsxs("div",{className:"max-w-3xl mx-auto p-4 space-y-4",children:[e.jsx(d,{children:e.jsxs(m,{className:"p-4 flex items-center justify-between gap-3 flex-wrap",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsxs("p",{className:"text-sm font-semibold flex items-center gap-1.5",children:[e.jsx(J,{className:"h-4 w-4 text-primary"})," Competitive practice analysis"]}),e.jsx("p",{className:"text-xs text-muted-foreground mt-0.5",children:a?`Last analysed ${new Date(a.generated_at).toLocaleString("en-IN",{dateStyle:"medium",timeStyle:"short"})}`:"You haven't run an analysis yet."})]}),e.jsxs(g,{onClick:()=>w.mutate(),disabled:w.isPending,size:"sm",children:[w.isPending?e.jsx(L,{className:"h-4 w-4 mr-2 animate-spin"}):e.jsx(oe,{className:"h-4 w-4 mr-2"}),a?"Re-analyse":"Analyse my pricing"]})]})}),A&&e.jsx(se,{className:"h-40 w-full"}),!A&&!a&&!w.isPending&&e.jsx(d,{children:e.jsxs(m,{className:"p-6 text-center text-sm text-muted-foreground",children:["Tap ",e.jsx("span",{className:"font-medium text-foreground",children:"Analyse my pricing"})," to compare your fees, family & organisation rates, coverage, surcharges and availability against comparable doctors near you — and see where you can win more bookings."]})}),a&&e.jsxs(e.Fragment,{children:[e.jsx(d,{className:"border-primary/20 bg-primary/5",children:e.jsxs(m,{className:"p-3 flex items-start gap-2 text-xs text-foreground",children:[e.jsx(W,{className:"h-4 w-4 text-primary shrink-0 mt-0.5"}),e.jsxs("p",{children:["Based on ",e.jsx("span",{className:"font-semibold",children:a.peer_count})," ",me[a.peer_scope]??"comparable doctors",a.peer_summary?.experienceRange&&e.jsxs(e.Fragment,{children:[" (",a.peer_summary.experienceRange.min,"–",a.peer_summary.experienceRange.max," yrs experience)"]}),a.peer_summary?.tierMixed&&a.peer_count>0&&e.jsxs(e.Fragment,{children:[" · compared across qualifications (too few ",a.peer_summary.tierLabel," doctors nearby)"]}),a.peer_count<=1&&e.jsx(e.Fragment,{children:" — that's a thin sample, so treat everything below as a signal, not a rule."}),a.peer_count>1&&e.jsxs(e.Fragment,{children:[' — their qualifications vary, and a more-qualified doctor charges more, so check "',e.jsx("span",{className:"font-medium",children:"Who you're compared with"}),'" below before trusting a median.']})]})]})}),e.jsx(ge,{groups:a.comparison??[]}),_&&e.jsx(d,{className:"border-amber-200 bg-amber-50",children:e.jsxs(m,{className:"p-3 flex items-start gap-2 text-xs text-amber-900",children:[e.jsx(q,{className:"h-4 w-4 shrink-0 mt-0.5"}),e.jsx("p",{children:"Your organisation manages your pricing, so these are for insight only — share them with your organisation if you'd like anything changed. You can't apply them directly."})]})}),S.length>0&&e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx("p",{className:"text-sm font-semibold",children:"Recommendations"}),i.length>0&&e.jsx("button",{className:"text-xs text-primary hover:underline",onClick:()=>z(h!==i.length),children:h===i.length?"Clear all":"Select all"})]}),S.map(s=>{const r=!_&&s.applyType==="profile_field",c=!_&&s.applyType==="schedule_nudge",f=s.applyType==="profile_field",C=r&&(s.field==="consultation_fee"||s.field==="base_radius_km"||s.field==="min_lead_minutes");return e.jsx(d,{className:u[s.id]?"border-primary/40 bg-primary/5":"",children:e.jsx(m,{className:"p-3",children:e.jsxs("div",{className:"flex items-start gap-2.5",children:[r?e.jsx(H,{className:"mt-0.5",checked:!!u[s.id],onCheckedChange:P=>b(T=>({...T,[s.id]:P===!0}))}):e.jsx(ue,{d:s.direction}),e.jsxs("div",{className:"min-w-0 flex-1",children:[e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsx("p",{className:"text-sm font-medium",children:s.label}),e.jsxs("div",{className:"flex items-center gap-1 shrink-0",children:[s.lever&&e.jsx(he,{l:s.lever}),e.jsx(pe,{c:s.confidence})]})]}),e.jsx("p",{className:"text-xs text-muted-foreground mt-1 leading-relaxed",children:s.evidence}),f&&e.jsxs("div",{className:"flex items-center gap-2 mt-2 text-xs",children:[e.jsxs("span",{className:"text-muted-foreground",children:["Now: ",e.jsx("span",{className:"font-medium text-foreground",children:typeof s.current=="number"?y(s.current):s.current})]}),e.jsx("span",{className:"text-muted-foreground",children:"→"}),C?e.jsxs("div",{className:"flex items-center gap-1",children:[s.unit==="₹"&&e.jsx("span",{className:"text-muted-foreground",children:"₹"}),e.jsx(ee,{className:"h-7 w-24 text-xs",type:"number",value:j[s.id]??String(s.suggested??""),onChange:P=>k(T=>({...T,[s.id]:P.target.value}))}),s.unit&&s.unit!=="₹"&&e.jsx("span",{className:"text-muted-foreground",children:s.unit})]}):e.jsx("span",{className:"font-semibold text-emerald-700",children:s.suggested})]}),c&&e.jsxs(g,{variant:"outline",size:"sm",className:"mt-2 h-7 text-xs",onClick:()=>p("/doctor/schedule"),children:[e.jsx(G,{className:"h-3.5 w-3.5 mr-1.5"})," Open my calendar"]})]})]})})},s.id)})]}),i.length>0&&e.jsx("div",{className:"sticky bottom-2 z-10",children:e.jsx(d,{className:"border-primary/30 shadow-md",children:e.jsxs(m,{className:"p-3 flex items-center justify-between gap-3",children:[e.jsx("p",{className:"text-xs text-muted-foreground",children:h===0?"Select recommendations to apply":`${h} selected`}),e.jsxs(g,{size:"sm",disabled:h===0,onClick:()=>N(!0),children:[e.jsx(X,{className:"h-4 w-4 mr-2"})," Apply to my profile"]})]})})}),a.peer_summary?.peers?.length>0&&e.jsxs(d,{children:[e.jsxs("button",{className:"w-full flex items-center justify-between p-3 text-sm font-medium",onClick:()=>l(s=>!s),children:[e.jsxs("span",{children:["Who you're compared with (",a.peer_summary.peers.length,")"]}),o?e.jsx(F,{className:"h-4 w-4"}):e.jsx(M,{className:"h-4 w-4"})]}),o&&e.jsxs(m,{className:"p-0 border-t",children:[a.peer_summary.experienceRange&&e.jsxs("p",{className:"text-[11px] text-amber-800 bg-amber-50 px-3 py-2 border-b",children:["These doctors range from ",e.jsx("span",{className:"font-semibold",children:a.peer_summary.experienceRange.min})," to"," ",e.jsx("span",{className:"font-semibold",children:a.peer_summary.experienceRange.max})," years of experience, with the qualifications shown below. A more-qualified or more-experienced doctor naturally charges more — read the list before you read the median."]}),e.jsx("div",{className:"divide-y divide-border/50",children:a.peer_summary.peers.map(s=>e.jsxs("div",{className:"px-3 py-2.5",children:[e.jsxs("div",{className:"flex items-start justify-between gap-2",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("p",{className:"text-sm font-medium",children:s.label}
1),e.jsxs("p",{className:"text-xs text-foreground/80 break-words",children:[s.qualification?.trim()||s.tierLabel,s.specialization&&!/general/i.test(s.specialization)?` · ${s.specialization}`:""]})]}),e.jsx("span",{className:"text-sm font-semibold tabular-nums shrink-0",children:y(s.consultationFee)})]}),e.jsxs("p",{className:"text-[11px] text-muted-foreground mt-1",children:[s.yearsExperience!=null?`${s.yearsExperience} yrs`:"experience n/a"," · ",s.baseRadiusKm," km radius"," · ",s.completedVisits," visits",s.distanceKm!=null?` · ${s.distanceKm} km away`:""]})]},s.label))}),e.jsx("p",{className:"text-[10px] text-muted-foreground px-3 py-2 border-t",children:"Names are hidden, but qualifications, experience and fees are shown exactly as on each doctor's public profile. Family-doctor rate, organisation rate and advance-notice are shown only as an anonymous group average, never per doctor."})]})]}),e.jsx("p",{className:"text-[11px] text-muted-foreground text-center px-4",children:"This is market information to help you decide — you set your own fees. Applied changes affect future bookings only and are recorded on your profile."})]})]}),e.jsx(ae,{open:D,onOpenChange:N,children:e.jsxs(te,{className:"max-w-md",children:[e.jsx(re,{children:e.jsx(ne,{children:"Apply these changes?"})}),e.jsx("div",{className:"space-y-2 text-sm",children:i.filter(s=>u[s.id]).map(s=>{const r=j[s.id],c=r!=null&&r!==""&&(s.field==="consultation_fee"||s.field==="base_radius_km"||s.field==="min_lead_minutes")?s.unit==="₹"?y(parseInt(r,10)):`${r} ${s.unit}`:typeof s.suggested=="number"?y(s.suggested):s.suggested;return e.jsxs("div",{className:"flex items-center justify-between gap-2 border-b pb-1.5 last:border-0",children:[e.jsx("span",{className:"text-muted-foreground",children:s.label}),e.jsxs("span",{className:"font-medium",children:[typeof s.current=="number"?y(s.current):s.current," → ",c]})]},s.id)})}),e.jsxs(ie,{children:[e.jsx(g,{variant:"outline",onClick:()=>N(!1),disabled:v.isPending,children:"Cancel"}),e.jsxs(g,{onClick:()=>{const s=O;N(!1),v.mutate(s)},disabled:v.isPending,children:[v.isPending&&e.jsx(L,{className:"h-4 w-4 mr-2 animate-spin"}),"Confirm & apply"]})]})]})})]})}export{Oe 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.