fix(scenario): recontact chats normally first then re-engages mid-chat; channel default=social; remove 'add more' button (15 personas auto)
- recontact persona now opens as a NORMAL customer (no 'I asked before' in the opening); the mid-chat time-lapse system note (turn 2) makes them re-engage warmer instead. - channel default changed facebook->social everywhere (create/analyze/store/simulator/me). - 15 personas auto-generated (TARGET=15); removed the 'สร้างบุคคลต้นแบบเพิ่มเติม' button/guide. All 9 backend suites pass. Rebuilt dist.
This commit is contained in:
@@ -139,7 +139,7 @@ def create_group():
|
||||
"product": product,
|
||||
"segment": (data.get("segment") or ""),
|
||||
"description": (data.get("description") or ""),
|
||||
"channel": (data.get("channel") or "facebook"),
|
||||
"channel": (data.get("channel") or "social"),
|
||||
"language": (data.get("language") or "th"),
|
||||
"files": saved_files,
|
||||
"file_text": file_text[:60000],
|
||||
@@ -209,7 +209,7 @@ def analyze_group(gid: str):
|
||||
segment=inp.get("segment", ""),
|
||||
description=inp.get("description", ""),
|
||||
file_text=inp.get("file_text", ""),
|
||||
channel=inp.get("channel", "facebook"),
|
||||
channel=inp.get("channel", "social"),
|
||||
)
|
||||
except Exception as exc:
|
||||
s["groups"].update(gid, status="failed", error=str(exc))
|
||||
@@ -223,7 +223,7 @@ def analyze_group(gid: str):
|
||||
personas = PersonaGenerator(s["llm"]).generate(
|
||||
sales_kit=sales_kit,
|
||||
language=inp.get("language", "th"),
|
||||
channel=inp.get("channel", "facebook"),
|
||||
channel=inp.get("channel", "social"),
|
||||
)
|
||||
personas = existing + personas
|
||||
except Exception as exc:
|
||||
|
||||
@@ -74,7 +74,7 @@ def _personal_group(s, actor) -> dict:
|
||||
g["id"],
|
||||
status="ready",
|
||||
owner_user_id=actor["id"],
|
||||
input={"channel": "facebook", "language": "th"},
|
||||
input={"channel": "social", "language": "th"},
|
||||
sales_kit={"productName": "personal practice", "valueProps": [], "features": []},
|
||||
)
|
||||
return s["groups"].get(g["id"])
|
||||
|
||||
@@ -35,7 +35,7 @@ def generate_own_persona(llm: LLMClient, *, mode: str, spec: dict[str, Any]) ->
|
||||
if not isinstance(persona, dict):
|
||||
raise ValueError("own-persona generator returned invalid data")
|
||||
persona.setdefault("tier", "B")
|
||||
persona.setdefault("channel", "facebook")
|
||||
persona.setdefault("channel", "social")
|
||||
persona.setdefault("initiation_mode", "customer")
|
||||
persona.setdefault("pains", [])
|
||||
persona.setdefault("negotiation_levers", [])
|
||||
|
||||
@@ -8,7 +8,8 @@ from ..llm import LLMClient
|
||||
from .persona_prompts import PERSONA_SYSTEM
|
||||
|
||||
TIERS = ["A", "B", "C"]
|
||||
PER_TIER = 5
|
||||
PER_TIER = 5 # 5 per tier = 15 total
|
||||
TARGET = 15 # total personas the system generates (no "add more" button needed)
|
||||
|
||||
|
||||
class PersonaGenerator:
|
||||
@@ -20,7 +21,7 @@ class PersonaGenerator:
|
||||
*,
|
||||
sales_kit: dict[str, Any],
|
||||
language: str = "en",
|
||||
channel: str = "facebook",
|
||||
channel: str = "social",
|
||||
) -> list[dict[str, Any]]:
|
||||
kit_json = json.dumps(sales_kit, ensure_ascii=False)[:12000]
|
||||
lang_name = "Thai" if language == "th" else "English"
|
||||
@@ -46,13 +47,15 @@ class PersonaGenerator:
|
||||
PERSONA_SYSTEM, prompt, temperature=0.8, max_tokens=14000
|
||||
)
|
||||
personas = result.get("personas") or []
|
||||
if (isinstance(personas, list) and len(personas) >= 15) or attempt >= 3:
|
||||
if (isinstance(personas, list) and len(personas) >= TARGET) or attempt >= 3:
|
||||
break
|
||||
if not isinstance(personas, list) or not personas:
|
||||
raise ValueError("persona generator returned no personas")
|
||||
|
||||
normalized, counts = [], {"A": 0, "B": 0, "C": 0}
|
||||
for idx, p in enumerate(personas, start=1):
|
||||
if len(normalized) >= TARGET:
|
||||
break # already reached 20 total
|
||||
if not isinstance(p, dict):
|
||||
continue
|
||||
tier = p.get("tier", p.get("intent_tier"))
|
||||
@@ -86,7 +89,6 @@ class PersonaGenerator:
|
||||
|
||||
if len(normalized) < 8:
|
||||
raise ValueError(f"expected ~15 personas, generated only {len(normalized)}")
|
||||
# NOTE: if we're short of 15 (real LLMs occasionally return 14/13), we ACCEPT what we
|
||||
# got rather than crashing the whole analyze — the caller/UI can top up with
|
||||
# "create more personas". A retry loop lives in generate().
|
||||
# NOTE: if we're short of 15 (real LLMs occasionally return 14), we ACCEPT what we
|
||||
# got rather than crashing the whole analyze — with TARGET=15 there's normally no gap.
|
||||
return normalized
|
||||
|
||||
@@ -102,21 +102,16 @@ class Simulator:
|
||||
"social": "Chat style: short, casual, quick social-messaging replies.",
|
||||
"f2f_call": "Style: natural, conversational like a live face-to-face or phone talk.",
|
||||
}.get(scenario, "")
|
||||
# Personality trait: a "recontact" customer asked about this before and is only now
|
||||
# coming back, already warmer / more ready to buy. Reference it in chat naturally.
|
||||
if persona.get("recontact"):
|
||||
adapt += (
|
||||
"\nYou contacted/interacted with this seller BEFORE (earlier contact) and are now "
|
||||
"coming back — you already know the product basics, so you're warmer and more ready "
|
||||
"to decide. Mention this naturally (e.g. 'I asked about this a while back')."
|
||||
)
|
||||
# NOTE: 'recontact' is a MID-CHAT behavior, not baked into the opening — the trainee
|
||||
# chats with this customer normally first. At the right turn (see chat_routes) a
|
||||
# time-lapse system note is inserted and only THEN does the customer re-engage warmer.
|
||||
tolerance = int(persona.get("tolerance", 3) or 3)
|
||||
system = CHAT_SYSTEM.format(
|
||||
name=persona.get("name", "Customer"),
|
||||
tone=persona.get("communication_style", "natural, casual"),
|
||||
profession=persona.get("profession", "customer"),
|
||||
age_group=persona.get("age_group", "adult"),
|
||||
channel=persona.get("channel", "facebook") + (f" ({scenario})" if scenario else ""),
|
||||
channel=persona.get("channel", "social") + (f" ({scenario})" if scenario else ""),
|
||||
background=persona.get("background", ""),
|
||||
personality=persona.get("personality", ""),
|
||||
lifestyle=persona.get("lifestyle", ""),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import{c as k,_ as h,p 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,H as U,g as f,F as V,x as C,y as w,r as y,o as i,C as M}from"./index-rfeHzF-F.js";import{U as z}from"./users-BgT8ke9W.js";/**
|
||||
import{c as k,_ as h,p 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,H as U,g as f,F as V,x as C,y as w,r as y,o as i,C as M}from"./index-yErsUbD6.js";import{U as z}from"./users-BK4yWB6N.js";/**
|
||||
* @license lucide-vue-next v1.0.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
@@ -1,4 +1,4 @@
|
||||
import{c as x,_ as L,p as M,a as p,b as s,l as i,u as a,m as c,t as e,i as n,q as w,w as f,v as b,s as U,g as N,F as R,x as j,y as A,z as B,r as m,h as E,o as y}from"./index-rfeHzF-F.js";import{U as P}from"./users-BgT8ke9W.js";import{P as S}from"./plus-GGHS2V4y.js";/**
|
||||
import{c as x,_ as L,p as M,a as p,b as s,l as i,u as a,m as c,t as e,i as n,q as w,w as f,v as b,s as U,g as N,F as R,x as j,y as A,z as B,r as m,h as E,o as y}from"./index-yErsUbD6.js";import{U as P}from"./users-BK4yWB6N.js";import{P as S}from"./plus-Y1qXSgej.js";/**
|
||||
* @license lucide-vue-next v1.0.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
@@ -1,4 +1,4 @@
|
||||
import{c as P,_ as G,p as K,y as S,a as l,l as k,q as D,u as a,b as s,t,i as n,F as j,x as T,m as g,g as m,C as L,w as R,v as $,d as q,k as H,r as u,B as J,E as O,z as U,o}from"./index-rfeHzF-F.js";import{T as Y}from"./target-CLzEfHJ7.js";import{A as Q}from"./arrow-left-De8eM538.js";/**
|
||||
import{c as P,_ as G,p as K,y as S,a as l,l as k,q as D,u as a,b as s,t,i as n,F as j,x as T,m as g,g as m,C as L,w as R,v as $,d as q,k as H,r as u,B as J,E as O,z as U,o}from"./index-yErsUbD6.js";import{T as Y}from"./target-DmESUw9c.js";import{A as Q}from"./arrow-left-hWxF5h5m.js";/**
|
||||
* @license lucide-vue-next v1.0.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
@@ -1,4 +1,4 @@
|
||||
import{c as v,_ as M,a as k,l as u,q as z,b as e,u as l,m as o,t as r,i,w as g,v as y,H as V,g as C,z as A,r as m,y as x,j as B,o as w}from"./index-rfeHzF-F.js";import{A as q}from"./arrow-left-De8eM538.js";/**
|
||||
import{c as v,_ as M,a as k,l as u,q as z,b as e,u as l,m as o,t as r,i,w as g,v as y,H as V,g as C,z as A,r as m,y as x,j as B,o as w}from"./index-yErsUbD6.js";import{A as q}from"./arrow-left-hWxF5h5m.js";/**
|
||||
* @license lucide-vue-next v1.0.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
14
frontend/dist/assets/GroupEdit-Bzhg1xqU.js
vendored
Normal file
14
frontend/dist/assets/GroupEdit-Bzhg1xqU.js
vendored
Normal file
File diff suppressed because one or more lines are too long
14
frontend/dist/assets/GroupEdit-Ci_uwcwx.js
vendored
14
frontend/dist/assets/GroupEdit-Ci_uwcwx.js
vendored
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
||||
.sec[data-v-59429170]{margin-top:20px}.sec h4[data-v-59429170]{margin:0 0 10px;padding-bottom:6px;border-bottom:1px solid var(--border)}.row[data-v-59429170]{display:flex;gap:12px;flex-wrap:wrap}.f[data-v-59429170]{flex:1;min-width:140px}label[data-v-59429170]{font-size:13px;color:var(--muted);display:block;margin:10px 0 4px}input[data-v-59429170],select[data-v-59429170],textarea[data-v-59429170]{width:100%}.actions[data-v-59429170]{margin-top:20px}.locked[data-v-59429170]{background:#fffaf5;border:1px dashed #d6c7a1;border-radius:12px;padding:12px 14px}.locked h4[data-v-59429170]{color:#b45309}.grid[data-v-255f109f]{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:14px}.pcard[data-v-255f109f]{display:flex;flex-direction:column}.edit-btn[data-v-255f109f]{margin-top:auto;display:inline-flex;align-items:center;gap:6px}.star[data-v-255f109f]{color:#d8dbe3}.star.on[data-v-255f109f]{color:#f59e0b}.badge.tier-a[data-v-255f109f]{background:#dcfce7;color:#166534}.badge.tier-b[data-v-255f109f]{background:#fef9c3;color:#854d0e}.badge.tier-c[data-v-255f109f]{background:#fee2e2;color:#991b1b}.guide[data-v-255f109f]{background:#eef2ff;border-color:#c7d2fe;margin-bottom:16px}.modal-backdrop[data-v-255f109f]{position:fixed;top:0;right:0;bottom:0;left:0;background:#0f172a80;display:flex;justify-content:center;align-items:flex-start;padding:40px 16px;z-index:50;overflow:auto}.modal[data-v-255f109f]{background:#fff;border-radius:14px;padding:24px;width:100%;max-width:720px;box-shadow:0 20px 50px #00000040}
|
||||
.sec[data-v-59429170]{margin-top:20px}.sec h4[data-v-59429170]{margin:0 0 10px;padding-bottom:6px;border-bottom:1px solid var(--border)}.row[data-v-59429170]{display:flex;gap:12px;flex-wrap:wrap}.f[data-v-59429170]{flex:1;min-width:140px}label[data-v-59429170]{font-size:13px;color:var(--muted);display:block;margin:10px 0 4px}input[data-v-59429170],select[data-v-59429170],textarea[data-v-59429170]{width:100%}.actions[data-v-59429170]{margin-top:20px}.locked[data-v-59429170]{background:#fffaf5;border:1px dashed #d6c7a1;border-radius:12px;padding:12px 14px}.locked h4[data-v-59429170]{color:#b45309}.grid[data-v-c3e7f19c]{display:grid;grid-template-columns:repeat(auto-fill,minmax(240px,1fr));gap:14px}.pcard[data-v-c3e7f19c]{display:flex;flex-direction:column}.edit-btn[data-v-c3e7f19c]{margin-top:auto;display:inline-flex;align-items:center;gap:6px}.star[data-v-c3e7f19c]{color:#d8dbe3}.star.on[data-v-c3e7f19c]{color:#f59e0b}.badge.tier-a[data-v-c3e7f19c]{background:#dcfce7;color:#166534}.badge.tier-b[data-v-c3e7f19c]{background:#fef9c3;color:#854d0e}.badge.tier-c[data-v-c3e7f19c]{background:#fee2e2;color:#991b1b}.guide[data-v-c3e7f19c]{background:#eef2ff;border-color:#c7d2fe;margin-bottom:16px}.modal-backdrop[data-v-c3e7f19c]{position:fixed;top:0;right:0;bottom:0;left:0;background:#0f172a80;display:flex;justify-content:center;align-items:flex-start;padding:40px 16px;z-index:50;overflow:auto}.modal[data-v-c3e7f19c]{background:#fff;border-radius:14px;padding:24px;width:100%;max-width:720px;box-shadow:0 20px 50px #00000040}
|
||||
@@ -1,6 +1,11 @@
|
||||
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,G as u,o as d}from"./index-rfeHzF-F.js";import{B as g}from"./book-open-tl-QQwuW.js";import{L as p}from"./layout-dashboard-DNjo1OkM.js";import{T as m}from"./target-CLzEfHJ7.js";import{S as y}from"./sparkles-DyyL2g7W.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,G as d,o as u}from"./index-yErsUbD6.js";import{B as g}from"./book-open-Cmnj20ue.js";import{L as p}from"./layout-dashboard-DplDGQ9R.js";import{T as y}from"./target-DmESUw9c.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"}},A={__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{A as default};
|
||||
*/const m=e("sparkles",[["path",{d:"M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0-1.594 1.594l-1.051 5.558a1 1 0 0 1-1.966 0l-1.051-5.558a2 2 0 0 0-1.594-1.594l-5.558-1.051a1 1 0 0 1 0-1.966l5.558-1.051a2 2 0 0 0 1.594-1.594z",key:"1s2grr"}],["path",{d:"M20 2v4",key:"1rf3ol"}],["path",{d:"M22 4h-4",key:"gwowj6"}],["circle",{cx:"4",cy:"20",r:"2",key:"6kqj1y"}]]);/**
|
||||
* @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"},c={style:{"margin-top":"0"}},v={class:"card"},x={style:{"margin-top":"0"}},f={class:"card"},w={style:{"margin-top":"0"}},z={class:"card"},_={style:{"margin-top":"0"}},b={__name:"Guide",setup(B){return(V,t)=>(u(),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",c,[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",v,[l("h3",x,[n(i(y),{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",f,[l("h3",w,[n(i(m),{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]=d('<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};
|
||||
@@ -1,4 +1,4 @@
|
||||
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-rfeHzF-F.js";/**
|
||||
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-yErsUbD6.js";/**
|
||||
* @license lucide-vue-next v1.0.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
@@ -1 +1 @@
|
||||
import{_ as f,p as x,y 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,A as N,F as D,x as S,r as m,B as c,o as i,C as T}from"./index-rfeHzF-F.js";import{L as V}from"./layout-dashboard-DNjo1OkM.js";const C={style:{margin:"0"}},L={key:0,class:"row stat-row"},M={class:"card stat"},z={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=m([]),u=m([]),p=m(!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{p.value=!1}}),(n,l)=>(i(),r("div",null,[t("div",null,[t("h2",C,[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))]),p.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",z,[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)])])),p.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};
|
||||
import{_ as f,p as x,y 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,A as N,F as D,x as S,r as m,B as c,o as i,C as T}from"./index-yErsUbD6.js";import{L as V}from"./layout-dashboard-DplDGQ9R.js";const C={style:{margin:"0"}},L={key:0,class:"row stat-row"},M={class:"card stat"},z={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=m([]),u=m([]),p=m(!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{p.value=!1}}),(n,l)=>(i(),r("div",null,[t("div",null,[t("h2",C,[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))]),p.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",z,[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)])])),p.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};
|
||||
@@ -1 +1 @@
|
||||
import{_ as T,p as $,a as l,l as u,q as _,b as t,t as s,u as e,i as n,h as g,m as d,g as x,F as y,x as p,k as L,y as N,z as V,r as w,o as a,S,C as b,f as A}from"./index-rfeHzF-F.js";import{T as F}from"./target-CLzEfHJ7.js";import{A as j}from"./arrow-left-De8eM538.js";const q={class:"row",style:{"align-items":"center"}},D={style:{margin:"0"}},E={class:"muted",style:{"margin-left":"auto"}},I={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,h=w([]),C=w(!0);async function B(){try{h.value=(await N.listPersonas(c)).personas}finally{C.value=!1}}function z(r){return h.value.filter(i=>i.tier===r)}function P(r){return n.t(r==="A"?"tierA":r==="B"?"tierB":"tierC")}function k(r){return r==="won"?n.t("won"):r==="lost"?n.t("lost"):n.t("notTried")}return $(B),(r,i)=>{const m=V("router-link");return a(),l("div",null,[u(m,{to:"/training",class:"btn-back"},{default:_(()=>[u(e(j),{size:16,"stroke-width":2}),d(" "+s(e(n).t("training")),1)]),_:1}),t("div",q,[t("h2",D,s(e(n).t("personas")),1),t("span",E,s(e(n).t("selectPersona")),1)]),e(g).isAdmin?x("",!0):(a(),l("div",I,[t("strong",null,[u(e(F),{size:17,"stroke-width":1.8,style:{"vertical-align":"-3px"}}),i[0]||(i[0]=d(" วิธีฝึก",-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,[d("กด "),t("strong",null,"แชท"),d(" → เลือกสถานการณ์ (โซเชียล / พบหน้า-โทร) → เริ่มคุยกับลูกค้า")]),t("li",null,"ลูกค้าจะตัดสินใจเองว่าซื้อหรือไม่ซื้อ (ฝึกได้คนละครั้งเท่านั้น)")],-1))])),e(g).isAdmin?(a(),l("div",M,[u(m,{to:`/admin/groups/${e(c)}/edit`},{default:_(()=>[t("button",R,[u(e(S),{size:18,"stroke-width":1.8}),d(" "+s(e(n).t("managePersonas")),1)])]),_:1},8,["to"]),i[2]||(i[2]=t("span",{class:"muted"},"Admin: จัดการรายละเอียดบุคคลต้นแบบได้ที่นี่",-1))])):x("",!0),(a(),l(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),l(y,null,p(z(f),o=>(a(),l("div",{key:o.id,class:"card pcard lift"},[t("div",H,[t("strong",null,s(o.name),1),t("span",{class:b(["badge",o.my_outcome])},s(k(o.my_outcome)),3)]),t("div",J,[(a(),l(y,null,p(5,v=>t("span",{key:v,class:b(["star",{on:v<=(o.difficulty||1)}])},"★",2)),64)),t("span",K,s(e(n).t("difficulty"))+" "+s(o.difficulty||1)+"/5",1)]),t("div",O,[d(s(o.profession)+" · "+s(o.age_group)+" · "+s(o.location),1),i[3]||(i[3]=t("br",null,null,-1)),t("span",Q,s(e(n).t("difficulty"))+" "+s(o.difficulty||1)+"/5",1)]),t("div",U,s(o.product_context),1),e(g).isAdmin?(a(),A(m,{key:0,to:`/groups/${e(c)}/chat/${o.id}`,style:{"margin-top":"auto"}},{default:_(()=>[t("button",W,s(e(n).t("chat")),1)]),_:1},8,["to"])):(a(),l(y,{key:1},[o.my_outcome==="not_tried"?(a(),A(m,{key:0,to:`/groups/${e(c)}/chat/${o.id}`,style:{"margin-top":"auto"}},{default:_(()=>[t("button",X,s(e(n).t("chat")),1)]),_:1},8,["to"])):(a(),l("div",Y,"✓ "+s(e(n).t("trained"))+" ("+s(k(o.my_outcome))+")",1))],64))]))),128))])])),64))])}}},at=T(Z,[["__scopeId","data-v-ec851b01"]]);export{at as default};
|
||||
import{_ as T,p as $,a as l,l as u,q as _,b as t,t as s,u as e,i as n,h as g,m as d,g as x,F as y,x as p,k as L,y as N,z as V,r as w,o as a,S,C as b,f as A}from"./index-yErsUbD6.js";import{T as F}from"./target-DmESUw9c.js";import{A as j}from"./arrow-left-hWxF5h5m.js";const q={class:"row",style:{"align-items":"center"}},D={style:{margin:"0"}},E={class:"muted",style:{"margin-left":"auto"}},I={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,h=w([]),C=w(!0);async function B(){try{h.value=(await N.listPersonas(c)).personas}finally{C.value=!1}}function z(r){return h.value.filter(i=>i.tier===r)}function P(r){return n.t(r==="A"?"tierA":r==="B"?"tierB":"tierC")}function k(r){return r==="won"?n.t("won"):r==="lost"?n.t("lost"):n.t("notTried")}return $(B),(r,i)=>{const m=V("router-link");return a(),l("div",null,[u(m,{to:"/training",class:"btn-back"},{default:_(()=>[u(e(j),{size:16,"stroke-width":2}),d(" "+s(e(n).t("training")),1)]),_:1}),t("div",q,[t("h2",D,s(e(n).t("personas")),1),t("span",E,s(e(n).t("selectPersona")),1)]),e(g).isAdmin?x("",!0):(a(),l("div",I,[t("strong",null,[u(e(F),{size:17,"stroke-width":1.8,style:{"vertical-align":"-3px"}}),i[0]||(i[0]=d(" วิธีฝึก",-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,[d("กด "),t("strong",null,"แชท"),d(" → เลือกสถานการณ์ (โซเชียล / พบหน้า-โทร) → เริ่มคุยกับลูกค้า")]),t("li",null,"ลูกค้าจะตัดสินใจเองว่าซื้อหรือไม่ซื้อ (ฝึกได้คนละครั้งเท่านั้น)")],-1))])),e(g).isAdmin?(a(),l("div",M,[u(m,{to:`/admin/groups/${e(c)}/edit`},{default:_(()=>[t("button",R,[u(e(S),{size:18,"stroke-width":1.8}),d(" "+s(e(n).t("managePersonas")),1)])]),_:1},8,["to"]),i[2]||(i[2]=t("span",{class:"muted"},"Admin: จัดการรายละเอียดบุคคลต้นแบบได้ที่นี่",-1))])):x("",!0),(a(),l(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),l(y,null,p(z(f),o=>(a(),l("div",{key:o.id,class:"card pcard lift"},[t("div",H,[t("strong",null,s(o.name),1),t("span",{class:b(["badge",o.my_outcome])},s(k(o.my_outcome)),3)]),t("div",J,[(a(),l(y,null,p(5,v=>t("span",{key:v,class:b(["star",{on:v<=(o.difficulty||1)}])},"★",2)),64)),t("span",K,s(e(n).t("difficulty"))+" "+s(o.difficulty||1)+"/5",1)]),t("div",O,[d(s(o.profession)+" · "+s(o.age_group)+" · "+s(o.location),1),i[3]||(i[3]=t("br",null,null,-1)),t("span",Q,s(e(n).t("difficulty"))+" "+s(o.difficulty||1)+"/5",1)]),t("div",U,s(o.product_context),1),e(g).isAdmin?(a(),A(m,{key:0,to:`/groups/${e(c)}/chat/${o.id}`,style:{"margin-top":"auto"}},{default:_(()=>[t("button",W,s(e(n).t("chat")),1)]),_:1},8,["to"])):(a(),l(y,{key:1},[o.my_outcome==="not_tried"?(a(),A(m,{key:0,to:`/groups/${e(c)}/chat/${o.id}`,style:{"margin-top":"auto"}},{default:_(()=>[t("button",X,s(e(n).t("chat")),1)]),_:1},8,["to"])):(a(),l("div",Y,"✓ "+s(e(n).t("trained"))+" ("+s(k(o.my_outcome))+")",1))],64))]))),128))])])),64))])}}},at=T(Z,[["__scopeId","data-v-ec851b01"]]);export{at as default};
|
||||
@@ -1,4 +1,4 @@
|
||||
import{c as U,_ 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,C as S,y as M,o as g}from"./index-rfeHzF-F.js";import{L as D}from"./lock-BhsUQe9Y.js";/**
|
||||
import{c as U,_ 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,C as S,y as M,o as g}from"./index-yErsUbD6.js";import{L as D}from"./lock-CCBV2bwv.js";/**
|
||||
* @license lucide-vue-next v1.0.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
@@ -1 +1 @@
|
||||
import{_ as U,a as v,b as e,l as K,u as s,m,t as a,i as l,h as _,w,v as b,d as h,n as N,g as T,r,j as B,o as f}from"./index-rfeHzF-F.js";import{L as C}from"./lock-BhsUQe9Y.js";const M={class:"setup-wrap"},D={class:"card setup-card"},L={class:"muted"},P={class:"terms"},j={key:0,class:"error",role:"alert"},z=["disabled"],E={key:0,class:"spinner"},I={key:1},V="/legal",R={__name:"Setup",setup(q){const S=B(),i=r(""),o=r(""),p=r(""),y=r(!1),u=r(""),d=r(!1);async function c(){if(u.value="",o.value.length<4){u.value=l.t("passwordTooShort");return}if(o.value!==p.value){u.value=l.t("passwordMismatch");return}d.value=!0;try{await _.finishSetup(i.value.trim(),o.value,!0),S.push("/")}catch(k){u.value=k.message}finally{d.value=!1}}return(k,t)=>{var g,x;return f(),v("div",M,[e("div",D,[e("h1",null,[K(s(C),{size:22,"stroke-width":1.8,style:{"vertical-align":"-4px"}}),m(" "+a(s(l).t("setupTitle")),1)]),e("p",L,[m(a(s(l).t("setupSubtitle"))+" ",1),e("strong",null,a(((g=s(_).user)==null?void 0:g.name)||((x=s(_).user)==null?void 0:x.username)),1)]),e("label",null,a(s(l).t("email")),1),w(e("input",{"onUpdate:modelValue":t[0]||(t[0]=n=>i.value=n),type:"email",autocomplete:"email",class:"wide",onKeyup:h(c,["enter"])},null,544),[[b,i.value]]),e("label",null,a(s(l).t("newPassword")),1),w(e("input",{"onUpdate:modelValue":t[1]||(t[1]=n=>o.value=n),type:"password",autocomplete:"new-password",class:"wide",onKeyup:h(c,["enter"])},null,544),[[b,o.value]]),e("label",null,a(s(l).t("confirmPassword")),1),w(e("input",{"onUpdate:modelValue":t[2]||(t[2]=n=>p.value=n),type:"password",autocomplete:"new-password",class:"wide",onKeyup:h(c,["enter"])},null,544),[[b,p.value]]),e("label",P,[w(e("input",{"onUpdate:modelValue":t[3]||(t[3]=n=>y.value=n),type:"checkbox"},null,512),[[N,y.value]]),e("span",null,[t[4]||(t[4]=m("ฉันยอมรับ ",-1)),e("a",{href:V,target:"_blank",rel:"noopener"},"ข้อกำหนดการใช้งาน"),t[5]||(t[5]=m(" และ ",-1)),e("a",{href:V,target:"_blank",rel:"noopener"},"นโยบายความเป็นส่วนตัว")])]),u.value?(f(),v("div",j,a(u.value),1)):T("",!0),e("button",{class:"primary",style:{width:"100%","margin-top":"16px"},disabled:d.value||!i.value||!o.value||o.value!==p.value||!y.value,onClick:c},[d.value?(f(),v("span",E)):(f(),v("span",I,a(s(l).t("save")),1))],8,z)])])}}},G=U(R,[["__scopeId","data-v-a3748c0a"]]);export{G as default};
|
||||
import{_ as U,a as v,b as e,l as K,u as s,m,t as a,i as l,h as _,w,v as b,d as h,n as N,g as T,r,j as B,o as f}from"./index-yErsUbD6.js";import{L as C}from"./lock-CCBV2bwv.js";const M={class:"setup-wrap"},D={class:"card setup-card"},L={class:"muted"},P={class:"terms"},j={key:0,class:"error",role:"alert"},z=["disabled"],E={key:0,class:"spinner"},I={key:1},V="/legal",R={__name:"Setup",setup(q){const S=B(),i=r(""),o=r(""),p=r(""),y=r(!1),u=r(""),d=r(!1);async function c(){if(u.value="",o.value.length<4){u.value=l.t("passwordTooShort");return}if(o.value!==p.value){u.value=l.t("passwordMismatch");return}d.value=!0;try{await _.finishSetup(i.value.trim(),o.value,!0),S.push("/")}catch(k){u.value=k.message}finally{d.value=!1}}return(k,t)=>{var g,x;return f(),v("div",M,[e("div",D,[e("h1",null,[K(s(C),{size:22,"stroke-width":1.8,style:{"vertical-align":"-4px"}}),m(" "+a(s(l).t("setupTitle")),1)]),e("p",L,[m(a(s(l).t("setupSubtitle"))+" ",1),e("strong",null,a(((g=s(_).user)==null?void 0:g.name)||((x=s(_).user)==null?void 0:x.username)),1)]),e("label",null,a(s(l).t("email")),1),w(e("input",{"onUpdate:modelValue":t[0]||(t[0]=n=>i.value=n),type:"email",autocomplete:"email",class:"wide",onKeyup:h(c,["enter"])},null,544),[[b,i.value]]),e("label",null,a(s(l).t("newPassword")),1),w(e("input",{"onUpdate:modelValue":t[1]||(t[1]=n=>o.value=n),type:"password",autocomplete:"new-password",class:"wide",onKeyup:h(c,["enter"])},null,544),[[b,o.value]]),e("label",null,a(s(l).t("confirmPassword")),1),w(e("input",{"onUpdate:modelValue":t[2]||(t[2]=n=>p.value=n),type:"password",autocomplete:"new-password",class:"wide",onKeyup:h(c,["enter"])},null,544),[[b,p.value]]),e("label",P,[w(e("input",{"onUpdate:modelValue":t[3]||(t[3]=n=>y.value=n),type:"checkbox"},null,512),[[N,y.value]]),e("span",null,[t[4]||(t[4]=m("ฉันยอมรับ ",-1)),e("a",{href:V,target:"_blank",rel:"noopener"},"ข้อกำหนดการใช้งาน"),t[5]||(t[5]=m(" และ ",-1)),e("a",{href:V,target:"_blank",rel:"noopener"},"นโยบายความเป็นส่วนตัว")])]),u.value?(f(),v("div",j,a(u.value),1)):T("",!0),e("button",{class:"primary",style:{width:"100%","margin-top":"16px"},disabled:d.value||!i.value||!o.value||o.value!==p.value||!y.value,onClick:c},[d.value?(f(),v("span",E)):(f(),v("span",I,a(s(l).t("save")),1))],8,z)])])}}},G=U(R,[["__scopeId","data-v-a3748c0a"]]);export{G as default};
|
||||
@@ -1,4 +1,4 @@
|
||||
import{c as x,_ as b,p as C,y as f,h as l,a as d,b as s,l as c,u as t,m,t as o,i as n,q as _,f as A,g as h,F as z,x as M,r as v,z as T,o as r,C as B,D as N}from"./index-rfeHzF-F.js";import{T as P}from"./target-CLzEfHJ7.js";import{B as V}from"./book-open-tl-QQwuW.js";import{P as $}from"./plus-GGHS2V4y.js";/**
|
||||
import{c as x,_ as b,p as C,y as f,h as l,a as d,b as s,l as c,u as t,m,t as o,i as n,q as _,f as A,g as h,F as z,x as M,r as v,z as T,o as r,C as B,D as N}from"./index-yErsUbD6.js";import{T as P}from"./target-DmESUw9c.js";import{B as V}from"./book-open-Cmnj20ue.js";import{P as $}from"./plus-Y1qXSgej.js";/**
|
||||
* @license lucide-vue-next v1.0.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
@@ -1,4 +1,4 @@
|
||||
import{c as e}from"./index-rfeHzF-F.js";/**
|
||||
import{c as e}from"./index-yErsUbD6.js";/**
|
||||
* @license lucide-vue-next v1.0.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
@@ -1,4 +1,4 @@
|
||||
import{c as a}from"./index-rfeHzF-F.js";/**
|
||||
import{c as a}from"./index-yErsUbD6.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
@@ -1,4 +1,4 @@
|
||||
import{c as t}from"./index-rfeHzF-F.js";/**
|
||||
import{c as t}from"./index-yErsUbD6.js";/**
|
||||
* @license lucide-vue-next v1.0.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
@@ -1,4 +1,4 @@
|
||||
import{c as e}from"./index-rfeHzF-F.js";/**
|
||||
import{c as e}from"./index-yErsUbD6.js";/**
|
||||
* @license lucide-vue-next v1.0.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
@@ -1,4 +1,4 @@
|
||||
import{c as e}from"./index-rfeHzF-F.js";/**
|
||||
import{c as e}from"./index-yErsUbD6.js";/**
|
||||
* @license lucide-vue-next v1.0.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
6
frontend/dist/assets/sparkles-DyyL2g7W.js
vendored
6
frontend/dist/assets/sparkles-DyyL2g7W.js
vendored
@@ -1,6 +0,0 @@
|
||||
import{c as a}from"./index-rfeHzF-F.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=a("sparkles",[["path",{d:"M11.017 2.814a1 1 0 0 1 1.966 0l1.051 5.558a2 2 0 0 0 1.594 1.594l5.558 1.051a1 1 0 0 1 0 1.966l-5.558 1.051a2 2 0 0 0-1.594 1.594l-1.051 5.558a1 1 0 0 1-1.966 0l-1.051-5.558a2 2 0 0 0-1.594-1.594l-5.558-1.051a1 1 0 0 1 0-1.966l5.558-1.051a2 2 0 0 0 1.594-1.594z",key:"1s2grr"}],["path",{d:"M20 2v4",key:"1rf3ol"}],["path",{d:"M22 4h-4",key:"gwowj6"}],["circle",{cx:"4",cy:"20",r:"2",key:"6kqj1y"}]]);export{l as S};
|
||||
@@ -1,4 +1,4 @@
|
||||
import{c}from"./index-rfeHzF-F.js";/**
|
||||
import{c}from"./index-yErsUbD6.js";/**
|
||||
* @license lucide-vue-next v1.0.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
@@ -1,4 +1,4 @@
|
||||
import{c as e}from"./index-rfeHzF-F.js";/**
|
||||
import{c as e}from"./index-yErsUbD6.js";/**
|
||||
* @license lucide-vue-next v1.0.0 - ISC
|
||||
*
|
||||
* This source code is licensed under the ISC license.
|
||||
2
frontend/dist/index.html
vendored
2
frontend/dist/index.html
vendored
@@ -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-rfeHzF-F.js"></script>
|
||||
<script type="module" crossorigin src="/assets/index-yErsUbD6.js"></script>
|
||||
<link rel="stylesheet" crossorigin href="/assets/index-B9WjPRES.css">
|
||||
</head>
|
||||
<body>
|
||||
|
||||
@@ -3,11 +3,6 @@
|
||||
<router-link to="/training" class="btn-back">← {{ i18n.t('training') }}</router-link>
|
||||
<div class="row" style="align-items:center;margin-bottom:8px">
|
||||
<h2 style="margin:0"><Users :size="22" :stroke-width="1.8" style="vertical-align:-4px" /> {{ i18n.t('managePersonas') }}</h2>
|
||||
<div class="row" style="margin-left:auto;gap:10px">
|
||||
<button @click="analyze" :disabled="busy" class="primary">
|
||||
<span v-if="busy" class="spinner"></span><Sparkles v-else :size="18" :stroke-width="1.8" /> {{ busy ? 'กำลังสร้าง…' : 'สร้างบุคคลต้นแบบเพิ่มเติม' }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<p class="muted" v-if="group">สินค้า: <strong>{{ group.title }}</strong></p>
|
||||
|
||||
@@ -17,9 +12,8 @@
|
||||
<div class="card guide">
|
||||
<strong>วิธีใช้หน้านี้</strong>
|
||||
<ol style="margin:8px 0 0;padding-left:20px;line-height:1.8">
|
||||
<li>ระบบสร้างบุคคลต้นแบบ (ลูกค้าจำลอง) ให้อัตโนมัติแล้ว หลังกดสร้าง</li>
|
||||
<li>ระบบสร้างบุคคลต้นแบบ 15 คนให้อัตโนมัติแล้ว หลังกดสร้าง</li>
|
||||
<li>แต่ละการ์ดคือลูกค้าจำลอง 1 คน — กด <strong>✏️ แก้ไข</strong> เพื่อปรับรายละเอียดให้ตรงใจ</li>
|
||||
<li>อยากได้ลูกค้าจำลองเพิ่ม กด <strong>สร้างบุคคลต้นแบบเพิ่มเติม</strong></li>
|
||||
<li><strong>วิธีเริ่มฝึก:</strong> ไปที่แท็บ <strong>การฝึก</strong> → เลือกสินค้านี้ → เลือกลูกค้าจำลอง 1 คน → กด <strong>แชท</strong> → เลือกสถานการณ์ → เริ่มคุย</li>
|
||||
</ol>
|
||||
</div>
|
||||
@@ -65,7 +59,7 @@
|
||||
<script setup>
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { Sparkles, Users, Pencil, MessageSquare } from 'lucide-vue-next'
|
||||
import { Users, Pencil, MessageSquare } from 'lucide-vue-next'
|
||||
import { api } from '../api'
|
||||
import { i18n } from '../i18n'
|
||||
import PersonaForm from '../components/PersonaForm.vue'
|
||||
|
||||
Reference in New Issue
Block a user