main
vue 111 lines 3.2 KB
Raw
1 <template>
2 <n-form :disabled="loading" label-placement="top">
3 <n-form-item label="Case name" required>
4 <n-input v-model:value="model.case_name" placeholder="Insert case name" />
5 </n-form-item>
6 <n-form-item label="Case status" required>
7 <n-select v-model:value="model.case_status" :options="statusOptions" placeholder="Select case status" />
8 </n-form-item>
9 <n-form-item label="Case description" required>
10 <n-input
11 v-model:value="model.case_description"
12 type="textarea"
13 :autosize="{ minRows: 4, maxRows: 8 }"
14 placeholder="Insert case description"
15 />
16 </n-form-item>
17 <n-form-item label="Assigned to (optional)">
18 <n-select
19 v-model:value="model.assigned_to"
20 :options="assignedToOptions"
21 :loading="optionsLoading"
22 clearable
23 filterable
24 placeholder="Select assignee"
25 />
26 </n-form-item>
27 <div class="flex justify-end gap-3">
28 <n-button :disabled="loading" @click="emit('cancel')">Cancel</n-button>
29 <n-button type="primary" :loading :disabled="!isValidForm" @click="handleSubmit">Create case</n-button>
30 </div>
31 </n-form>
32 </template>
33
34 <script setup lang="ts">
35 import type { CasePayload } from "@/api/endpoints/cases"
36 import type { ApiError } from "@/types/common"
37 import { NButton, NForm, NFormItem, NInput, NSelect, useMessage } from "naive-ui"
38 import { computed, onBeforeMount, ref } from "vue"
39 import Api from "@/api"
40 import { useAuthStore } from "@/stores/auth"
41 import { getApiErrorMessage } from "@/utils"
42
43 const emit = defineEmits<{
44 (e: "success"): void
45 (e: "cancel"): void
46 }>()
47
48 const message = useMessage()
49 const authStore = useAuthStore()
50 const customerCode = computed(() => authStore.userCustomerCode)
51 const loading = ref(false)
52 const optionsLoading = ref(false)
53 const assignedToOptions = ref<{ label: string; value: string }[]>([])
54 const statusOptions = [
55 { label: "Open", value: "OPEN" },
56 { label: "In Progress", value: "IN_PROGRESS" },
57 { label: "Closed", value: "CLOSED" }
58 ]
59 const model = ref<CasePayload>({
60 case_name: "",
61 case_description: "",
62 assigned_to: undefined,
63 case_status: "OPEN"
64 })
65
66 const isValidForm = computed(
67 () =>
68 model.value.case_name.trim().length > 0 &&
69 model.value.case_description.trim().length > 0 &&
70 Boolean(model.value.case_status)
71 )
72
73 async function loadAssignedToOptions() {
74 optionsLoading.value = true
75
76 try {
77 const response = await Api.cases.getCasesFilters()
78 assignedToOptions.value = response.data.assigned_to.map(o => ({ label: o, value: o }))
79 } catch (err) {
80 message.error(getApiErrorMessage(err as ApiError))
81 } finally {
82 optionsLoading.value = false
83 }
84 }
85
86 async function handleSubmit() {
87 if (!isValidForm.value || loading.value) return
88
89 loading.value = true
90
91 try {
92 const response = await Api.cases.createCase({
93 case_name: model.value.case_name.trim(),
94 case_description: model.value.case_description.trim(),
95 assigned_to: model.value.assigned_to || undefined,
96 case_status: model.value.case_status,
97 customer_code: customerCode.value || undefined
98 })
99 message.success(response.data.message || "Case created successfully")
100 emit("success")
101 } catch (err) {
102 message.error(getApiErrorMessage(err as ApiError))
103 } finally {
104 loading.value = false
105 }
106 }
107
108 onBeforeMount(() => {
109 loadAssignedToOptions()
110 })
111 </script>