feat(ui): 3-tab UI per spec — admin dashboard + date filter, personal dashboard, training w/ difficulty, settings profile
Tab 1 Admin overview (/): aggregate stats + DATE FILTER (?from&to), hardest personas, admin quick actions (Users / + Add product). Tab 2 My dashboard (/my/board): per-user win/lose/session summary (works for admin too). Tab 3 Training (/training): product list w/ status + persona count; admins see all groups (draft->analyze/edit), trainees see ready->personas; persona list shows DIFFICULTY (1-5 stars); admins get a Manage-personas button. Settings (/settings): profile (name/email) via new PATCH /api/auth/profile + change password + language. Backend: analytics date filter; profile endpoint; /api/me/board + /api/chat/sessions opened to any authed user. Rebuilt frontend/dist.
This commit is contained in:
1
frontend/dist/assets/Analytics-RkoZ0rjl.js
vendored
Normal file
1
frontend/dist/assets/Analytics-RkoZ0rjl.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
import{_ as x,k,c as u,a as s,t as e,u as l,i as n,l as m,m as y,w as f,v as h,e as C,F as N,n as V,p as A,q as B,r as c,o as _}from"./index-Hx407ukZ.js";const L={class:"row",style:{"align-items":"center","margin-bottom":"16px"}},D={style:{margin:"0"}},F={class:"row",style:{"margin-left":"auto",gap:"10px"}},M={class:"soft"},P={class:"primary"},S={class:"card filter-bar"},T={class:"muted"},U=["disabled"],W=["disabled"],j={class:"row",style:{gap:"16px",margin:"16px 0"}},q={class:"card stat"},E={class:"card stat"},I={style:{color:"var(--green)"}},O={class:"card stat"},R={style:{color:"var(--red)"}},z={class:"card stat"},G={class:"card stat"},H={class:"card stat"},J={key:0,class:"card empty-state"},K={class:"grid"},Q={class:"row",style:{"justify-content":"space-between"}},X={class:"muted"},Y={class:"row",style:{"margin-top":"10px",gap:"8px"}},Z={class:"badge won"},$={class:"badge lost"},ss={class:"badge not_tried"},ts={class:"muted",style:{"margin-top":"8px"}},es={__name:"Analytics",setup(as){const a=c({overall:{total_sessions:0,wins:0,losses:0,close_rate:0,avg_score:0},trainee_count:0,hardest_personas:[]}),i=c(""),r=c(""),d=c(!1);async function v(){d.value=!0;try{a.value=await A.analytics({from:i.value,to:r.value})}finally{d.value=!1}}function w(){v()}function b(){i.value="",r.value="",v()}return k(v),(os,t)=>{const p=B("router-link");return _(),u("div",null,[s("div",L,[s("h2",D,"📊 "+e(l(n).t("adminOverview")),1),s("div",F,[m(p,{to:"/admin/users"},{default:y(()=>[s("button",M,"👥 "+e(l(n).t("users")),1)]),_:1}),m(p,{to:"/admin/new-group"},{default:y(()=>[s("button",P,"+ "+e(l(n).t("addProduct")),1)]),_:1})])]),s("div",S,[s("span",T,"🗓 "+e(l(n).t("dateRange")),1),f(s("input",{type:"date","onUpdate:modelValue":t[0]||(t[0]=o=>i.value=o)},null,512),[[h,i.value]]),t[2]||(t[2]=s("span",null,"–",-1)),f(s("input",{type:"date","onUpdate:modelValue":t[1]||(t[1]=o=>r.value=o)},null,512),[[h,r.value]]),s("button",{class:"primary",onClick:w,disabled:d.value},"→ "+e(l(n).t("apply")),9,U),s("button",{onClick:b,disabled:d.value},e(l(n).t("clear")),9,W)]),s("div",j,[s("div",q,[t[3]||(t[3]=s("div",null,"Sessions",-1)),s("strong",null,e(a.value.overall.total_sessions),1)]),s("div",E,[t[4]||(t[4]=s("div",null,"Wins",-1)),s("strong",I,e(a.value.overall.wins),1)]),s("div",O,[t[5]||(t[5]=s("div",null,"Losses",-1)),s("strong",R,e(a.value.overall.losses),1)]),s("div",z,[t[6]||(t[6]=s("div",null,"Close rate",-1)),s("strong",null,e(a.value.overall.close_rate)+"%",1)]),s("div",G,[t[7]||(t[7]=s("div",null,"Avg score",-1)),s("strong",null,e(a.value.overall.avg_score),1)]),s("div",H,[t[8]||(t[8]=s("div",null,"Trainees",-1)),s("strong",null,e(a.value.trainee_count),1)])]),s("h3",null,e(l(n).t("hardestPersonas")),1),a.value.hardest_personas.length===0?(_(),u("div",J,[...t[9]||(t[9]=[s("strong",null,"No data",-1),s("span",null,"No sessions in this date range.",-1)])])):C("",!0),s("div",K,[(_(!0),u(N,null,V(a.value.hardest_personas,(o,g)=>(_(),u("div",{key:g,class:"card lift tier-card"},[s("div",Q,[s("strong",null,e(o.persona_name),1),s("span",X,"#"+e(g+1),1)]),s("div",Y,[s("span",Z,e(o.wins)+"W",1),s("span",$,e(o.losses)+"L",1),s("span",ss,e(o.plays)+" plays",1)]),s("div",ts,e(l(n).t("score"))+": "+e(o.avg_score),1)]))),128))])])}}},ns=x(es,[["__scopeId","data-v-c411a8cc"]]);export{ns as default};
|
||||
Reference in New Issue
Block a user