| 1 | <template> |
| 2 | <n-form ref="addFormRef" :model="addForm" :rules="addFormRules" label-placement="top" :disabled="submitting"> |
| 3 | <n-form-item label="Title" path="title"> |
| 4 | <n-input v-model:value="addForm.title" placeholder="What needs to be done?" /> |
| 5 | </n-form-item> |
| 6 | <n-form-item v-if="alertOptions.length" label="Attach to alert (optional)" path="alertId"> |
| 7 | <n-select |
| 8 | v-model:value="addForm.alertId" |
| 9 | :options="alertOptions" |
| 10 | placeholder="Case-wide / general (no alert)" |
| 11 | clearable |
| 12 | :consistent-menu-width="false" |
| 13 | /> |
| 14 | </n-form-item> |
| 15 | <n-form-item path="mandatory" :show-label="false"> |
| 16 | <n-checkbox v-model:checked="addForm.mandatory">Mandatory (blocks close-with-warning)</n-checkbox> |
| 17 | </n-form-item> |
| 18 | <n-form-item label="Description (optional)" path="description"> |
| 19 | <n-input v-model:value="addForm.description" type="textarea" :autosize="{ minRows: 2, maxRows: 4 }" /> |
| 20 | </n-form-item> |
| 21 | <n-form-item label="Guidelines (optional)" path="guidelines"> |
| 22 | <n-input |
| 23 | v-model:value="addForm.guidelines" |
| 24 | type="textarea" |
| 25 | placeholder="Best practices / steps to follow" |
| 26 | :autosize="{ minRows: 2, maxRows: 6 }" |
| 27 | /> |
| 28 | </n-form-item> |
| 29 | <div class="flex justify-end gap-2"> |
| 30 | <n-button type="primary" :loading="submitting" :disabled="!isValid" @click="submitAddTask"> |
| 31 | Add task |
| 32 | </n-button> |
| 33 | </div> |
| 34 | </n-form> |
| 35 | </template> |
| 36 | |
| 37 | <script setup lang="ts"> |
| 38 | import type { FormInst, FormRules } from "naive-ui" |
| 39 | import type { ApiError } from "@/types/common" |
| 40 | import type { Alert } from "@/types/incidentManagement/alerts.d" |
| 41 | import { NButton, NCheckbox, NForm, NFormItem, NInput, NSelect, useMessage } from "naive-ui" |
| 42 | import { computed, ref } from "vue" |
| 43 | import Api from "@/api" |
| 44 | import { getApiErrorMessage } from "@/utils" |
| 45 | |
| 46 | const { caseId, linkedAlerts } = defineProps<{ |
| 47 | caseId: number |
| 48 | linkedAlerts?: Alert[] |
| 49 | }>() |
| 50 | |
| 51 | const emit = defineEmits<{ |
| 52 | (e: "success"): void |
| 53 | }>() |
| 54 | |
| 55 | const message = useMessage() |
| 56 | |
| 57 | const submitting = ref(false) |
| 58 | const addFormRef = ref<FormInst | null>(null) |
| 59 | const addForm = ref<{ |
| 60 | title: string |
| 61 | description: string |
| 62 | guidelines: string |
| 63 | mandatory: boolean |
| 64 | alertId: number | null |
| 65 | }>({ |
| 66 | title: "", |
| 67 | description: "", |
| 68 | guidelines: "", |
| 69 | mandatory: false, |
| 70 | alertId: null |
| 71 | }) |
| 72 | |
| 73 | const addFormRules: FormRules = { |
| 74 | title: { required: true, message: "Title is required", trigger: "blur" } |
| 75 | } |
| 76 | |
| 77 | const alertOptions = computed(() => |
| 78 | (linkedAlerts || []).map(a => ({ |
| 79 | label: `#${a.id} — ${a.alert_name} (${a.source})`, |
| 80 | value: a.id |
| 81 | })) |
| 82 | ) |
| 83 | |
| 84 | const isValid = computed(() => { |
| 85 | return addForm.value.title.trim() !== "" |
| 86 | }) |
| 87 | |
| 88 | function resetForm() { |
| 89 | addForm.value = { title: "", description: "", guidelines: "", mandatory: false, alertId: null } |
| 90 | } |
| 91 | |
| 92 | async function submitAddTask() { |
| 93 | try { |
| 94 | await addFormRef.value?.validate() |
| 95 | } catch { |
| 96 | return |
| 97 | } |
| 98 | submitting.value = true |
| 99 | |
| 100 | try { |
| 101 | const res = await Api.incidentManagement.caseTemplates.addCaseTask(caseId, { |
| 102 | title: addForm.value.title, |
| 103 | description: addForm.value.description || null, |
| 104 | guidelines: addForm.value.guidelines || null, |
| 105 | mandatory: addForm.value.mandatory, |
| 106 | alert_id: addForm.value.alertId |
| 107 | }) |
| 108 | if (res.data.success && res.data.task) { |
| 109 | resetForm() |
| 110 | emit("success") |
| 111 | } else { |
| 112 | message.warning(res.data.message) |
| 113 | } |
| 114 | } catch (err) { |
| 115 | message.error(getApiErrorMessage(err as ApiError) || "Failed to add task") |
| 116 | } finally { |
| 117 | submitting.value = false |
| 118 | } |
| 119 | } |
| 120 | </script> |