ux(ui): readable persona form instead of raw JSON + step-by-step guides for non-IT users

- GroupEdit: replace raw JSON persona dump with a labeled, sectioned PersonaForm
  (ข้อมูลพื้นฐาน / ข้อมูลลูกค้า / การขาย / ช่องทาง) shown in a modal; admin edits by field.
- New reusable components/PersonaForm.vue.
- GroupBuilder + Personas: add friendly step-by-step guidance cards ('วิธีสร้าง',
  'วิธีฝึก') so admins/trainees know what to do at each step.
- Rebuild dist.
This commit is contained in:
Macky
2026-08-08 10:24:53 +07:00
parent 55759a3a50
commit 39d1aa04e4
25 changed files with 273 additions and 83 deletions

View File

@@ -1,39 +1,53 @@
<template>
<div class="card">
<h2>{{ i18n.t('groupBuilder') }}</h2>
<label>{{ i18n.t('product') }}</label>
<textarea v-model="form.product" rows="3" placeholder="e.g. Cloud POS for small restaurants"></textarea>
<div>
<router-link to="/training" class="btn-back"> {{ i18n.t('training') }}</router-link>
<label>{{ i18n.t('segment') }}</label>
<input v-model="form.segment" />
<label>{{ i18n.t('description') }}</label>
<textarea v-model="form.description" rows="3"></textarea>
<div class="row">
<div style="flex:1">
<label>{{ i18n.t('channel') }}</label>
<select v-model="form.channel">
<option value="facebook">{{ i18n.t('facebook') }}</option>
<option value="line">{{ i18n.t('line') }}</option>
</select>
</div>
<div style="flex:1">
<label>{{ i18n.t('language') }}</label>
<select v-model="form.language">
<option value="th">{{ i18n.t('thai') }}</option>
<option value="en">{{ i18n.t('english') }}</option>
</select>
</div>
<!-- Step guidance -->
<div class="card guide">
<strong>📋 สรางกลมบคคลตนแบบ</strong>
<ol style="margin:8px 0 0;padding-left:20px;line-height:1.8">
<li>กรอก <strong>/รายละเอยดสนคาหรอบรการ</strong> อยากใหมฝกขาย (องดานลาง)</li>
<li>(ไมงค) ระบกลมลกคาเปาหมาย หรออปโหลดไฟลเอกสารสนค .pdf/.md/.txt</li>
<li>กด <strong>สราง</strong> ระบบจะพาไปหนาสรางบคคลตนแบบ (กคาจำลอง)</li>
</ol>
</div>
<label>📎 Files (.pdf/.md/.txt) {{ i18n.t('product') }} can come from here</label>
<input type="file" multiple accept=".pdf,.md,.txt" @change="onFiles" />
<div class="card">
<h2 style="margin-top:0">📦 {{ i18n.t('addProduct') }}</h2>
<label>{{ i18n.t('product') }} <span class="req">*</span></label>
<textarea v-model="form.product" rows="3" placeholder="เช่น ระบบ POS สำหรับร้านอาหาร Cloud POS for small restaurants"></textarea>
<div class="error" v-if="error">{{ error }}</div>
<button class="primary" style="margin-top:16px" :disabled="busy || (!form.product && !files.length)" @click="create">
{{ busy ? '...' : i18n.t('create') }}
</button>
<label>{{ i18n.t('segment') }}</label>
<input v-model="form.segment" placeholder="เช่น SMEs ร้านอาหารในกรุงเทพ" />
<label>{{ i18n.t('description') }}</label>
<textarea v-model="form.description" rows="3" placeholder="รายละเอียดเพิ่มเติม เช่น จุดเด่นสินค้า ราคา ฯลฯ (ไม่บังคับ)"></textarea>
<div class="row">
<div style="flex:1">
<label>{{ i18n.t('channel') }}</label>
<select v-model="form.channel">
<option value="facebook">{{ i18n.t('facebook') }}</option>
<option value="line">{{ i18n.t('line') }}</option>
</select>
</div>
<div style="flex:1">
<label>{{ i18n.t('language') }}</label>
<select v-model="form.language">
<option value="th">{{ i18n.t('thai') }}</option>
<option value="en">{{ i18n.t('english') }}</option>
</select>
</div>
</div>
<label>📎 ไฟลเอกสารสนค (.pdf/.md/.txt) ใชเปนขอมลใหระบบได</label>
<input type="file" multiple accept=".pdf,.md,.txt" @change="onFiles" />
<div class="error" v-if="error">{{ error }}</div>
<button class="primary" style="margin-top:16px" :disabled="busy || (!form.product && !files.length)" @click="create">
{{ busy ? 'กำลังสร้าง' : ' สร้างกลุ่มบุคคลต้นแบบ' }}
</button>
</div>
</div>
</template>
@@ -73,3 +87,8 @@ async function create() {
}
}
</script>
<style scoped>
.guide { background: #eef2ff; border-color: #c7d2fe; margin-bottom: 16px; }
.req { color: var(--red); }
</style>