PageSourceSearch

https://app.backstagebaton.com/app/assets/EnsemblesPage-B6PvwRO6.js

js backstagebaton.com collected 2026-10-07 08:50:29 UTC 32,285 bytes, 1 lines download raw bytes

1import{c as Q,r as n,j as e,B as L,S as K,h as se,a as ne,z as be,p as ge,E as ye,u as le,t as re,C as ve,F as oe,l as je,m as Ne,b as Se,k as we,g as ke,a2 as Ce,a1 as Ee}from"./index-_aijvlUq.js";import{u as Ie,P as De}from"./PageHeader-DCofr6qo.js";import{e as H}from"./ensembles-WGlB365j.js";import{U as Re}from"./UsageLimitBanner-FQhQBbSE.js";import{I as Y}from"./Input-ysTyZFq5.js";import{a as Me}from"./Skeleton-B3Wj6cNd.js";import{s as J}from"./sections-BvnWLeCW.js";import{m as ce}from"./members-I3UAoZ9P.js";import{I as Fe}from"./InstrumentTag-CHdSvMU6.js";import{C as Le}from"./ChipToggleGroup-DiMa_Ns9.js";import{i as Ae}from"./instruments-CRxWHJ-h.js";import{v as Te}from"./venues-DxAiztOL.js";import{C as ze}from"./ConfirmDialog-CODvETNM.js";import{p as Pe}from"./performances-duTJPchz.js";import{M as Oe}from"./MapLink-BG5aOsD1.js";import{E as de}from"./EmptyState-CPGKooqj.js";import{b as ee}from"./badges-sJrwZCWE.js";import{u as me,s as Be}from"./useHighlightParam-DCzFvxlk.js";import{M as $e}from"./MobileListSkeleton-BxuyWDCs.js";import{M as Ve}from"./MobileFab-CAyx0Bpg.js";import{B as ue}from"./BottomSheet-BiQNSujt.js";import{e as _e}from"./ensembleTag-kZVL-M-W.js";import"./downscaleImage-qyGK-a3D.js";import"./Badge-DJIi163x.js";import"./ChipToggle-hmCaOMqs.js";import"./paletteHash-DBBw93pZ.js";const te=["brass","woodwind","percussion","string","keyboard","vocal"];function Ue(t){const m={};for(const h of t){const l=h.family??"other";m[l]||(m[l]=[]),m[l].push(h)}return m}function fe({ensembleId:t}){const{showSuccess:m,showError:h}=Q(),l=n.useRef(null),[x,f]=n.useState([]),[k,I]=n.useState(!0),[g,M]=n.useState(!1),[v,u]=n.useState(null),[j,b]=n.useState(""),[E,N]=n.useState(new Set),[z,D]=n.useState([]),[V,O]=n.useState(!1),[R,F]=n.useState(!1),[_,U]=n.useState([]);n.useEffect(()=>{t&&o()},[t]);async function o(){I(!0);try{const[r,p]=await Promise.all([J.list(t),ce.list({ensembleId:t,limit:500})]);f(r),U(p.members??[])}catch{h("Failed to load sections")}finally{I(!1)}}async function i(){u(null),b(""),N(new Set),M(!0),await y(null),requestAnimationFrame(()=>l.current?.scrollIntoView({behavior:"smooth",block:"nearest"}))}async function a(r){u(r),b(r.name),N(new Set(r.instruments.map(p=>p.id))),M(!0),await y(r.id),requestAnimationFrame(()=>l.current?.scrollIntoView({behavior:"smooth",block:"nearest"}))}async function y(r){O(!0);try{const p=await J.getAvailableInstruments(t,r);if(r){const B=x.find($=>$.id===r)?.instruments??[],P=[...p];for(const $ of B)P.find(C=>C.id===$.id)||P.push($);P.sort(($,C)=>{const G=te.indexOf($.family),Z=te.indexOf(C.family);return G!==Z?G-Z:$.name.localeCompare(C.name)}),D(P)}else D(p)}catch{h("Failed to load instruments")}finally{O(!1)}}function S(){M(!1),u(null)}function W(r){N(p=>{const T=new Set(p);return T.has(r)?T.delete(r):T.add(r),T})}async function c(r){if(r?.preventDefault(),!!j.trim()){F(!0);try{const p=Array.from(E);if(v){const T=await J.update(t,v.id,{name:j,instrumentIds:p});f(B=>B.map(P=>P.id===v.id?T:P)),m("Section updated")}else{const T=await J.create(t,{name:j,instrumentIds:p});f(B=>[...B,T]),m("Section created")}S()}catch(p){h(p.message||"Save failed")}finally{F(!1)}}}async function d(){if(v){F(!0);try{await J.remove(t,v.id),f(r=>r.filter(p=>p.id!==v.id)),S(),m("Section deleted")}catch(r){h(r.message||"Delete failed")}finally{F(!1)}}}async function w(r,p){try{const T=await J.setLeader(t,r.id,p);f(B=>B.map(P=>P.id===r.id?T:P))}catch{h("Failed to update section leader")}}function s(r){const p=new Set((r.instruments??[]).map(C=>C.id)),T=[],B=[];for(const C of _){if(C.memberStatus==="retired")continue;C.instruments?.some(Z=>p.has(Z.instrumentId))?T.push(C):B.push(C)}const P=(C,G)=>(C.lastName||"").localeCompare(G.lastName||"")||(C.firstName||"").localeCompare(G.firstName||"");T.sort(P),B.sort(P);const $=[{value:"",label:"No leader"}];for(const C of T)$.push({value:C.id,label:`${C.firstName} ${C.lastName}`});T.length>0&&B.length>0&&$.push({value:"__divider__",label:"────────────────",disabled:!0});for(const C of B)$.push({value:C.id,label:`${C.firstName} ${C.lastName}`});return $}const A=Ue(z),q=te.filter(r=>A[r]),X=Object.keys(A).filter(r=>!te.includes(r));return k?e.jsxs("div",{className:"mt-4 pt-4 border-t border-gray-100",children:[e.jsx("p",{className:"text-sm font-medium text-gray-700 mb-2",children:"Sections"}),e.jsx("p",{className:"text-sm text-gray-400",children:"Loading sections..."})]}):e.jsxs("div",{className:"mt-4 pt-4 border-t border-gray-100",children:[e.jsxs("div",{className:"flex items-center justify-between mb-3",children:[e.jsx("p",{className:"text-sm font-medium text-gray-700",children:"Sections"}),!g&&e.jsx(L,{size:"sm",onClick:i,children:"New section"})]}),g&&e.jsxs("div",{ref:l,className:"bg-gray-50 rounded-lg border border-gray-100 p-4 mb-3",children:[e.jsx("h3",{className:"text-sm font-semibold text-gray-500 uppercase tracking-wide mb-4",children:v?"Edit Section":"New Section"}),e.jsxs("div",{className:"flex gap-2 pt-1 mb-4",children:[e.jsx(L,{type:"submit",size:"sm",isLoading:R,children:v?"Save changes":"Create"}),e.jsx(L,{type:"button",variant:"secondary",size:"sm",onClick:S,children:"Cancel"}),v&&e.jsx(L,{type:"button",variant:"danger",size:"sm",className:"ml-auto",onClick:d,children:"Delete"})]}),e.jsxs("form",{onSubmit:c,className:"space-y-4",children:[e.jsx(Y,{label:"Name",placeholder:"Brass Section",value:j,onChange:r=>b(r.target.value),required:!0}),e.jsxs("div",{children:[e.jsx("p",{className:"text-sm font-medium text-gray-700 mb-2",children:"Instruments"}),V?e.jsx("p",{className:"text-sm text-gray-400",children:"Loading instruments..."}):z.length===0?e.jsx("p",{className:"text-sm text-gray-400",children:"No instruments available."}):e.jsx(Le,{groups:[...q,...X].map(r=>({label:r,items:A[r].map(p=>({id:p.id,name:p.name}))})),selectedIds:E,onToggle:W})]})]})]}),g?null:x.length===0?e.jsx("p",{className:"text-sm text-gray-400 mb-3",children:"No sections in this ensemble."}):e.jsx("div",{className:"space-y-2",children:x.map(r=>e.jsx("div",{className:"px-3 py-2.5 rounded-lg bg-gray-50 border border-gray-100",children:e.jsxs("div",{className:"flex items-start gap-3",children:[e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("p",{className:"text-sm font-medium text-gray-800",children:r.name}),e.jsxs("span",{className:"text-xs text-gray-400",children:[r.memberCount," ",r.memberCount===1?"member":"members"]})]}),r.instruments?.length>0&&e.jsx("div",{className:"flex flex-wrap gap-1 mt-1",children:r.instruments.map(p=>e.jsx(Fe,{name:p.name,family:p.family},p.id))}),e.jsx("div",{className:"mt-2",children:e.jsx(K,{value:r.leader?.id||"",onChange:p=>w(r,p.target.value),options:s(r),className:"w-full"})})]}),e.jsx(L,{variant:"ghost",size:"sm",onClick:()=>a(r),children:"Edit"})]})},r.id))})]})}const ie=["flute","clarinet","saxophone","double reed","horn","trumpet","trombone","euphonium","tuba","percussion","string","keyboard","vocal","other"];function xe({ensembleId:t}){const{showSuccess:m,showError:h}=Q(),[l,x]=n.useState([]),[f,k]=n.useState([]),[I,g]=n.useState(!0),[M,v]=n.useState(!1),[u,j]=n.useState(!1),[b,E]=n.useState(""),[N,z]=n.useState(1);n.useEffect(()=>{D()},[t]);async function D(){g(!0);try{const[c,d]=await Promise.all([H.getInstrumentation(t),Ae.list("member")]);x(c),k(d),j(!1)}catch{h("Failed to load instrumentation")}finally{g(!1)}}function V(){if(!b)return;if(l.some(d=>d.instrumentId===b)){h("That instrument is already in the list");return}const c=f.find(d=>d.id===b);x(d=>[...d,{instrumentId:b,instrumentName:c?.name||"",instrumentFamily:c?.family||"",maxPerformers:Number(N)||1,minPerformers:0,currentCount:0}]),E(""),z(1),j(!0)}function O(c){x(d=>d.filter(w=>w.instrumentId!==c)),j(!0)}function R(c,d){x(w=>w.map(s=>s.instrumentId===c?{...s,maxPerformers:Math.max(1,Number(d)||1)}:s)),j(!0)}function F(c,d){x(w=>w.map(s=>s.instrumentId===c?{...s,minPerformers:Math.max(0,Number(d)||0)}:s)),j(!0)}async function _(){v(!0);try{const c=l.map(w=>({instrumentId:w.instrumentId,maxPerformers:w.maxPerformers,minPerformers:w.minPerformers})),d=await H.setInstrumentation(t,c);x(d),j(!1),m("Instrumentation saved")}catch{h("Failed to save instrumentation")}finally{v(!1)}}const U=new Set(l.map(c=>c.instrumentId)),o=f.filter(c=>!U.has(c.id)),i=[];for(const c of ie){const d=o.filter(w=>w.family===c);if(d.length>0)for(const w of d)i.push({value:w.id,label:`${w.name} (${c})`})}const a={};for(const c of l){const d=c.instrumentFamily||"other";a[d]||(a[d]=[]),a[d].push(c)}const y=ie.filter(c=>a[c]);if(I)return e.jsxs("div",{className:"border-t border-gray-200 mt-4 pt-4",children:[e.jsx("h4",{className:"text-sm font-semibold text-gray-500 uppercase tracking-wide mb-3",children:"Instrumentation Limits"}),e.jsx("p",{className:"text-sm text-gray-400",children:"Loading..."})]});const S=l.reduce((c,d)=>c+d.maxPerformers,0),W=l.reduce((c,d)=>c+d.currentCount,0);return e.jsxs("div",{className:"border-t border-gray-200 mt-4 pt-4",children:[e.jsxs("div",{className:"flex items-center justify-between mb-3",children:[e.jsxs("h4",{className:"text-sm font-semibold text-gray-500 uppercase tracking-wide",children:["Instrumentation Limits",l.length>0&&e.jsxs("span",{className:"ml-1.5 font-normal normal-case text-gray-400",children:["(",W,"/",S," slots filled)"]})]}),u&&e.jsx(L,{size:"sm",onClick:_,isLoading:M,children:"Save instrumentation"})]}),l.length===0&&e.jsx("p",{className:"text-sm text-gray-400 mb-3",children:'No instrumentation limits set. All members will be considered "performing" for every performance.'}),y.map(c=>e.jsxs("div",{className:"mb-3",children:[e.jsx("h5",{className:"text-xs font-medium text-gray-400 uppercase tracking-wider mb-1.5 capitalize",children:c}),e.jsx("div",{className:"space-y-1.5",children:a[c].map(d=>e.jsxs("div",{className:"flex items-center gap-3 bg-gray-50 rounded-lg px-3 py-2",children:[e.jsx("span",{className:"text-sm font-medium text-gray-900 flex-1 min-w-0",children:d.instrumentName}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("label",{className:"text-xs text-gray-500",children:"Min"}),e.jsx("input",{type:"number",min:"0",value:d.minPerformers,onChange:w=>F(d.instrumentId,w.target.value),className:"w-14 px-2 py-1 text-sm border border-gray-200 rounded text-center focus:ring-2 focus:ring-band-500 focus:border-band-500"}),e.jsx("label",{className:"text-xs text-gray-500",children:"Max"}),e.jsx("input",{type:"number",min:"1",value:d.maxPerformers,onChange:w=>R(d.instrumentId,w.target.value),className:"w-14 px-2 py-1 text-sm border border-gray-200 rounded text-center focus:ring-2 focus:ring-band-500 focus:border-band-500"})]}),e.jsxs("span",{className:"text-xs text-gray-400 w-16 text-right",children:[d.currentCount," assigned"]}),e.jsx("button",{type:"button",onClick:()=>O(d.instrumentId),className:"text-gray-300 hover:text-red-500 transition-colors",title:"Remove",children:e.jsx("svg",{className:"h-4 w-4",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M6 18L18 6M6 6l12 12"})})})]},d.instrumentId))})]},c)),e.jsxs("div",{className:"flex items-end gap-2 mt-3",children:[e.jsx("div",{className:"flex-1",children:e.jsx(K,{label:"Add instrument",value:b,onChange:c=>E(c.target.value),options:[{value:"",label:"Select instrument..."},...i]})}),e.jsx("div",{className:"w-20",children:e.jsx(Y,{label:"Max",type:"number",min:"1",value:N,onChange:c=>z(c.target.value)})}),e.jsx(L,{size:"sm",variant:"secondary",onClick:V,disabled:!b,className:"mb-0.5",children:"Add"})]})]})}const We=["#4f46e5","#dc2626","#059669","#d97706","#7c3aed","#0891b2","#c026d3","#65a30d"],qe=[{value:"",label:"Select classification"},{value:"concert",label:"Concert Band"},{value:"orchestra",label:"Orchestra"},{value:"marching",label:"Marching Band"},{value:"jazz",label:"Jazz Ensemble"}],Ye=[{value:"",label:"No default day"},{value:"0",label:"Sunday"},{value:"1",label:"Monday"},{value:"2",label:"Tuesday"},{value:"3",label:"Wednesday"},{value:"4",label:"Thursday"},{value:"5",label:"Friday"},{value:"6",label:"Saturday"}];function ae(t){return t?{name:t.name,description:t.description??"",classification:t.classification??"",color:t.color??"",defaultRehearsalVenueId:t.defaultRehearsalVenueId??"",defaultRehearsalDay:t.defaultRehearsalDay!=null?String(t.defaultRehearsalDay):"",defaultRehearsalStartTime:t.defaultRehearsalStartTime??"",defaultRehearsalEndTime:t.defaultRehearsalEndTime??"",libraryMode:t.libraryMode??"librarian_managed"}:{name:"",description:"",classification:"",color:"",defaultRehearsalVenueId:"",defaultRehearsalDay:"",defaultRehearsalStartTime:"",defaultRehearsalEndTime:"",libraryMode:"librarian_managed"}}function he({ensemble:t=null,onSaved:m,onCancel:h,onDeleted:l,showTopActions:x=!1}){const f=!!t,k=se(a=>a.currentOrg?.id),{showSuccess:I,showError:g}=Q(),{canFully:M}=ne(),v=M("ensemble:create"),[u,j]=n.useState(()=>ae(t)),[b,E]=n.useState([]),[N,z]=n.useState(!1),[D,V]=n.useState(!1),O=n.useRef(f?ae(t):null);n.useEffect(()=>{if(!f||!k)return;let a=!1;return Te.list(k).then(y=>{a||E(Array.isArray(y)?y:[])}).catch(be("venue picker in the ensemble form is optional")),()=>{a=!0}},[f,k]);const R=a=>y=>j(S=>({...S,[a]:y.target.value})),F=!f||!O.current||Object.keys(ae(t)).some(a=>u[a]!==O.current[a]),_=!!u.name.trim()&&F;async function U(a){if(a?.preventDefault?.(),!u.name.trim())return;z(!0);const y={...u,color:u.color||null,defaultRehearsalVenueId:u.defaultRehearsalVenueId||null,defaultRehearsalDay:u.defaultRehearsalDay!==""?Number(u.defaultRehearsalDay):null,defaultRehearsalStartTime:u.defaultRehearsalStartTime||null,defaultRehearsalEndTime:u.defaultRehearsalEndTime||null};try{if(f){const S=await H.update(t.id,y);I("Ensemble updated"),m?.(S,"edit")}else{const S=await H.create({...y,orgId:k});I("Ensemble created"),m?.(S,"create")}}catch(S){g(S.message||ye)}finally{z(!1)}}async function o(){try{await H.remove(t.id),I("Ensemble deleted"),V(!1),l?.(t.id)}catch(a){g(a.message||ge)}}const i=()=>e.jsxs("div",{className:"flex gap-2 pt-1",children:[e.jsx(L,{type:"button",size:"sm",isLoading:N,disabled:!_,onClick:U,children:f?"
1Save changes":"Create"}),e.jsx(L,{type:"button",variant:"secondary",size:"sm",onClick:h,children:"Cancel"}),f&&v&&l&&e.jsx(L,{type:"button",variant:"danger",size:"sm",className:"ml-auto",onClick:()=>V(!0),children:"Delete"})]});return e.jsxs(e.Fragment,{children:[e.jsx(ze,{isOpen:D,onClose:()=>V(!1),onConfirm:o,title:"Delete Ensemble",message:`Delete "${t?.name}"? Members will lose this ensemble assignment.`,confirmLabel:"Delete"}),x&&e.jsx("div",{className:"mb-4",children:i()}),e.jsxs("form",{onSubmit:U,className:"space-y-3",children:[e.jsx(Y,{label:"Name",placeholder:"Concert Band",value:u.name,onChange:R("name"),required:!0}),e.jsx(Y,{label:"Description",placeholder:"Optional description",value:u.description,onChange:R("description")}),e.jsx(K,{label:"Classification",value:u.classification,onChange:R("classification"),options:qe}),e.jsxs("div",{children:[e.jsx("p",{className:"text-sm font-medium text-gray-700 mb-1.5",children:"Calendar Color"}),e.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[We.map(a=>e.jsx("button",{type:"button",onClick:()=>j(y=>({...y,color:y.color===a?"":a})),className:`w-7 h-7 rounded-full border-2 transition-all ${u.color===a?"border-gray-900 scale-110":"border-transparent hover:border-gray-300"}`,style:{backgroundColor:a},"aria-label":`Color ${a}`},a)),!u.color&&e.jsx("span",{className:"text-xs text-gray-400 ml-1",children:"Auto"})]})]}),f&&e.jsxs(e.Fragment,{children:[e.jsx("h4",{className:"text-sm font-semibold text-gray-500 uppercase tracking-wide mt-6 mb-2",children:"Rehearsal Defaults"}),e.jsx(K,{label:"Default Venue",value:u.defaultRehearsalVenueId,onChange:R("defaultRehearsalVenueId"),options:[{value:"",label:"No default venue"},...b.map(a=>({value:a.id,label:a.name}))]}),e.jsx(K,{label:"Default Day of Week",value:u.defaultRehearsalDay,onChange:R("defaultRehearsalDay"),options:Ye}),e.jsxs("div",{className:"flex gap-3",children:[e.jsx("div",{className:"flex-1",children:e.jsx(Y,{label:"Default Start Time",type:"time",value:u.defaultRehearsalStartTime,onChange:R("defaultRehearsalStartTime")})}),e.jsx("div",{className:"flex-1",children:e.jsx(Y,{label:"Default End Time",type:"time",value:u.defaultRehearsalEndTime,onChange:R("defaultRehearsalEndTime")})})]}),e.jsx(K,{label:"Library Management",value:u.libraryMode,onChange:R("libraryMode"),options:[{value:"librarian_managed",label:"Librarian-managed (physical check-in/out)"},{value:"self_managed",label:"Self-managed (members hold their own parts)"}]}),e.jsx("p",{className:"text-xs text-gray-500 -mt-2",children:"Self-managed ensembles skip the librarian check-in / check-out tasks on every performance, and their concerts don’t appear in Music Folders — members keep their own parts."})]}),i()]})]})}function pe({ensembleId:t,orgId:m}){const h=le(),{showError:l}=Q(),[x,f]=n.useState(void 0),[k,I]=n.useState([]),[g,M]=n.useState(!1);if(n.useEffect(()=>{if(!t||!m)return;let o=!1;return Promise.all([ce.list({ensembleId:t,status:"active",limit:500}),Pe.list(m,{ensembleId:t})]).then(([i,a])=>{o||(f(i.members??[]),I(a??[]))}).catch(()=>{o||(f([]),l(re("ensemble details")))}),()=>{o=!0}},[t,m]),x===void 0)return e.jsx("div",{className:"px-5 py-4",children:e.jsx("p",{className:"text-sm text-gray-400",children:"Loading…"})});const v={};for(const o of x)for(const i of o.instruments||[])v[i.instrumentId]||(v[i.instrumentId]={name:i.name,count:0}),v[i.instrumentId].count++;const u=Object.entries(v).sort((o,i)=>i[1].count-o[1].count);function j(o){const i=new URLSearchParams({ensembleId:t,...o});h(`/members?${i}`)}const b=k??[],E=new Date;E.setFullYear(E.getFullYear()-1);const N=ve(E),z=[],D=[];for(const o of b)!o.performanceDate||o.performanceDate>=N?z.push(o):D.push(o);const V=g?b:z;function O(o){const i=[],a={};for(const y of o){const S=y.performanceDate?y.performanceDate.slice(0,7):"undated";a[S]||(a[S]={key:S,performances:[]},i.push(a[S])),a[S].performances.push(y)}return i}const R=O(V);function F(o){if(o==="undated")return"Date TBD";const[i,a]=o.split("-"),y=new Date(Number(i),Number(a)-1),S=new Date,W=y.toLocaleDateString("en-US",{month:"long",year:"numeric"});return Number(i)===S.getFullYear()&&Number(a)-1===S.getMonth()?`${W} (this month)`:W}function _(o){if(!o)return null;const[i,a,y]=o.split("-");return new Date(Number(i),Number(a)-1,Number(y)).toLocaleDateString("en-US",{weekday:"short",day:"numeric"})}function U(o){return o?o>=je():!0}return e.jsxs("div",{className:"bg-gray-50 rounded-lg",children:[e.jsxs("div",{className:"px-5 py-3 space-y-3",children:[u.length>0&&e.jsxs("div",{children:[e.jsx("h4",{className:"text-xs font-semibold text-gray-500 uppercase tracking-wide mb-2",children:"Instrumentation"}),e.jsx("div",{className:"flex flex-wrap gap-2",children:u.map(([o,{name:i,count:a}])=>e.jsxs("button",{type:"button",onClick:()=>j({instrumentId:o}),className:"inline-flex items-center gap-1 px-2 py-0.5 rounded-full bg-white border border-gray-200 text-xs text-gray-700 hover:border-band-400 hover:text-band-700 transition-colors cursor-pointer",children:[i,e.jsx("span",{className:"text-gray-400 font-medium",children:a})]},o))})]}),e.jsx("button",{type:"button",onClick:()=>j({}),className:"text-sm font-medium text-band-600 hover:text-band-700 transition-colors",children:"View Members →"})]}),e.jsxs("div",{className:"border-t border-gray-200 px-5 py-3",children:[e.jsxs("h4",{className:"text-xs font-semibold text-gray-500 uppercase tracking-wide mb-3",children:["Performance History",b.length>0&&e.jsxs("span",{className:"ml-1.5 font-normal normal-case text-gray-400",children:["(",b.length,")"]})]}),b.length===0?e.jsx(de,{size:"compact",title:"No performances yet."}):e.jsxs("div",{className:"relative",children:[e.jsx("div",{className:"absolute left-[5px] top-2 bottom-2 w-px bg-gray-200"}),R.map(o=>e.jsxs("div",{className:"mb-3 last:mb-0",children:[e.jsxs("div",{className:"relative flex items-center gap-3 mb-1.5",children:[e.jsx("span",{className:"relative z-10 w-[11px] h-[11px] rounded-full bg-gray-300 shrink-0"}),e.jsx("span",{className:"text-xs font-semibold text-gray-500",children:F(o.key)})]}),e.jsx("div",{className:"ml-[5px] pl-5 border-l border-transparent space-y-1",children:o.performances.map(i=>{const a=U(i.performanceDate);return e.jsxs("div",{className:"group flex items-start gap-3 py-1.5 px-2.5 -ml-1 rounded-lg hover:bg-white hover:shadow-sm transition-all cursor-pointer",onClick:()=>h(`/performances?highlight=${i.id}`),children:[e.jsx("span",{className:`shrink-0 text-xs font-medium w-12 pt-0.5 ${a?"text-band-600":"text-gray-400"}`,children:_(i.performanceDate)??"TBD"}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("p",{className:`text-sm font-medium truncate ${a?"text-gray-900":"text-gray-600"}`,children:i.title}),e.jsxs("div",{className:"flex items-center gap-2 text-xs text-gray-400 mt-0.5",children:[i.venueName&&e.jsx(Oe,{name:i.venueName,city:i.venueCity,size:"xs"}),i.performanceTime&&e.jsx("span",{className:"shrink-0",children:oe(i.performanceTime)}),i.principalDirectorName&&e.jsxs("span",{className:"shrink-0 hidden sm:inline",children:[e.jsx("svg",{className:"inline-block h-3 w-3 mr-0.5 -mt-px",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"})}),i.principalDirectorName]})]})]}),a&&e.jsx("span",{className:"shrink-0 text-[10px] font-semibold uppercase tracking-wider text-band-600 bg-band-50 px-1.5 py-0.5 rounded",children:"Upcoming"})]},i.id)})})]},o.key)),D.length>0&&!g&&e.jsxs("div",{className:"relative flex items-center gap-3 mt-2",children:[e.jsx("span",{className:"relative z-10 w-[11px] h-[11px] rounded-full bg-gray-200 shrink-0 flex items-center justify-center",children:e.jsx("span",{className:"w-[5px] h-[5px] rounded-full bg-gray-400"})}),e.jsxs("button",{type:"button",onClick:()=>M(!0),className:"text-xs font-medium text-band-600 hover:text-band-700 transition-colors",children:["Show ",D.length," earlier ",D.length===1?"performance":"performances"," →"]})]}),g&&D.length>0&&e.jsxs("div",{className:"relative flex items-center gap-3 mt-2",children:[e.jsx("span",{className:"relative z-10 w-[11px] h-[11px] rounded-full bg-gray-200 shrink-0"}),e.jsx("button",{type:"button",onClick:()=>M(!1),className:"text-xs font-medium text-gray-400 hover:text-gray-600 transition-colors",children:"Show recent only"})]})]})]})]})}function He({isOpen:t,onClose:m,ensemble:h=null,onSaved:l,onDeleted:x}){return e.jsx(ue,{isOpen:t,onClose:m,title:h?"Edit ensemble":"New ensemble",children:e.jsx("div",{style:{padding:"var(--bb-space-4)"},children:t&&e.jsx(he,{ensemble:h,onCancel:m,onSaved:(f,k)=>{l?.(f,k),m?.()},onDeleted:f=>{x?.(f),m?.()}},h?.id||"new")})})}const Ge=[{key:"details",label:"Details"},{key:"sections",label:"Sections"},{key:"instrumentation",label:"Instrumentation"}];function Je({ensemble:t,isOpen:m,onClose:h,canManage:l,onEdit:x}){const f=se(g=>g.currentOrg?.id),[k,I]=n.useState("details");return n.useEffect(()=>{m&&I("details")},[m,t?.id]),e.jsx(ue,{isOpen:m&&!!t,onClose:h,title:t?.name||"",children:t&&e.jsxs("div",{style:{padding:"var(--bb-space-4)"},children:[t.description&&e.jsx("p",{className:"text-sm text-gray-500",children:t.description}),l&&e.jsx("div",{className:"mt-3 mb-1",children:e.jsx(L,{size:"sm",variant:"secondary",onClick:()=>x?.(t),children:"Edit ensemble"})}),l?e.jsx("div",{className:"flex border-b border-gray-200 my-4",children:Ge.map(g=>e.jsx("button",{type:"button",onClick:()=>I(g.key),className:`px-3 py-2 text-xs font-medium border-b-2 transition-colors ${k===g.key?"border-band-500 text-band-700":"border-transparent text-gray-400"}`,children:g.label},g.key))}):e.jsx("div",{className:"my-3"}),k==="details"&&e.jsx(pe,{ensembleId:t.id,orgId:f}),l&&k==="sections"&&e.jsx(fe,{ensembleId:t.id}),l&&k==="instrumentation"&&e.jsx(xe,{ensembleId:t.id})]})})}const Ke=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"];function Qe(t){const m=[];return t.defaultRehearsalDay!=null&&m.push(Ke[t.defaultRehearsalDay]),t.defaultRehearsalStartTime&&m.push(oe(t.defaultRehearsalStartTime)),m.join(" ")||null}function Xe(){const t=se(N=>N.currentOrg?.id),{showError:m}=Q(),{canFully:h}=ne(),l=h("ensemble:create"),[x,f]=n.useState([]),[k,I]=n.useState(!0),[g,M]=n.useState(!1),[v,u]=n.useState(null),[j,b]=n.useState(null);me(x,k,b);const E=n.useCallback(()=>{t&&(I(!0),H.list(t).then(N=>f(Array.isArray(N)?N:[])).catch(()=>m(re("ensembles"))).finally(()=>I(!1)))},[t]);return n.useEffect(()=>{E()},[E]),e.jsxs("div",{style:{paddingBottom:l?96:void 0},children:[k?e.jsx($e,{variant:"performance",count:3}):x.length===0?e.jsx("div",{style:{margin:"var(--bb-space-4)",padding:"var(--bb-space-6)",background:"var(--bb-surface)",border:"1px solid var(--bb-border-soft)",borderRadius:"var(--bb-radius-lg)",textAlign:"center",color:"var(--bb-fg-muted)"},children:"No ensembles yet."}):e.jsx("ul",{"data-testid":"mobile-ensembles-list",style:{listStyle:"none",margin:0,padding:"var(--bb-space-3) 0 0"},children:x.map(N=>e.jsx(Ze,{ensemble:N,onOpen:()=>b(N)},N.id))}),l&&e.jsx(Ve,{onClick:()=>M(!0),label:"New ensemble",testId:"mobile-ensemble-fab"}),e.jsx(He,{isOpen:g||!!v,ensemble:v,onClose:()=>{M(!1),u(null)},onSaved:E,onDeleted:E}),e.jsx(Je,{ensemble:j,isOpen:!!j,onClose:()=>b(null),canManage:l,onEdit:N=>{b(null),u(N)}})]})}function Ze({ensemble:t,onOpen:m}){const h=_e({id:t.id,color:t.color}),l=Qe(t),x=t.memberCount??t.activeMembers??null,f=t.libraryMode==="self_managed"?"
1Self-managed library":null;return e.jsxs("li",{onClick:m,style:{margin:"0 var(--bb-space-4) var(--bb-space-3)",padding:"var(--bb-space-4)",background:"var(--bb-surface)",border:"1px solid var(--bb-border)",borderRadius:"var(--bb-radius-lg)",boxShadow:"var(--bb-shadow-xs)",cursor:"pointer"},children:[e.jsxs("div",{style:{display:"flex",alignItems:"center",gap:"var(--bb-space-2)",marginBottom:4},children:[e.jsx("span",{"aria-hidden":"true",style:{width:10,height:10,borderRadius:"50%",flexShrink:0,background:h.fg}}),e.jsx("div",{style:{fontSize:17,fontWeight:700,color:"var(--bb-fg)",flex:1,minWidth:0,overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},children:t.name})]}),t.description&&e.jsx("div",{style:{fontSize:13,color:"var(--bb-fg-muted)",marginBottom:8},children:t.description}),e.jsxs("div",{style:{display:"flex",flexWrap:"wrap",gap:8,fontSize:13,color:"var(--bb-fg-body)"},children:[x!=null&&e.jsxs("div",{children:[x," member",x===1?"":"s"]}),l&&e.jsxs("div",{children:["· Rehearses ",l]}),t.classification&&e.jsxs("div",{children:["· ",t.classification]})]}),f&&e.jsx("div",{style:{marginTop:6},children:e.jsx("span",{style:{display:"inline-block",padding:"2px 8px",borderRadius:"var(--bb-radius-pill)",background:"var(--bb-info-soft)",color:"var(--bb-info-ink)",fontSize:11,fontWeight:600},children:f})})]})}const et={concert:"Concert Band",orchestra:"Orchestra",marching:"Marching Band",jazz:"Jazz Ensemble"};function Et(){Ie();const t=Ne(),m=le(),h=Se(s=>s.user?.orgId),l=t.orgId||h,x=!!t.orgId,{orgs:f}=se(),{showError:k}=Q(),{canFully:I}=ne(),g=I("ensemble:create"),M=we(s=>s.getMetric("ensembles")),v=ke(),u=f.find(s=>s.id===l),j=n.useRef(null),[b,E]=n.useState([]),[N,z]=n.useState(!0),[D,V]=n.useState(""),[O,R]=n.useState(!1),[F,_]=n.useState(null),[U,o]=n.useState(null);n.useEffect(()=>{i()},[l]);async function i(){if(!l){z(!1);return}z(!0);try{const s=await H.list(l);E(s)}catch{k(re("ensembles"))}finally{z(!1)}}me(b,N||v,s=>{o(s.id),Be(s.id)});function a(s){o(A=>A===s?null:s)}function y(){_(null),R(!0),requestAnimationFrame(()=>j.current?.scrollIntoView({behavior:"smooth",block:"start"}))}function S(s){_(s),R(!0),requestAnimationFrame(()=>j.current?.scrollIntoView({behavior:"smooth",block:"start"}))}function W(){R(!1),_(null)}function c(s,A){E(A==="edit"?q=>q.map(X=>X.id===s.id?s:X):q=>[...q,s]),W()}function d(s){E(A=>A.filter(q=>q.id!==s)),W()}const w=D?b.filter(s=>s.name.toLowerCase().includes(D.toLowerCase())):b;return v?e.jsx(Xe,{}):e.jsxs("div",{children:[e.jsx(De,{title:x?`${u?.name??"Organization"} — Ensembles`:"Ensembles",breadcrumbs:x?[{label:"Home",to:"/"},{label:"Settings"},{label:"Organizations",to:"/settings/organizations"},{label:u?.name??"Organization",to:`/settings/organizations/${l}`},{label:"Ensembles"}]:[{label:"Home",to:"/"},{label:"Ensembles"}],actions:e.jsxs("div",{className:"flex gap-2",children:[x&&e.jsx(L,{variant:"secondary",onClick:()=>m("/settings/organizations"),children:"← Organizations"}),g&&e.jsx(L,{onClick:y,children:"New ensemble"})]})}),M&&e.jsx(Re,{metricName:"Ensembles",current:M.current,limit:M.limit}),e.jsx("div",{className:"mb-4",children:e.jsx(Y,{placeholder:"Search ensembles…",value:D,onChange:s=>V(s.target.value),className:"w-64"})}),O&&e.jsxs("div",{ref:j,className:"bg-white rounded-xl border border-gray-200 p-6 mb-4",children:[e.jsx("h3",{className:"text-sm font-semibold text-gray-500 uppercase tracking-wide mb-4",children:F?"Edit Ensemble":"New Ensemble"}),e.jsx(he,{ensemble:F,showTopActions:!0,onSaved:c,onCancel:W,onDeleted:d}),F&&e.jsx(fe,{ensembleId:F.id}),F&&e.jsx(xe,{ensembleId:F.id})]}),!O&&(N?e.jsx("div",{className:"space-y-2",children:Array.from({length:4}).map((s,A)=>e.jsx(Me,{lines:2},A))}):w.length===0?e.jsx(de,{card:!0,title:D?"No ensembles match your search.":"No ensembles yet.",action:g&&!D?e.jsx(L,{onClick:y,children:"Create first ensemble"}):null}):e.jsx("div",{className:"space-y-2",children:w.map(s=>{const A=U===s.id;return e.jsxs("div",{id:`row-${s.id}`,className:"bg-white rounded-xl border border-gray-200 overflow-hidden flex scroll-mt-4",children:[e.jsx("div",{className:`${A?"w-7":"w-8"} shrink-0 cursor-pointer flex items-center justify-center`,style:{backgroundColor:s.color||Ee(s.name)},onClick:()=>
1a(s.id),title:s.name,children:A?e.jsx("span",{className:"text-white/90 font-semibold text-[10px] tracking-wide whitespace-nowrap",style:{writingMode:"vertical-rl",transform:"rotate(180deg)",textOrientation:"mixed"},children:s.name}):e.jsx("span",{className:"text-white/90 font-bold text-[10px] leading-none tracking-tight",children:Ce(s.name)})}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"px-5 py-4 flex items-center gap-4 cursor-pointer hover:bg-gray-50 transition-colors",onClick:()=>a(s.id),children:[e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("p",{className:"font-medium text-gray-900",children:s.name}),s.classification&&e.jsx("span",{className:"inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-band-100 text-band-700",children:et[s.classification]}),s.libraryMode==="self_managed"&&e.jsx("span",{className:"inline-flex items-center px-2 py-0.5 rounded-full text-xs font-medium bg-indigo-100 text-indigo-700",title:"Members hold their own parts — no librarian tasks",children:"Self-managed library"})]}),s.description&&e.jsx("p",{className:"text-sm text-gray-500 mt-0.5",children:s.description})]}),e.jsxs("span",{className:"text-xs text-gray-400 shrink-0",children:[s.memberCount," ",s.memberCount===1?"member":"members",s.sectionCount>0&&` · ${s.sectionCount} ${s.sectionCount===1?"section":"sections"}`]}),g&&e.jsxs("div",{className:"flex gap-2 shrink-0",onClick:q=>q.stopPropagation(),children:[e.jsx(L,{variant:"ghost",size:"sm",onClick:()=>ee.openPdf(ee.urlForEnsemble(s.id)),children:"Print badges"}),e.jsx(L,{variant:"ghost",size:"sm",onClick:()=>ee.openPdf(ee.tentUrlForEnsemble(s.id)),children:"Stand tents"}),e.jsx(L,{variant:"ghost",size:"sm",onClick:()=>S(s),children:"Edit"})]}),e.jsx("svg",{className:`h-4 w-4 text-gray-400 shrink-0 transition-transform duration-200 ${A?"rotate-180":""}`,fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",strokeWidth:2,children:e.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M19 9l-7 7-7-7"})})]}),A&&e.jsx("div",{className:"border-t border-gray-100 p-3",children:e.jsx(pe,{ensembleId:s.id,orgId:l})})]})]},s.id)})}))]})}export{Et as EnsemblesPage};

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.