PageSourceSearch

https://dancepulse.ai/assets/TuitionManager-CpgABaTK.js

js dancepulse.ai collected 2026-10-05 15:31:57 UTC 6,837 bytes, 1 lines download raw bytes

1import{r as N,j as e,m as E,F as h,q as v,as as L,K as b,U as k,w as R,x as A,y as B,a4 as M,W as I,z as D,L as y,B as c,a5 as U}from"./index-DsKq7xQs.js";import{S as d}from"./skeleton-9Oy70iop.js";import{T as $,a as z,b as C,c as o,d as H,e as m}from"./table-tXtjlVqV.js";import{T as O,a as q,b as g,c as G}from"./tabs-DLwNjey7.js";import{S as u}from"./StatCard-DBb5LdPj.js";import{u as K,a as V}from"./useRealtimeDashboard-05R1oMyC.js";import{P as W}from"./phone-Dq0V24gk.js";const x=i=>new Intl.NumberFormat("en-US",{style:"currency",currency:"USD",minimumFractionDigits:2,maximumFractionDigits:2}).format(i);function se(){const{data:i,isLoading:l,isFetching:j,refetch:w}=K();V();const[p,F]=N.useState(""),[r,T]=N.useState("all"),f=N.useMemo(()=>{const s=i?.families??[],a=p.trim().toLowerCase();return s.filter(n=>r==="carded"&&!n.hasCardOnFile||r==="uncarded"&&n.hasCardOnFile?!1:!!(!a||n.familyName.toLowerCase().includes(a)||n.parentEmail?.toLowerCase().includes(a)||n.students.some(P=>P.studentName.toLowerCase().includes(a))))},[i,p,r]),t=i?.totals,S=(t?.billedTotal??0)+(t?.unbilledTotal??0);return e.jsxs(E.div,{initial:{opacity:0,y:12},animate:{opacity:1,y:0},transition:{duration:.35,ease:[.22,1,.36,1]},className:"space-y-6",children:[e.jsxs("div",{className:"flex flex-col gap-3 sm:flex-row sm:items-start sm:justify-between",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-3xl md:text-4xl font-extrabold tracking-tight",style:{fontFamily:"var(--font-display)"},children:"Tuition Manager"}),e.jsxs("p",{className:"text-muted-foreground mt-1 text-sm",children:["Students enrolled in classes billing in"," ",e.jsx("span",{className:"font-medium",children:i?.monthLabel??"the next cycle"}),". Click a family name to open their account."]}),!l&&(t?.staleSubscriptionFamilies??0)>0&&e.jsxs("p",{className:"mt-2 text-xs text-warning-text flex items-start gap-1.5",children:[e.jsx(h,{className:"h-3.5 w-3.5 mt-px shrink-0"}),t?.staleSubscriptionFamilies," famil",(t?.staleSubscriptionFamilies??0)===1?"y has":"ies have"," an active tuition subscription but no classes billing this cycle — they aren't included in these totals and won't be charged."]})]}),e.jsxs(v,{variant:"outline",size:"sm",onClick:()=>w(),disabled:j,className:"shrink-0",children:[e.jsx(L,{className:`h-4 w-4 mr-2 ${j?"animate-spin":""}`}),j?"Refreshing…":"Refresh"]})]}),e.jsxs("div",{className:"grid gap-4 grid-cols-1 sm:grid-cols-2 lg:grid-cols-4",children:[e.jsx(u,{label:"Families Auto-Billed",value:l?e.jsx(d,{className:"h-7 w-16"}):t?.billedFamilies??0,icon:b,hint:l?void 0:x(t?.billedTotal??0)+" next cycle",valueClassName:"text-success-text"}),e.jsx(u,{label:"No Card on File",value:l?e.jsx(d,{className:"h-7 w-16"}):t?.unbilledFamilies??0,icon:h,hint:l?void 0:x(t?.unbilledTotal??0)+" at risk",valueClassName:"text-destructive"}),e.jsx(u,{label:"Students Enrolled",value:l?e.jsx(d,{className:"h-7 w-16"}):t?.students??0,icon:k}),e.jsx(u,{label:"Combined Projected",value:l?e.jsx(d,{className:"h-7 w-24"}):x(S),icon:b,valueClassName:"text-success-text"})]}),e.jsxs(R,{children:[e.jsxs(A,{className:"flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between",children:[e.jsx(B,{className:"text-base",children:"Families Scheduled for Tuition"}),e.jsx("div",{className:"flex items-center gap-2 w-full sm:w-auto",children:e.jsxs("div",{className:"relative flex-1 sm:w-72",children:[e.jsx(M,{className:"h-4 w-4 absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground"}),e.jsx(I,{value:p,onChange:s=>F(s.target.value),placeholder:"Search family or student…",className:"pl-9"})]})})]}),e.jsxs(D,{children:[e.jsxs(O,{value:r,onValueChange:s=>T(s),className:"space-y-4",children:[e.jsxs(q,{children:[e.jsxs(g,{value:"all",children:["All (",i?.families.length??0,")"]}),e.jsxs(g,{value:"uncarded",children:["No Card (",t?.unbilledFamilies??0,")"]}),e.jsxs(g,{value:"carded",children:["Auto-Pay (",t?.billedFamilies??0,")"]})]}),e.jsx(G,{value:r,className:"m-0",children:l?e.jsx("div",{className:"space-y-2",children:Array.from({length:6}).map((s,a)=>e.jsx(d,{className:"h-14 w-full"},a))}):f.length===0?e.jsx("div",{className:"text-center text-sm text-muted-foreground py-12",children:"No families match this filter."}):e.jsx("div",{className:"overflow-x-auto rounded-lg border border-border",children:e.jsxs($,{children:[e.jsx(z,{children:e.jsxs(C,{children:[e.jsx(o,{children:"Family"}),e.jsx(o,{children:"Students"}),e.jsx(o,{children:"Contact"}),e.jsx(o,{children:"Auto-Pay"}),e.jsx(o,{className:"text-right",children:"Projected Next Cycle"})]})}),e.jsx(H,{children:f.map(s=>e.jsxs(C,{children:[e.jsx(m,{className:"align-top",children:e.jsx(y,{to:`/students?family=${s.familyId}`,className:"font-semibold text-primary hover:underline",children:s.familyName})}),e.jsx(m,{className:"align-top",children:e.jsx("div",{className:"space-y-1",children:s.students.map(a=>e.jsxs("div",{className:"text-sm flex flex-wrap items-center gap-2",children:[e.jsx("span",{children:a.studentName}),e.jsxs(c,{variant:"secondary",className:"text-[10px]",children:[a.classCount," ",a.classCount===1?"class":"classes"]}
1),a.monthlyEstimate>0&&e.jsxs("span",{className:"text-xs text-muted-foreground",children:[x(a.monthlyEstimate),"/mo"]}),a.isFlatRate&&e.jsx(c,{variant:"outline",className:"text-[10px] border-primary/40 text-primary",children:"Custom amount"})]},a.studentId))})}),e.jsx(m,{className:"align-top",children:e.jsxs("div",{className:"space-y-1 text-xs text-muted-foreground",children:[s.parentEmail&&e.jsxs("a",{href:`mailto:${s.parentEmail}`,className:"flex items-center gap-1.5 hover:text-foreground",children:[e.jsx(U,{className:"h-3 w-3"})," ",s.parentEmail]}),s.parentPhone&&e.jsxs("a",{href:`tel:${s.parentPhone}`,className:"flex items-center gap-1.5 hover:text-foreground",children:[e.jsx(W,{className:"h-3 w-3"})," ",s.parentPhone]}),!s.parentEmail&&!s.parentPhone&&e.jsx("span",{className:"italic",children:"No contact info"})]})}),e.jsx(m,{className:"align-top",children:s.hasCardOnFile?s.paymentFailed?e.jsxs(c,{className:"bg-amber-500/15 text-warning-text hover:bg-amber-500/20 border-0",children:[e.jsx(h,{className:"h-3 w-3 mr-1"})," Card on File — Payment Failed"]}):e.jsxs(c,{className:"bg-emerald-500/15 text-success-text hover:bg-emerald-500/20 border-0",children:[e.jsx(b,{className:"h-3 w-3 mr-1"})," Card on File"]}):e.jsxs(c,{variant:"destructive",className:"bg-destructive/15 text-destructive hover:bg-destructive/20 border-0",children:[e.jsx(h,{className:"h-3 w-3 mr-1"})," No Card"]})}),e.jsx(m,{className:"align-top text-right font-semibold",children:x(s.projectedMonthly)})]},s.familyId))})]})})})]}),e.jsx("div",{className:"flex justify-end pt-4",children:e.jsx(v,{variant:"outline",size:"sm",asChild:!0,children:e.jsx(y,{to:"/billing",children:"Go to Billing"})})})]})]})]})}export{se 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.