1import{e as G,r as x,y as c,j as e,G as U,X as F,aO as i,aG as V,k as Y,A as Z}from"./index-CzMEFmtw.js";import{C as w,P as L,a as E}from"./ui-BklIU2Vp.js";import{L as Q,b as I,C as K,B as W}from"./badges-DaqdU7p1.js";import{L as ee}from"./loader-circle-B3V02kMX.js";import{P}from"./plus-DZqQktxt.js";import{D as X}from"./download-D1O7GOuA.js";import{T as se}from"./trash-2-gzkfqCHP.js";/** 2 * @license lucide-react v0.462.0 - ISC 3 * 4 * This source code is licensed under the ISC license. 5 * See the LICENSE file in the root directory of this source tree. 6 */const ae=G("KeyRound",[["path",{d:"M2.586 17.414A2 2 0 0 0 2 18.828V21a1 1 0 0 0 1 1h3a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h1a1 1 0 0 0 1-1v-1a1 1 0 0 1 1-1h.172a2 2 0 0 0 1.414-.586l.814-.814a6.5 6.5 0 1 0-4-4z",key:"1s6t7t"}],["circle",{cx:"16.5",cy:"7.5",r:".5",fill:"currentColor",key:"w0ekpg"}]]);/** 7 * @license lucide-react v0.462.0 - ISC 8 * 9 * This source code is licensed under the ISC license. 10 * See the LICENSE file in the root directory of this source tree. 11 */const M=G("Minus",[["path",{d:"M5 12h14",key:"1ays0h"}]]),J="career_hub_access";function te(){const[l,g]=x.useState({private:!0,allowed_emails:[]}),[o,u]=x.useState(!0),[h,_]=x.useState(!1),[C,N]=x.useState("");x.useEffect(()=>{(async()=>{const{data:a}=await c.from("site_settings").select("value").eq("key",J).maybeSingle(),d=(a==null?void 0:a.value)??{};g({private:d.private!==!1,allowed_emails:Array.isArray(d.allowed_emails)?d.allowed_emails.map(String):[]}),u(!1)})()},[]);const r=async a=>{_(!0),g(a);const{error:d}=await c.from("site_settings").upsert({key:J,value:a},{onConflict:"key"});if(_(!1),d)return i.error(d.message);i.success("Career Hub access updated")},y=()=>{const a=C.trim().toLowerCase();if(!/^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(a))return i.error("Enter a valid email address");if(l.allowed_emails.some(d=>d.toLowerCase()===a))return i.error("Already on the list");N(""),r({...l,allowed_emails:[...l.allowed_emails,a]})};return o?e.jsxs(w,{className:"p-6 mb-6 flex items-center gap-2 text-sm text-gray-600",children:[e.jsx(ee,{className:"w-4 h-4 animate-spin"})," Loading access settingsâ¦"]}):e.jsxs(w,{className:"p-5 mb-6",children:[e.jsxs("div",{className:"flex flex-wrap items-start justify-between gap-4",children:[e.jsxs("div",{children:[e.jsxs("h3",{className:"font-heading text-base font-bold text-gray-900 flex items-center gap-2",children:[l.private?e.jsx(Q,{className:"w-4 h-4 text-[#F9A01B]"}):e.jsx(U,{className:"w-4 h-4 text-[#2CC5F4]"}),"Career Hub visibility"]}),e.jsx("p",{className:"text-sm text-gray-600 mt-1",children:l.private?"Private preview â only the emails below can sign in. Everyone else sees the âcoming soonâ screen.":"Public â anyone can register and use the Career Hub."})]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx("button",{onClick:()=>r({...l,private:!0}),disabled:h,className:`rounded-lg px-3.5 py-2 text-xs font-bold transition ${l.private?"bg-[#F9A01B] text-white":"border border-gray-200 bg-white text-gray-700 hover:bg-gray-50"}`,children:"Private preview"}),e.jsx("button",{onClick:()=>r({...l,private:!1}),disabled:h,className:`rounded-lg px-3.5 py-2 text-xs font-bold transition ${l.private?"border border-gray-200 bg-white text-gray-700 hover:bg-gray-50":"bg-[#2CC5F4] text-white"}`,children:"Public"})]})]}),l.private&&e.jsxs("div",{className:"mt-5 border-t border-gray-100 pt-4",children:[e.jsx("p",{className:"text-[11px] uppercase tracking-wide text-gray-500 mb-2",children:"Allowed team emails"}),e.jsxs("div",{className:"flex flex-wrap gap-2 mb-3",children:[l.allowed_emails.length===0&&e.jsx("span",{className:"text-sm text-gray-500",children:"No emails yet â nobody can access the hub."}),l.allowed_emails.map(a=>e.jsxs("span",{className:"inline-flex items-center gap-1.5 rounded-full bg-gray-100 px-3 py-1.5 text-xs font-semibold text-gray-800",children:[a,e.jsx("button",{onClick:()=>r({...l,allowed_emails:l.allowed_emails.filter(d=>d!==a)}),className:"text-gray-500 hover:text-red-600","aria-label":`Remove ${a}`,children:e.jsx(F,{className:"w-3.5 h-3.5"})})]},a))]}),e.jsxs("div",{className:"flex gap-2 max-w-md",children:[e.jsx("input",{value:C,onChange:a=>N(a.target.value),onKeyDown:a=>a.key==="Enter"&&y(),placeholder:"[email protected]",className:"flex-1 rounded-lg border border-gray-200 bg-white px-3 py-2 text-sm text-gray-900 outline-none focus:border-[#2CC5F4]"}),e.jsxs("button",{onClick:y,disabled:h,className:"inline-flex items-center gap-1.5 rounded-lg bg-gray-900 px-3.5 py-2 text-xs font-bold text-white hover:bg-gray-800",children:[e.jsx(P,{className:"w-3.5 h-3.5"})," Add"]})]})]})]})}const p="inline-flex items-center gap-1.5 rounded-lg border border-gray-200 bg-white px-2.5 py-1.5 text-xs font-semibold text-gray-700 hover:bg-gray-50 transition",D=l=>{if(!l.length)return"";const g=Object.keys(l[0]),o=u=>`"${String(u??"").replace(/"/g,'""')}"`;return[g.join(","),...l.map(u=>g.map(h=>o(u[h])).join(","))].join(` 12`)},O=(l,g)=>{const o=URL.createObjectURL(new Blob([g],{type:"text/csv;charset=utf-8"})),u=document.createElement("a");u.href=o,u.download=l,u.click(),URL.revokeObjectURL(o)};function me(){const{isStaff:l,isAdmin:g}=V(),[o,u]=x.useState([]),[h,_]=x.useState(""),[C,N]=x.useState(!0),[r,y]=x.useState(null),[a,d]=x.useState(null),f=async()=>{N(!0);const{data:s}=await c.from("career_members").select("*").order("registered_at",{ascending:!1});u(s??[]),N(!1)};x.useEffect(()=>{f()},[]);const $=async s=>{y(s),d(null);const[t,n,m,j,b]=await Promise.all([c.from("career_login_history").select("created_at, user_agent").eq("user_id",s.user_id
12).order("created_at",{ascending:!1}).limit(20),c.from("career_tool_progress").select("tool_key, runs, completed, updated_at").eq("user_id",s.user_id),c.from("career_achievements").select("badge_key").eq("user_id",s.user_id),c.from("career_webinar_activity").select("webinar_title, registered, attended").eq("user_id",s.user_id),c.from("career_gold_cards").select("card_number, approved, issued_at").eq("user_id",s.user_id).maybeSingle()]);d({logins:t.data??[],tools:n.data??[],badges:(m.data??[]).map(v=>v.badge_key),webinars:j.data??[],card:b.data??null})},k=async(s,t)=>{const{error:n}=await c.from("career_xp_events").insert({user_id:s.user_id,event_key:"admin_adjustment",dedupe_key:`admin:${Date.now()}:${Math.random().toString(36).slice(2)}`,xp:t});if(n)return i.error(n.message);const m=Math.max(0,s.xp+t),j=I(m),{error:b}=await c.from("career_members").update({xp:m,level:j.level,gold_unlocked:m>=5e3}).eq("user_id",s.user_id);if(b)return i.error(b.message);i.success(`XP ${t>0?"+":""}${t} applied`),f(),y(v=>v&&{...v,xp:m,level:j.level})},R=async(s,t)=>{const{error:n}=await c.from("career_members").update({status:t}
12).eq("user_id",s.user_id);if(n)return i.error(n.message);i.success(`Account ${t}`),f()},q=async s=>{await c.from("career_gold_cards").update({approved:!0,approved_at:new Date().toISOString()}).eq("user_id",s.user_id);const{error:t}=await c.from("career_members").update({gold_approved:!0}).eq("user_id",s.user_id);if(t)return i.error(t.message);i.success("Gold membership approved"),f()},z=async(s,t)=>{const{error:n}=await c.from("career_achievements").insert({user_id:s.user_id,badge_key:t});if(n&&!/duplicate/i.test(n.message))return i.error(n.message);i.success("Badge issued"),$(s)},B=async(s,t)=>{const{error:n}=await c.from("career_members").update({counselor:t}).eq("user_id",s.user_id);if(n)return i.error(n.message);i.success("Counsellor assigned"),f()},T=async s=>{await fetch("https://nzaweyjfkrxnydlavsln.supabase.co/functions/v1/career-auth",{method:"POST",headers:{"Content-Type":"application/json",apikey:"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Im56YXdleWpma3J4bnlkbGF2c2xuIiwicm9sZSI6ImFub24iLCJpYXQiOjE3Nzg5MjUwNjQsImV4cCI6MjA5NDUwMTA2NH0.E3JAGw56VmKq0Cb13TapBxP2rCYPEStF6AgZOQXck6E"},body:JSON.stringify({action:"forgot-password",identifier:s.email,redirectTo:`${window.location.origin}/career-hub/reset-password`})}),i.success(`Password reset email sent to ${s.email}`)},H=async s=>{var j;if(!window.confirm(`Permanently delete ${s.full_name} (@${s.username})? 13 14This removes their login, XP, badges, tool progress and gold card. This cannot be undone.`))return;const{data:t}=await c.auth.getSession(),n=await fetch("https://nzaweyjfkrxnydlavsln.supabase.co/functions/v1/career-auth",{method:"POST",headers:{"Content-Type":"application/json",apikey:"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Im56YXdleWpma3J4b
14nlkbGF2c2xuIiwicm9sZSI6ImFub24iLCJpYXQiOjE3Nzg5MjUwNjQsImV4cCI6MjA5NDUwMTA2NH0.E3JAGw56VmKq0Cb13TapBxP2rCYPEStF6AgZOQXck6E",Authorization:`Bearer ${((j=t.session)==null?void 0:j.access_token)??""}`},body:JSON.stringify({action:"delete-member",user_id:s.user_id})}),m=await n.json().catch(()=>({}));if(!n.ok||!(m!=null&&m.ok))return i.error((m==null?void 0:m.error)??"Could not delete this member.");i.success("Member deleted"),y(b=>(b==null?void 0:b.user_id)===s.user_id?null:b),f()},A=x.useMemo(()=>{const s=h.trim().toLowerCase();return s?o.filter(t=>[t.full_name,t.username,t.email,t.member_id,t.country,t.city].some(n=>(n??"").toLowerCase().includes(s))):o},[o,h]),S=x.useMemo(()=>({total:o.length,active:o.filter(s=>s.status==="active").length,gold:o.filter(s=>s.gold_unlocked).length,pendingGold:o.filter(s=>s.gold_unlocked&&!s.gold_approved).length}),[o]);return l?e.jsxs(L,{children:[e.jsx(E,{title:"Career Hub",description:"Members, XP, badges, gold approvals and activity reports."}),e.jsx(te,{}),e.jsx("div",{className:"grid grid-cols-2 lg:grid-cols-4 gap-4 mb-6",children:[["Members",S.total],["Active",S.active],["Gold unlocked",S.gold],["Gold pending approval",S.pendingGold]].map(([s,t])=>e.jsxs(w,{className:"p-4",children:[e.jsx("p",{className:"text-[11px] uppercase tracking-wide text-gray-500",children:s}),e.jsx("p",{className:"font-mono text-2xl font-bold text-gray-900 mt-1",children:t})]},s))}),e.jsxs(w,{children:[e.jsxs("div",{className:"p-4 border-b border-gray-200 flex flex-wrap items-center gap-3 justify-between",children:[e.jsxs("div",{className:"relative flex-1 min-w-[220px]",children:[e.jsx(Y,{className:"w-4 h-4 absolute left-3 top-1/2 -translate-y-1/2 text-gray-400"}),e.jsx("input",{value:h,onChange:s=>_(s.target.value),placeholder:"Search name, username, email, member IDâ¦",className:"w-full rounded-lg border border-gray-200 bg-white pl-9 pr-3 py-2 text-sm text-gray-900 outline-none focus:border-[#2CC5F4]"})]}),e.jsxs("button",{className:p,onClick:()=>O(`career-hub-members-${new Date().toISOString().slice(0,10)}.csv`,D(A)),children:[e.jsx(X,{className:"w-3.5 h-3.5"})," Export CSV"]})]}),e.jsx("div",{className:"overflow-x-auto",children:e.jsxs("table",{className:"w-full text-sm min-w-[900px]",children:[e.jsx("thead",{className:"text-left text-[11px] uppercase tracking-wider text-gray-500 border-b border-gray-200",children:e.jsxs("tr",{children:[e.jsx("th",{className:"p-4",children:"Member"}),e.jsx("th",{className:"p-4",children:"Location"}),e.jsx("th",{className:"p-4",children:"XP / Level"}),e.jsx("th",{className:"p-4",children:"Streak"}),e.jsx("th",{className:"p-4",children:"Status"}),e.jsx("th",{className:"p-4",children:"Gold"}),e.jsx("th",{className:"p-4",children:"Actions"})]})}),e.jsxs("tbody",{children:[A.map(s=>e.jsxs("tr",{className:"border-b border-gray-100 last:border-0 hover:bg-gray-50/70",children:[e.jsx("td",{className:"p-4",children:e.jsxs("button",{onClick:()=>$(s),className:"text-left",children:[e.jsx("div",{className:"font-semibold text-gray-900",children:s.full_name}),e.jsxs("div",{className:"text-xs text-gray-500",children:["@",s.username," · ",s.email]}),e.jsx("div",{className:"text-[11px] font-mono text-gray-400",children:s.member_id})]})}),e.jsxs("td",{className:"p-4 text-gray-600 text-xs",children:[s.city,", ",s.country]}),e.jsxs("td",{className:"p-4",children:[e.jsx("span",{className:"font-mono font-bold text-gray-900",children:s.xp.toLocaleString()}),e.jsxs("div",{className:"text-[11px] text-gray-500",children:["L",s.level," · ",I(s.xp).name]})]}),e.jsxs("td",{className:"p-4 text-gray-700",children:[s.streak_count,"d"]}),e.jsx("td",{className:"p-4",children:e.jsx("span",{className:`rounded-full px-2 py-0.5 text-[11px] font-bold ${s.status==="active"?"bg-emerald-50 text-emerald-700":"bg-red-50 text-red-700"}`,children:s.status})}),e.jsx("td",{className:"p-4 text-xs",children:s.gold_approved?e.jsx("span",{className:"text-[#a3660b] font-bold",children:"Approved"}):s.gold_unlocked?e.jsxs("button",{onClick:()=>q(s),className:p,children:[e.jsx(K,{className:"w-3.5 h-3.5"})," Approve"]}):e.jsx("span",{className:"text-gray-400",children:"â"})}),e.jsx("td",{className:"p-4",children:e.jsxs("div",{className:"flex flex-wrap gap-1.5",children:[e.jsxs("button",{className:p,onClick:()=>k(s,50),title:"Add 50 XP",children:[e.jsx(P,{className:"w-3.5 h-3.5"})," 50"]}),e.jsxs("button",{className:p,onClick:()=>k(s,-50),title:"Remove 50 XP",children:[e.jsx(M,{className:"w-3.5 h-3.5"})," 50"]}),e.jsx("button",{className:p,onClick:()=>R(s,s.status==="active"?"deactivated":"active"),children:s.status==="active"?"Deactivate":"Activate"}),g&&e.jsxs("button",{className:p,onClick:()=>T(s),children:[e.jsx(ae,{className:"w-3.5 h-3.5"})," Reset"]}),g&&e.jsxs("button",{className:`${p} border-red-200 text-red-600 hover:bg-red-50`,onClick:()=>H(s),title:"Permanently delete this member",children:[e.jsx(se,{className:"w-3.5 h-3.5"})," Delete"]})]})})]}
14,s.user_id)),!C&&A.length===0&&e.jsx("tr",{children:e.jsx("td",{colSpan:7,className:"p-8 text-center text-gray-500 text-sm",children:"No Career Hub members yet."})})]})]})})]}),r&&e.jsx("div",{className:"fixed inset-0 z-50 flex items-start justify-center overflow-y-auto bg-black/40 backdrop-blur-sm p-4",children:e.jsxs("div",{className:"w-full max-w-3xl rounded-2xl bg-white shadow-2xl my-8",children:[e.jsxs("div",{className:"flex items-start justify-between p-5 border-b border-gray-200",children:[e.jsxs("div",{children:[e.jsx("h3",{className:"font-bold text-gray-900",children:r.full_name}),e.jsxs("p",{className:"text-xs text-gray-500",children:["@",r.username," · ",r.member_id," · joined ",new Date(r.registered_at).toLocaleDateString()]})]}),e.jsx("button",{onClick:()=>y(null),className:"p-1.5 rounded-lg hover:bg-gray-100 text-gray-500",children:e.jsx(F,{className:"w-4 h-4"})})]}),e.jsxs("div",{className:"p-5 space-y-6 text-sm",children:[e.jsx("div",{className:"grid sm:grid-cols-3 gap-3",children:[["XP",r.xp.toLocaleString()],["Level",`${r.level} · ${I(r.xp).name}`],["Streak",`${r.streak_count} days`],["Email",r.email],["Phone",r.phone],["Location",`${r.city}, ${r.country}`]].map(([s,t])=>e.jsxs("div",{className:"rounded-xl border border-gray-100 bg-gray-50 p-3",children:[e.jsx("p",{className:"text-[11px] uppercase text-gray-500",children:s}),e.jsx("p",{className:"font-semibold text-gray-900 break-words",children:t})]},s))}),e.jsxs("div",{children:[e.jsx("p",{className:"font-semibold text-gray-900 mb-2",children:"Assign counsellor"}),e.jsx("div",{className:"flex gap-2",children:e.jsx("input",{defaultValue:r.counselor??"",placeholder:"Counsellor name",className:"flex-1 rounded-lg border border-gray-200 px-3 py-2 text-sm",onBlur:s=>s.target.value!==(r.counselor??"")&&B(r,s.target.value)})})]}),e.jsxs("div",{children:[e.jsx("p",{className:"font-semibold text-gray-900 mb-2",children:"Issue a badge"}),e.jsx("div",{className:"flex flex-wrap gap-1.5",children:W.map(s=>e.jsxs("button",{className:`${p} ${a!=null&&a.badges.includes(s.key)?"opacity-40":""}`,onClick:()=>z(r,s.key),children:[e.jsx(Z,{className:"w-3.5 h-3.5"})," ",s.emoji," ",s.name]},s.key))})]}),e.jsxs("div",{className:"grid md:grid-cols-2 gap-6",children:[e.jsxs("div",{children:[e.jsx("p",{className:"font-semibold text-gray-900 mb-2",children:"Career tool usage"}),e.jsx("ul",{className:"space-y-1 text-xs text-gray-600",children:a!=null&&a.tools.length?a.tools.map(s=>e.jsxs("li",{className:"flex justify-between border-b border-gray-100 py-1",children:[e.jsx("span",{children:s.tool_key}),e.jsxs("span",{children:[s.runs," run(s) ",s.completed?"â":""]})]},s.tool_key)):e.jsx("li",{className:"text-gray-400",children:"No tool usage yet."})})]}),e.jsxs("div",{children:[e.jsx("p",{className:"font-semibold text-gray-900 mb-2",children:"Login history"}),e.jsx("ul",{className:"space-y-1 text-xs text-gray-600 max-h-48 overflow-y-auto",children:a!=null&&a.logins.length?a.logins.map((s,t)=>e.jsx("li",{children:new Date(s.created_at).toLocaleString()},t)):e.jsx("li",{className:"text-gray-400",children:"No logins recorded."})})]}),e.jsxs("div",{children:[e.jsx("p",{className:"font-semibold text-gray-900 mb-2",children:"Webinars"}),e.jsx("ul",{className:"space-y-1 text-xs text-gray-600",children:a!=null&&a.webinars.length?a.webinars.map((s,t)=>e.jsxs("li",{className:"flex justify-between border-b border-gray-100 py-1",children:[e.jsx("span",{children:s.webinar_title}),e.jsx("span",{children:s.attended?"Attended":s.registered?"Registered":"â"})]},t)):e.jsx("li",{className:"text-gray-400",children:"No webinar activity."})})]}),e.jsxs("div",{children:[e.jsx("p",{className:"font-semibold text-gray-900 mb-2",children:"Gold card"}),a!=null&&a.card?e.jsxs("p",{className:"text-xs text-gray-600",children:[a.card.card_number," · issued ",new Date(a.card.issued_at).toLocaleDateString()," ·"," ",a.card.approved?"Approved":"Pending verification"]}):e.jsx("p",{className:"text-xs text-gray-400",children:"No card issued."})]})]}),e.jsxs("div",{className:"flex flex-wrap gap-2 pt-2 border-t border-gray-200",children:[e.jsxs("button",{className:p,onClick:()=>k(r,100),children:[e.jsx(P,{className:"w-3.5 h-3.5"})," 100 XP"]}),e.jsxs("button",{className:p,onClick:()=>k(r,-100),children:[e.jsx(M,{className:"w-3.5 h-3.5"})," 100 XP"]}),e.jsxs("button",{className:p,onClick:()=>O(`career-member-${r.username}.csv`,D([{...r,badges:a==null?void 0:a.badges.join(" | "),tools:a==null?void 0:a.tools.map(s=>`${s.tool_key}(${s.runs})`).join(" | "),logins:a==null?void 0:a.logins.length}])),children:[e.jsx(X,{className:"w-3.5 h-3.5"})," Download report"]})]})]})]})})]}):e.jsxs(L,{children:[e.jsx(E,{title:"Career Hub"}),e.jsx(w,{className:"p-6 text-sm text-gray-600",children:"Only staff can manage Career Hub members."})]})}
14export{me 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.