PageSourceSearch

https://genealogydirect.net/assets/ExpAllocationAdmin-DakfvUd0.js

js genealogydirect.net collected 2026-09-24 14:25:42 UTC 14,888 bytes, 1 lines download raw bytes

1import{r as s,j as e,P as W,_ as z}from"./index-D1aKNduO.js";import{P as G}from"./PageBreadCrumb-BHH2LLyg.js";import{E as w}from"./ExpAllocationService-BKdkwvV1.js";import"./firebase-DGovvYsO.js";const v=[{code:"profile_completed",subjectType:"user",description:"User completes mandatory profile fields."},{code:"solution_submitted",subjectType:"solution",description:"User submits a solution or attempt for a question."},{code:"solution_accepted",subjectType:"solution",description:"Requestor accepts a solution."},{code:"comment_posted",subjectType:"comment",description:"User posts a comment on a question or solution."},{code:"question_created",subjectType:"question",description:"User creates a question."},{code:"content_reported",subjectType:"report",description:"User reports content for moderation review."},{code:"comment_liked",subjectType:"comment",description:"User's comment is liked by another user."}],A={amount:"0",notes:"",cooldownSeconds:"",perQuestionPerUser:!1,enabled:!0},J=(g,u)=>{const d=u[g.code];return{...A,amount:d?String(d.amount):"0",notes:d?.notes??"",cooldownSeconds:d&&d.cooldownSeconds!==void 0&&d.cooldownSeconds!==null?String(d.cooldownSeconds):"",perQuestionPerUser:d?.perQuestionPerUser??!1,enabled:d?.enabled??!0}},te=()=>{const[g,u]=s.useState({}),[d,b]=s.useState({}),[I,X]=s.useState(!0),[M,h]=s.useState({}),[L,c]=s.useState(null),[f,S]=s.useState(null),[P,_]=s.useState(""),[j,D]=s.useState(""),[E,U]=s.useState([]),[y,Q]=s.useState(!1),[C,k]=s.useState(null);s.useEffect(()=>{(async()=>{try{X(!0);const r=await w.getAll();u(r);const a={};v.forEach(o=>{a[o.code]=J(o,r)}),b(a)}catch(r){console.error("Failed to load EXP allocations",r),c("Unable to load EXP allocations right now.")}finally{X(!1)}})()},[]),s.useEffect(()=>{if(!f)return;const t=setTimeout(()=>S(null),4e3);return()=>clearTimeout(t)},[f]);const R=s.useMemo(()=>{const t=P.trim().toLowerCase();return t?v.filter(r=>r.code.toLowerCase().includes(t)||r.subjectType.toLowerCase().includes(t)||r.description.toLowerCase().includes(t)):v},[P]),F=s.useMemo(()=>Object.keys(g).length,[g]),p=(t,r,a)=>{b(o=>({...o,[t]:{...o[t]??{...A},[r]:a}}))},q=async t=>{const r=d[t],a=r.amount.trim();if(a===""){c("EXP must be a non-negative integer.");return}const o=Number.parseInt(a,10);if(Number.isNaN(o)||o<0){c("EXP must be a non-negative integer.");return}const N=r.notes.trim(),n=r.cooldownSeconds.trim();let m=null;if(n!==""){const l=Number.parseInt(n,10);if(Number.isNaN(l)||l<0){c("Cooldown must be a non-negative integer or blank.");return}m=l}try{h(x=>({...x,[t]:!0}));const l=await w.setAllocation(t,o,{notes:N||void 0,cooldownSeconds:m,perQuestionPerUser:r.perQuestionPerUser,enabled:r.enabled});u(x=>({...x,[t]:l})),b(x=>({...x,[t]:{amount:String(o),notes:N,cooldownSeconds:m!==null?String(m):"",perQuestionPerUser:r.perQuestionPerUser,enabled:r.enabled}})),S(`Saved EXP allocation for ${t}.`),c(null)}catch(l){console.error("Failed to save allocation",l),c("Unable to save allocation. Try again.")}finally{h(l=>({...l,[t]:!1}))}},H=async t=>{try{h(r=>({...r,[t]:!0})),await w.clearAllocation(t),u(r=>{const a={...r};return delete a[t],a}),b(r=>({...r,[t]:{amount:"0",notes:"",cooldownSeconds:"",perQuestionPerUser:!1,enabled:!0}})),S(`Cleared custom EXP for ${t}.`),c(null)}catch(r){console.error("Failed to clear allocation",r),c("Unable to clear allocation. Try again.")}finally{h(r=>({...r,[t]:!1}))}},O=async()=>{const t=j.trim();if(!t){k("Enter a user ID."),U([]);return}Q(!0),k(null);try{const r=await w.getHistoryForAdmin(t);U(r),r.length===0&&k("No EXP transactions found for this user.")}catch(r){console.error("Failed to load user EXP ledger",r),k("Unable to load ledger. Try again."),U([])}finally{Q(!1)}};return e.jsxs(e.Fragment,{children:[e.jsx(W,{title:"EXP Allocation",description:"Configure EXP rewards for client-initiated actions."}),e.jsx(G,{pageTitle:"EXP Allocation"}),e.jsxs("div",{className:"space-y-6",children:[e.jsxs("section",{className:"rounded-2xl border border-gray-200 bg-white p-6 shadow-sm dark:border-gray-800 dark:bg-gray-900",children:[e.jsxs("div",{className:"flex flex-col gap-4 md:flex-row md:items-center md:justify-between",children:[e.jsxs("div",{children:[e.jsx("h1",{className:"text-2xl font-semibold text-gray-900 dark:text-white",children:"EXP Allocation"}),e.jsx("p",{className:"text-sm text-gray-600 dark:text-gray-400",children:"Set the base EXP awarded when each client action is logged. Changes apply immediately to future events."})]}),e.jsxs("div",{className:"flex gap-4",children:[e.jsxs("div",{className:"rounded-lg border border-gray-200 bg-gray-50 px-4 py-2 text-sm dark:border-gray-700 dark:bg-gray-800 dark:text-gray-200",children:[e.jsx("span",{className:"font-semibold text-gray-900 dark:text-white",children:F})," customised actions"]}),e.jsxs("div",{className:"rounded-lg border border-gray-200 bg-gray-50 px-4 py-2 text-sm dark:border-gray-700 dark:bg-gray-800 dark:text-gray-200",children:[e.jsx("span",{className:"font-semibold text-gray-900 dark:text-white",children:v.length})," total actions"]})]})]}),e.jsx("div",{className:"mt-4",children:e.jsx("input",{type:"search",value:P,onChange:t=>_(t.target.value),placeholder:"Search actions by code, subject, or description",className:"w-full rounded-lg border border-gray-200 px-4 py-2 text-sm shadow-sm focus:border-brand-400 focus:outline-hidden focu
1s:ring-2 focus:ring-brand-200 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-100"})})]}),L&&e.jsx("div",{className:"rounded-xl border border-red-200 bg-red-50 px-4 py-3 text-sm text-red-700 dark:border-red-500/40 dark:bg-red-900/30 dark:text-red-100",children:L}),f&&e.jsx("div",{className:"rounded-xl border border-emerald-200 bg-emerald-50 px-4 py-3 text-sm text-emerald-700 dark:border-emerald-500/40 dark:bg-emerald-900/30 dark:text-emerald-100",children:f}),e.jsx("section",{className:"rounded-2xl border border-gray-200 bg-white shadow-sm dark:border-gray-800 dark:bg-gray-900",children:e.jsx("div",{className:"overflow-x-auto",children:e.jsxs("table",{className:"min-w-full divide-y divide-gray-200 dark:divide-gray-700",children:[e.jsx("thead",{className:"bg-gray-50 dark:bg-gray-800/60",children:e.jsxs("tr",{children:[e.jsx("th",{className:"px-4 py-3 text-left text-xs font-semibold uppercase tracking-wider text-gray-500 dark:text-gray-300",children:"Action"}),e.jsx("th",{className:"px-4 py-3 text-left text-xs font-semibold uppercase tracking-wider text-gray-500 dark:text-gray-300",children:"Subject"}),e.jsx("th",{className:"px-4 py-3 text-left text-xs font-semibold uppercase tracking-wider text-gray-500 dark:text-gray-300",children:"Description"}),e.jsx("th",{className:"px-4 py-3 text-left text-xs font-semibold uppercase tracking-wider text-gray-500 dark:text-gray-300",children:"EXP"}),e.jsx("th",{className:"px-4 py-3 text-left text-xs font-semibold uppercase tracking-wider text-gray-500 dark:text-gray-300",children:"Cooldown (s)"}),e.jsx("th",{className:"px-4 py-3 text-left text-xs font-semibold uppercase tracking-wider text-gray-500 dark:text-gray-300",children:"Per Question/User"}),e.jsx("th",{className:"px-4 py-3 text-left text-xs font-semibold uppercase tracking-wider text-gray-500 dark:text-gray-300",children:"Enabled"}),e.jsx("th",{className:"px-4 py-3 text-left text-xs font-semibold uppercase tracking-wider text-gray-500 dark:text-gray-300",children:"Notes"}),e.jsx("th",{className:"px-4 py-3"})]})}),e.jsx("tbody",{className:"divide-y divide-gray-200 dark:divide-gray-800",children:I?e.jsx("tr",{children:e.jsx("td",{colSpan:9,className:"px-4 py-6 text-center text-sm text-gray-500 dark:text-gray-300",children:"Loading actions…"})}):R.length===0?e.jsx("tr",{children:e.jsx("td",{colSpan:9,className:"px-4 py-6 text-center text-sm text-gray-500 dark:text-gray-300",children:"No actions match your search."})}):R.map(t=>{const r=d[t.code]??{...A},a=r.amount.trim(),o=r.notes.trim(),N=r.cooldownSeconds.trim(),n=g[t.code],m=a===(n?String(n.amount):"0"),l=o===(n?.notes??""),x=N===(n?.cooldownSeconds!==void 0&&n?.cooldownSeconds!==null?String(n.cooldownSeconds):""),$=r.perQuestionPerUser===(n?.perQuestionPerUser??!1),B=r.enabled===(n?.enabled??!0),V=!m||!l||!x||!$||!B,T=!!M[t.code];return e.jsxs("tr",{className:"bg-white dark:bg-gray-900",children:[e.jsx("td",{className:"px-4 py-3",children:e.jsx("div",{className:"font-mono text-sm text-gray-900 dark:text-gray-100",children:t.code})}),e.jsx("td",{className:"px-4 py-3 text-sm text-gray-600 dark:text-gray-300",children:t.subjectType}),e.jsx("td",{className:"px-4 py-3 text-sm text-gray-600 dark:text-gray-300",children:t.description}),e.jsx("td",{className:"px-4 py-3",children:e.jsx("input",{type:"number",min:0,value:r.amount,onChange:i=>p(t.code,"amount",i.target.value),className:"w-24 rounded-lg border border-gray-200 px-3 py-2 text-sm shadow-sm focus:border-brand-400 focus:outline-hidden focus:ring-2 focus:ring-brand-200 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-100"})}),e.jsx("td",{className:"px-4 py-3",children:e.jsx("input",{type:"number",min:0,value:r.cooldownSeconds,onChange:i=>p(t.code,"cooldownSeconds",i.target.value),placeholder:"None",className:"w-28 rounded-lg border border-gray-200 px-3 py-2 text-sm shadow-sm focus:border-brand-400 focus:outline-hidden focus:ring-2 focus:ring-brand-200 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-100"})}),e.jsx("td",{className:"px-4 py-3",children:e.jsxs("label",{className:"inline-flex items-center gap-2 text-sm text-gray-600 dark:text-gray-300",children:[e.jsx("input",{type:"checkbox",checked:r.perQuestionPerUser,onChange:i=>p(t.code,"perQuestionPerUser",i.target.checked),className:"rounded border-gray-300 text-brand-600 focus:ring-brand-500 dark:border-gray-600"}),"Per question per user"]})}),e.jsx("td",{className:"px-4 py-3",children:e.jsxs("label",{className:"inline-flex items-center gap-2 text-sm text-gray-600 dark:text-gray-300",children:[e.jsx("input",{type:"checkbox",checked:r.enabled,onChange:i=>p(t.code,"enabled",i.target.checked),className:"rounded border-gray-300 text-brand-600 focus:ring-brand-500 dark:border-gray-600"}),"Enabled"]})}),e.jsx("td",{className:"px-4 py-3",children:e.jsx("input",{type:"text",value:r.notes,onChange:i=>p(t.code,"notes",i.target.value),placeholder:"Optional notes",className:"w-full min-w-[180px] rounded-lg border border-gray-200 px-3 py-2 text-sm shadow-sm focus:border-brand-400 focus:outline-hidden focu
1s:ring-2 focus:ring-brand-200 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-100"})}),e.jsx("td",{className:"px-4 py-3",children:e.jsxs("div",{className:"flex gap-2",children:[e.jsx("button",{type:"button",onClick:()=>q(t.code),disabled:T||!V,className:"rounded-lg bg-brand-600 px-3 py-2 text-sm font-medium text-white shadow-sm transition hover:bg-brand-700 disabled:cursor-not-allowed disabled:bg-brand-400",children:T?"Saving":"Save"}),e.jsx("button",{type:"button",onClick:()=>H(t.code),disabled:T||!g[t.code],className:"rounded-lg border border-gray-300 px-3 py-2 text-sm font-medium text-gray-600 transition hover:bg-gray-100 disabled:cursor-not-allowed disabled:opacity-60 dark:border-gray-600 dark:text-gray-300 dark:hover:bg-gray-800",children:"Reset"})]})})]},t.code)})})]})})}),e.jsxs("section",{className:"rounded-2xl border border-gray-200 bg-white p-6 shadow-sm dark:border-gray-800 dark:bg-gray-900",children:[e.jsxs("div",{className:"flex flex-col gap-4 md:flex-row md:items-end md:justify-between",children:[e.jsxs("div",{children:[e.jsx("h2",{className:"text-lg font-semibold text-gray-900 dark:text-white",children:"User EXP Ledger"}),e.jsx("p",{className:"text-sm text-gray-600 dark:text-gray-400",children:"Review EXP transactions from a specific user's ledger."})]}),e.jsxs("div",{className:"flex flex-col items-stretch gap-2 sm:flex-row sm:items-center",children:[e.jsx("input",{type:"text",value:j,onChange:t=>D(t.target.value),placeholder:"User ID",className:"w-full rounded-lg border border-gray-200 px-4 py-2 text-sm shadow-sm focus:border-brand-400 focus:outline-hidden focus:ring-2 focus:ring-brand-200 dark:border-gray-700 dark:bg-gray-800 dark:text-gray-100 sm:w-64"}),e.jsx("button",{type:"button",onClick:O,disabled:y||!j.trim(),className:"inline-flex items-center justify-center rounded-lg bg-brand-600 px-4 py-2 text-sm font-medium text-white shadow-sm transition hover:bg-brand-700 disabled:cursor-not-allowed disabled:bg-brand-400",children:y?"Loading…":"Load ledger"})]})]}),e.jsx("div",{className:"mt-4","aria-live":"polite",children:C&&e.jsx("div",{className:"mb-4 rounded-lg border border-red-200 bg-red-50 px-4 py-3 text-sm text-red-700 dark:border-red-500/40 dark:bg-red-900/30 dark:text-red-200",children:C})}),!y&&E.length>0&&e.jsx("div",{className:"mt-4 overflow-x-auto",children:e.jsxs("table",{className:"min-w-full divide-y divide-gray-200 text-sm dark:divide-gray-800",children:[e.jsx("thead",{className:"bg-gray-50 dark:bg-gray-800/60",children:e.jsxs("tr",{children:[e.jsx("th",{className:"px-4 py-2 text-left font-semibold text-gray-500 dark:text-gray-300",children:"Timestamp"}),e.jsx("th",{className:"px-4 py-2 text-left font-semibold text-gray-500 dark:text-gray-300",children:"Reason"}),e.jsx("th",{className:"px-4 py-2 text-left font-semibold text-gray-500 dark:text-gray-300",children:"EXP"}),e.jsx("th",{className:"px-4 py-2 text-left font-semibold text-gray-500 dark:text-gray-300",children:"Entity Ref"}),e.jsx("th",{className:"px-4 py-2 text-left font-semibold text-gray-500 dark:text-gray-300",children:"Tags"}),e.jsx("th",{className:"px-4 py-2 text-left font-semibold text-gray-500 dark:text-gray-300",children:"Notes"})]})}),e.jsx("tbody",{className:"divide-y divide-gray-200 dark:divide-gray-800",children:E.map(t=>{let r=null,a="—";if(t.createdAt)try{r=new Date(t.createdAt),isNaN(r.getTime())||(a=`${r.toLocaleString()} · ${z(r,{addSuffix:!0})}`)}catch(o){console.warn("Invalid date format for entry:",t.id,t.createdAt,o)}return e.jsxs("tr",{className:"bg-white dark:bg-gray-900",children:[e.jsx("td",{className:"px-4 py-2 text-gray-600 dark:text-gray-300",children:a}),e.jsx("td",{className:"px-4 py-2 text-gray-900 dark:text-gray-100",children:t.reason||"—"}),e.jsx("td",{className:"px-4 py-2 text-gray-900 dark:text-gray-100",children:t.amount}),e.jsx("td",{className:"px-4 py-2 text-gray-600 dark:text-gray-300",children:t.entityRef||"—"}),e.jsx("td",{className:"px-4 py-2 text-gray-600 dark:text-gray-300",children:t.tags&&t.tags.length>0?t.tags.join(", "):"—"}),e.jsx("td",{className:"px-4 py-2 text-gray-600 dark:text-gray-300",children:t.notes||"—"})]},t.id)})})]})}),y&&e.jsx("div",{className:"mt-6 text-sm text-gray-500 dark:text-gray-300",children:"Loading ledger…"}),!y&&E.length===0&&!C&&j.trim()!==""&&e.jsx("div",{className:"mt-4 text-sm text-gray-500 dark:text-gray-300",children:"No ledger entries available for this user."})]})]})]})};export{te 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.