fix(ui): widen login/setup forms so inputs don't truncate text; line icons

- Login card 360->460px (max-width:100%), wider inputs (46px, 15px, more padding),
  mobile side padding; eye-toggles -> lucide Eye/EyeOff line icons (no emoji).
- Setup card 380->460px (max-width:100%), wider inputs, Lock line icon instead of emoji.
Rebuilt dist.
This commit is contained in:
Macky
2026-08-08 17:00:09 +07:00
parent b41bfee03b
commit a04bc2add8
32 changed files with 95 additions and 62 deletions

View File

@@ -1,11 +1,11 @@
import{k as w,_ as h,l as U,c as r,a as e,m,u as o,j as l,t as n,i as u,w as p,v,E as b,e as f,F as V,q as M,s as k,r as y,o as i,A as C}from"./index-C0_i8cDF.js";import{U as z}from"./users-qxBh6IGP.js";/**
import{c as k,_ as h,n as b,a as r,b as e,l as m,u as o,m as l,t as n,i as u,w as p,v,E as U,g as f,F as V,s as M,x as w,r as y,o as i,B as C}from"./index-DOaJiTJw.js";import{U as z}from"./users-SQMCzZpr.js";/**
* @license lucide-vue-next v1.0.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const L=w("info",[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M12 16v-4",key:"1dtifu"}],["path",{d:"M12 8h.01",key:"e9boi3"}]]);/**
*/const B=k("info",[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M12 16v-4",key:"1dtifu"}],["path",{d:"M12 8h.01",key:"e9boi3"}]]);/**
* @license lucide-vue-next v1.0.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const N=w("user-plus",[["path",{d:"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2",key:"1yyitq"}],["circle",{cx:"9",cy:"7",r:"4",key:"nufk8"}],["line",{x1:"19",x2:"19",y1:"8",y2:"14",key:"1bvyxn"}],["line",{x1:"22",x2:"16",y1:"11",y2:"11",key:"1shjgl"}]]),A={class:"card guide"},B={class:"card",style:{"margin-bottom":"16px"}},I={style:{"margin-top":"0"}},j={class:"row"},q={class:"row",style:{"margin-top":"10px"}},D=["disabled"],E={key:0,class:"error"},F={key:0,class:"card empty-state"},S={style:{flex:"1"}},T={class:"badge"},H={__name:"AdminUsers",setup(P){const c=y([]),d=y(""),t=y({username:"",name:"",password:"",role:"user"});async function g(){c.value=(await k.adminListUsers()).users}async function _(){d.value="";try{await k.adminCreateUser({...t.value}),t.value={username:"",name:"",password:"",role:"user"},await g()}catch(x){d.value=x.message}}return U(g),(x,s)=>(i(),r("div",null,[e("h2",null,[m(o(z),{size:22,"stroke-width":1.8,style:{"vertical-align":"-4px"}}),l(" "+n(o(u).t("users")),1)]),e("div",A,[e("strong",null,[m(o(L),{size:17,"stroke-width":1.8,style:{"vertical-align":"-3px"}}),s[4]||(s[4]=l(" ",-1))]),s[5]||(s[5]=e("ol",{style:{margin:"8px 0 0","padding-left":"20px","line-height":"1.8"}},[e("li",null,[l(" "),e("strong",null," ()"),l(", , ")]),e("li",null,[l(": "),e("strong",null,"user"),l(" = , "),e("strong",null,"admin"),l(" = ")]),e("li",null,[l(" "),e("strong",null,""),l(" + ")])],-1))]),e("div",B,[e("h4",I,[m(o(N),{size:18,"stroke-width":1.8,style:{"vertical-align":"-3px"}}),l(" "+n(o(u).t("create"))+" "+n(o(u).t("users").toLowerCase()),1)]),e("div",j,[p(e("input",{"onUpdate:modelValue":s[0]||(s[0]=a=>t.value.username=a),placeholder:" ()",style:{flex:"1"}},null,512),[[v,t.value.username]]),p(e("input",{"onUpdate:modelValue":s[1]||(s[1]=a=>t.value.name=a),placeholder:"",style:{flex:"1"}},null,512),[[v,t.value.name]]),p(e("input",{"onUpdate:modelValue":s[2]||(s[2]=a=>t.value.password=a),type:"password",placeholder:"",style:{flex:"1"}},null,512),[[v,t.value.password]])]),e("div",q,[p(e("select",{"onUpdate:modelValue":s[3]||(s[3]=a=>t.value.role=a),style:{flex:"1"}},[...s[6]||(s[6]=[e("option",{value:"user"},"🙂 user ",-1),e("option",{value:"admin"},"🛠 admin ",-1)])],512),[[b,t.value.role]]),e("button",{class:"primary",onClick:_,disabled:!t.value.username||!t.value.password}," "+n(o(u).t("create")),9,D)]),d.value?(i(),r("div",E,n(d.value),1)):f("",!0)]),c.value.length===0?(i(),r("div",F,[...s[7]||(s[7]=[e("strong",null,"",-1),e("span",null,"",-1)])])):f("",!0),(i(!0),r(V,null,M(c.value,a=>(i(),r("div",{class:"card",key:a.id,style:{"margin-bottom":"8px",display:"flex","align-items":"center",gap:"12px"}},[e("strong",S,n(a.name)+" ("+n(a.username)+")",1),e("span",T,n(a.role),1),e("span",{class:C(["badge",a.active?"won":"lost"])},n(a.active?"active":"inactive"),3)]))),128))]))}},K=h(H,[["__scopeId","data-v-924406be"]]);export{K as default};
*/const L=k("user-plus",[["path",{d:"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2",key:"1yyitq"}],["circle",{cx:"9",cy:"7",r:"4",key:"nufk8"}],["line",{x1:"19",x2:"19",y1:"8",y2:"14",key:"1bvyxn"}],["line",{x1:"22",x2:"16",y1:"11",y2:"11",key:"1shjgl"}]]),N={class:"card guide"},I={class:"card",style:{"margin-bottom":"16px"}},A={style:{"margin-top":"0"}},D={class:"row"},E={class:"row",style:{"margin-top":"10px"}},F=["disabled"],S={key:0,class:"error"},T={key:0,class:"card empty-state"},j={style:{flex:"1"}},q={class:"badge"},H={__name:"AdminUsers",setup(P){const c=y([]),d=y(""),t=y({username:"",name:"",password:"",role:"user"});async function g(){c.value=(await w.adminListUsers()).users}async function _(){d.value="";try{await w.adminCreateUser({...t.value}),t.value={username:"",name:"",password:"",role:"user"},await g()}catch(x){d.value=x.message}}return b(g),(x,s)=>(i(),r("div",null,[e("h2",null,[m(o(z),{size:22,"stroke-width":1.8,style:{"vertical-align":"-4px"}}),l(" "+n(o(u).t("users")),1)]),e("div",N,[e("strong",null,[m(o(B),{size:17,"stroke-width":1.8,style:{"vertical-align":"-3px"}}),s[4]||(s[4]=l(" ",-1))]),s[5]||(s[5]=e("ol",{style:{margin:"8px 0 0","padding-left":"20px","line-height":"1.8"}},[e("li",null,[l(" "),e("strong",null," ()"),l(", , ")]),e("li",null,[l(": "),e("strong",null,"user"),l(" = , "),e("strong",null,"admin"),l(" = ")]),e("li",null,[l(" "),e("strong",null,""),l(" + ")])],-1))]),e("div",I,[e("h4",A,[m(o(L),{size:18,"stroke-width":1.8,style:{"vertical-align":"-3px"}}),l(" "+n(o(u).t("create"))+" "+n(o(u).t("users").toLowerCase()),1)]),e("div",D,[p(e("input",{"onUpdate:modelValue":s[0]||(s[0]=a=>t.value.username=a),placeholder:" ()",style:{flex:"1"}},null,512),[[v,t.value.username]]),p(e("input",{"onUpdate:modelValue":s[1]||(s[1]=a=>t.value.name=a),placeholder:"",style:{flex:"1"}},null,512),[[v,t.value.name]]),p(e("input",{"onUpdate:modelValue":s[2]||(s[2]=a=>t.value.password=a),type:"password",placeholder:"",style:{flex:"1"}},null,512),[[v,t.value.password]])]),e("div",E,[p(e("select",{"onUpdate:modelValue":s[3]||(s[3]=a=>t.value.role=a),style:{flex:"1"}},[...s[6]||(s[6]=[e("option",{value:"user"},"🙂 user ",-1),e("option",{value:"admin"},"🛠 admin ",-1)])],512),[[U,t.value.role]]),e("button",{class:"primary",onClick:_,disabled:!t.value.username||!t.value.password}," "+n(o(u).t("create")),9,F)]),d.value?(i(),r("div",S,n(d.value),1)):f("",!0)]),c.value.length===0?(i(),r("div",T,[...s[7]||(s[7]=[e("strong",null,"",-1),e("span",null,"",-1)])])):f("",!0),(i(!0),r(V,null,M(c.value,a=>(i(),r("div",{class:"card",key:a.id,style:{"margin-bottom":"8px",display:"flex","align-items":"center",gap:"12px"}},[e("strong",j,n(a.name)+" ("+n(a.username)+")",1),e("span",q,n(a.role),1),e("span",{class:C(["badge",a.active?"won":"lost"])},n(a.active?"active":"inactive"),3)]))),128))]))}},K=h(H,[["__scopeId","data-v-924406be"]]);export{K as default};

View File

@@ -1,4 +1,4 @@
import{k as x,_ as L,l as M,c as p,a as s,m as i,u as a,j as c,t as e,i as n,n as w,w as f,v as b,p as U,e as N,F as R,q as j,s as A,x as B,r as m,f as E,o as y}from"./index-C0_i8cDF.js";import{U as P}from"./users-qxBh6IGP.js";import{P as S}from"./plus-BiLb0OIF.js";/**
import{c as x,_ as L,n as M,a as p,b as s,l as i,u as a,m as c,t as e,i as n,p as w,w as f,v as b,q as U,g as N,F as R,s as j,x as A,y as B,r as m,h as E,o as y}from"./index-DOaJiTJw.js";import{U as P}from"./users-SQMCzZpr.js";import{P as S}from"./plus-CODydpxS.js";/**
* @license lucide-vue-next v1.0.0 - ISC
*
* This source code is licensed under the ISC license.

File diff suppressed because one or more lines are too long

View File

@@ -1,4 +1,4 @@
import{k as g,_ as M,c as f,m as d,n as V,a as e,u as l,j as r,t as s,i as o,w as u,v as y,E as k,e as C,x as z,r as v,s as B,g as A,o as x}from"./index-C0_i8cDF.js";import{A as P}from"./arrow-left-neyuEczm.js";/**
import{c as g,_ as M,a as f,l as d,p as V,b as e,u as l,m as r,t as s,i as o,w as u,v as y,E as k,g as C,y as z,r as v,x as B,j as A,o as x}from"./index-DOaJiTJw.js";import{A as P}from"./arrow-left-BUCak2lw.js";/**
* @license lucide-vue-next v1.0.0 - ISC
*
* This source code is licensed under the ISC license.

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +1,6 @@
import{k as e,c as o,a as l,m as n,u as i,j as s,t as r,i as a,D as u,o as d}from"./index-C0_i8cDF.js";import{B as g}from"./book-open-E7lWrK45.js";import{L as p}from"./layout-dashboard-C4nLoaIz.js";import{T as m}from"./target-DoOGVGr0.js";import{S as y}from"./sparkles-D66jVNJm.js";/**
import{c as e,a as o,b as l,l as n,u as i,m as s,t as r,i as a,D as u,o as d}from"./index-DOaJiTJw.js";import{B as g}from"./book-open-Ckxqlz0w.js";import{L as p}from"./layout-dashboard-CmUmS5d8.js";import{T as m}from"./target-QJk_fUDu.js";import{S as y}from"./sparkles-CwNig9QR.js";/**
* @license lucide-vue-next v1.0.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const h=e("wrench",[["path",{d:"M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.106-3.105c.32-.322.863-.22.983.218a6 6 0 0 1-8.259 7.057l-7.91 7.91a1 1 0 0 1-2.999-3l7.91-7.91a6 6 0 0 1 7.057-8.259c.438.12.54.662.219.984z",key:"1ngwbx"}]]),k={class:"card"},v={style:{"margin-top":"0"}},x={class:"card"},f={style:{"margin-top":"0"}},c={class:"card"},w={style:{"margin-top":"0"}},z={class:"card"},_={style:{"margin-top":"0"}},b={__name:"Guide",setup(B){return(S,t)=>(d(),o("div",null,[l("h2",null,[n(i(g),{size:22,"stroke-width":1.8,style:{"vertical-align":"-4px"}}),s(" "+r(i(a).t("guideTitle")),1)]),t[8]||(t[8]=l("p",{class:"muted"},"คู่มือสั้นๆ สำหรับพนักงานใหม่ — เข้าใจระบบได้ใน 5 นาที",-1)),l("div",k,[l("h3",v,[n(i(p),{size:18,"stroke-width":1.8,style:{"vertical-align":"-3px"}}),t[0]||(t[0]=s(" 1. หน้า 3 แท็บ (menu ด้านบน)",-1))]),t[1]||(t[1]=l("ul",{style:{"line-height":"1.9"}},[l("li",null,[l("strong",null,"ภาพรวมผู้ดูแล"),s(" — เฉพาะ admin ดูสถิติผลการฝึกของทีม + กรองตามช่วงเวลา")]),l("li",null,[l("strong",null,"ภาพรวมผลการฝึก"),s(" — ของตัวคุณเอง: ชนะ/แพ้/ยังไม่ได้ฝึก")]),l("li",null,[l("strong",null,"การฝึก"),s(" — เลือกสินค้า → เลือกลูกค้า (บุคคลต้นแบบ) → เริ่มแชท")]),l("li",null,[l("strong",null,"การตั้งค่า (⚙︎)"),s(" — แก้ชื่อ/อีเมล, เปลี่ยนรหัสผ่าน, เปลี่ยนภาษา")])],-1))]),l("div",x,[l("h3",f,[n(i(m),{size:18,"stroke-width":1.8,style:{"vertical-align":"-3px"}}),t[2]||(t[2]=s(" 2. วิธีฝึก (start a session)",-1))]),t[3]||(t[3]=l("ol",{style:{"line-height":"1.9","padding-left":"20px"}},[l("li",null,[s("เข้าแท็บ "),l("strong",null,"การฝึก"),s(" → เลือกสินค้าที่อยากฝึก")]),l("li",null,"เลือกลูกค้า (บุคคลต้นแบบ) — ระดับ A ง่ายสุด / C ยากส (ดาวความยาก)"),l("li",null,[s("เลอก "),l("strong",null,"สถานการณ"),s(": โซเชยล (กคาทกกอน) / พบหน-โทร (ณทกกอน) / กลบมาตดต")]),l("li",null,"แชทกบลกค กปดการขาย กคาจะตดสนใจเองวาซอหรอไม"),l("li",null,"หลงจบ ผล + อเสนอแนะ + อมลลกคาทกซอนไว")],-1))]),l("div",c,[l("h3",w,[n(i(y),{size:18,"stroke-width":1.8,style:{"vertical-align":"-3px"}}),t[4]||(t[4]=s(" 3. เคลดล",-1))]),t[5]||(t[5]=l("ul",{style:{"line-height":"1.9"}},[l("li",null,[s('ลูกค้าแต่ละคน หรือ "คคลตนแบบ" ฝึกได้ '),l("strong",null,"คนละคร"),s(" (one-shot) กจนจบแลวลองคนอ")]),l("li",null,"าออกกลางค กลบมาได ยตอจากเด (งไมบวาจบ)"),l("li",null,"ดการขาย = แกญหาจรงของลกค + บมอขอโตแย + ดราคา")],-1))]),l("div",z,[l("h3",_,[n(i(h),{size:18,"stroke-width":1.8,style:{"vertical-align":"-3px"}}),t[6]||(t[6]=s(" 4. สำหร Admin",-1))]),t[7]||(t[7]=u('<ul style="line-height:1.9;"><li> <strong>เพมสนค</strong> ( ) </li><li> <strong></strong> </li><li> <strong></strong> (username + )</li><li> <strong>CSV</strong> ( ) </li></ul>',1))])]))}};export{b as default};
*/const h=e("wrench",[["path",{d:"M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.106-3.105c.32-.322.863-.22.983.218a6 6 0 0 1-8.259 7.057l-7.91 7.91a1 1 0 0 1-2.999-3l7.91-7.91a6 6 0 0 1 7.057-8.259c.438.12.54.662.219.984z",key:"1ngwbx"}]]),k={class:"card"},v={style:{"margin-top":"0"}},x={class:"card"},f={style:{"margin-top":"0"}},c={class:"card"},w={style:{"margin-top":"0"}},z={class:"card"},_={style:{"margin-top":"0"}},L={__name:"Guide",setup(B){return(S,t)=>(d(),o("div",null,[l("h2",null,[n(i(g),{size:22,"stroke-width":1.8,style:{"vertical-align":"-4px"}}),s(" "+r(i(a).t("guideTitle")),1)]),t[8]||(t[8]=l("p",{class:"muted"},"คู่มือสั้นๆ สำหรับพนักงานใหม่ — เข้าใจระบบได้ใน 5 นาที",-1)),l("div",k,[l("h3",v,[n(i(p),{size:18,"stroke-width":1.8,style:{"vertical-align":"-3px"}}),t[0]||(t[0]=s(" 1. หน้า 3 แท็บ (menu ด้านบน)",-1))]),t[1]||(t[1]=l("ul",{style:{"line-height":"1.9"}},[l("li",null,[l("strong",null,"ภาพรวมผู้ดูแล"),s(" — เฉพาะ admin ดูสถิติผลการฝึกของทีม + กรองตามช่วงเวลา")]),l("li",null,[l("strong",null,"ภาพรวมผลการฝึก"),s(" — ของตัวคุณเอง: ชนะ/แพ้/ยังไม่ได้ฝึก")]),l("li",null,[l("strong",null,"การฝึก"),s(" — เลือกสินค้า → เลือกลูกค้า (บุคคลต้นแบบ) → เริ่มแชท")]),l("li",null,[l("strong",null,"การตั้งค่า (⚙︎)"),s(" — แก้ชื่อ/อีเมล, เปลี่ยนรหัสผ่าน, เปลี่ยนภาษา")])],-1))]),l("div",x,[l("h3",f,[n(i(m),{size:18,"stroke-width":1.8,style:{"vertical-align":"-3px"}}),t[2]||(t[2]=s(" 2. วิธีฝึก (start a session)",-1))]),t[3]||(t[3]=l("ol",{style:{"line-height":"1.9","padding-left":"20px"}},[l("li",null,[s("เข้าแท็บ "),l("strong",null,"การฝึก"),s(" → เลือกสินค้าที่อยากฝึก")]),l("li",null,"เลือกลูกค้า (บุคคลต้นแบบ) — ระดับ A ง่ายสุด / C ยากส (ดาวความยาก)"),l("li",null,[s("เลอก "),l("strong",null,"สถานการณ"),s(": โซเชยล (กคาทกกอน) / พบหน-โทร (ณทกกอน) / กลบมาตดต")]),l("li",null,"แชทกบลกค กปดการขาย กคาจะตดสนใจเองวาซอหรอไม"),l("li",null,"หลงจบ ผล + อเสนอแนะ + อมลลกคาทกซอนไว")],-1))]),l("div",c,[l("h3",w,[n(i(y),{size:18,"stroke-width":1.8,style:{"vertical-align":"-3px"}}),t[4]||(t[4]=s(" 3. เคลดล",-1))]),t[5]||(t[5]=l("ul",{style:{"line-height":"1.9"}},[l("li",null,[s('ลูกค้าแต่ละคน หรือ "คคลตนแบบ" ฝึกได้ '),l("strong",null,"คนละคร"),s(" (one-shot) กจนจบแลวลองคนอ")]),l("li",null,"าออกกลางค กลบมาได ยตอจากเด (งไมบวาจบ)"),l("li",null,"ดการขาย = แกญหาจรงของลกค + บมอขอโตแย + ดราคา")],-1))]),l("div",z,[l("h3",_,[n(i(h),{size:18,"stroke-width":1.8,style:{"vertical-align":"-3px"}}),t[6]||(t[6]=s(" 4. สำหร Admin",-1))]),t[7]||(t[7]=u('<ul style="line-height:1.9;"><li> <strong>เพมสนค</strong> ( ) </li><li> <strong></strong> </li><li> <strong></strong> (username + )</li><li> <strong>CSV</strong> ( ) </li></ul>',1))])]))}};export{L as default};

View File

@@ -1 +0,0 @@
.login-wrap[data-v-f7904d9f]{display:flex;justify-content:center;padding-top:10vh}.login-card[data-v-f7904d9f]{width:360px}h1[data-v-f7904d9f]{margin-top:0}.pw-wrap[data-v-f7904d9f]{position:relative}.pw-toggle[data-v-f7904d9f]{position:absolute;right:4px;top:50%;transform:translateY(-50%);background:transparent;border:none;padding:6px;min-height:36px;cursor:pointer}

11
frontend/dist/assets/Login-DxHA8GYa.js vendored Normal file
View File

@@ -0,0 +1,11 @@
import{c as k,_ as x,a as y,b as e,t as l,u as a,i as n,w as h,v as M,d as w,e as B,f as _,g as E,r,h as f,j as S,k as V,o as s}from"./index-DOaJiTJw.js";/**
* @license lucide-vue-next v1.0.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const z=k("eye-off",[["path",{d:"M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49",key:"ct8e1f"}],["path",{d:"M14.084 14.158a3 3 0 0 1-4.242-4.242",key:"151rxh"}],["path",{d:"M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143",key:"13bj9a"}],["path",{d:"m2 2 20 20",key:"1ooewy"}]]);/**
* @license lucide-vue-next v1.0.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const C=k("eye",[["path",{d:"M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0",key:"1nclc0"}],["circle",{cx:"12",cy:"12",r:"3",key:"1v7zrd"}]]),D={class:"login-wrap"},K={class:"card login-card"},L={class:"pw-wrap"},j=["type"],I=["aria-label"],N={key:0,class:"error",role:"alert"},R=["disabled"],U={key:0,class:"spinner"},q={key:1},H={__name:"Login",setup(O){const g=V(),m=S(),u=r(""),i=r(""),o=r(!1),d=r(""),c=r(!1);async function v(){d.value="",c.value=!0;try{await f.login(u.value.trim(),i.value),f.mustSetup?m.push({path:"/setup"}):m.push(g.query.redirect||"/")}catch{d.value=n.t("loginError")}finally{c.value=!1}}return(b,t)=>(s(),y("div",D,[e("div",K,[e("h1",null,l(a(n).t("app")),1),t[3]||(t[3]=e("p",{class:"muted",style:{"margin-top":"-8px"}},"Sales training simulator",-1)),e("label",null,l(a(n).t("username")),1),h(e("input",{"onUpdate:modelValue":t[0]||(t[0]=p=>u.value=p),type:"text",autocomplete:"username",placeholder:"username",class:"wide",onKeyup:w(v,["enter"])},null,544),[[M,u.value]]),e("label",null,l(a(n).t("password")),1),e("div",L,[h(e("input",{"onUpdate:modelValue":t[1]||(t[1]=p=>i.value=p),type:o.value?"text":"password",autocomplete:"current-password",placeholder:"••••••••",class:"wide",onKeyup:w(v,["enter"])},null,40,j),[[B,i.value]]),e("button",{type:"button",class:"pw-toggle",onClick:t[2]||(t[2]=p=>o.value=!o.value),"aria-label":o.value?"Hide password":"Show password"},[o.value?(s(),_(a(z),{key:0,size:20,"stroke-width":1.8})):(s(),_(a(C),{key:1,size:20,"stroke-width":1.8}))],8,I)]),d.value?(s(),y("div",N,l(d.value),1)):E("",!0),e("button",{class:"primary",style:{width:"100%","margin-top":"18px"},disabled:c.value||!u.value||!i.value,onClick:v},[c.value?(s(),y("span",U)):(s(),y("span",q,l(a(n).t("login")),1))],8,R)])]))}},T=x(H,[["__scopeId","data-v-491f49d6"]]);export{T as default};

View File

@@ -0,0 +1 @@
.login-wrap[data-v-491f49d6]{display:flex;justify-content:center;padding-top:8vh;padding-left:16px;padding-right:16px}.login-card[data-v-491f49d6]{width:460px;max-width:100%;padding:28px 30px}h1[data-v-491f49d6]{margin-top:0;font-size:24px}.wide[data-v-491f49d6]{width:100%;min-height:46px;font-size:15px;padding:12px 14px}.pw-wrap[data-v-491f49d6]{position:relative}.pw-wrap input[data-v-491f49d6]{padding-right:48px}.pw-toggle[data-v-491f49d6]{position:absolute;right:4px;top:50%;transform:translateY(-50%);background:transparent;border:none;padding:8px;min-height:40px;cursor:pointer;color:var(--muted)}.pw-toggle[data-v-491f49d6]:hover{color:var(--ink)}

View File

@@ -1 +0,0 @@
import{_ as b,c as d,a as e,t as s,u as c,i as o,w as y,v as x,b as w,d as k,e as S,r as l,f,g as V,h as B,o as v}from"./index-C0_i8cDF.js";const C={class:"login-wrap"},D={class:"card login-card"},K={class:"pw-wrap"},E=["type"],L=["aria-label"],M={key:0,class:"error",role:"alert"},N=["disabled"],R={key:0,class:"spinner"},U={key:1},q={__name:"Login",setup(H){const g=B(),_=V(),n=l(""),u=l(""),a=l(!1),r=l(""),i=l(!1);async function m(){r.value="",i.value=!0;try{await f.login(n.value.trim(),u.value),f.mustSetup?_.push({path:"/setup"}):_.push(g.query.redirect||"/")}catch{r.value=o.t("loginError")}finally{i.value=!1}}return(h,t)=>(v(),d("div",C,[e("div",D,[e("h1",null,"🎯 "+s(c(o).t("app")),1),t[3]||(t[3]=e("p",{class:"muted",style:{"margin-top":"-8px"}},"Sales training simulator",-1)),e("label",null,s(c(o).t("username")),1),y(e("input",{"onUpdate:modelValue":t[0]||(t[0]=p=>n.value=p),type:"text",autocomplete:"username",onKeyup:w(m,["enter"])},null,544),[[x,n.value]]),e("label",null,s(c(o).t("password")),1),e("div",K,[y(e("input",{"onUpdate:modelValue":t[1]||(t[1]=p=>u.value=p),type:a.value?"text":"password",autocomplete:"current-password",onKeyup:w(m,["enter"])},null,40,E),[[k,u.value]]),e("button",{type:"button",class:"pw-toggle",onClick:t[2]||(t[2]=p=>a.value=!a.value),"aria-label":a.value?"Hide password":"Show password"},s(a.value?"🙈":"👁"),9,L)]),r.value?(v(),d("div",M,s(r.value),1)):S("",!0),e("button",{class:"primary",style:{width:"100%","margin-top":"16px"},disabled:i.value||!n.value||!u.value,onClick:m},[i.value?(v(),d("span",R)):(v(),d("span",U,s(c(o).t("login")),1))],8,N)])]))}},P=b(q,[["__scopeId","data-v-f7904d9f"]]);export{P as default};

View File

@@ -1 +1 @@
import{_ as f,l as x,s as v,c as r,a as t,m as b,u as e,j as k,t as s,i as a,e as _,w as B,y as N,F as D,q as S,r as p,z as c,o as i,A as T}from"./index-C0_i8cDF.js";import{L as V}from"./layout-dashboard-C4nLoaIz.js";const z={style:{margin:"0"}},L={key:0,class:"row stat-row"},M={class:"card stat"},j={class:"card stat won"},C={class:"card stat lost"},F={class:"card stat"},q={key:1,class:"card"},A={key:2,class:"card empty-state"},E={class:"card",style:{"margin-top":"20px"}},G={style:{"margin-top":"0"}},I={__name:"MyBoard",setup(H){const o=p([]),u=p([]),m=p(!0),y=c(()=>o.value.length),g=c(()=>o.value.filter(n=>n.my_outcome==="won").length),h=c(()=>o.value.filter(n=>n.my_outcome==="lost").length),w=c(()=>o.value.filter(n=>n.my_outcome==="not_tried").length);return x(async()=>{try{o.value=(await v.myBoard()).board||[],u.value=(await v.mySessions()).sessions||[]}finally{m.value=!1}}),(n,l)=>(i(),r("div",null,[t("div",null,[t("h2",z,[b(e(V),{size:22,"stroke-width":1.8,style:{"vertical-align":"-4px"}}),k(" "+s(e(a).t("myDashboard")),1)]),l[0]||(l[0]=t("div",{class:"muted",style:{"margin-top":"4px","margin-bottom":"16px"}},"สรุปผลการฝึกของตัวคุณเอง — ดูว่าปิดการขายได้กี่ครั้ง ยังฝึกกับใครบ้าง",-1))]),m.value?_("",!0):(i(),r("div",L,[t("div",M,[t("span",null,s(e(a).t("total")),1),t("strong",null,s(y.value),1)]),t("div",j,[t("span",null,s(e(a).t("won")),1),t("strong",null,s(g.value),1)]),t("div",C,[t("span",null,s(e(a).t("lost")),1),t("strong",null,s(h.value),1)]),t("div",F,[t("span",null,s(e(a).t("notTried")),1),t("strong",null,s(w.value),1)])])),m.value?(i(),r("div",q,[...l[1]||(l[1]=[t("div",{class:"skeleton",style:{height:"50px"}},null,-1)])])):o.value.length===0?(i(),r("div",A,[...l[2]||(l[2]=[t("strong",null,"No practice yet",-1),t("span",null,"Go to Training and try closing a sale with a persona.",-1)])])):_("",!0),B(t("div",E,[t("h3",G,s(e(a).t("mySessions")),1),(i(!0),r(D,null,S(u.value,d=>(i(),r("div",{key:d.id,style:{display:"flex","justify-content":"space-between",padding:"8px 0","border-bottom":"1px solid var(--border)"}},[t("span",null,s(d.persona_name),1),t("span",{class:T(["badge",d.outcome])},s(d.outcome==="won"?e(a).t("won"):e(a).t("lost")),3)]))),128))],512),[[N,u.value.length]])]))}},O=f(I,[["__scopeId","data-v-6767b6b8"]]);export{O as default};
import{_ as f,n as x,x as v,a as r,b as t,l as b,u as e,m as k,t as s,i as a,g as _,w as B,z as N,F as D,s as S,r as p,A as c,o as i,B as T}from"./index-DOaJiTJw.js";import{L as V}from"./layout-dashboard-CmUmS5d8.js";const z={style:{margin:"0"}},L={key:0,class:"row stat-row"},M={class:"card stat"},C={class:"card stat won"},F={class:"card stat lost"},j={class:"card stat"},A={key:1,class:"card"},E={key:2,class:"card empty-state"},G={class:"card",style:{"margin-top":"20px"}},I={style:{"margin-top":"0"}},q={__name:"MyBoard",setup(H){const o=p([]),u=p([]),m=p(!0),y=c(()=>o.value.length),g=c(()=>o.value.filter(n=>n.my_outcome==="won").length),h=c(()=>o.value.filter(n=>n.my_outcome==="lost").length),w=c(()=>o.value.filter(n=>n.my_outcome==="not_tried").length);return x(async()=>{try{o.value=(await v.myBoard()).board||[],u.value=(await v.mySessions()).sessions||[]}finally{m.value=!1}}),(n,l)=>(i(),r("div",null,[t("div",null,[t("h2",z,[b(e(V),{size:22,"stroke-width":1.8,style:{"vertical-align":"-4px"}}),k(" "+s(e(a).t("myDashboard")),1)]),l[0]||(l[0]=t("div",{class:"muted",style:{"margin-top":"4px","margin-bottom":"16px"}},"สรุปผลการฝึกของตัวคุณเอง — ดูว่าปิดการขายได้กี่ครั้ง ยังฝึกกับใครบ้าง",-1))]),m.value?_("",!0):(i(),r("div",L,[t("div",M,[t("span",null,s(e(a).t("total")),1),t("strong",null,s(y.value),1)]),t("div",C,[t("span",null,s(e(a).t("won")),1),t("strong",null,s(g.value),1)]),t("div",F,[t("span",null,s(e(a).t("lost")),1),t("strong",null,s(h.value),1)]),t("div",j,[t("span",null,s(e(a).t("notTried")),1),t("strong",null,s(w.value),1)])])),m.value?(i(),r("div",A,[...l[1]||(l[1]=[t("div",{class:"skeleton",style:{height:"50px"}},null,-1)])])):o.value.length===0?(i(),r("div",E,[...l[2]||(l[2]=[t("strong",null,"No practice yet",-1),t("span",null,"Go to Training and try closing a sale with a persona.",-1)])])):_("",!0),B(t("div",G,[t("h3",I,s(e(a).t("mySessions")),1),(i(!0),r(D,null,S(u.value,d=>(i(),r("div",{key:d.id,style:{display:"flex","justify-content":"space-between",padding:"8px 0","border-bottom":"1px solid var(--border)"}},[t("span",null,s(d.persona_name),1),t("span",{class:T(["badge",d.outcome])},s(d.outcome==="won"?e(a).t("won"):e(a).t("lost")),3)]))),128))],512),[[N,u.value.length]])]))}},O=f(q,[["__scopeId","data-v-6767b6b8"]]);export{O as default};

View File

@@ -1 +1 @@
import{_ as T,l as $,c as r,m as d,n as m,a as t,t as s,u as e,i as n,f as g,j as _,e as w,F as y,q as p,h as L,s as N,x as V,r as b,o as a,S as I,A as h,B as A}from"./index-C0_i8cDF.js";import{T as S}from"./target-DoOGVGr0.js";import{A as j}from"./arrow-left-neyuEczm.js";const F={class:"row",style:{"align-items":"center"}},q={style:{margin:"0"}},D={class:"muted",style:{"margin-left":"auto"}},E={key:0,class:"card guide"},M={key:1,class:"row",style:{margin:"12px 0",gap:"10px"}},R={class:"primary"},G={class:"grid"},H={class:"row",style:{"justify-content":"space-between"}},J={class:"diff"},K={class:"muted"},O={class:"muted"},Q={class:"muted"},U={class:"muted",style:{"margin-top":"6px"}},W={class:"primary",style:{width:"100%"}},X={class:"primary",style:{width:"100%"}},Y={key:1,class:"muted",style:{"margin-top":"auto","font-size":"12px"}},Z={__name:"Personas",setup(tt){const c=L().params.gid,k=b([]),B=b(!0);async function C(){try{k.value=(await N.listPersonas(c)).personas}finally{B.value=!1}}function z(l){return k.value.filter(i=>i.tier===l)}function P(l){return n.t(l==="A"?"tierA":l==="B"?"tierB":"tierC")}function v(l){return l==="won"?n.t("won"):l==="lost"?n.t("lost"):n.t("notTried")}return $(C),(l,i)=>{const u=V("router-link");return a(),r("div",null,[d(u,{to:"/training",class:"btn-back"},{default:m(()=>[d(e(j),{size:16,"stroke-width":2}),_(" "+s(e(n).t("training")),1)]),_:1}),t("div",F,[t("h2",q,s(e(n).t("personas")),1),t("span",D,s(e(n).t("selectPersona")),1)]),e(g).isAdmin?w("",!0):(a(),r("div",E,[t("strong",null,[d(e(S),{size:17,"stroke-width":1.8,style:{"vertical-align":"-3px"}}),i[0]||(i[0]=_(" วิธีฝึก",-1))]),i[1]||(i[1]=t("ol",{style:{margin:"8px 0 0","padding-left":"20px","line-height":"1.8"}},[t("li",null,"เลือกลูกค้าจำลอง (บุคคลต้นแบบ) คนหนึ่งที่อยากฝึกด้วย"),t("li",null,"ระดับ A ง่ายสุด → ระดับ C ยากสุด (ดูจากดาว ★ ความยาก)"),t("li",null,"กดปุ่มสำหรับฝึกแชทกับลูกค้าคนนั้น (ฝึกได้คนละครั้งเท่านั้น)")],-1))])),e(g).isAdmin?(a(),r("div",M,[d(u,{to:`/admin/groups/${e(c)}/edit`},{default:m(()=>[t("button",R,[d(e(I),{size:18,"stroke-width":1.8}),_(" "+s(e(n).t("managePersonas")),1)])]),_:1},8,["to"]),i[2]||(i[2]=t("span",{class:"muted"},"Admin: จัดการรายละเอียดบุคคลต้นแบบได้ที่นี่",-1))])):w("",!0),(a(),r(y,null,p(["A","B","C"],f=>t("div",{key:f,style:{margin:"20px 0"}},[t("h4",null,s(P(f)),1),t("div",G,[(a(!0),r(y,null,p(z(f),o=>(a(),r("div",{key:o.id,class:"card pcard lift"},[t("div",H,[t("strong",null,s(o.name),1),t("span",{class:h(["badge",o.my_outcome])},s(v(o.my_outcome)),3)]),t("div",J,[(a(),r(y,null,p(5,x=>t("span",{key:x,class:h(["star",{on:x<=(o.difficulty||1)}])},"★",2)),64)),t("span",K,s(e(n).t("difficulty"))+" "+s(o.difficulty||1)+"/5",1)]),t("div",O,[_(s(o.profession)+" · "+s(o.age_group)+" · "+s(o.location),1),i[3]||(i[3]=t("br",null,null,-1)),t("span",{class:h(["badge",o.channel])},s(o.channel),3),t("span",Q," · "+s(o.initiation_mode==="seller"?e(n).t("sellerInitiated"):e(n).t("customerInitiated")),1)]),t("div",U,s(o.product_context),1),e(g).isAdmin?(a(),A(u,{key:0,to:`/groups/${e(c)}/chat/${o.id}`,style:{"margin-top":"auto"}},{default:m(()=>[t("button",W,s(e(n).t("chat")),1)]),_:1},8,["to"])):(a(),r(y,{key:1},[o.my_outcome==="not_tried"?(a(),A(u,{key:0,to:`/groups/${e(c)}/chat/${o.id}`,style:{"margin-top":"auto"}},{default:m(()=>[t("button",X,s(e(n).t("chat")),1)]),_:1},8,["to"])):(a(),r("div",Y,"✓ "+s(e(n).t("trained"))+" ("+s(v(o.my_outcome))+")",1))],64))]))),128))])])),64))])}}},at=T(Z,[["__scopeId","data-v-46d50c99"]]);export{at as default};
import{_ as T,n as $,a as r,l as d,p as m,b as t,t as s,u as e,i as n,h as f,m as _,g as w,F as y,s as p,k as L,x as N,y as V,r as b,o as a,S as I,B as h,f as A}from"./index-DOaJiTJw.js";import{T as S}from"./target-QJk_fUDu.js";import{A as F}from"./arrow-left-BUCak2lw.js";const j={class:"row",style:{"align-items":"center"}},D={style:{margin:"0"}},E={class:"muted",style:{"margin-left":"auto"}},M={key:0,class:"card guide"},R={key:1,class:"row",style:{margin:"12px 0",gap:"10px"}},q={class:"primary"},G={class:"grid"},H={class:"row",style:{"justify-content":"space-between"}},J={class:"diff"},K={class:"muted"},O={class:"muted"},Q={class:"muted"},U={class:"muted",style:{"margin-top":"6px"}},W={class:"primary",style:{width:"100%"}},X={class:"primary",style:{width:"100%"}},Y={key:1,class:"muted",style:{"margin-top":"auto","font-size":"12px"}},Z={__name:"Personas",setup(tt){const c=L().params.gid,k=b([]),B=b(!0);async function C(){try{k.value=(await N.listPersonas(c)).personas}finally{B.value=!1}}function z(l){return k.value.filter(i=>i.tier===l)}function P(l){return n.t(l==="A"?"tierA":l==="B"?"tierB":"tierC")}function v(l){return l==="won"?n.t("won"):l==="lost"?n.t("lost"):n.t("notTried")}return $(C),(l,i)=>{const u=V("router-link");return a(),r("div",null,[d(u,{to:"/training",class:"btn-back"},{default:m(()=>[d(e(F),{size:16,"stroke-width":2}),_(" "+s(e(n).t("training")),1)]),_:1}),t("div",j,[t("h2",D,s(e(n).t("personas")),1),t("span",E,s(e(n).t("selectPersona")),1)]),e(f).isAdmin?w("",!0):(a(),r("div",M,[t("strong",null,[d(e(S),{size:17,"stroke-width":1.8,style:{"vertical-align":"-3px"}}),i[0]||(i[0]=_(" วิธีฝึก",-1))]),i[1]||(i[1]=t("ol",{style:{margin:"8px 0 0","padding-left":"20px","line-height":"1.8"}},[t("li",null,"เลือกลูกค้าจำลอง (บุคคลต้นแบบ) คนหนึ่งที่อยากฝึกด้วย"),t("li",null,"ระดับ A ง่ายสุด → ระดับ C ยากสุด (ดูจากดาว ★ ความยาก)"),t("li",null,"กดปุ่มสำหรับฝึกแชทกับลูกค้าคนนั้น (ฝึกได้คนละครั้งเท่านั้น)")],-1))])),e(f).isAdmin?(a(),r("div",R,[d(u,{to:`/admin/groups/${e(c)}/edit`},{default:m(()=>[t("button",q,[d(e(I),{size:18,"stroke-width":1.8}),_(" "+s(e(n).t("managePersonas")),1)])]),_:1},8,["to"]),i[2]||(i[2]=t("span",{class:"muted"},"Admin: จัดการรายละเอียดบุคคลต้นแบบได้ที่นี่",-1))])):w("",!0),(a(),r(y,null,p(["A","B","C"],g=>t("div",{key:g,style:{margin:"20px 0"}},[t("h4",null,s(P(g)),1),t("div",G,[(a(!0),r(y,null,p(z(g),o=>(a(),r("div",{key:o.id,class:"card pcard lift"},[t("div",H,[t("strong",null,s(o.name),1),t("span",{class:h(["badge",o.my_outcome])},s(v(o.my_outcome)),3)]),t("div",J,[(a(),r(y,null,p(5,x=>t("span",{key:x,class:h(["star",{on:x<=(o.difficulty||1)}])},"★",2)),64)),t("span",K,s(e(n).t("difficulty"))+" "+s(o.difficulty||1)+"/5",1)]),t("div",O,[_(s(o.profession)+" · "+s(o.age_group)+" · "+s(o.location),1),i[3]||(i[3]=t("br",null,null,-1)),t("span",{class:h(["badge",o.channel])},s(o.channel),3),t("span",Q," · "+s(o.initiation_mode==="seller"?e(n).t("sellerInitiated"):e(n).t("customerInitiated")),1)]),t("div",U,s(o.product_context),1),e(f).isAdmin?(a(),A(u,{key:0,to:`/groups/${e(c)}/chat/${o.id}`,style:{"margin-top":"auto"}},{default:m(()=>[t("button",W,s(e(n).t("chat")),1)]),_:1},8,["to"])):(a(),r(y,{key:1},[o.my_outcome==="not_tried"?(a(),A(u,{key:0,to:`/groups/${e(c)}/chat/${o.id}`,style:{"margin-top":"auto"}},{default:m(()=>[t("button",X,s(e(n).t("chat")),1)]),_:1},8,["to"])):(a(),r("div",Y,"✓ "+s(e(n).t("trained"))+" ("+s(v(o.my_outcome))+")",1))],64))]))),128))])])),64))])}}},at=T(Z,[["__scopeId","data-v-46d50c99"]]);export{at as default};

View File

@@ -1,16 +0,0 @@
import{k as z,_ as T,r as c,f as i,c as h,a as e,m as k,u as a,S as $,j as v,t as o,i as s,w as x,v as b,e as V,A as S,s as U,o as w}from"./index-C0_i8cDF.js";/**
* @license lucide-vue-next v1.0.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const j=z("globe",[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20",key:"13o1zl"}],["path",{d:"M2 12h20",key:"9i4pu4"}]]);/**
* @license lucide-vue-next v1.0.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const D=z("lock",[["rect",{width:"18",height:"11",x:"3",y:"11",rx:"2",ry:"2",key:"1w4ew1"}],["path",{d:"M7 11V7a5 5 0 0 1 10 0v4",key:"fwvmzm"}]]);/**
* @license lucide-vue-next v1.0.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const E=z("user",[["path",{d:"M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2",key:"975kel"}],["circle",{cx:"12",cy:"7",r:"4",key:"17ys0d"}]]),I={class:"card"},A={style:{"margin-top":"0"}},G={class:"muted"},H=["value"],O={class:"row",style:{gap:"10px","margin-top":"16px"}},q=["disabled"],F={key:0,class:"spinner"},J={class:"card",style:{"margin-top":"16px"}},K={style:{"margin-top":"0"}},Q={class:"row",style:{gap:"10px","margin-top":"16px"}},R=["disabled"],W={key:0,class:"spinner"},X={class:"card",style:{"margin-top":"16px"}},Y={style:{"margin-top":"0"}},Z={class:"row"},ee={key:0,class:"error",role:"alert"},ae={key:1,class:"ok",role:"status"},se={__name:"Settings",setup(te){var C,M;const y=c(((C=i.user)==null?void 0:C.name)||""),p=c(((M=i.user)==null?void 0:M.email)||""),u=c(""),_=c(""),r=c(""),m=c(""),g=c(!1),f=c(!1);async function B(){var d,t;r.value="",m.value="",g.value=!0;try{const n={};if(y.value&&y.value!==((d=i.user)==null?void 0:d.name)&&(n.name=y.value),p.value&&p.value!==((t=i.user)==null?void 0:t.email)&&(n.email=p.value),Object.keys(n).length){const l=await U.updateProfile(n);i.user=l.user,m.value=s.t("saved")}}catch(n){r.value=n.message}finally{g.value=!1}}async function N(){var d,t,n;if(r.value="",m.value="",u.value.length<4){r.value=s.t("passwordTooShort");return}if(u.value!==_.value){r.value=s.t("passwordMismatch");return}f.value=!0;try{const l=((d=i.user)==null?void 0:d.username)||((t=i.user)==null?void 0:t.id)||"",L=await U.setup({username:l,email:p.value||((n=i.user)==null?void 0:n.email),password:u.value});i.user=L.user,u.value="",_.value="",m.value=s.t("saved")}catch(l){r.value=l.message}finally{f.value=!1}}function P(d){s.set(d)}return(d,t)=>{var n;return w(),h("div",null,[e("h2",null,[k(a($),{size:22,"stroke-width":1.8,style:{"vertical-align":"-4px"}}),v(" "+o(a(s).t("settings")),1)]),e("div",I,[e("h3",A,[k(a(E),{size:18,"stroke-width":1.8,style:{"vertical-align":"-3px"}}),v(" "+o(a(s).t("profile")),1)]),e("label",null,[v(o(a(s).t("username"))+" ",1),e("span",G,"("+o(a(s).t("readonly"))+")",1)]),e("input",{value:((n=a(i).user)==null?void 0:n.username)||"",disabled:""},null,8,H),e("label",null,o(a(s).t("name")),1),x(e("input",{"onUpdate:modelValue":t[0]||(t[0]=l=>y.value=l),type:"text"},null,512),[[b,y.value]]),e("label",null,o(a(s).t("email")),1),x(e("input",{"onUpdate:modelValue":t[1]||(t[1]=l=>p.value=l),type:"email"},null,512),[[b,p.value]]),e("div",O,[e("button",{class:"primary",disabled:g.value,onClick:B},[g.value?(w(),h("span",F)):V("",!0),v(o(a(s).t("saveProfile")),1)],8,q)])]),e("div",J,[e("h3",K,[k(a(D),{size:18,"stroke-width":1.8,style:{"vertical-align":"-3px"}}),v(" "+o(a(s).t("changePassword")),1)]),e("label",null,o(a(s).t("newPassword")),1),x(e("input",{"onUpdate:modelValue":t[2]||(t[2]=l=>u.value=l),type:"password",autocomplete:"new-password"},null,512),[[b,u.value]]),e("label",null,o(a(s).t("confirmPassword")),1),x(e("input",{"onUpdate:modelValue":t[3]||(t[3]=l=>_.value=l),type:"password",autocomplete:"new-password"},null,512),[[b,_.value]]),e("div",Q,[e("button",{class:"primary",disabled:f.value||!u.value||u.value!==_.value,onClick:N},[f.value?(w(),h("span",W)):V("",!0),v(o(a(s).t("save")),1)],8,R)])]),e("div",X,[e("h3",Y,[k(a(j),{size:18,"stroke-width":1.8,style:{"vertical-align":"-3px"}}),v(" "+o(a(s).t("language")),1)]),e("div",Z,[e("button",{class:S({active:a(s).locale==="th"}),onClick:t[4]||(t[4]=l=>P("th"))},"ไทย",2),e("button",{class:S({active:a(s).locale==="en"}),onClick:t[5]||(t[5]=l=>P("en"))},"English",2)])]),r.value?(w(),h("div",ee,o(r.value),1)):V("",!0),m.value?(w(),h("div",ae,"✅ "+o(m.value),1)):V("",!0)])}}},oe=T(se,[["__scopeId","data-v-4a5a3af4"]]);export{oe as default};

View File

@@ -0,0 +1,11 @@
import{c as M,_ as T,r as c,h as u,a as h,b as e,l as k,u as a,S as $,m as v,t as o,i as s,w as b,v as x,g as V,B as S,x as B,o as g}from"./index-DOaJiTJw.js";import{L as D}from"./lock-WqnzR3ED.js";/**
* @license lucide-vue-next v1.0.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const E=M("globe",[["circle",{cx:"12",cy:"12",r:"10",key:"1mglay"}],["path",{d:"M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20",key:"13o1zl"}],["path",{d:"M2 12h20",key:"9i4pu4"}]]);/**
* @license lucide-vue-next v1.0.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const I=M("user",[["path",{d:"M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2",key:"975kel"}],["circle",{cx:"12",cy:"7",r:"4",key:"17ys0d"}]]),j={class:"card"},G={style:{"margin-top":"0"}},H={class:"muted"},O=["value"],q={class:"row",style:{gap:"10px","margin-top":"16px"}},A=["disabled"],F={key:0,class:"spinner"},J={class:"card",style:{"margin-top":"16px"}},K={style:{"margin-top":"0"}},Q={class:"row",style:{gap:"10px","margin-top":"16px"}},R=["disabled"],W={key:0,class:"spinner"},X={class:"card",style:{"margin-top":"16px"}},Y={style:{"margin-top":"0"}},Z={class:"row"},ee={key:0,class:"error",role:"alert"},ae={key:1,class:"ok",role:"status"},se={__name:"Settings",setup(te){var z,C;const y=c(((z=u.user)==null?void 0:z.name)||""),p=c(((C=u.user)==null?void 0:C.email)||""),i=c(""),_=c(""),r=c(""),m=c(""),f=c(!1),w=c(!1);async function U(){var d,t;r.value="",m.value="",f.value=!0;try{const n={};if(y.value&&y.value!==((d=u.user)==null?void 0:d.name)&&(n.name=y.value),p.value&&p.value!==((t=u.user)==null?void 0:t.email)&&(n.email=p.value),Object.keys(n).length){const l=await B.updateProfile(n);u.user=l.user,m.value=s.t("saved")}}catch(n){r.value=n.message}finally{f.value=!1}}async function L(){var d,t,n;if(r.value="",m.value="",i.value.length<4){r.value=s.t("passwordTooShort");return}if(i.value!==_.value){r.value=s.t("passwordMismatch");return}w.value=!0;try{const l=((d=u.user)==null?void 0:d.username)||((t=u.user)==null?void 0:t.id)||"",N=await B.setup({username:l,email:p.value||((n=u.user)==null?void 0:n.email),password:i.value});u.user=N.user,i.value="",_.value="",m.value=s.t("saved")}catch(l){r.value=l.message}finally{w.value=!1}}function P(d){s.set(d)}return(d,t)=>{var n;return g(),h("div",null,[e("h2",null,[k(a($),{size:22,"stroke-width":1.8,style:{"vertical-align":"-4px"}}),v(" "+o(a(s).t("settings")),1)]),e("div",j,[e("h3",G,[k(a(I),{size:18,"stroke-width":1.8,style:{"vertical-align":"-3px"}}),v(" "+o(a(s).t("profile")),1)]),e("label",null,[v(o(a(s).t("username"))+" ",1),e("span",H,"("+o(a(s).t("readonly"))+")",1)]),e("input",{value:((n=a(u).user)==null?void 0:n.username)||"",disabled:""},null,8,O),e("label",null,o(a(s).t("name")),1),b(e("input",{"onUpdate:modelValue":t[0]||(t[0]=l=>y.value=l),type:"text"},null,512),[[x,y.value]]),e("label",null,o(a(s).t("email")),1),b(e("input",{"onUpdate:modelValue":t[1]||(t[1]=l=>p.value=l),type:"email"},null,512),[[x,p.value]]),e("div",q,[e("button",{class:"primary",disabled:f.value,onClick:U},[f.value?(g(),h("span",F)):V("",!0),v(o(a(s).t("saveProfile")),1)],8,A)])]),e("div",J,[e("h3",K,[k(a(D),{size:18,"stroke-width":1.8,style:{"vertical-align":"-3px"}}),v(" "+o(a(s).t("changePassword")),1)]),e("label",null,o(a(s).t("newPassword")),1),b(e("input",{"onUpdate:modelValue":t[2]||(t[2]=l=>i.value=l),type:"password",autocomplete:"new-password"},null,512),[[x,i.value]]),e("label",null,o(a(s).t("confirmPassword")),1),b(e("input",{"onUpdate:modelValue":t[3]||(t[3]=l=>_.value=l),type:"password",autocomplete:"new-password"},null,512),[[x,_.value]]),e("div",Q,[e("button",{class:"primary",disabled:w.value||!i.value||i.value!==_.value,onClick:L},[w.value?(g(),h("span",W)):V("",!0),v(o(a(s).t("save")),1)],8,R)])]),e("div",X,[e("h3",Y,[k(a(E),{size:18,"stroke-width":1.8,style:{"vertical-align":"-3px"}}),v(" "+o(a(s).t("language")),1)]),e("div",Z,[e("button",{class:S({active:a(s).locale==="th"}),onClick:t[4]||(t[4]=l=>P("th"))},"ไทย",2),e("button",{class:S({active:a(s).locale==="en"}),onClick:t[5]||(t[5]=l=>P("en"))},"English",2)])]),r.value?(g(),h("div",ee,o(r.value),1)):V("",!0),m.value?(g(),h("div",ae,"✅ "+o(m.value),1)):V("",!0)])}}},ne=T(se,[["__scopeId","data-v-4a5a3af4"]]);export{ne as default};

View File

@@ -1 +0,0 @@
.setup-wrap[data-v-f190e120]{display:flex;justify-content:center;padding-top:8vh}.setup-card[data-v-f190e120]{width:380px}h1[data-v-f190e120]{margin-top:0}

View File

@@ -0,0 +1 @@
import{_ as V,a as v,b as e,l as S,u as s,m as g,t,i as a,h as w,w as _,v as y,d as f,g as K,r,j as N,o as m}from"./index-DOaJiTJw.js";import{L as T}from"./lock-WqnzR3ED.js";const B={class:"setup-wrap"},U={class:"card setup-card"},C={class:"muted"},D={key:0,class:"error",role:"alert"},L=["disabled"],M={key:0,class:"spinner"},P={key:1},j={__name:"Setup",setup(z){const x=N(),i=r(""),l=r(""),p=r(""),o=r(""),d=r(!1);async function c(){if(o.value="",l.value.length<4){o.value=a.t("passwordTooShort");return}if(l.value!==p.value){o.value=a.t("passwordMismatch");return}d.value=!0;try{await w.finishSetup(i.value.trim(),l.value),x.push("/")}catch(h){o.value=h.message}finally{d.value=!1}}return(h,u)=>{var b,k;return m(),v("div",B,[e("div",U,[e("h1",null,[S(s(T),{size:22,"stroke-width":1.8,style:{"vertical-align":"-4px"}}),g(" "+t(s(a).t("setupTitle")),1)]),e("p",C,[g(t(s(a).t("setupSubtitle"))+" ",1),e("strong",null,t(((b=s(w).user)==null?void 0:b.name)||((k=s(w).user)==null?void 0:k.username)),1)]),e("label",null,t(s(a).t("email")),1),_(e("input",{"onUpdate:modelValue":u[0]||(u[0]=n=>i.value=n),type:"email",autocomplete:"email",class:"wide",onKeyup:f(c,["enter"])},null,544),[[y,i.value]]),e("label",null,t(s(a).t("newPassword")),1),_(e("input",{"onUpdate:modelValue":u[1]||(u[1]=n=>l.value=n),type:"password",autocomplete:"new-password",class:"wide",onKeyup:f(c,["enter"])},null,544),[[y,l.value]]),e("label",null,t(s(a).t("confirmPassword")),1),_(e("input",{"onUpdate:modelValue":u[2]||(u[2]=n=>p.value=n),type:"password",autocomplete:"new-password",class:"wide",onKeyup:f(c,["enter"])},null,544),[[y,p.value]]),o.value?(m(),v("div",D,t(o.value),1)):K("",!0),e("button",{class:"primary",style:{width:"100%","margin-top":"16px"},disabled:d.value||!i.value||!l.value||l.value!==p.value,onClick:c},[d.value?(m(),v("span",M)):(m(),v("span",P,t(s(a).t("save")),1))],8,L)])])}}},R=V(j,[["__scopeId","data-v-477fc775"]]);export{R as default};

View File

@@ -0,0 +1 @@
.setup-wrap[data-v-477fc775]{display:flex;justify-content:center;padding-top:8vh;padding-left:16px;padding-right:16px}.setup-card[data-v-477fc775]{width:460px;max-width:100%;padding:28px 30px}h1[data-v-477fc775]{margin-top:0;font-size:24px}.wide[data-v-477fc775]{width:100%;min-height:46px;font-size:15px;padding:12px 14px}

View File

@@ -1 +0,0 @@
import{_ as x,c as v,a as e,t,u as s,i as a,j as S,f as _,w,v as f,b as y,e as V,r,g as K,o as m}from"./index-C0_i8cDF.js";const T={class:"setup-wrap"},B={class:"card setup-card"},N={class:"muted"},U={key:0,class:"error",role:"alert"},C=["disabled"],D={key:0,class:"spinner"},M={key:1},P={__name:"Setup",setup(j){const k=K(),i=r(""),l=r(""),p=r(""),o=r(""),d=r(!1);async function c(){if(o.value="",l.value.length<4){o.value=a.t("passwordTooShort");return}if(l.value!==p.value){o.value=a.t("passwordMismatch");return}d.value=!0;try{await _.finishSetup(i.value.trim(),l.value),k.push("/")}catch(h){o.value=h.message}finally{d.value=!1}}return(h,u)=>{var b,g;return m(),v("div",T,[e("div",B,[e("h1",null,"🔐 "+t(s(a).t("setupTitle")),1),e("p",N,[S(t(s(a).t("setupSubtitle"))+" ",1),e("strong",null,t(((b=s(_).user)==null?void 0:b.name)||((g=s(_).user)==null?void 0:g.username)),1)]),e("label",null,t(s(a).t("email")),1),w(e("input",{"onUpdate:modelValue":u[0]||(u[0]=n=>i.value=n),type:"email",autocomplete:"email",onKeyup:y(c,["enter"])},null,544),[[f,i.value]]),e("label",null,t(s(a).t("newPassword")),1),w(e("input",{"onUpdate:modelValue":u[1]||(u[1]=n=>l.value=n),type:"password",autocomplete:"new-password",onKeyup:y(c,["enter"])},null,544),[[f,l.value]]),e("label",null,t(s(a).t("confirmPassword")),1),w(e("input",{"onUpdate:modelValue":u[2]||(u[2]=n=>p.value=n),type:"password",autocomplete:"new-password",onKeyup:y(c,["enter"])},null,544),[[f,p.value]]),o.value?(m(),v("div",U,t(o.value),1)):V("",!0),e("button",{class:"primary",style:{width:"100%","margin-top":"16px"},disabled:d.value||!i.value||!l.value||l.value!==p.value,onClick:c},[d.value?(m(),v("span",D)):(m(),v("span",M,t(s(a).t("save")),1))],8,C)])])}}},I=x(P,[["__scopeId","data-v-f190e120"]]);export{I as default};

View File

@@ -1 +0,0 @@
import{_ as w,l as b,s as A,f as d,c as l,a as t,m as c,u as s,j as _,t as e,i as n,n as m,B as h,e as f,F as B,q as C,r as g,x as N,o as i,A as k}from"./index-C0_i8cDF.js";import{T as P}from"./target-DoOGVGr0.js";import{B as T}from"./book-open-E7lWrK45.js";import{P as z}from"./plus-BiLb0OIF.js";const V={class:"row",style:{"align-items":"center","margin-bottom":"16px"}},j={style:{margin:"0"}},F={class:"row",style:{"margin-left":"auto",gap:"10px"}},L={class:"soft"},S={class:"primary"},$={class:"muted"},q={key:0,class:"card",style:{"min-height":"80px"}},D={key:1,class:"card empty-state"},E={key:0},G={key:1},I={class:"grid"},M={class:"card lift train-card"},O={class:"row",style:{"justify-content":"space-between"}},H={class:"muted",style:{margin:"6px 0 12px"}},J={class:"row",style:{gap:"8px"}},K={class:"muted"},Q={class:"primary",style:{width:"100%","margin-top":"12px"}},R={__name:"Training",setup(U){const u=g([]),y=g(!0);function v(a){return a.sales_kit&&a.sales_kit.productName||a.input&&a.input.product||""}function x(a){return a.personas||a.persona_count||0}return b(async()=>{try{const a=(await A.listGroups()).groups||[];u.value=d.isAdmin?a:a.filter(r=>r.status==="ready")}finally{y.value=!1}}),(a,r)=>{const p=N("router-link");return i(),l("div",null,[t("div",V,[t("h2",j,[c(s(P),{size:22,"stroke-width":1.8,style:{"vertical-align":"-4px"}}),_(" "+e(s(n).t("training")),1)]),t("div",F,[c(p,{to:"/guide"},{default:m(()=>[t("button",L,[c(s(T),{size:18,"stroke-width":1.8}),r[0]||(r[0]=_(" คู่มือ",-1))])]),_:1}),s(d).isAdmin?(i(),h(p,{key:0,to:"/admin/new-group"},{default:m(()=>[t("button",S,[c(s(z),{size:18,"stroke-width":2}),_(" "+e(s(n).t("addProduct")),1)])]),_:1})):f("",!0)])]),t("p",$,e(s(n).t("trainingSubtitle")),1),y.value?(i(),l("div",q,[...r[1]||(r[1]=[t("div",{class:"skeleton",style:{height:"50px"}},null,-1)])])):u.value.length===0?(i(),l("div",D,[t("strong",null,e(s(n).t("noTraining")),1),s(d).isAdmin?(i(),l("span",E,'Click "'+e(s(n).t("addProduct"))+'" to create a persona group.',1)):(i(),l("span",G,"Ask an admin to create a persona group first."))])):f("",!0),t("div",I,[(i(!0),l(B,null,C(u.value,o=>(i(),h(p,{key:o.id,to:s(d).isAdmin?`/admin/groups/${o.id}/edit`:`/groups/${o.id}/personas`,style:{"text-decoration":"none"}},{default:m(()=>[t("div",M,[t("div",O,[t("strong",null,e(o.title),1),t("span",{class:k(["badge",o.status==="ready"?"ready":"draft"])},e(o.status),3)]),t("div",H,e(v(o)),1),t("div",J,[t("span",{class:k(["badge",o.channel||"line"])},e(o.channel||"line"),3),t("span",K,e(x(o))+" "+e(s(n).t("personas").toLowerCase()),1)]),t("button",Q,e(s(d).isAdmin?o.status==="ready"?s(n).t("managePersonas"):s(n).t("analyze"):s(n).t("selectPersona")),1)])]),_:2},1032,["to"]))),128))])])}}},tt=w(R,[["__scopeId","data-v-e39df241"]]);export{tt as default};

View File

@@ -0,0 +1 @@
import{_ as w,n as b,x as B,h as d,a as l,b as t,l as c,u as s,m as _,t as e,i as n,p as m,f as h,g as f,F as C,s as A,r as g,y as N,o as i,B as k}from"./index-DOaJiTJw.js";import{T as P}from"./target-QJk_fUDu.js";import{B as T}from"./book-open-Ckxqlz0w.js";import{P as z}from"./plus-CODydpxS.js";const V={class:"row",style:{"align-items":"center","margin-bottom":"16px"}},F={style:{margin:"0"}},L={class:"row",style:{"margin-left":"auto",gap:"10px"}},S={class:"soft"},$={class:"primary"},j={class:"muted"},D={key:0,class:"card",style:{"min-height":"80px"}},E={key:1,class:"card empty-state"},G={key:0},I={key:1},M={class:"grid"},O={class:"card lift train-card"},q={class:"row",style:{"justify-content":"space-between"}},H={class:"muted",style:{margin:"6px 0 12px"}},J={class:"row",style:{gap:"8px"}},K={class:"muted"},Q={class:"primary",style:{width:"100%","margin-top":"12px"}},R={__name:"Training",setup(U){const u=g([]),y=g(!0);function v(a){return a.sales_kit&&a.sales_kit.productName||a.input&&a.input.product||""}function x(a){return a.personas||a.persona_count||0}return b(async()=>{try{const a=(await B.listGroups()).groups||[];u.value=d.isAdmin?a:a.filter(r=>r.status==="ready")}finally{y.value=!1}}),(a,r)=>{const p=N("router-link");return i(),l("div",null,[t("div",V,[t("h2",F,[c(s(P),{size:22,"stroke-width":1.8,style:{"vertical-align":"-4px"}}),_(" "+e(s(n).t("training")),1)]),t("div",L,[c(p,{to:"/guide"},{default:m(()=>[t("button",S,[c(s(T),{size:18,"stroke-width":1.8}),r[0]||(r[0]=_(" คู่มือ",-1))])]),_:1}),s(d).isAdmin?(i(),h(p,{key:0,to:"/admin/new-group"},{default:m(()=>[t("button",$,[c(s(z),{size:18,"stroke-width":2}),_(" "+e(s(n).t("addProduct")),1)])]),_:1})):f("",!0)])]),t("p",j,e(s(n).t("trainingSubtitle")),1),y.value?(i(),l("div",D,[...r[1]||(r[1]=[t("div",{class:"skeleton",style:{height:"50px"}},null,-1)])])):u.value.length===0?(i(),l("div",E,[t("strong",null,e(s(n).t("noTraining")),1),s(d).isAdmin?(i(),l("span",G,'Click "'+e(s(n).t("addProduct"))+'" to create a persona group.',1)):(i(),l("span",I,"Ask an admin to create a persona group first."))])):f("",!0),t("div",M,[(i(!0),l(C,null,A(u.value,o=>(i(),h(p,{key:o.id,to:s(d).isAdmin?`/admin/groups/${o.id}/edit`:`/groups/${o.id}/personas`,style:{"text-decoration":"none"}},{default:m(()=>[t("div",O,[t("div",q,[t("strong",null,e(o.title),1),t("span",{class:k(["badge",o.status==="ready"?"ready":"draft"])},e(o.status),3)]),t("div",H,e(v(o)),1),t("div",J,[t("span",{class:k(["badge",o.channel||"line"])},e(o.channel||"line"),3),t("span",K,e(x(o))+" "+e(s(n).t("personas").toLowerCase()),1)]),t("button",Q,e(s(d).isAdmin?o.status==="ready"?s(n).t("managePersonas"):s(n).t("analyze"):s(n).t("selectPersona")),1)])]),_:2},1032,["to"]))),128))])])}}},tt=w(R,[["__scopeId","data-v-e39df241"]]);export{tt as default};

View File

@@ -1,4 +1,4 @@
import{k as e}from"./index-C0_i8cDF.js";/**
import{c as e}from"./index-DOaJiTJw.js";/**
* @license lucide-vue-next v1.0.0 - ISC
*
* This source code is licensed under the ISC license.

View File

@@ -1,4 +1,4 @@
import{k as a}from"./index-C0_i8cDF.js";/**
import{c as a}from"./index-DOaJiTJw.js";/**
* @license lucide-vue-next v1.0.0 - ISC
*
* This source code is licensed under the ISC license.

File diff suppressed because one or more lines are too long

View File

@@ -1,4 +1,4 @@
import{k as t}from"./index-C0_i8cDF.js";/**
import{c as t}from"./index-DOaJiTJw.js";/**
* @license lucide-vue-next v1.0.0 - ISC
*
* This source code is licensed under the ISC license.

6
frontend/dist/assets/lock-WqnzR3ED.js vendored Normal file
View File

@@ -0,0 +1,6 @@
import{c as e}from"./index-DOaJiTJw.js";/**
* @license lucide-vue-next v1.0.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const t=e("lock",[["rect",{width:"18",height:"11",x:"3",y:"11",rx:"2",ry:"2",key:"1w4ew1"}],["path",{d:"M7 11V7a5 5 0 0 1 10 0v4",key:"fwvmzm"}]]);export{t as L};

View File

@@ -1,4 +1,4 @@
import{k as e}from"./index-C0_i8cDF.js";/**
import{c as e}from"./index-DOaJiTJw.js";/**
* @license lucide-vue-next v1.0.0 - ISC
*
* This source code is licensed under the ISC license.

View File

@@ -1,4 +1,4 @@
import{k as a}from"./index-C0_i8cDF.js";/**
import{c as a}from"./index-DOaJiTJw.js";/**
* @license lucide-vue-next v1.0.0 - ISC
*
* This source code is licensed under the ISC license.

View File

@@ -1,4 +1,4 @@
import{k as c}from"./index-C0_i8cDF.js";/**
import{c}from"./index-DOaJiTJw.js";/**
* @license lucide-vue-next v1.0.0 - ISC
*
* This source code is licensed under the ISC license.

View File

@@ -1,6 +1,6 @@
import{k as e}from"./index-C0_i8cDF.js";/**
import{c as e}from"./index-DOaJiTJw.js";/**
* @license lucide-vue-next v1.0.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const r=e("users",[["path",{d:"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2",key:"1yyitq"}],["path",{d:"M16 3.128a4 4 0 0 1 0 7.744",key:"16gr8j"}],["path",{d:"M22 21v-2a4 4 0 0 0-3-3.87",key:"kshegd"}],["circle",{cx:"9",cy:"7",r:"4",key:"nufk8"}]]);export{r as U};
*/const c=e("users",[["path",{d:"M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2",key:"1yyitq"}],["path",{d:"M16 3.128a4 4 0 0 1 0 7.744",key:"16gr8j"}],["path",{d:"M22 21v-2a4 4 0 0 0-3-3.87",key:"kshegd"}],["circle",{cx:"9",cy:"7",r:"4",key:"nufk8"}]]);export{c as U};

View File

@@ -4,7 +4,7 @@
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Sales Trainer</title>
<script type="module" crossorigin src="/assets/index-C0_i8cDF.js"></script>
<script type="module" crossorigin src="/assets/index-DOaJiTJw.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-B9WjPRES.css">
</head>
<body>

View File

@@ -1,19 +1,23 @@
<template>
<div class="login-wrap">
<div class="card login-card">
<h1>🎯 {{ i18n.t('app') }}</h1>
<h1>{{ i18n.t('app') }}</h1>
<p class="muted" style="margin-top:-8px">Sales training simulator</p>
<label>{{ i18n.t('username') }}</label>
<input v-model="username" type="text" autocomplete="username" @keyup.enter="submit" />
<input v-model="username" type="text" autocomplete="username" placeholder="username" class="wide" @keyup.enter="submit" />
<label>{{ i18n.t('password') }}</label>
<div class="pw-wrap">
<input v-model="password" :type="showPw ? 'text' : 'password'" autocomplete="current-password" @keyup.enter="submit" />
<input v-model="password" :type="showPw ? 'text' : 'password'" autocomplete="current-password" placeholder="••••••••" class="wide" @keyup.enter="submit" />
<button type="button" class="pw-toggle" @click="showPw = !showPw" :aria-label="showPw ? 'Hide password' : 'Show password'">
{{ showPw ? '🙈' : '👁' }}
<EyeOff v-if="showPw" :size="20" :stroke-width="1.8" />
<Eye v-else :size="20" :stroke-width="1.8" />
</button>
</div>
<div class="error" role="alert" v-if="error">{{ error }}</div>
<button class="primary" style="width:100%;margin-top:16px" :disabled="loading || !username || !password" @click="submit">
<button class="primary" style="width:100%;margin-top:18px" :disabled="loading || !username || !password" @click="submit">
<span v-if="loading" class="spinner"></span>
<span v-else>{{ i18n.t('login') }}</span>
</button>
@@ -24,6 +28,7 @@
<script setup>
import { ref } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { Eye, EyeOff } from 'lucide-vue-next'
import { auth } from '../store/auth'
import { i18n } from '../i18n'
@@ -55,12 +60,24 @@ async function submit() {
</script>
<style scoped>
.login-wrap { display: flex; justify-content: center; padding-top: 10vh; }
.login-card { width: 360px; }
h1 { margin-top: 0; }
.login-wrap {
display: flex;
justify-content: center;
padding-top: 8vh;
padding-left: 16px;
padding-right: 16px;
}
/* Wider card so inputs don't truncate / cut text */
.login-card { width: 460px; max-width: 100%; padding: 28px 30px; }
h1 { margin-top: 0; font-size: 24px; }
/* Full-width, uncramped inputs (global input already width:100%) */
.wide { width: 100%; min-height: 46px; font-size: 15px; padding: 12px 14px; }
.pw-wrap { position: relative; }
.pw-wrap input { padding-right: 48px; }
.pw-toggle {
position: absolute; right: 4px; top: 50%; transform: translateY(-50%);
background: transparent; border: none; padding: 6px; min-height: 36px; cursor: pointer;
background: transparent; border: none; padding: 8px; min-height: 40px; cursor: pointer;
color: var(--muted);
}
.pw-toggle:hover { color: var(--ink); }
</style>

View File

@@ -1,17 +1,17 @@
<template>
<div class="setup-wrap">
<div class="card setup-card">
<h1>🔐 {{ i18n.t('setupTitle') }}</h1>
<h1><Lock :size="22" :stroke-width="1.8" style="vertical-align:-4px" /> {{ i18n.t('setupTitle') }}</h1>
<p class="muted">{{ i18n.t('setupSubtitle') }} <strong>{{ auth.user?.name || auth.user?.username }}</strong></p>
<label>{{ i18n.t('email') }}</label>
<input v-model="email" type="email" autocomplete="email" @keyup.enter="submit" />
<input v-model="email" type="email" autocomplete="email" class="wide" @keyup.enter="submit" />
<label>{{ i18n.t('newPassword') }}</label>
<input v-model="password" type="password" autocomplete="new-password" @keyup.enter="submit" />
<input v-model="password" type="password" autocomplete="new-password" class="wide" @keyup.enter="submit" />
<label>{{ i18n.t('confirmPassword') }}</label>
<input v-model="confirm" type="password" autocomplete="new-password" @keyup.enter="submit" />
<input v-model="confirm" type="password" autocomplete="new-password" class="wide" @keyup.enter="submit" />
<div class="error" role="alert" v-if="error">{{ error }}</div>
@@ -26,6 +26,7 @@
<script setup>
import { ref } from 'vue'
import { useRouter } from 'vue-router'
import { Lock } from 'lucide-vue-next'
import { auth } from '../store/auth'
import { i18n } from '../i18n'
@@ -59,7 +60,11 @@ async function submit() {
</script>
<style scoped>
.setup-wrap { display: flex; justify-content: center; padding-top: 8vh; }
.setup-card { width: 380px; }
h1 { margin-top: 0; }
.setup-wrap {
display: flex; justify-content: center; padding-top: 8vh;
padding-left: 16px; padding-right: 16px;
}
.setup-card { width: 460px; max-width: 100%; padding: 28px 30px; }
h1 { margin-top: 0; font-size: 24px; }
.wide { width: 100%; min-height: 46px; font-size: 15px; padding: 12px 14px; }
</style>