PageSourceSearch

https://tiaflorida.com/assets/ElectionAdmin-3FQH9c47.js

js tiaflorida.com collected 2026-10-09 22:24:33 UTC 13,156 bytes, 1 lines download raw bytes

1import{i as $,x as H,r as c,j as e,y as u,X as J,t as g}from"./index-BtfH9wlj.js";import{C as B,b as X,c as q,a as I}from"./card-DyZSDQ4d.js";import{B as p}from"./button-BOklcLP3.js";import{I as N}from"./input-BwcwB3Vl.js";import{T as O}from"./textarea-DdnFK6Er.js";import{L as w}from"./label-CIY4XlA3.js";import{B as F}from"./badge-aVCiQrRq.js";import{P as S}from"./plus-Do01sbVQ.js";import{L as C}from"./loader-circle-DYPCNajK.js";import{U as G}from"./users-3UcLK3PV.js";import{T as K}from"./trash-2-DLhO2uwa.js";import{U as Q}from"./user-plus-CrNUhvdF.js";import{V as W}from"./vote-GtvluTsq.js";import{L as Y}from"./lock-DsaIslzT.js";import{T as U}from"./trophy-CByPZ1yo.js";import"./index-F-KguS3Q.js";import"./index-CYtkBTWk.js";function Z({election:d,onChanged:h}){const{toast:f}=$(),y=H(),[P,L]=c.useState([]),[E,A]=c.useState([]),[o,x]=c.useState(!0),[l,b]=c.useState({title:"",description:"",max_selections:1}),[D,T]=c.useState(!1),[k,v]=c.useState({}),[_,z]=c.useState({}),j=async()=>{x(!0);try{const t=await g.functions.invoke("getElectionAdminData",{election_id:d.id}),a=(t==null?void 0:t.data)||t||{};if(a.error)throw new Error(a.error);L(a.positions||[]),A(a.candidates||[])}catch(t){f({title:"Load failed",description:t.message,variant:"destructive"})}finally{x(!1)}};c.useEffect(()=>{j()},[d.id]);const M=async()=>{if(l.title){T(!0);try{const t=await g.functions.invoke("saveElectionPosition",{position:{election_id:d.id,election_title:d.title,title:l.title,description:l.description,max_selections:Math.max(1,Number(l.max_selections)||1),sort_order:P.length},is_new:!0}),a=(t==null?void 0:t.data)||t;if(a!=null&&a.error)throw new Error(a.error);b({title:"",description:"",max_selections:1}),j(),h()}catch(t){f({title:"Failed",description:t.message,variant:"destructive"})}finally{T(!1)}}},R=async t=>{const a=k[t.id]||{name:"",bio:"",image_url:""};if(a.name){z(i=>({...i,[t.id]:!0}));try{const i=await g.functions.invoke("saveElectionCandidate",{candidate:{election_id:d.id,position_id:t.id,position_title:t.title,name:a.name,bio:a.bio,image_url:a.image_url,sort_order:E.filter(m=>m.position_id===t.id).length},is_new:!0}),r=(i==null?void 0:i.data)||i;if(r!=null&&r.error)throw new Error(r.error);v(m=>({...m,[t.id]:{name:"",bio:"",image_url:""}})),j()}catch(i){f({title:"Failed",description:i.message,variant:"destructive"})}finally{z(i=>({...i,[t.id]:!1}))}}},s=async t=>{if(confirm(`Delete position "${t.title}" and all its candidates?`))try{const a=await g.functions.invoke("deleteElectionPosition",{position_id:t.id}),i=(a==null?void 0:a.data)||a;if(i!=null&&i.error)throw new Error(i.error);j(),h()}catch(a){f({title:"Failed",description:a.message,variant:"destructive"})}},n=async t=>{try{const a=await g.functions.invoke("deleteElectionCandidate",{candidate_id:t.id}),i=(a==null?void 0:a.data)||a;if(i!=null&&i.error)throw new Error(i.error);j()}catch(a){f({title:"Failed",description:a.message,variant:"destructive"})}};return e.jsxs("div",{className:"space-y-4",children:[e.jsxs(B,{children:[e.jsx(X,{children:e.jsxs(q,{className:"text-base flex items-center gap-2",children:[e.jsx(S,{className:"w-4 h-4"}),"Add position"]})}),e.jsxs(I,{className:"space-y-3",children:[e.jsxs("div",{children:[e.jsx(w,{children:"Title"}),e.jsx(N,{value:l.title,onChange:t=>b({...l,title:t.target.value}),placeholder:"e.g. President"})]}),e.jsxs("div",{children:[e.jsx(w,{children:"Description"}),e.jsx(O,{rows:2,value:l.description,onChange:t=>b({...l,description:t.target.value})})]}),e.jsxs("div",{className:"w-40",children:[e.jsx(w,{children:"Max selections per ballot"}),e.jsx(N,{type:"number",min:1,value:l.max_selections,onChange:t=>b({...l,max_selections:t.target.value})})]}),e.jsxs(p,{size:"sm",onClick:M,disabled:D||!l.title||!u(y,"elections.manage_positions"),children:[D?e.jsx(C,{className:"w-4 h-4 animate-spin mr-2"}):e.jsx(S,{className:"w-4 h-4 mr-2"}),"Add position"]})]})]}),o?e.jsx(C,{className:"w-4 h-4 animate-spin"}):P.map(t=>{const a=E.filter(r=>r.position_id===t.id),i=k[t.id]||{name:"",bio:"",image_url:""};return e.jsx(B,{children:e.jsxs(I,{className:"py-4 space-y-3",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{children:[e.jsx("span",{className:"font-semibold",children:t.title}),e.jsxs(F,{variant:"outline",className:"ml-2",children:[t.max_selections||1," max"]}),e.jsxs("span",{className:"ml-2 text-xs text-muted-foreground flex items-center gap-1 inline-flex",children:[e.jsx(G,{className:"w-3 h-3"}),a.length," candidate",a.length===1?"":"s"]})]}),u(y,"elections.manage_positions")&&e.jsx(p,{size:"sm",variant:"ghost",onClick:()=>s(t),children:e.jsx(K,{className:"w-3.5 h-3.5 text-red-500"})})]}),t.description&&e.jsx("p",{className:"text-xs text-muted-foreground",children:t.description}),e.jsxs("div",{className:"space-y-1",children:[a.map(r=>e.jsxs("div",{className:"flex items-center gap-2 rounded border px-2 py-1",children:[r.image_url&&e.jsx("img",{src:r.image_url,className:"w-7 h-7 rounded-full object-cover",alt:""}),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsx("div",{className:"text-sm font-medium truncate",children:r.name}),r.bio&&e.jsx("div",{className:"text-xs text-muted-foreground truncate",children:r.bio})]}),u(y,"elections.manage_candidates")&&e.jsx(p,{size:"sm",variant:"ghost",onClick:()=>n(r),children:e.jsx(J,{className:"w-3.5 h-3.5 text-red-500"})})]},r.id)),a.length===0&&e.jsx("span",{className:"text-xs text-muted-foreground",children:"No candidates yet."})]}),e.jsxs("div",{className:"rounded-lg border border-dashed p-2 space-y-2",children:[e.jsxs("div",{className:"flex items-center gap-1 text-xs font-semibold text-muted-foreground",children:[e.jsx(Q,{className:"w-3.5 h-3.5"}),"Add candidate"]}),e.jsx(N,{placeholder:"Name",value:i.name,onChange:r=>v(m=>({...m,[t.id]:{...i,name:r.target.value}}))}),e.jsx(N,{placeholder:"Image URL (optional)",value:i.image_url,onChange:r=>v(m=>({...m,[t.id]:{...i,image_url:r.target.value}}))}),e.jsx(O,{rows:2,placeholder:"Bio (optional)",value:i.bio,onChange:r=>v(m=>({...m,[t.id]:{...i,bio:r.target.value}}))}),e.jsxs(p,{size:"sm",variant:"outline",onClick:()=>R(t),disabled:_[t.id]||!i.name||!u(y,"elections.manage_candidates"),children:[_[t.id]?e.jsx(C,{className:"w-4 h-4 animate-spin mr-2"}):e.jsx(S,{className:"w-4 h-4 mr-2"}),"Add"]})]})]})},t.id)})]})}const V={title:"",description:"",open_at:"",close_at:"",is_member_only:!0,show_results_after_close:!0};function je(){const{toast:d}=$(),h=H(),[f,y]=c.useState([]),[P,L]=c.useState(!0),[E,A]=c.useState(!1),[o,x]=c.useState(V),[l,b]=c.useState(null),[D,T]=c.useState({}),[k,v]=c.useState({}),_=async()=>{L(!0);try{const s=await g.functions.invoke("getElectionAdminData",{}),n=(s==null?void 0:s.data)||s||{};if(n.error)throw new Error(n.error);y(n.elections||[])}catch(s){d({title:"Load failed",description:s.message,variant:"destructive"})}finally{L(!1)}};c.useEffect(()=>{_()},[]);const z=async()=>
1{if(o.title){A(!0);try{const s=await g.functions.invoke("saveElection",{election:{title:o.title,description:o.description,status:"draft",open_at:o.open_at?new Date(o.open_at).toISOString():void 0,close_at:o.close_at?new Date(o.close_at).toISOString():void 0,is_member_only:o.is_member_only,show_results_after_close:o.show_results_after_close,is_active:!0},is_new:!0}),n=(s==null?void 0:s.data)||s;if(n!=null&&n.error)throw new Error(n.error);x(V),d({title:"Election created"}),_()}catch(s){d({title:"Create failed",description:s.message,variant:"destructive"})}finally{A(!1)}}},j=async(s,n)=>{try{const t=await g.functions.invoke("setElectionStatus",{election_id:s.id,status:n}),a=(t==null?void 0:t.data)||t;if(a!=null&&a.error)throw new Error(a.error);d({title:`Election ${n}`}),_()}catch(t){d({title:"Failed",description:t.message,variant:"destructive"})}},M=async s=>{v(n=>({...n,[s.id]:!0}));try{const n=await fetch(`/api/functions/getElectionResults?election_id=${s.id}`),t=await n.json();if(!n.ok)throw new Error(t.error||"Results unavailable");T(a=>({...a,[s.id]:t}))}catch(n){d({title:"Results unavailable",description:n.message,variant:"destructive"})}finally{v(n=>({...n,[s.id]:!1}))}},R=s=>s?new Date(s).toLocaleString(void 0,{dateStyle:"medium",timeStyle:"short"}):"";return e.jsxs("div",{className:"max-w-5xl mx-auto px-6 py-8 space-y-6",children:[e.jsxs("div",{children:[e.jsxs("h1",{className:"text-2xl font-bold flex items-center gap-2",children:[e.jsx(W,{className:"w-6 h-6 text-amber-600"}),"Election Administration"]}),e.jsxs("p",{className:"text-sm text-muted-foreground flex items-center gap-1",children:[e.jsx(Y,{className:"w-3 h-3"}),"Secret-ballot elections — votes are stored anonymously and can never be traced to a voter."]})]}),e.jsxs(B,{children:[e.jsx(X,{children:e.jsxs(q,{className:"text-base flex items-center gap-2",children:[e.jsx(S,{className:"w-4 h-4"}),"New election"]})}),e.jsxs(I,{className:"space-y-3",children:[e.jsxs("div",{children:[e.jsx(w,{children:"Title"}),e.jsx(N,{value:o.title,onChange:s=>x({...o,title:s.target.value}),placeholder:"e.g. 2026 Board of Directors Election"})]}),e.jsxs("div",{children:[e.jsx(w,{children:"Description"}),e.jsx(O,{rows:2,value:o.description,onChange:s=>x({...o,description:s.target.value})})]}),e.jsxs("div",{className:"grid gap-3 sm:grid-cols-2",children:[e.jsxs("div",{children:[e.jsx(w,{children:"Voting opens"}),e.jsx(N,{type:"datetime-local",value:o.open_at,onChange:s=>x({...o,open_at:s.target.value})})]}),e.jsxs("div",{children:[e.jsx(w,{children:"Voting closes"}),e.jsx(N,{type:"datetime-local",value:o.close_at,onChange:s=>x({...o,close_at:s.target.value})})]})]}),e.jsxs("div",{className:"flex gap-6",children:[e.jsxs("label",{className:"flex items-center gap-2 text-sm",children:[e.jsx("input",{type:"checkbox",checked:o.is_member_only,onChange:s=>x({...o,is_member_only:s.target.checked})}),"Members only"]}),e.jsxs("label",{className:"flex items-center gap-2 text-sm",children:[e.jsx("input",{type:"checkbox",checked:o.show_results_after_close,onChange:s=>x({...o,show_results_after_close:s.target.checked})}),"Publish results after close"]})]}),e.jsxs(p,{onClick:z,disabled:E||!o.title||!u(h,"elections.create"),children:[E?e.jsx(C,{className:"w-4 h-4 animate-spin mr-2"}):e.jsx(S,{className:"w-4 h-4 mr-2"}),"Create election"]})]})]}),P?e.jsx("div",{className:"flex justify-center py-8",children:e.jsx(C,{className:"w-5 h-5 animate-spin"})}):e.jsxs("div",{className:"space-y-3",children:[f.map(s=>{const n=D[s.id],t=s.status==="draft"||s.status==="scheduled",a=s.status==="open";return e.jsxs(B,{children:[e.jsxs(I,{className:"py-4 space-y-3",children:[e.jsxs("div",{className:"flex items-start justify-between gap-3",children:[e.jsxs("div",{children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("h3",{className:"font-semibold",children:s.title}),e.jsx(F,{variant:"outline",className:"capitalize",children:s.status}),s.is_member_only&&e.jsx(F,{variant:"secondary",className:"text-xs",children:"Members"})]}),s.description&&e.jsx("p",{className:"text-xs text-muted-foreground mt-1",children:s.description}),e.jsxs("div",{className:"text-xs text-muted-foreground mt-1",children:[s.open_at&&e.jsxs("span",{children:["Opens ",R(s.open_at)]}),s.close_at&&e.jsxs("span",{children:[" · Closes ",R(s.close_at)]})]})]}),e.jsxs("div",{className:"flex gap-2 shrink-0",children:[t&&u(h,"elections.publish")&&e.jsx(p,{size:"sm",onClick:()=>j(s,"open"),children:"Open voting"}),a&&u(h,"elections.unpublish")&&e.jsx(p,{size:"sm",onClick:()=>j(s,"closed"),children:"Close & tally"}),(u(h,"elections.manage_positions")||u(h,"elections.manage_candidates"))&&e.jsx(p,{size:"sm",variant:"outline",onClick:()=>b(l===s.id?null:s.id),children:l===s.id?"Hide":"Manage"}),u(h,"elections.view_results")&&e.jsx(p,{size:"sm",variant:"ghost",onClick:()=>M(s),disabled:k[s.id],children:k[s.id]?e.jsx(C,{className:"w-4 h-4 animate-spin"}):e.jsx(U,{className:"w-4 h-4"})})]})]}),n&&e.jsxs("div",{className:"rounded-lg border p-3 space-y-3",children:[e.jsxs("div",{className:"flex items-center gap-2 text-sm text-muted-foreground",children:[e.jsx(G,{className:"w-4 h-4"}),n.total_voters," voter",n.total_voters===1?"":"s"," ",n.is_live&&e.jsx(F,{variant:"secondary",className:"ml-1",children:"live"})]}),n.positions.map(i=>e.jsxs("div",{children:[e.jsxs("div",{className:"font-semibold text-sm mb-1",children:[i.title," ",e.jsxs("span",{className:"text-xs text-muted-foreground font-normal",children:["(",i.total_votes," votes)"]})]}),i.candidates.map((r,m)=>e.jsxs("div",{className:"flex items-center justify-between text-sm pl-2",children:[e.jsxs("span",{className:"flex items-center gap-1",children:[m===0&&r.votes>0&&e.jsx(U,{className:"w-3 h-3 text-amber-600"}),r.name]}),e.jsx("span",{className:"font-medium",children:r.votes})]},r.id)),i.candidates.length===0&&e.jsx("span",{className:"text-xs text-muted-foreground pl-2",children:"No candidates."})]},i.id))]})]}),l===s.id&&e.jsx("div",{className:"border-t px-4 py-4 bg-muted/20",children:e.jsx(Z,{election:s,onChanged:_})})]},s.id)}),f.length===0&&e.jsx("p",{className:"text-center text-sm text-muted-foreground py-4",children:"No elections yet."})]})]})}export{je 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.