[verified] fix debrief pain display ([object Object]) + add 'create persona from this one' button
- formatValue(): render arrays of objects (e.g. pains) as readable text instead of '[object Object], [object Object]' - SessionDetail: new 'สร้างบุคคลต้นแบบจากต้นแบบนี้' button calls the existing group persona-variant endpoint so trainees/orders can regenerate a persona based on the revealed one after a session
This commit is contained in:
@@ -45,6 +45,16 @@
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
|
||||
<button
|
||||
v-if="session.group_id && session.persona_id"
|
||||
class="soft variant-btn"
|
||||
@click="makeVariant"
|
||||
:disabled="creating"
|
||||
>
|
||||
{{ creating ? i18n.t('creating') : i18n.t('createVariant') }}
|
||||
</button>
|
||||
<div v-if="variantMsg" class="muted" style="margin-top:8px">{{ variantMsg }}</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
@@ -52,14 +62,17 @@
|
||||
|
||||
<script setup>
|
||||
import { computed, onMounted, ref } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { api } from '../api'
|
||||
import { i18n } from '../i18n'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const session = ref(null)
|
||||
const loading = ref(true)
|
||||
const error = ref('')
|
||||
const creating = ref(false)
|
||||
const variantMsg = ref('')
|
||||
|
||||
const statusClass = computed(() => session.value?.status === 'active' ? 'active' : session.value?.outcome || 'not_tried')
|
||||
const statusLabel = computed(() => {
|
||||
@@ -80,11 +93,43 @@ function fieldLabel(key) {
|
||||
return labels[key] || key
|
||||
}
|
||||
function formatValue(value) {
|
||||
if (Array.isArray(value)) return value.join(', ')
|
||||
if (Array.isArray(value)) {
|
||||
// Arrays may hold plain strings OR objects (e.g. pains [{title,description}]).
|
||||
// Never let join() stringify an object into "[object Object]".
|
||||
return value
|
||||
.map((item) => {
|
||||
if (item && typeof item === 'object') {
|
||||
const readable = item.description ?? item.title ?? item.text
|
||||
return readable && typeof readable === 'string' && readable.trim()
|
||||
? readable.trim()
|
||||
: JSON.stringify(item)
|
||||
}
|
||||
return String(item)
|
||||
})
|
||||
.join(', ')
|
||||
}
|
||||
if (value && typeof value === 'object') return JSON.stringify(value)
|
||||
return String(value == null ? '—' : value)
|
||||
}
|
||||
|
||||
async function makeVariant() {
|
||||
if (!session.value?.group_id || !session.value?.persona_id) return
|
||||
creating.value = true
|
||||
variantMsg.value = ''
|
||||
try {
|
||||
const created = await api.createPersonaVariant(session.value.group_id, session.value.persona_id)
|
||||
const target = created && typeof created === 'object' && created.group_id
|
||||
? created.group_id
|
||||
: session.value.group_id
|
||||
// Trainee variants land in the private group; admin variants in the shared group.
|
||||
await router.push(`/groups/${target}/personas`)
|
||||
} catch (e) {
|
||||
variantMsg.value = i18n.t('requestFailed')
|
||||
} finally {
|
||||
creating.value = false
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
try {
|
||||
session.value = (await api.getSession(route.params.sid)).session
|
||||
@@ -101,6 +146,7 @@ onMounted(async () => {
|
||||
.bubble { max-width:72%; padding:10px 14px; white-space:pre-wrap; word-break:break-word; }
|
||||
.msg-system { align-self:center; background:#fef3c7; color:#92400e; font-size:12px; max-width:88%; border-radius:999px; }
|
||||
.debrief { margin-top:16px; }
|
||||
.variant-btn { margin-top:14px; }
|
||||
.reveal-grid { display:grid; grid-template-columns:1fr 1fr; gap:8px; margin-top:8px; }
|
||||
.rev { display:flex; flex-direction:column; background:#f8fafc; border:1px solid var(--border); border-radius:8px; padding:8px 10px; }
|
||||
.rk { font-size:12px; color:var(--muted); }
|
||||
|
||||
Reference in New Issue
Block a user