164 lines
6.6 KiB
Vue
164 lines
6.6 KiB
Vue
<script setup lang="ts">
|
|
/** FR-9 UI — upload template ใหม่: ระบบ detect fields (SDT tags) จากไฟล์ให้อัตโนมัติ */
|
|
import type { CreateTemplateResponse } from '~/types/api'
|
|
|
|
const { apiUpload } = useApi()
|
|
useHead({ title: 'สร้าง template ใหม่ — e-Court Documents Versioning' })
|
|
|
|
const name = ref('')
|
|
const description = ref('')
|
|
const file = ref<File | null>(null)
|
|
const fileInput = ref<HTMLInputElement | null>(null)
|
|
|
|
const submitting = ref(false)
|
|
const error = ref<string | null>(null)
|
|
const created = ref<CreateTemplateResponse | null>(null)
|
|
|
|
function onFileChange(e: Event) {
|
|
const input = e.target as HTMLInputElement
|
|
file.value = input.files?.[0] ?? null
|
|
}
|
|
|
|
async function submit() {
|
|
error.value = null
|
|
if (!name.value.trim()) {
|
|
error.value = 'กรอกชื่อ template ด้วย'
|
|
return
|
|
}
|
|
if (!file.value) {
|
|
error.value = 'เลือกไฟล์ .docx ของ template ด้วย'
|
|
return
|
|
}
|
|
if (!file.value.name.toLowerCase().endsWith('.docx')) {
|
|
error.value = 'รองรับเฉพาะไฟล์ .docx เท่านั้น'
|
|
return
|
|
}
|
|
|
|
const form = new FormData()
|
|
form.append('name', name.value.trim())
|
|
if (description.value.trim()) form.append('description', description.value.trim())
|
|
form.append('file', file.value)
|
|
|
|
submitting.value = true
|
|
try {
|
|
created.value = await apiUpload<CreateTemplateResponse>('/api/templates', form)
|
|
} catch (err) {
|
|
error.value = err instanceof Error ? err.message : 'อัปโหลด template ไม่สำเร็จ'
|
|
} finally {
|
|
submitting.value = false
|
|
}
|
|
}
|
|
|
|
/** เคลียร์ฟอร์มเพื่ออัปโหลดไฟล์ถัดไป */
|
|
function resetForm() {
|
|
created.value = null
|
|
name.value = ''
|
|
description.value = ''
|
|
file.value = null
|
|
if (fileInput.value) fileInput.value.value = ''
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<AuthGate>
|
|
<section class="mx-auto max-w-2xl space-y-5">
|
|
<h1 class="text-2xl font-bold">สร้าง template ใหม่</h1>
|
|
|
|
<!-- ผลลัพธ์หลังอัปโหลดสำเร็จ: field list ที่ detect ได้จากไฟล์ -->
|
|
<template v-if="created">
|
|
<AlertBox type="success">
|
|
อัปโหลดสำเร็จ — ตรวจพบ <strong>{{ created.fields.length }}</strong> fields จากไฟล์
|
|
</AlertBox>
|
|
|
|
<div class="overflow-x-auto rounded-lg border border-slate-200 bg-white dark:border-slate-700 dark:bg-slate-800">
|
|
<table class="w-full text-sm">
|
|
<thead class="border-b border-slate-200 text-left text-xs uppercase text-slate-500 dark:border-slate-700 dark:text-slate-400">
|
|
<tr>
|
|
<th class="px-4 py-3">key (SDT tag)</th>
|
|
<th class="px-4 py-3">label เริ่มต้น</th>
|
|
<th class="px-4 py-3">type เริ่มต้น</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody class="divide-y divide-slate-100 dark:divide-slate-700">
|
|
<tr v-for="f in created.fields" :key="f.key">
|
|
<td class="px-4 py-2 font-mono text-xs">{{ f.key }}</td>
|
|
<td class="px-4 py-2">{{ f.label }}</td>
|
|
<td class="px-4 py-2">{{ f.type }}</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
|
|
<div class="flex gap-3">
|
|
<NuxtLink
|
|
:to="`/templates/${created.id}/edit`"
|
|
class="rounded-md bg-sky-600 px-4 py-2 text-sm font-medium text-white hover:bg-sky-700"
|
|
>
|
|
ตั้งค่า label/type/required ต่อ →
|
|
</NuxtLink>
|
|
<button
|
|
type="button"
|
|
class="rounded-md border border-slate-300 px-4 py-2 text-sm hover:bg-slate-100 dark:border-slate-600 dark:hover:bg-slate-800"
|
|
@click="resetForm"
|
|
>
|
|
อัปโหลดอีกไฟล์
|
|
</button>
|
|
</div>
|
|
</template>
|
|
|
|
<form v-else class="space-y-4" @submit.prevent="submit">
|
|
<AlertBox v-if="error" type="error">{{ error }}</AlertBox>
|
|
|
|
<div>
|
|
<label for="tpl-name" class="mb-1 block text-sm font-medium">ชื่อ template <span class="text-red-500">*</span></label>
|
|
<input
|
|
id="tpl-name"
|
|
v-model="name"
|
|
type="text"
|
|
required
|
|
placeholder="เช่น สัญญาจ้างงาน"
|
|
class="w-full rounded-md border border-slate-300 bg-white px-3 py-2 text-sm dark:border-slate-600 dark:bg-slate-800"
|
|
/>
|
|
</div>
|
|
|
|
<div>
|
|
<label for="tpl-desc" class="mb-1 block text-sm font-medium">คำอธิบาย</label>
|
|
<textarea
|
|
id="tpl-desc"
|
|
v-model="description"
|
|
rows="2"
|
|
placeholder="คำอธิบายสั้นๆ ว่าเอกสารนี้ใช้ทำอะไร"
|
|
class="w-full rounded-md border border-slate-300 bg-white px-3 py-2 text-sm dark:border-slate-600 dark:bg-slate-800"
|
|
/>
|
|
</div>
|
|
|
|
<div>
|
|
<label for="tpl-file" class="mb-1 block text-sm font-medium">ไฟล์ template (.docx) <span class="text-red-500">*</span></label>
|
|
<input
|
|
id="tpl-file"
|
|
ref="fileInput"
|
|
type="file"
|
|
accept=".docx"
|
|
required
|
|
class="w-full rounded-md border border-slate-300 bg-white px-3 py-2 text-sm file:mr-3 file:rounded file:border-0 file:bg-slate-100 file:px-3 file:py-1 file:text-sm dark:border-slate-600 dark:bg-slate-800 dark:file:bg-slate-700"
|
|
@change="onFileChange"
|
|
/>
|
|
<p class="mt-1 text-xs text-slate-500 dark:text-slate-400">
|
|
สร้างไฟล์ด้วย Word แล้วใส่
|
|
<strong>Content Controls</strong> (Developer → Rich Text/Plain Text Control) โดยตั้งค่า
|
|
<span class="font-mono">Tag</span> ของแต่ละ control เป็น field key — ระบบจะ detect tags
|
|
ออกมาเป็นรายการ fields ให้อัตโนมัติ
|
|
</p>
|
|
</div>
|
|
|
|
<button
|
|
type="submit"
|
|
:disabled="submitting"
|
|
class="rounded-md bg-sky-600 px-4 py-2 text-sm font-medium text-white hover:bg-sky-700 disabled:opacity-50"
|
|
>
|
|
{{ submitting ? 'กำลังอัปโหลด…' : 'อัปโหลด template' }}
|
|
</button>
|
|
</form>
|
|
</section>
|
|
</AuthGate>
|
|
</template>
|