@dragonmastery/dragoncore-vue 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (138) hide show
  1. package/LICENSE +75 -0
  2. package/dist/AppLink-CHMMrSFI.js +54 -0
  3. package/dist/AppLink-CHMMrSFI.js.map +1 -0
  4. package/dist/Appearance-BfPdKMXw.js +70 -0
  5. package/dist/Appearance-BfPdKMXw.js.map +1 -0
  6. package/dist/Appearance-C3WguxT-.js +3 -0
  7. package/dist/ChangePasswordPage-Btu5lf-r.js +86 -0
  8. package/dist/ChangePasswordPage-Btu5lf-r.js.map +1 -0
  9. package/dist/ChangePasswordPage-mBBuQMkT.js +6 -0
  10. package/dist/CreateTeamForm-n2ut93vM.js +43 -0
  11. package/dist/CreateTeamMemberForm-CcH3AxNL.js +43 -0
  12. package/dist/CreateUserPage-CDrGuW9B.js +6 -0
  13. package/dist/CreateUserPage-Cmx8xjjv.js +76 -0
  14. package/dist/CreateUserPage-Cmx8xjjv.js.map +1 -0
  15. package/dist/CreditBalanceDashboard-DLz0ioP3.js +43 -0
  16. package/dist/CreditManagement-D3q5S-qc.js +43 -0
  17. package/dist/CustomerCreateSupportTicketForm-Ci7QYkG-.js +43 -0
  18. package/dist/CustomerEditSupportTicketForm-Dd5ZB74k.js +159 -0
  19. package/dist/CustomerEditSupportTicketForm-Dd5ZB74k.js.map +1 -0
  20. package/dist/CustomerEditSupportTicketForm-lLchVjnw.js +9 -0
  21. package/dist/CustomerSupportTicketAttachmentsTab-gBrVO97t.js +43 -0
  22. package/dist/CustomerSupportTicketCustomerNotesTab-D0jhzbOY.js +8 -0
  23. package/dist/CustomerSupportTicketCustomerNotesTab-D1aa9It7.js +23 -0
  24. package/dist/CustomerSupportTicketCustomerNotesTab-D1aa9It7.js.map +1 -0
  25. package/dist/CustomerSupportTicketHistoryTab-BNTf8EZq.js +6 -0
  26. package/dist/CustomerSupportTicketHistoryTab-CFYN_Sa4.js +17 -0
  27. package/dist/CustomerSupportTicketHistoryTab-CFYN_Sa4.js.map +1 -0
  28. package/dist/CustomerSupportTicketList-BkOzFxMP.js +6 -0
  29. package/dist/CustomerSupportTicketList-C2nUPawb.js +166 -0
  30. package/dist/CustomerSupportTicketList-C2nUPawb.js.map +1 -0
  31. package/dist/CustomerSupportTicketParent-2mONd9kL.js +66 -0
  32. package/dist/CustomerSupportTicketParent-2mONd9kL.js.map +1 -0
  33. package/dist/CustomerSupportTicketParent-N8ko1yFE.js +7 -0
  34. package/dist/CustomerSupportTicketSuccess-w_-9NXT4.js +43 -0
  35. package/dist/CustomerViewSupportTicket-CVwNH0lS.js +11 -0
  36. package/dist/CustomerViewSupportTicket-tZkxragu.js +363 -0
  37. package/dist/CustomerViewSupportTicket-tZkxragu.js.map +1 -0
  38. package/dist/EditTeamForm-BioqiTWE.js +43 -0
  39. package/dist/EditTeamMemberForm-DCq0Gsn_.js +7 -0
  40. package/dist/EditTeamMemberForm-ru4WgLz-.js +169 -0
  41. package/dist/EditTeamMemberForm-ru4WgLz-.js.map +1 -0
  42. package/dist/EditUserPage-BxJ5QvIM.js +112 -0
  43. package/dist/EditUserPage-BxJ5QvIM.js.map +1 -0
  44. package/dist/EditUserPage-XOBuxUxd.js +7 -0
  45. package/dist/FieldsetSection-CsHN38_o.js +27 -0
  46. package/dist/FieldsetSection-CsHN38_o.js.map +1 -0
  47. package/dist/ForgotPassword-CpqvcSFg.js +7 -0
  48. package/dist/ForgotPassword-CqhenzUG.js +73 -0
  49. package/dist/ForgotPassword-CqhenzUG.js.map +1 -0
  50. package/dist/InlineAttachments-I39rOvip.js +1351 -0
  51. package/dist/InlineAttachments-I39rOvip.js.map +1 -0
  52. package/dist/LoginForm-AM0qkfbU.js +7 -0
  53. package/dist/LoginForm-_PZ51Uwe.js +116 -0
  54. package/dist/LoginForm-_PZ51Uwe.js.map +1 -0
  55. package/dist/Logout-BMjiqHnS.js +38 -0
  56. package/dist/Logout-BMjiqHnS.js.map +1 -0
  57. package/dist/Logout-BfiBjlaH.js +6 -0
  58. package/dist/NoteList-C0hRPNMO.js +497 -0
  59. package/dist/NoteList-C0hRPNMO.js.map +1 -0
  60. package/dist/NotificationEmailsPage-BjRqtW95.js +141 -0
  61. package/dist/NotificationEmailsPage-BjRqtW95.js.map +1 -0
  62. package/dist/NotificationEmailsPage-bx-9rg3x.js +7 -0
  63. package/dist/ResetPassword-BQLkR9TZ.js +43 -0
  64. package/dist/Signup-CnCcQlB8.js +7 -0
  65. package/dist/Signup-c2-_yMOM.js +106 -0
  66. package/dist/Signup-c2-_yMOM.js.map +1 -0
  67. package/dist/StaffCreateSupportTicketForm-ChVFDJdA.js +43 -0
  68. package/dist/StaffEditSupportTicketForm-DY1Zkf5k.js +9 -0
  69. package/dist/StaffEditSupportTicketForm-DuUKuIGg.js +263 -0
  70. package/dist/StaffEditSupportTicketForm-DuUKuIGg.js.map +1 -0
  71. package/dist/StaffSupportTicketAttachmentsTab-DpDXsHXP.js +43 -0
  72. package/dist/StaffSupportTicketCustomerNotesTab-CusqQV2-.js +23 -0
  73. package/dist/StaffSupportTicketCustomerNotesTab-CusqQV2-.js.map +1 -0
  74. package/dist/StaffSupportTicketCustomerNotesTab-rbJHJ0_V.js +8 -0
  75. package/dist/StaffSupportTicketHistoryTab-D24myEm3.js +17 -0
  76. package/dist/StaffSupportTicketHistoryTab-D24myEm3.js.map +1 -0
  77. package/dist/StaffSupportTicketHistoryTab-nmVma5vp.js +6 -0
  78. package/dist/StaffSupportTicketInternalNotesTab-D8HM--dp.js +23 -0
  79. package/dist/StaffSupportTicketInternalNotesTab-D8HM--dp.js.map +1 -0
  80. package/dist/StaffSupportTicketInternalNotesTab-DihYd5XI.js +8 -0
  81. package/dist/StaffSupportTicketList-DelptSmK.js +43 -0
  82. package/dist/StaffSupportTicketParent-BCrj3ckV.js +7 -0
  83. package/dist/StaffSupportTicketParent-Cx1buQZw.js +66 -0
  84. package/dist/StaffSupportTicketParent-Cx1buQZw.js.map +1 -0
  85. package/dist/StaffSupportTicketSuccess-BYxtY5wZ.js +43 -0
  86. package/dist/StaffSupportTicketWorkflowTab-BrDDBeK9.js +9 -0
  87. package/dist/StaffSupportTicketWorkflowTab-DmVTPzxS.js +1234 -0
  88. package/dist/StaffSupportTicketWorkflowTab-DmVTPzxS.js.map +1 -0
  89. package/dist/SupportTicketHistoryTab-CLMopA7a.js +220 -0
  90. package/dist/SupportTicketHistoryTab-CLMopA7a.js.map +1 -0
  91. package/dist/SupportTicketStatusBadge-YdZzjvkh.js +163 -0
  92. package/dist/SupportTicketStatusBadge-YdZzjvkh.js.map +1 -0
  93. package/dist/TeamAttachmentsTab-BxUpTWYh.js +43 -0
  94. package/dist/TeamHistoryTab-CUCT9MRG.js +5 -0
  95. package/dist/TeamHistoryTab-gB3H2KZv.js +219 -0
  96. package/dist/TeamHistoryTab-gB3H2KZv.js.map +1 -0
  97. package/dist/TeamList-By6pzWm5.js +43 -0
  98. package/dist/TeamMemberList-CYV9fWEb.js +43 -0
  99. package/dist/TeamMemberParent-CVvGqpxD.js +43 -0
  100. package/dist/TeamMembersTab-4gmnP9sD.js +21 -0
  101. package/dist/TeamMembersTab-4gmnP9sD.js.map +1 -0
  102. package/dist/TeamMembersTab-CpE9BaCi.js +3 -0
  103. package/dist/TeamNotesTab-pfXTDhg6.js +23 -0
  104. package/dist/TeamNotesTab-pfXTDhg6.js.map +1 -0
  105. package/dist/TeamNotesTab-u4cDC67X.js +8 -0
  106. package/dist/TeamParent-BxT1KubK.js +43 -0
  107. package/dist/UserListPage-DsQdH2Sm.js +4 -0
  108. package/dist/UserListPage-WU56KiWj.js +153 -0
  109. package/dist/UserListPage-WU56KiWj.js.map +1 -0
  110. package/dist/UserProfilePage-B73JhjUu.js +7 -0
  111. package/dist/UserProfilePage-BtLUY1kt.js +125 -0
  112. package/dist/UserProfilePage-BtLUY1kt.js.map +1 -0
  113. package/dist/ViewTeam-DzX-obEl.js +43 -0
  114. package/dist/ViewTeamMember-PF6S_4Pb.js +43 -0
  115. package/dist/ZiniaContainer-C7c7Vwkh.js +18 -0
  116. package/dist/ZiniaContainer-C7c7Vwkh.js.map +1 -0
  117. package/dist/convertToLocalDateTime-D4IoNvRj.js +111 -0
  118. package/dist/convertToLocalDateTime-D4IoNvRj.js.map +1 -0
  119. package/dist/creditValueFormatter-DftEzu8d.js +128 -0
  120. package/dist/creditValueFormatter-DftEzu8d.js.map +1 -0
  121. package/dist/displayIdFormatter-Dz900Awr.js +13 -0
  122. package/dist/displayIdFormatter-Dz900Awr.js.map +1 -0
  123. package/dist/index.d.ts +6068 -0
  124. package/dist/index.js +45 -0
  125. package/dist/src-o5fMIo5_.js +6649 -0
  126. package/dist/src-o5fMIo5_.js.map +1 -0
  127. package/dist/useBreadcrumbs-DmgSucoe.js +41 -0
  128. package/dist/useBreadcrumbs-DmgSucoe.js.map +1 -0
  129. package/dist/useMutation-CFwe7H9j.js +50 -0
  130. package/dist/useMutation-CFwe7H9j.js.map +1 -0
  131. package/dist/useQuery-p7oJO7OD.js +107 -0
  132. package/dist/useQuery-p7oJO7OD.js.map +1 -0
  133. package/dist/useQueryCache-ByayvZgZ.js +254 -0
  134. package/dist/useQueryCache-ByayvZgZ.js.map +1 -0
  135. package/dist/useRpcAuth-BLlRSHy8.js +722 -0
  136. package/dist/useRpcAuth-BLlRSHy8.js.map +1 -0
  137. package/package.json +62 -0
  138. package/src/daisyui.css +63 -0
@@ -0,0 +1,1234 @@
1
+ import { t as useMutation } from "./useMutation-CFwe7H9j.js";
2
+ import { t as useQuery } from "./useQuery-p7oJO7OD.js";
3
+ import { t as ZiniaContainer_default } from "./ZiniaContainer-C7c7Vwkh.js";
4
+ import { n as formatStaffCreditValue, r as SupportTicketTypeBadge_default } from "./creditValueFormatter-DftEzu8d.js";
5
+ import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createStaticVNode, createTextVNode, createVNode, defineComponent, inject, normalizeClass, openBlock, ref, toDisplayString, unref, withCtx, withModifiers } from "vue";
6
+ import { useRoute, useRouter } from "vue-router";
7
+ import { CompleteSupportTicketSchema } from "@dragonmastery/dragoncore-shared";
8
+ import { useForm, withMetadata } from "@dragonmastery/zinia-forms-core";
9
+ import { toast } from "vue3-toastify";
10
+
11
+ //#region src/slices/support_ticket/components/SupportTicketApprovalBadge.vue
12
+ const _hoisted_1$9 = ["aria-label"];
13
+ const _sfc_main$9 = /* @__PURE__ */ defineComponent({
14
+ __name: "SupportTicketApprovalBadge",
15
+ props: {
16
+ approvalStatus: {},
17
+ size: { default: "md" },
18
+ variant: { default: "default" }
19
+ },
20
+ setup(__props) {
21
+ /**
22
+ * SupportTicketApprovalBadge - A reusable Vue component for displaying support ticket approval status
23
+ * as color-coded badges with consistent DaisyUI styling and accessibility features.
24
+ *
25
+ * @example
26
+ * <SupportTicketApprovalBadge :approvalStatus="'PENDING'" size="md" />
27
+ * <SupportTicketApprovalBadge :approvalStatus="'APPROVED'" size="sm" variant="outline" />
28
+ */
29
+ const props = __props;
30
+ /**
31
+ * Configuration for each approval status badge
32
+ */
33
+ const approvalConfig = {
34
+ PENDING: {
35
+ color: "badge-warning",
36
+ text: "Pending",
37
+ ariaLabel: "Approval: Awaiting staff decision"
38
+ },
39
+ APPROVED: {
40
+ color: "badge-success",
41
+ text: "Approved",
42
+ ariaLabel: "Approval: Approved by staff"
43
+ },
44
+ REJECTED: {
45
+ color: "badge-error",
46
+ text: "Rejected",
47
+ ariaLabel: "Approval: Rejected by staff"
48
+ },
49
+ INTERNAL: {
50
+ color: "badge-info",
51
+ text: "Internal",
52
+ ariaLabel: "Approval: Internal staff ticket"
53
+ }
54
+ };
55
+ const getApprovalConfig = (approvalStatus) => {
56
+ const config$1 = approvalConfig[approvalStatus];
57
+ if (!config$1) return {
58
+ color: "badge-neutral",
59
+ text: approvalStatus || "Unknown",
60
+ ariaLabel: `Approval: ${approvalStatus || "Unknown status"}`
61
+ };
62
+ return config$1;
63
+ };
64
+ const config = computed(() => getApprovalConfig(props.approvalStatus));
65
+ const badgeClasses = computed(() => {
66
+ const baseClasses = ["badge", "text-xs"];
67
+ baseClasses.push(config.value.color);
68
+ if (props.size === "sm") baseClasses.push("badge-sm", "text-xs");
69
+ else if (props.size === "lg") baseClasses.push("badge-lg", "text-sm");
70
+ else baseClasses.push("text-xs", "sm:text-sm");
71
+ if (props.variant === "outline") baseClasses.push("badge-outline");
72
+ return baseClasses.join(" ");
73
+ });
74
+ const displayText = computed(() => config.value.text);
75
+ const ariaLabel = computed(() => config.value.ariaLabel);
76
+ return (_ctx, _cache) => {
77
+ return openBlock(), createElementBlock("div", {
78
+ class: normalizeClass(badgeClasses.value),
79
+ "aria-label": ariaLabel.value,
80
+ role: "status"
81
+ }, toDisplayString(displayText.value), 11, _hoisted_1$9);
82
+ };
83
+ }
84
+ });
85
+ var SupportTicketApprovalBadge_default = _sfc_main$9;
86
+
87
+ //#endregion
88
+ //#region src/slices/support_ticket/components/SupportTicketDevLifecycleBadge.vue
89
+ const _hoisted_1$8 = ["aria-label"];
90
+ const _sfc_main$8 = /* @__PURE__ */ defineComponent({
91
+ __name: "SupportTicketDevLifecycleBadge",
92
+ props: {
93
+ devLifecycle: {},
94
+ size: { default: "md" },
95
+ variant: { default: "default" }
96
+ },
97
+ setup(__props) {
98
+ /**
99
+ * SupportTicketDevLifecycleBadge - A reusable Vue component for displaying support ticket dev lifecycle
100
+ * as color-coded badges with consistent DaisyUI styling and accessibility features.
101
+ *
102
+ * @example
103
+ * <SupportTicketDevLifecycleBadge :devLifecycle="'DEVELOPMENT'" size="md" />
104
+ * <SupportTicketDevLifecycleBadge :devLifecycle="'TESTING'" size="sm" variant="outline" />
105
+ */
106
+ const props = __props;
107
+ /**
108
+ * Configuration for each dev lifecycle badge
109
+ */
110
+ const devLifecycleConfig = {
111
+ PENDING: {
112
+ color: "badge-neutral",
113
+ text: "Pending",
114
+ ariaLabel: "Dev Stage: Pending"
115
+ },
116
+ BACKLOG: {
117
+ color: "badge-info",
118
+ text: "Backlog",
119
+ ariaLabel: "Dev Stage: In backlog"
120
+ },
121
+ PLANNING: {
122
+ color: "badge-info",
123
+ text: "Planning",
124
+ ariaLabel: "Dev Stage: Planning phase"
125
+ },
126
+ DEVELOPMENT: {
127
+ color: "badge-secondary",
128
+ text: "Dev",
129
+ ariaLabel: "Dev Stage: In development"
130
+ },
131
+ CODE_REVIEW: {
132
+ color: "badge-secondary",
133
+ text: "Review",
134
+ ariaLabel: "Dev Stage: Code review"
135
+ },
136
+ TESTING: {
137
+ color: "badge-warning",
138
+ text: "Testing",
139
+ ariaLabel: "Dev Stage: Testing phase"
140
+ },
141
+ STAGING: {
142
+ color: "badge-warning",
143
+ text: "Staging",
144
+ ariaLabel: "Dev Stage: On staging"
145
+ },
146
+ PO_APPROVAL: {
147
+ color: "badge-warning",
148
+ text: "PO Review",
149
+ ariaLabel: "Dev Stage: Awaiting PO approval"
150
+ },
151
+ DEPLOYED: {
152
+ color: "badge-success",
153
+ text: "Live",
154
+ ariaLabel: "Dev Stage: Deployed to production"
155
+ },
156
+ CANCELLED: {
157
+ color: "badge-error",
158
+ text: "Cancelled",
159
+ ariaLabel: "Dev Stage: Cancelled"
160
+ }
161
+ };
162
+ const getDevLifecycleConfig = (devLifecycle) => {
163
+ const config$1 = devLifecycleConfig[devLifecycle];
164
+ if (!config$1) return {
165
+ color: "badge-neutral",
166
+ text: devLifecycle || "Unknown",
167
+ ariaLabel: `Dev Stage: ${devLifecycle || "Unknown stage"}`
168
+ };
169
+ return config$1;
170
+ };
171
+ const config = computed(() => getDevLifecycleConfig(props.devLifecycle));
172
+ const badgeClasses = computed(() => {
173
+ const baseClasses = ["badge", "text-xs"];
174
+ baseClasses.push(config.value.color);
175
+ if (props.size === "sm") baseClasses.push("badge-sm", "text-xs");
176
+ else if (props.size === "lg") baseClasses.push("badge-lg", "text-sm");
177
+ else baseClasses.push("text-xs", "sm:text-sm");
178
+ if (props.variant === "outline") baseClasses.push("badge-outline");
179
+ return baseClasses.join(" ");
180
+ });
181
+ const displayText = computed(() => config.value.text);
182
+ const ariaLabel = computed(() => config.value.ariaLabel);
183
+ return (_ctx, _cache) => {
184
+ return openBlock(), createElementBlock("div", {
185
+ class: normalizeClass(badgeClasses.value),
186
+ "aria-label": ariaLabel.value,
187
+ role: "status"
188
+ }, toDisplayString(displayText.value), 11, _hoisted_1$8);
189
+ };
190
+ }
191
+ });
192
+ var SupportTicketDevLifecycleBadge_default = _sfc_main$8;
193
+
194
+ //#endregion
195
+ //#region src/slices/support_ticket/staff/components/CustomerCreditBalance.vue
196
+ const _hoisted_1$7 = {
197
+ key: 0,
198
+ class: "flex items-center gap-2"
199
+ };
200
+ const _hoisted_2$7 = { class: "space-y-2" };
201
+ const _hoisted_3$7 = { class: "grid grid-cols-2 gap-2 text-sm" };
202
+ const _hoisted_4$7 = { class: "font-bold ml-2" };
203
+ const _hoisted_5$7 = { class: "font-bold ml-2" };
204
+ const _hoisted_6$7 = {
205
+ key: 0,
206
+ class: "alert alert-warning alert-sm"
207
+ };
208
+ const _sfc_main$7 = /* @__PURE__ */ defineComponent({
209
+ __name: "CustomerCreditBalance",
210
+ setup(__props) {
211
+ const { data, loading, error } = useQuery((api) => api.customer.getCreditBalance(), { staleTime: 120 * 1e3 });
212
+ const creditBalance = computed(() => data.value ?? null);
213
+ const totalAvailable = computed(() => {
214
+ if (!creditBalance.value) return 0;
215
+ return (parseFloat(creditBalance.value.monthly) || 0) + (parseFloat(creditBalance.value.rollover) || 0);
216
+ });
217
+ return (_ctx, _cache) => {
218
+ return openBlock(), createElementBlock("div", null, [createCommentVNode(" Loading State "), unref(loading) ? (openBlock(), createElementBlock("div", _hoisted_1$7, [..._cache[0] || (_cache[0] = [createElementVNode("span", { class: "loading loading-spinner loading-sm" }, null, -1), createElementVNode("span", { class: "text-sm" }, "Loading customer balance...", -1)])])) : unref(error) ? (openBlock(), createElementBlock(Fragment, { key: 1 }, [createCommentVNode(" Error State "), _cache[1] || (_cache[1] = createElementVNode("div", { class: "alert alert-error alert-sm" }, [createElementVNode("span", { class: "text-xs" }, "Failed to load customer balance")], -1))], 2112)) : creditBalance.value ? (openBlock(), createElementBlock(Fragment, { key: 2 }, [createCommentVNode(" Balance Display "), createElementVNode("div", _hoisted_2$7, [
219
+ createElementVNode("div", _hoisted_3$7, [createElementVNode("div", null, [_cache[2] || (_cache[2] = createElementVNode("span", { class: "text-base-content/60" }, "Monthly:", -1)), createElementVNode("span", _hoisted_4$7, toDisplayString(unref(formatStaffCreditValue)(creditBalance.value.monthly)), 1)]), createElementVNode("div", null, [_cache[3] || (_cache[3] = createElementVNode("span", { class: "text-base-content/60" }, "Rollover:", -1)), createElementVNode("span", _hoisted_5$7, toDisplayString(unref(formatStaffCreditValue)(creditBalance.value.rollover)), 1)])]),
220
+ createElementVNode("div", { class: normalizeClass(["flex items-center justify-between p-2 rounded", {
221
+ "bg-success/20": totalAvailable.value > 0,
222
+ "bg-error/20": totalAvailable.value === 0
223
+ }]) }, [_cache[4] || (_cache[4] = createElementVNode("span", { class: "text-sm font-medium" }, "Total Available:", -1)), createElementVNode("span", { class: normalizeClass(["font-bold", {
224
+ "text-success": totalAvailable.value > 0,
225
+ "text-error": totalAvailable.value === 0
226
+ }]) }, toDisplayString(unref(formatStaffCreditValue)(totalAvailable.value.toString())), 3)], 2),
227
+ createCommentVNode(" Warning if no balance "),
228
+ totalAvailable.value === 0 ? (openBlock(), createElementBlock("div", _hoisted_6$7, [..._cache[5] || (_cache[5] = [createElementVNode("svg", {
229
+ xmlns: "http://www.w3.org/2000/svg",
230
+ class: "stroke-current shrink-0 h-4 w-4",
231
+ fill: "none",
232
+ viewBox: "0 0 24 24"
233
+ }, [createElementVNode("path", {
234
+ "stroke-linecap": "round",
235
+ "stroke-linejoin": "round",
236
+ "stroke-width": "2",
237
+ d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
238
+ })], -1), createElementVNode("span", { class: "text-xs" }, "Customer has insufficient credits", -1)])])) : createCommentVNode("v-if", true)
239
+ ])], 2112)) : createCommentVNode("v-if", true)]);
240
+ };
241
+ }
242
+ });
243
+ var CustomerCreditBalance_default = _sfc_main$7;
244
+
245
+ //#endregion
246
+ //#region src/slices/support_ticket/staff/components/ApproveRejectActions.vue
247
+ const _hoisted_1$6 = {
248
+ key: 0,
249
+ class: "alert alert-warning py-2"
250
+ };
251
+ const _hoisted_2$6 = {
252
+ key: 1,
253
+ class: "space-y-3"
254
+ };
255
+ const _hoisted_3$6 = { class: "alert alert-info py-2" };
256
+ const _hoisted_4$6 = { class: "text-xs sm:text-sm" };
257
+ const _hoisted_5$6 = { class: "bg-base-100 rounded-lg p-3" };
258
+ const _hoisted_6$6 = { class: "flex flex-col sm:flex-row gap-2 sm:gap-3 justify-end mt-4" };
259
+ const _hoisted_7$6 = ["disabled"];
260
+ const _hoisted_8$6 = {
261
+ key: 0,
262
+ class: "loading loading-spinner loading-sm mr-2"
263
+ };
264
+ const _hoisted_9$5 = ["disabled"];
265
+ const _hoisted_10$2 = {
266
+ key: 0,
267
+ class: "loading loading-spinner loading-sm mr-2"
268
+ };
269
+ const _hoisted_11$2 = {
270
+ key: 2,
271
+ class: "alert alert-error mt-2 py-2"
272
+ };
273
+ const _hoisted_12$2 = { class: "text-sm" };
274
+ const _hoisted_13$2 = { class: "alert alert-warning py-2" };
275
+ const _hoisted_14$2 = { class: "text-xs sm:text-sm" };
276
+ const _hoisted_15$1 = { class: "font-semibold" };
277
+ const _hoisted_16$1 = {
278
+ key: 0,
279
+ class: "alert alert-info py-2"
280
+ };
281
+ const _hoisted_17$1 = { class: "text-xs sm:text-sm" };
282
+ const _hoisted_18 = { class: "flex mt-4" };
283
+ const _hoisted_19 = ["disabled"];
284
+ const _hoisted_20 = {
285
+ key: 0,
286
+ class: "loading loading-spinner loading-sm mr-2"
287
+ };
288
+ const _hoisted_21 = {
289
+ key: 1,
290
+ class: "alert alert-error mt-2 py-2"
291
+ };
292
+ const _hoisted_22 = { class: "text-sm" };
293
+ const _hoisted_23 = { class: "modal-box" };
294
+ const _hoisted_24 = { class: "font-bold text-lg" };
295
+ const _hoisted_25 = { class: "py-4 whitespace-pre-line" };
296
+ const _hoisted_26 = { class: "modal-action" };
297
+ const _sfc_main$6 = /* @__PURE__ */ defineComponent({
298
+ __name: "ApproveRejectActions",
299
+ props: { support_ticket: {} },
300
+ emits: ["update"],
301
+ setup(__props, { emit: __emit }) {
302
+ const props = __props;
303
+ const emit = __emit;
304
+ const error = ref(null);
305
+ const confirmModal = ref(null);
306
+ const modalTitle = ref("");
307
+ const modalMessage = ref("");
308
+ const modalButtonText = ref("");
309
+ const modalButtonClass = ref("");
310
+ const modalCallback = ref(null);
311
+ const { mutate: approveSupportTicket, loading: isApproving } = useMutation((api, input) => api.supportTickets.approveTicket(input), { invalidate: /^support-tickets?:/ });
312
+ const { mutate: rejectSupportTicket, loading: isRejecting } = useMutation((api, input) => api.supportTickets.rejectTicket(input), { invalidate: /^support-tickets?:/ });
313
+ const { mutate: revertSupportTicket, loading: isReverting } = useMutation((api, input) => api.supportTickets.revertTicket(input), { invalidate: /^support-tickets?:/ });
314
+ const showApproveModal = () => {
315
+ const creditDisplay = formatStaffCreditValue(props.support_ticket.credit_value, props.support_ticket.approval_status);
316
+ const credits = creditDisplay === "TBD" || creditDisplay === "N/A" ? 0 : parseFloat(creditDisplay);
317
+ modalTitle.value = "Approve Support Ticket?";
318
+ modalMessage.value = `This will:\n\n• Deduct ${credits.toFixed(2)} credits from customer\n• Lock the support ticket item\n• Start development workflow\n\nThis action cannot be undone.`;
319
+ modalButtonText.value = "Approve & Deduct";
320
+ modalButtonClass.value = "btn-success";
321
+ modalCallback.value = handleApprove;
322
+ confirmModal.value?.showModal();
323
+ };
324
+ const showRejectModal = () => {
325
+ modalTitle.value = "Reject Support Ticket?";
326
+ modalMessage.value = "This will:\n\n• Reject this support ticket request\n• Lock the support ticket item\n• No credits will be deducted\n\nThe customer will be notified.";
327
+ modalButtonText.value = "Reject";
328
+ modalButtonClass.value = "btn-error";
329
+ modalCallback.value = handleReject;
330
+ confirmModal.value?.showModal();
331
+ };
332
+ const showRevertModal = () => {
333
+ modalTitle.value = "Revert Support Ticket to PENDING?";
334
+ const creditDisplay = formatStaffCreditValue(props.support_ticket.credit_value, props.support_ticket.approval_status);
335
+ modalMessage.value = "This will:\n\n• Change status back to PENDING\n• Unlock the support ticket item\n" + (creditDisplay !== "TBD" && creditDisplay !== "N/A" ? `• Refund ${creditDisplay} credits to customer\n` : "") + "• Allow the customer to edit again\n\nAre you sure you want to revert this decision?";
336
+ modalButtonText.value = "Revert to PENDING";
337
+ modalButtonClass.value = "btn-warning";
338
+ modalCallback.value = handleRevert;
339
+ confirmModal.value?.showModal();
340
+ };
341
+ const closeModal = () => {
342
+ confirmModal.value?.close();
343
+ modalCallback.value = null;
344
+ };
345
+ const handleApprove = async () => {
346
+ error.value = null;
347
+ closeModal();
348
+ try {
349
+ const response = await approveSupportTicket({ id: props.support_ticket.id });
350
+ toast.success(`Support Ticket approved! ${formatStaffCreditValue(props.support_ticket.credit_value, props.support_ticket.approval_status)} credits deducted.`);
351
+ emit("update", response);
352
+ } catch (e) {
353
+ const errorMessage = e instanceof Error ? e.message : "An unknown error occurred.";
354
+ error.value = errorMessage;
355
+ toast.error(errorMessage);
356
+ }
357
+ };
358
+ const handleReject = async () => {
359
+ error.value = null;
360
+ closeModal();
361
+ try {
362
+ const response = await rejectSupportTicket({ id: props.support_ticket.id });
363
+ toast.info("Support Ticket rejected.");
364
+ emit("update", response);
365
+ } catch (e) {
366
+ const errorMessage = e instanceof Error ? e.message : "An unknown error occurred.";
367
+ error.value = errorMessage;
368
+ toast.error(errorMessage);
369
+ }
370
+ };
371
+ const handleRevert = async () => {
372
+ error.value = null;
373
+ closeModal();
374
+ try {
375
+ const response = await revertSupportTicket({ id: props.support_ticket.id });
376
+ const creditDisplay = formatStaffCreditValue(props.support_ticket.credit_value, props.support_ticket.approval_status);
377
+ const refundMessage = creditDisplay !== "TBD" && creditDisplay !== "N/A" ? ` ${creditDisplay} credits refunded.` : "";
378
+ toast.success(`Support Ticket reverted to PENDING.${refundMessage}`);
379
+ emit("update", response);
380
+ } catch (e) {
381
+ const errorMessage = e instanceof Error ? e.message : "An unknown error occurred.";
382
+ error.value = errorMessage;
383
+ toast.error(errorMessage);
384
+ }
385
+ };
386
+ return (_ctx, _cache) => {
387
+ return openBlock(), createElementBlock(Fragment, null, [
388
+ createCommentVNode(" Approve/Reject Section (PENDING only) "),
389
+ props.support_ticket.approval_status === "PENDING" ? (openBlock(), createBlock(ZiniaContainer_default, { key: 0 }, {
390
+ default: withCtx(() => [
391
+ _cache[3] || (_cache[3] = createElementVNode("h3", { class: "card-title text-base sm:text-lg" }, "Approve or Reject", -1)),
392
+ unref(formatStaffCreditValue)(props.support_ticket.credit_value, props.support_ticket.approval_status) === "TBD" ? (openBlock(), createElementBlock("div", _hoisted_1$6, [..._cache[1] || (_cache[1] = [createElementVNode("div", null, [createElementVNode("svg", {
393
+ xmlns: "http://www.w3.org/2000/svg",
394
+ class: "stroke-current shrink-0 h-5 w-5",
395
+ fill: "none",
396
+ viewBox: "0 0 24 24"
397
+ }, [createElementVNode("path", {
398
+ "stroke-linecap": "round",
399
+ "stroke-linejoin": "round",
400
+ "stroke-width": "2",
401
+ d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
402
+ })]), createElementVNode("span", { class: "text-xs sm:text-sm" }, "You must set an estimate before approving")], -1)])])) : (openBlock(), createElementBlock("div", _hoisted_2$6, [
403
+ createElementVNode("div", _hoisted_3$6, [createElementVNode("div", null, [createElementVNode("span", _hoisted_4$6, "Estimate: " + toDisplayString(unref(formatStaffCreditValue)(props.support_ticket.credit_value, props.support_ticket.approval_status)) + " credits", 1)])]),
404
+ createCommentVNode(" Show Customer's Credit Balance "),
405
+ createElementVNode("div", _hoisted_5$6, [_cache[2] || (_cache[2] = createElementVNode("h4", { class: "text-xs sm:text-sm font-medium mb-2" }, "Customer Balance Check", -1)), createVNode(CustomerCreditBalance_default)])
406
+ ])),
407
+ createElementVNode("div", _hoisted_6$6, [createElementVNode("button", {
408
+ class: "btn btn-error btn-outline w-full sm:w-auto order-2 sm:order-1",
409
+ onClick: withModifiers(showRejectModal, ["prevent"]),
410
+ disabled: unref(isApproving) || unref(isRejecting)
411
+ }, [unref(isRejecting) ? (openBlock(), createElementBlock("span", _hoisted_8$6)) : createCommentVNode("v-if", true), createTextVNode(" " + toDisplayString(unref(isRejecting) ? "Rejecting..." : "Reject"), 1)], 8, _hoisted_7$6), createElementVNode("button", {
412
+ class: "btn btn-success w-full sm:w-auto order-1 sm:order-2",
413
+ onClick: withModifiers(showApproveModal, ["prevent"]),
414
+ disabled: unref(formatStaffCreditValue)(props.support_ticket.credit_value, props.support_ticket.approval_status) === "TBD" || unref(isApproving) || unref(isRejecting)
415
+ }, [unref(isApproving) ? (openBlock(), createElementBlock("span", _hoisted_10$2)) : createCommentVNode("v-if", true), createTextVNode(" " + toDisplayString(unref(isApproving) ? "Approving..." : "Approve & Deduct"), 1)], 8, _hoisted_9$5)]),
416
+ error.value ? (openBlock(), createElementBlock("div", _hoisted_11$2, [createElementVNode("span", _hoisted_12$2, toDisplayString(error.value), 1)])) : createCommentVNode("v-if", true)
417
+ ]),
418
+ _: 1
419
+ })) : props.support_ticket.approval_status === "APPROVED" || props.support_ticket.approval_status === "REJECTED" ? (openBlock(), createElementBlock(Fragment, { key: 1 }, [createCommentVNode(" Revert Section (APPROVED/REJECTED only) "), createVNode(ZiniaContainer_default, null, {
420
+ default: withCtx(() => [
421
+ _cache[8] || (_cache[8] = createElementVNode("h3", { class: "card-title text-base sm:text-lg" }, "Revert Decision", -1)),
422
+ createElementVNode("div", _hoisted_13$2, [_cache[7] || (_cache[7] = createElementVNode("svg", {
423
+ xmlns: "http://www.w3.org/2000/svg",
424
+ class: "stroke-current shrink-0 h-5 w-5",
425
+ fill: "none",
426
+ viewBox: "0 0 24 24"
427
+ }, [createElementVNode("path", {
428
+ "stroke-linecap": "round",
429
+ "stroke-linejoin": "round",
430
+ "stroke-width": "2",
431
+ d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
432
+ })], -1)), createElementVNode("div", _hoisted_14$2, [_cache[6] || (_cache[6] = createElementVNode("div", { class: "font-medium mb-1" }, "Admin Action Required", -1)), createElementVNode("div", null, [
433
+ _cache[4] || (_cache[4] = createTextVNode(" This support ticket is currently ", -1)),
434
+ createElementVNode("span", _hoisted_15$1, toDisplayString(props.support_ticket.approval_status), 1),
435
+ _cache[5] || (_cache[5] = createTextVNode(". You can revert it back to PENDING status. ", -1))
436
+ ])])]),
437
+ unref(formatStaffCreditValue)(props.support_ticket.credit_value, props.support_ticket.approval_status) !== "TBD" && unref(formatStaffCreditValue)(props.support_ticket.credit_value, props.support_ticket.approval_status) !== "N/A" ? (openBlock(), createElementBlock("div", _hoisted_16$1, [createElementVNode("div", _hoisted_17$1, " Credits: " + toDisplayString(unref(formatStaffCreditValue)(props.support_ticket.credit_value, props.support_ticket.approval_status)) + " will be refunded to customer ", 1)])) : createCommentVNode("v-if", true),
438
+ createElementVNode("div", _hoisted_18, [createElementVNode("button", {
439
+ class: "btn btn-warning w-full sm:w-auto",
440
+ onClick: withModifiers(showRevertModal, ["prevent"]),
441
+ disabled: unref(isReverting)
442
+ }, [unref(isReverting) ? (openBlock(), createElementBlock("span", _hoisted_20)) : createCommentVNode("v-if", true), createTextVNode(" " + toDisplayString(unref(isReverting) ? "Reverting..." : "Revert to PENDING"), 1)], 8, _hoisted_19)]),
443
+ error.value ? (openBlock(), createElementBlock("div", _hoisted_21, [createElementVNode("span", _hoisted_22, toDisplayString(error.value), 1)])) : createCommentVNode("v-if", true)
444
+ ]),
445
+ _: 1
446
+ })], 2112)) : createCommentVNode("v-if", true),
447
+ createCommentVNode(" Confirmation Modal "),
448
+ createElementVNode("dialog", {
449
+ ref_key: "confirmModal",
450
+ ref: confirmModal,
451
+ class: "modal"
452
+ }, [createElementVNode("div", _hoisted_23, [
453
+ createElementVNode("h3", _hoisted_24, toDisplayString(modalTitle.value), 1),
454
+ createElementVNode("p", _hoisted_25, toDisplayString(modalMessage.value), 1),
455
+ createElementVNode("div", _hoisted_26, [createElementVNode("button", {
456
+ class: "btn btn-ghost",
457
+ onClick: closeModal
458
+ }, "Cancel"), createElementVNode("button", {
459
+ class: normalizeClass(["btn", modalButtonClass.value]),
460
+ onClick: _cache[0] || (_cache[0] = () => modalCallback.value?.())
461
+ }, toDisplayString(modalButtonText.value), 3)])
462
+ ]), createElementVNode("form", {
463
+ method: "dialog",
464
+ class: "modal-backdrop"
465
+ }, [createElementVNode("button", { onClick: closeModal }, "close")])], 512)
466
+ ], 64);
467
+ };
468
+ }
469
+ });
470
+ var ApproveRejectActions_default = _sfc_main$6;
471
+
472
+ //#endregion
473
+ //#region src/slices/support_ticket/staff/components/CancelInternalTaskWorkflow.vue
474
+ const _hoisted_1$5 = { class: "flex justify-end mt-4" };
475
+ const _hoisted_2$5 = ["disabled"];
476
+ const _hoisted_3$5 = {
477
+ key: 0,
478
+ class: "loading loading-spinner loading-sm mr-2"
479
+ };
480
+ const _hoisted_4$5 = {
481
+ key: 0,
482
+ class: "alert alert-error mt-2 py-2"
483
+ };
484
+ const _hoisted_5$5 = { class: "text-sm" };
485
+ const _hoisted_6$5 = { class: "modal-box" };
486
+ const _hoisted_7$5 = { class: "font-bold text-lg" };
487
+ const _hoisted_8$5 = { class: "py-4 whitespace-pre-line" };
488
+ const _hoisted_9$4 = { class: "modal-action" };
489
+ const _sfc_main$5 = /* @__PURE__ */ defineComponent({
490
+ __name: "CancelInternalTaskWorkflow",
491
+ props: { support_ticket: {} },
492
+ emits: ["update"],
493
+ setup(__props, { emit: __emit }) {
494
+ const props = __props;
495
+ const emit = __emit;
496
+ const error = ref(null);
497
+ const confirmModal = ref(null);
498
+ const modalTitle = ref("");
499
+ const modalMessage = ref("");
500
+ const modalButtonText = ref("");
501
+ const modalCallback = ref(null);
502
+ const { mutate: cancelInternalTask, loading: isCancelling } = useMutation((api, input) => api.supportTickets.cancelInternalTask(input), { invalidate: /^support-tickets?:/ });
503
+ const showCancelModal = () => {
504
+ modalTitle.value = "Cancel Internal Task?";
505
+ modalMessage.value = "This will:\n\n• Set dev lifecycle to CANCELLED\n• Record completion timestamp\n• Mark task as complete (terminal state)\n\nThis action cannot be undone. The task will remain in the system as cancelled.";
506
+ modalButtonText.value = "Cancel Task";
507
+ modalCallback.value = handleCancel;
508
+ confirmModal.value?.showModal();
509
+ };
510
+ const handleCancel = async () => {
511
+ error.value = null;
512
+ try {
513
+ const result = await cancelInternalTask({ id: props.support_ticket.id });
514
+ toast.success("✅ Internal task cancelled successfully");
515
+ closeModal();
516
+ emit("update", result);
517
+ } catch (err) {
518
+ error.value = err instanceof Error ? err.message : "Failed to cancel task";
519
+ toast.error(`❌ ${error.value}`);
520
+ }
521
+ };
522
+ const closeModal = () => {
523
+ confirmModal.value?.close();
524
+ };
525
+ return (_ctx, _cache) => {
526
+ return openBlock(), createElementBlock(Fragment, null, [
527
+ createCommentVNode(" Cancel Internal Task Section (INTERNAL only, not CANCELLED) "),
528
+ props.support_ticket.approval_status === "INTERNAL" && props.support_ticket.dev_lifecycle !== "CANCELLED" ? (openBlock(), createBlock(ZiniaContainer_default, { key: 0 }, {
529
+ default: withCtx(() => [
530
+ _cache[1] || (_cache[1] = createElementVNode("h3", { class: "card-title text-base sm:text-lg" }, "Cancel Internal Task", -1)),
531
+ _cache[2] || (_cache[2] = createElementVNode("div", { class: "alert alert-warning py-2" }, [createElementVNode("div", { class: "flex flex-col gap-2" }, [createElementVNode("span", { class: "font-semibold text-sm" }, "What happens when you cancel:"), createElementVNode("ul", { class: "text-xs sm:text-sm space-y-1 ml-4 list-disc" }, [
532
+ createElementVNode("li", null, "Sets dev lifecycle to CANCELLED"),
533
+ createElementVNode("li", null, "Records completion timestamp"),
534
+ createElementVNode("li", null, "Task is marked as terminal state"),
535
+ createElementVNode("li", null, "No credit impact (internal tasks have no credits)")
536
+ ])])], -1)),
537
+ createElementVNode("div", _hoisted_1$5, [createElementVNode("button", {
538
+ class: "btn btn-error w-full sm:w-auto",
539
+ onClick: withModifiers(showCancelModal, ["prevent"]),
540
+ disabled: unref(isCancelling)
541
+ }, [unref(isCancelling) ? (openBlock(), createElementBlock("span", _hoisted_3$5)) : createCommentVNode("v-if", true), createTextVNode(" " + toDisplayString(unref(isCancelling) ? "Cancelling..." : "Cancel Internal Task"), 1)], 8, _hoisted_2$5)]),
542
+ error.value ? (openBlock(), createElementBlock("div", _hoisted_4$5, [createElementVNode("span", _hoisted_5$5, toDisplayString(error.value), 1)])) : createCommentVNode("v-if", true)
543
+ ]),
544
+ _: 1
545
+ })) : createCommentVNode("v-if", true),
546
+ createCommentVNode(" Confirmation Modal "),
547
+ createElementVNode("dialog", {
548
+ ref_key: "confirmModal",
549
+ ref: confirmModal,
550
+ class: "modal"
551
+ }, [createElementVNode("div", _hoisted_6$5, [
552
+ createElementVNode("h3", _hoisted_7$5, toDisplayString(modalTitle.value), 1),
553
+ createElementVNode("p", _hoisted_8$5, toDisplayString(modalMessage.value), 1),
554
+ createElementVNode("div", _hoisted_9$4, [createElementVNode("button", {
555
+ class: "btn btn-ghost",
556
+ onClick: closeModal
557
+ }, "Cancel"), createElementVNode("button", {
558
+ class: "btn btn-error",
559
+ onClick: _cache[0] || (_cache[0] = () => modalCallback.value?.())
560
+ }, toDisplayString(modalButtonText.value), 1)])
561
+ ]), createElementVNode("form", {
562
+ method: "dialog",
563
+ class: "modal-backdrop"
564
+ }, [createElementVNode("button", { onClick: closeModal }, "close")])], 512)
565
+ ], 64);
566
+ };
567
+ }
568
+ });
569
+ var CancelInternalTaskWorkflow_default = _sfc_main$5;
570
+
571
+ //#endregion
572
+ //#region src/slices/support_ticket/staff/components/CompleteSupportTicketForm.vue
573
+ const _hoisted_1$4 = { class: "text-xs sm:text-sm text-base-content/70 mb-4" };
574
+ const _hoisted_2$4 = { class: "font-semibold" };
575
+ const _hoisted_3$4 = { class: "text-xs sm:text-sm" };
576
+ const _hoisted_4$4 = { class: "grid grid-cols-2 gap-2 sm:gap-4 mt-2" };
577
+ const _hoisted_5$4 = { class: "bg-base-100 p-3 rounded-lg" };
578
+ const _hoisted_6$4 = { class: "text-lg sm:text-xl font-bold text-primary" };
579
+ const _hoisted_7$4 = { class: "bg-base-100 p-3 rounded-lg" };
580
+ const _hoisted_8$4 = { class: "text-xs text-base-content/60" };
581
+ const _sfc_main$4 = /* @__PURE__ */ defineComponent({
582
+ __name: "CompleteSupportTicketForm",
583
+ props: { support_ticket: {} },
584
+ emits: ["update"],
585
+ setup(__props, { emit: __emit }) {
586
+ const props = __props;
587
+ const emit = __emit;
588
+ const { form, zinia, ZiniaSubmitButton, ZiniaForm } = useForm(withMetadata(CompleteSupportTicketSchema.pick({ delivered_value: true }), "completeSupportTicketSchema", { delivered_value: {
589
+ inputType: "text",
590
+ placeholder: "100.00"
591
+ } }), {
592
+ storeName: `complete-support_ticket-${props.support_ticket.id}`,
593
+ persistToLocalStorage: false,
594
+ renderStyle: "daisy_ui",
595
+ initialValues: { delivered_value: formatStaffCreditValue(props.support_ticket.credit_value, props.support_ticket.approval_status) === "TBD" || formatStaffCreditValue(props.support_ticket.credit_value, props.support_ticket.approval_status) === "N/A" ? "0.00" : formatStaffCreditValue(props.support_ticket.credit_value, props.support_ticket.approval_status) }
596
+ });
597
+ const { mutate: completeSupportTicket } = useMutation((api, input) => api.supportTickets.completeTicket(input), { invalidate: /^support-tickets?:/ });
598
+ const isCompleted = computed(() => props.support_ticket.status === "COMPLETED");
599
+ const getComparisonClass = () => {
600
+ const creditDisplay = formatStaffCreditValue(props.support_ticket.credit_value, props.support_ticket.approval_status);
601
+ if (!form.values.delivered_value || creditDisplay === "TBD" || creditDisplay === "N/A") return "";
602
+ const actual = parseFloat(form.values.delivered_value);
603
+ const final = parseFloat(creditDisplay);
604
+ if (isNaN(actual) || isNaN(final)) return "";
605
+ if (actual > final) return "alert-warning";
606
+ if (actual === final) return "alert-success";
607
+ return "alert-info";
608
+ };
609
+ const getComparisonMessage = () => {
610
+ const creditDisplay = formatStaffCreditValue(props.support_ticket.credit_value, props.support_ticket.approval_status);
611
+ if (!form.values.delivered_value || creditDisplay === "TBD" || creditDisplay === "N/A") return "";
612
+ const actual = parseFloat(form.values.delivered_value);
613
+ const final = parseFloat(creditDisplay);
614
+ if (isNaN(actual) || isNaN(final)) return "";
615
+ const variance = ((actual - final) / final * 100).toFixed(1);
616
+ if (actual > final) return `📈 Took ${(actual - final).toFixed(2)} more effort (+${variance}%)`;
617
+ else if (actual === final) return "🎯 Exactly on estimate!";
618
+ else return `📉 Took ${(final - actual).toFixed(2)} less effort (${variance}%)`;
619
+ };
620
+ const getActualClass = () => {
621
+ const creditDisplay = formatStaffCreditValue(props.support_ticket.credit_value, props.support_ticket.approval_status);
622
+ if (!props.support_ticket.delivered_value || creditDisplay === "TBD" || creditDisplay === "N/A") return "";
623
+ const actual = parseFloat(props.support_ticket.delivered_value);
624
+ const final = parseFloat(creditDisplay);
625
+ if (isNaN(actual) || isNaN(final)) return "";
626
+ if (actual > final) return "text-warning";
627
+ if (actual === final) return "text-success";
628
+ return "text-info";
629
+ };
630
+ const getVarianceLabel = () => {
631
+ const creditDisplay = formatStaffCreditValue(props.support_ticket.credit_value, props.support_ticket.approval_status);
632
+ if (!props.support_ticket.delivered_value || creditDisplay === "TBD" || creditDisplay === "N/A") return "Work performed";
633
+ const actual = parseFloat(props.support_ticket.delivered_value);
634
+ const final = parseFloat(creditDisplay);
635
+ if (isNaN(actual) || isNaN(final)) return "Work performed";
636
+ const diff = actual - final;
637
+ const variance = (diff / final * 100).toFixed(1);
638
+ if (diff > 0) return `+${variance}% over estimate`;
639
+ if (diff < 0) return `${variance}% under estimate`;
640
+ return "On target";
641
+ };
642
+ const handleComplete = async (formData) => {
643
+ const response = await completeSupportTicket({
644
+ id: props.support_ticket.id,
645
+ delivered_value: formData.delivered_value
646
+ });
647
+ if (!response) throw new Error("Failed to complete support ticket");
648
+ return response;
649
+ };
650
+ const handleSuccess = () => {
651
+ toast.success("SupportTicket marked as completed!", {});
652
+ emit("update");
653
+ };
654
+ const handleError = (error) => {
655
+ const errorMessage = error instanceof Error ? error.message : "An unknown error occurred.";
656
+ toast.error(errorMessage);
657
+ };
658
+ return (_ctx, _cache) => {
659
+ return ["APPROVED", "INTERNAL"].includes(props.support_ticket.approval_status) && !isCompleted.value ? (openBlock(), createBlock(unref(ZiniaForm), {
660
+ key: 0,
661
+ onHandleSubmit: handleComplete,
662
+ onSuccess: handleSuccess,
663
+ onError: handleError
664
+ }, {
665
+ default: withCtx(() => [
666
+ _cache[2] || (_cache[2] = createElementVNode("h3", { class: "card-title text-base sm:text-lg" }, "Complete Support Ticket", -1)),
667
+ createElementVNode("p", _hoisted_1$4, [
668
+ _cache[0] || (_cache[0] = createTextVNode(" Customer was charged ", -1)),
669
+ createElementVNode("span", _hoisted_2$4, toDisplayString(unref(formatStaffCreditValue)(props.support_ticket.credit_value, props.support_ticket.approval_status)), 1),
670
+ _cache[1] || (_cache[1] = createTextVNode(" credits ", -1))
671
+ ]),
672
+ createCommentVNode(" Delivered Value Field "),
673
+ createVNode(unref(zinia).DeliveredValueField, {
674
+ label: "Actual Effort Delivered",
675
+ placeholder: "100.00",
676
+ hint: "How much effort did it actually take?"
677
+ }),
678
+ createCommentVNode(" Variance Indicator "),
679
+ unref(form).values.delivered_value && unref(formatStaffCreditValue)(props.support_ticket.credit_value, props.support_ticket.approval_status) !== "TBD" && unref(formatStaffCreditValue)(props.support_ticket.credit_value, props.support_ticket.approval_status) !== "N/A" ? (openBlock(), createElementBlock("div", {
680
+ key: 0,
681
+ class: normalizeClass(["alert py-2", getComparisonClass()])
682
+ }, [createElementVNode("span", _hoisted_3$4, toDisplayString(getComparisonMessage()), 1)], 2)) : createCommentVNode("v-if", true),
683
+ createVNode(unref(ZiniaSubmitButton), {
684
+ submitText: "Mark as Completed",
685
+ submittingText: "Completing..."
686
+ })
687
+ ]),
688
+ _: 1
689
+ })) : isCompleted.value ? (openBlock(), createBlock(ZiniaContainer_default, { key: 1 }, {
690
+ default: withCtx(() => [_cache[6] || (_cache[6] = createElementVNode("h3", { class: "card-title text-success text-base sm:text-lg" }, "✅ Completed", -1)), createElementVNode("div", _hoisted_4$4, [createElementVNode("div", _hoisted_5$4, [
691
+ _cache[3] || (_cache[3] = createElementVNode("div", { class: "text-xs text-base-content/70" }, "Customer Charged", -1)),
692
+ createElementVNode("div", _hoisted_6$4, toDisplayString(unref(formatStaffCreditValue)(props.support_ticket.credit_value, props.support_ticket.approval_status)), 1),
693
+ _cache[4] || (_cache[4] = createElementVNode("div", { class: "text-xs text-base-content/60" }, "Fixed price", -1))
694
+ ]), createElementVNode("div", _hoisted_7$4, [
695
+ _cache[5] || (_cache[5] = createElementVNode("div", { class: "text-xs text-base-content/70" }, "Actual Effort", -1)),
696
+ createElementVNode("div", { class: normalizeClass(["text-lg sm:text-xl font-bold", getActualClass()]) }, toDisplayString(props.support_ticket.delivered_value ?? "N/A"), 3),
697
+ createElementVNode("div", _hoisted_8$4, toDisplayString(getVarianceLabel()), 1)
698
+ ])])]),
699
+ _: 1
700
+ })) : createCommentVNode("v-if", true);
701
+ };
702
+ }
703
+ });
704
+ var CompleteSupportTicketForm_default = _sfc_main$4;
705
+
706
+ //#endregion
707
+ //#region src/slices/support_ticket/staff/components/ConvertToCustomerWorkflow.vue
708
+ const _hoisted_1$3 = { class: "flex justify-end mt-4" };
709
+ const _hoisted_2$3 = ["disabled"];
710
+ const _hoisted_3$3 = {
711
+ key: 0,
712
+ class: "loading loading-spinner loading-sm mr-2"
713
+ };
714
+ const _hoisted_4$3 = {
715
+ key: 0,
716
+ class: "alert alert-error mt-2 py-2"
717
+ };
718
+ const _hoisted_5$3 = { class: "text-sm" };
719
+ const _hoisted_6$3 = { class: "modal-box" };
720
+ const _hoisted_7$3 = { class: "font-bold text-lg" };
721
+ const _hoisted_8$3 = { class: "py-4 whitespace-pre-line" };
722
+ const _hoisted_9$3 = { class: "modal-action" };
723
+ const _sfc_main$3 = /* @__PURE__ */ defineComponent({
724
+ __name: "ConvertToCustomerWorkflow",
725
+ props: { support_ticket: {} },
726
+ emits: ["update"],
727
+ setup(__props, { emit: __emit }) {
728
+ const props = __props;
729
+ const emit = __emit;
730
+ const error = ref(null);
731
+ const confirmModal = ref(null);
732
+ const modalTitle = ref("");
733
+ const modalMessage = ref("");
734
+ const modalButtonText = ref("");
735
+ const modalCallback = ref(null);
736
+ const { mutate: convertToCustomer, loading: isConverting } = useMutation((api, input) => api.supportTickets.convertToCustomer(input.id), { invalidate: /^support-tickets?:/ });
737
+ const showConvertModal = () => {
738
+ modalTitle.value = "Convert to Customer Support Ticket?";
739
+ modalMessage.value = "This will:\n\n• Change status to PENDING\n• Require approval workflow\n• Clear dev lifecycle stage\n• Reset to planning phase\n\nYou'll need to set a credit estimate before the support ticket can be approved.";
740
+ modalButtonText.value = "Convert to Customer Support Ticket";
741
+ modalCallback.value = handleConvert;
742
+ confirmModal.value?.showModal();
743
+ };
744
+ const handleConvert = async () => {
745
+ error.value = null;
746
+ try {
747
+ const result = await convertToCustomer({ id: props.support_ticket.id });
748
+ toast.success("✅ Converted to customer support ticket successfully");
749
+ closeModal();
750
+ emit("update", result);
751
+ } catch (err) {
752
+ error.value = err instanceof Error ? err.message : "Failed to convert";
753
+ toast.error(`❌ ${error.value}`);
754
+ }
755
+ };
756
+ const closeModal = () => {
757
+ confirmModal.value?.close();
758
+ };
759
+ return (_ctx, _cache) => {
760
+ return openBlock(), createElementBlock(Fragment, null, [
761
+ createCommentVNode(" Convert to Customer SupportTicket Section (INTERNAL only) "),
762
+ props.support_ticket.approval_status === "INTERNAL" ? (openBlock(), createBlock(ZiniaContainer_default, { key: 0 }, {
763
+ default: withCtx(() => [
764
+ _cache[1] || (_cache[1] = createElementVNode("h3", { class: "card-title text-base sm:text-lg" }, "Convert to Customer SupportTicket", -1)),
765
+ _cache[2] || (_cache[2] = createElementVNode("div", { class: "alert alert-info py-2" }, [createElementVNode("div", { class: "flex flex-col gap-2" }, [createElementVNode("span", { class: "font-semibold text-sm" }, "What happens when you convert:"), createElementVNode("ul", { class: "text-xs sm:text-sm space-y-1 ml-4 list-disc" }, [
766
+ createElementVNode("li", null, "Changes status from internal task to customer support_ticket"),
767
+ createElementVNode("li", null, "Requires approval workflow (goes to PENDING)"),
768
+ createElementVNode("li", null, "Clears dev lifecycle (back to planning)"),
769
+ createElementVNode("li", null, "Staff must set credit estimate before approval")
770
+ ])])], -1)),
771
+ createElementVNode("div", _hoisted_1$3, [createElementVNode("button", {
772
+ class: "btn btn-primary w-full sm:w-auto",
773
+ onClick: withModifiers(showConvertModal, ["prevent"]),
774
+ disabled: unref(isConverting)
775
+ }, [unref(isConverting) ? (openBlock(), createElementBlock("span", _hoisted_3$3)) : createCommentVNode("v-if", true), createTextVNode(" " + toDisplayString(unref(isConverting) ? "Converting..." : "Convert to Customer SupportTicket"), 1)], 8, _hoisted_2$3)]),
776
+ error.value ? (openBlock(), createElementBlock("div", _hoisted_4$3, [createElementVNode("span", _hoisted_5$3, toDisplayString(error.value), 1)])) : createCommentVNode("v-if", true)
777
+ ]),
778
+ _: 1
779
+ })) : createCommentVNode("v-if", true),
780
+ createCommentVNode(" Confirmation Modal "),
781
+ createElementVNode("dialog", {
782
+ ref_key: "confirmModal",
783
+ ref: confirmModal,
784
+ class: "modal"
785
+ }, [createElementVNode("div", _hoisted_6$3, [
786
+ createElementVNode("h3", _hoisted_7$3, toDisplayString(modalTitle.value), 1),
787
+ createElementVNode("p", _hoisted_8$3, toDisplayString(modalMessage.value), 1),
788
+ createElementVNode("div", _hoisted_9$3, [createElementVNode("button", {
789
+ class: "btn btn-ghost",
790
+ onClick: closeModal
791
+ }, "Cancel"), createElementVNode("button", {
792
+ class: "btn btn-primary",
793
+ onClick: _cache[0] || (_cache[0] = () => modalCallback.value?.())
794
+ }, toDisplayString(modalButtonText.value), 1)])
795
+ ]), createElementVNode("form", {
796
+ method: "dialog",
797
+ class: "modal-backdrop"
798
+ }, [createElementVNode("button", { onClick: closeModal }, "close")])], 512)
799
+ ], 64);
800
+ };
801
+ }
802
+ });
803
+ var ConvertToCustomerWorkflow_default = _sfc_main$3;
804
+
805
+ //#endregion
806
+ //#region src/slices/support_ticket/staff/components/ConvertToInternalWorkflow.vue
807
+ const _hoisted_1$2 = { class: "flex justify-end mt-4" };
808
+ const _hoisted_2$2 = ["disabled"];
809
+ const _hoisted_3$2 = {
810
+ key: 0,
811
+ class: "loading loading-spinner loading-sm mr-2"
812
+ };
813
+ const _hoisted_4$2 = {
814
+ key: 0,
815
+ class: "alert alert-error mt-2 py-2"
816
+ };
817
+ const _hoisted_5$2 = { class: "text-sm" };
818
+ const _hoisted_6$2 = { class: "modal-box" };
819
+ const _hoisted_7$2 = { class: "font-bold text-lg" };
820
+ const _hoisted_8$2 = { class: "py-4 whitespace-pre-line" };
821
+ const _hoisted_9$2 = { class: "modal-action" };
822
+ const _sfc_main$2 = /* @__PURE__ */ defineComponent({
823
+ __name: "ConvertToInternalWorkflow",
824
+ props: { support_ticket: {} },
825
+ emits: ["update"],
826
+ setup(__props, { emit: __emit }) {
827
+ const props = __props;
828
+ const emit = __emit;
829
+ const error = ref(null);
830
+ const confirmModal = ref(null);
831
+ const modalTitle = ref("");
832
+ const modalMessage = ref("");
833
+ const modalButtonText = ref("");
834
+ const modalCallback = ref(null);
835
+ const { mutate: convertToInternal, loading: isConverting } = useMutation((api, input) => api.supportTickets.convertToInternal(input.id), { invalidate: /^support-tickets?:/ });
836
+ const showConvertModal = () => {
837
+ const hasCredits = props.support_ticket.credit_value && parseFloat(props.support_ticket.credit_value) > 0;
838
+ modalTitle.value = "Convert to Internal Task?";
839
+ modalMessage.value = "This will:\n\n• Change status to INTERNAL\n• Bypass customer approval workflow\n" + (hasCredits ? `• Clear ${props.support_ticket.credit_value} credit estimate\n` : "") + "• Set dev lifecycle to BACKLOG\n• Allow immediate development start\n\nThis change can be useful for converting customer ideas into internal improvements.";
840
+ modalButtonText.value = "Convert to Internal";
841
+ modalCallback.value = handleConvert;
842
+ confirmModal.value?.showModal();
843
+ };
844
+ const handleConvert = async () => {
845
+ error.value = null;
846
+ try {
847
+ const result = await convertToInternal({ id: props.support_ticket.id });
848
+ toast.success("✅ Converted to internal task successfully");
849
+ closeModal();
850
+ emit("update", result);
851
+ } catch (err) {
852
+ error.value = err instanceof Error ? err.message : "Failed to convert";
853
+ toast.error(`❌ ${error.value}`);
854
+ }
855
+ };
856
+ const closeModal = () => {
857
+ confirmModal.value?.close();
858
+ };
859
+ return (_ctx, _cache) => {
860
+ return openBlock(), createElementBlock(Fragment, null, [
861
+ createCommentVNode(" Convert to Internal Section (PENDING only) "),
862
+ props.support_ticket.approval_status === "PENDING" ? (openBlock(), createBlock(ZiniaContainer_default, { key: 0 }, {
863
+ default: withCtx(() => [
864
+ _cache[1] || (_cache[1] = createElementVNode("h3", { class: "card-title text-base sm:text-lg" }, "Convert to Internal Task", -1)),
865
+ _cache[2] || (_cache[2] = createElementVNode("div", { class: "alert alert-info py-2" }, [createElementVNode("div", { class: "flex flex-col gap-2" }, [createElementVNode("span", { class: "font-semibold text-sm" }, "What happens when you convert:"), createElementVNode("ul", { class: "text-xs sm:text-sm space-y-1 ml-4 list-disc" }, [
866
+ createElementVNode("li", null, "Changes status from customer support_ticket to internal task"),
867
+ createElementVNode("li", null, "Bypasses approval workflow entirely"),
868
+ createElementVNode("li", null, "Automatically clears any credit estimates (internal tasks = no credits)"),
869
+ createElementVNode("li", null, "Can start development immediately")
870
+ ])])], -1)),
871
+ createElementVNode("div", _hoisted_1$2, [createElementVNode("button", {
872
+ class: "btn btn-primary w-full sm:w-auto",
873
+ onClick: withModifiers(showConvertModal, ["prevent"]),
874
+ disabled: unref(isConverting)
875
+ }, [unref(isConverting) ? (openBlock(), createElementBlock("span", _hoisted_3$2)) : createCommentVNode("v-if", true), createTextVNode(" " + toDisplayString(unref(isConverting) ? "Converting..." : "Convert to Internal Task"), 1)], 8, _hoisted_2$2)]),
876
+ error.value ? (openBlock(), createElementBlock("div", _hoisted_4$2, [createElementVNode("span", _hoisted_5$2, toDisplayString(error.value), 1)])) : createCommentVNode("v-if", true)
877
+ ]),
878
+ _: 1
879
+ })) : createCommentVNode("v-if", true),
880
+ createCommentVNode(" Confirmation Modal "),
881
+ createElementVNode("dialog", {
882
+ ref_key: "confirmModal",
883
+ ref: confirmModal,
884
+ class: "modal"
885
+ }, [createElementVNode("div", _hoisted_6$2, [
886
+ createElementVNode("h3", _hoisted_7$2, toDisplayString(modalTitle.value), 1),
887
+ createElementVNode("p", _hoisted_8$2, toDisplayString(modalMessage.value), 1),
888
+ createElementVNode("div", _hoisted_9$2, [createElementVNode("button", {
889
+ class: "btn btn-ghost",
890
+ onClick: closeModal
891
+ }, "Cancel"), createElementVNode("button", {
892
+ class: "btn btn-primary",
893
+ onClick: _cache[0] || (_cache[0] = () => modalCallback.value?.())
894
+ }, toDisplayString(modalButtonText.value), 1)])
895
+ ]), createElementVNode("form", {
896
+ method: "dialog",
897
+ class: "modal-backdrop"
898
+ }, [createElementVNode("button", { onClick: closeModal }, "close")])], 512)
899
+ ], 64);
900
+ };
901
+ }
902
+ });
903
+ var ConvertToInternalWorkflow_default = _sfc_main$2;
904
+
905
+ //#endregion
906
+ //#region src/slices/support_ticket/staff/components/ReactivateInternalTaskWorkflow.vue
907
+ const _hoisted_1$1 = { class: "alert alert-info py-2" };
908
+ const _hoisted_2$1 = { class: "flex flex-col gap-2" };
909
+ const _hoisted_3$1 = { class: "text-xs sm:text-sm space-y-1 ml-4 list-disc" };
910
+ const _hoisted_4$1 = { key: 0 };
911
+ const _hoisted_5$1 = { key: 1 };
912
+ const _hoisted_6$1 = { class: "flex justify-end mt-4" };
913
+ const _hoisted_7$1 = ["disabled"];
914
+ const _hoisted_8$1 = {
915
+ key: 0,
916
+ class: "loading loading-spinner loading-sm mr-2"
917
+ };
918
+ const _hoisted_9$1 = {
919
+ key: 0,
920
+ class: "alert alert-error mt-2 py-2"
921
+ };
922
+ const _hoisted_10$1 = { class: "text-sm" };
923
+ const _hoisted_11$1 = { class: "modal-box" };
924
+ const _hoisted_12$1 = { class: "font-bold text-lg" };
925
+ const _hoisted_13$1 = { class: "py-4 whitespace-pre-line" };
926
+ const _hoisted_14$1 = { class: "modal-action" };
927
+ const _sfc_main$1 = /* @__PURE__ */ defineComponent({
928
+ __name: "ReactivateInternalTaskWorkflow",
929
+ props: { support_ticket: {} },
930
+ emits: ["update"],
931
+ setup(__props, { emit: __emit }) {
932
+ const props = __props;
933
+ const emit = __emit;
934
+ const error = ref(null);
935
+ const confirmModal = ref(null);
936
+ const modalTitle = ref("");
937
+ const modalMessage = ref("");
938
+ const modalButtonText = ref("");
939
+ const modalCallback = ref(null);
940
+ const { mutate: reactivateInternalTask, loading: isReactivating } = useMutation((api, input) => api.supportTickets.reactivateInternalTask(input), { invalidate: /^support-tickets?:/ });
941
+ const showReactivateModal = () => {
942
+ const isCancelled = props.support_ticket.dev_lifecycle === "CANCELLED";
943
+ const targetState = isCancelled ? "BACKLOG" : "PO_APPROVAL";
944
+ modalTitle.value = `Reopen ${isCancelled ? "Cancelled" : "Deployed"} Task?`;
945
+ modalMessage.value = `This will:\n\n• Set dev lifecycle to ${targetState}\n• Clear completion timestamp\n• Resume task as active\n\n` + (isCancelled ? `Task will restart from backlog for fresh planning.` : `Task will go to PO approval stage for review/fixes.`);
946
+ modalButtonText.value = "Reopen Task";
947
+ modalCallback.value = handleReactivate;
948
+ confirmModal.value?.showModal();
949
+ };
950
+ const handleReactivate = async () => {
951
+ error.value = null;
952
+ try {
953
+ const result = await reactivateInternalTask({ id: props.support_ticket.id });
954
+ toast.success("✅ Internal task reopened successfully");
955
+ closeModal();
956
+ emit("update", result);
957
+ } catch (err) {
958
+ error.value = err instanceof Error ? err.message : "Failed to reactivate task";
959
+ toast.error(`❌ ${error.value}`);
960
+ }
961
+ };
962
+ const closeModal = () => {
963
+ confirmModal.value?.close();
964
+ };
965
+ return (_ctx, _cache) => {
966
+ return openBlock(), createElementBlock(Fragment, null, [
967
+ createCommentVNode(" Reactivate Terminal Internal Task Section (INTERNAL + CANCELLED or DEPLOYED) "),
968
+ props.support_ticket.approval_status === "INTERNAL" && (props.support_ticket.dev_lifecycle === "CANCELLED" || props.support_ticket.dev_lifecycle === "DEPLOYED") ? (openBlock(), createBlock(ZiniaContainer_default, { key: 0 }, {
969
+ default: withCtx(() => [
970
+ _cache[5] || (_cache[5] = createElementVNode("h3", { class: "card-title text-base sm:text-lg" }, "Reopen Internal Task", -1)),
971
+ createElementVNode("div", _hoisted_1$1, [createElementVNode("div", _hoisted_2$1, [_cache[4] || (_cache[4] = createElementVNode("span", { class: "font-semibold text-sm" }, "What happens when you reopen:", -1)), createElementVNode("ul", _hoisted_3$1, [
972
+ props.support_ticket.dev_lifecycle === "CANCELLED" ? (openBlock(), createElementBlock("li", _hoisted_4$1, " Sets dev lifecycle to BACKLOG (fresh start) ")) : (openBlock(), createElementBlock("li", _hoisted_5$1, "Sets dev lifecycle to PO_APPROVAL (ready for review/fixes)")),
973
+ _cache[1] || (_cache[1] = createElementVNode("li", null, "Clears completion timestamp", -1)),
974
+ _cache[2] || (_cache[2] = createElementVNode("li", null, "Task becomes active again", -1)),
975
+ _cache[3] || (_cache[3] = createElementVNode("li", null, "You can resume work or make additional changes", -1))
976
+ ])])]),
977
+ createElementVNode("div", _hoisted_6$1, [createElementVNode("button", {
978
+ class: "btn btn-success w-full sm:w-auto",
979
+ onClick: withModifiers(showReactivateModal, ["prevent"]),
980
+ disabled: unref(isReactivating)
981
+ }, [unref(isReactivating) ? (openBlock(), createElementBlock("span", _hoisted_8$1)) : createCommentVNode("v-if", true), createTextVNode(" " + toDisplayString(unref(isReactivating) ? "Reopening..." : "Reopen Task"), 1)], 8, _hoisted_7$1)]),
982
+ error.value ? (openBlock(), createElementBlock("div", _hoisted_9$1, [createElementVNode("span", _hoisted_10$1, toDisplayString(error.value), 1)])) : createCommentVNode("v-if", true)
983
+ ]),
984
+ _: 1
985
+ })) : createCommentVNode("v-if", true),
986
+ createCommentVNode(" Confirmation Modal "),
987
+ createElementVNode("dialog", {
988
+ ref_key: "confirmModal",
989
+ ref: confirmModal,
990
+ class: "modal"
991
+ }, [createElementVNode("div", _hoisted_11$1, [
992
+ createElementVNode("h3", _hoisted_12$1, toDisplayString(modalTitle.value), 1),
993
+ createElementVNode("p", _hoisted_13$1, toDisplayString(modalMessage.value), 1),
994
+ createElementVNode("div", _hoisted_14$1, [createElementVNode("button", {
995
+ class: "btn btn-ghost",
996
+ onClick: closeModal
997
+ }, "Cancel"), createElementVNode("button", {
998
+ class: "btn btn-success",
999
+ onClick: _cache[0] || (_cache[0] = () => modalCallback.value?.())
1000
+ }, toDisplayString(modalButtonText.value), 1)])
1001
+ ]), createElementVNode("form", {
1002
+ method: "dialog",
1003
+ class: "modal-backdrop"
1004
+ }, [createElementVNode("button", { onClick: closeModal }, "close")])], 512)
1005
+ ], 64);
1006
+ };
1007
+ }
1008
+ });
1009
+ var ReactivateInternalTaskWorkflow_default = _sfc_main$1;
1010
+
1011
+ //#endregion
1012
+ //#region src/slices/support_ticket/staff/StaffSupportTicketWorkflowTab.vue
1013
+ const _hoisted_1 = {
1014
+ key: 0,
1015
+ class: "flex justify-center items-center p-8"
1016
+ };
1017
+ const _hoisted_2 = {
1018
+ key: 1,
1019
+ class: "alert alert-error mb-4"
1020
+ };
1021
+ const _hoisted_3 = {
1022
+ key: 3,
1023
+ class: "space-y-6"
1024
+ };
1025
+ const _hoisted_4 = { class: "flex gap-4 items-center" };
1026
+ const _hoisted_5 = {
1027
+ key: 1,
1028
+ class: "badge badge-lg badge-warning"
1029
+ };
1030
+ const _hoisted_6 = ["disabled"];
1031
+ const _hoisted_7 = { class: "modal-box" };
1032
+ const _hoisted_8 = { class: "text-center mb-6" };
1033
+ const _hoisted_9 = {
1034
+ key: 0,
1035
+ class: "bg-base-200 p-3 rounded-lg mb-3"
1036
+ };
1037
+ const _hoisted_10 = { class: "font-semibold" };
1038
+ const _hoisted_11 = { class: "text-sm text-base-content/70" };
1039
+ const _hoisted_12 = { class: "text-sm text-base-content/70" };
1040
+ const _hoisted_13 = { key: 1 };
1041
+ const _hoisted_14 = { class: "modal-action justify-center gap-3" };
1042
+ const _hoisted_15 = ["disabled"];
1043
+ const _hoisted_16 = ["disabled"];
1044
+ const _hoisted_17 = {
1045
+ key: 0,
1046
+ class: "loading loading-spinner loading-sm"
1047
+ };
1048
+ const _sfc_main = /* @__PURE__ */ defineComponent({
1049
+ __name: "StaffSupportTicketWorkflowTab",
1050
+ props: {
1051
+ ticket: {},
1052
+ isLoading: { type: Boolean },
1053
+ error: {}
1054
+ },
1055
+ setup(__props) {
1056
+ const props = __props;
1057
+ const route = useRoute();
1058
+ const router = useRouter();
1059
+ const support_ticket_id = route.params.id;
1060
+ const refreshTicket = inject("refreshTicket");
1061
+ const currentSupportTicket = computed(() => {
1062
+ return props.ticket ? {
1063
+ ...props.ticket,
1064
+ __typename: "AdminSupportTicket"
1065
+ } : null;
1066
+ });
1067
+ const showDeleteModal = ref(false);
1068
+ const { mutate: deleteSupportTicket, loading: isDeleting } = useMutation((api, input) => api.supportTickets.deleteTicket(input.id), { invalidate: /^support-tickets?:/ });
1069
+ const handleWorkflowUpdate = async () => {
1070
+ if (refreshTicket) await refreshTicket();
1071
+ };
1072
+ function openDeleteModal() {
1073
+ showDeleteModal.value = true;
1074
+ }
1075
+ function closeDeleteModal() {
1076
+ showDeleteModal.value = false;
1077
+ }
1078
+ async function confirmDelete() {
1079
+ closeDeleteModal();
1080
+ try {
1081
+ await deleteSupportTicket({ id: support_ticket_id });
1082
+ await router.push({ name: "StaffSupportTicketList" });
1083
+ toast.success("Support ticket deleted successfully");
1084
+ } catch (err) {
1085
+ const errorMsg = err instanceof Error ? err.message : "Failed to delete support ticket";
1086
+ if (errorMsg.includes("Cannot delete approved tickets")) toast.error(errorMsg);
1087
+ else toast.error("Failed to delete support ticket");
1088
+ console.error(err);
1089
+ }
1090
+ }
1091
+ return (_ctx, _cache) => {
1092
+ return openBlock(), createElementBlock(Fragment, null, [
1093
+ __props.isLoading ? (openBlock(), createElementBlock("div", _hoisted_1, [..._cache[0] || (_cache[0] = [createElementVNode("span", { class: "loading loading-spinner loading-lg" }, null, -1)])])) : __props.error ? (openBlock(), createElementBlock("div", _hoisted_2, [_cache[1] || (_cache[1] = createElementVNode("svg", {
1094
+ xmlns: "http://www.w3.org/2000/svg",
1095
+ class: "stroke-current shrink-0 h-6 w-6",
1096
+ fill: "none",
1097
+ viewBox: "0 0 24 24"
1098
+ }, [createElementVNode("path", {
1099
+ "stroke-linecap": "round",
1100
+ "stroke-linejoin": "round",
1101
+ "stroke-width": "2",
1102
+ d: "M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z"
1103
+ })], -1)), createElementVNode("span", null, toDisplayString(__props.error.message), 1)])) : unref(isDeleting) ? (openBlock(), createElementBlock(Fragment, { key: 2 }, [createCommentVNode(" Deleting State "), _cache[2] || (_cache[2] = createStaticVNode("<div class=\"max-w-7xl mx-auto p-6\"><div class=\"flex flex-col items-center justify-center p-16\"><div class=\"loading loading-spinner loading-lg mb-4\"></div><p class=\"text-lg mb-2\">Deleting support ticket...</p><p class=\"text-sm text-base-content/70\">This may take a moment</p></div></div>", 1))], 2112)) : currentSupportTicket.value ? (openBlock(), createElementBlock("div", _hoisted_3, [
1104
+ createCommentVNode(" Status Badge "),
1105
+ createVNode(ZiniaContainer_default, null, {
1106
+ default: withCtx(() => [_cache[3] || (_cache[3] = createElementVNode("h3", { class: "card-title" }, "Current Status", -1)), createElementVNode("div", _hoisted_4, [
1107
+ createVNode(SupportTicketApprovalBadge_default, {
1108
+ approvalStatus: currentSupportTicket.value.approval_status,
1109
+ size: "lg"
1110
+ }, null, 8, ["approvalStatus"]),
1111
+ currentSupportTicket.value.dev_lifecycle ? (openBlock(), createBlock(SupportTicketDevLifecycleBadge_default, {
1112
+ key: 0,
1113
+ devLifecycle: currentSupportTicket.value.dev_lifecycle,
1114
+ size: "lg"
1115
+ }, null, 8, ["devLifecycle"])) : createCommentVNode("v-if", true),
1116
+ currentSupportTicket.value.is_locked ? (openBlock(), createElementBlock("div", _hoisted_5, " 🔒 LOCKED ")) : createCommentVNode("v-if", true)
1117
+ ])]),
1118
+ _: 1
1119
+ }),
1120
+ createCommentVNode(" Complete: For both APPROVED and INTERNAL (not cancelled or already deployed) "),
1121
+ currentSupportTicket.value.dev_lifecycle !== "CANCELLED" && currentSupportTicket.value.dev_lifecycle !== "DEPLOYED" ? (openBlock(), createBlock(CompleteSupportTicketForm_default, {
1122
+ key: 0,
1123
+ support_ticket: currentSupportTicket.value,
1124
+ onUpdate: handleWorkflowUpdate
1125
+ }, null, 8, ["support_ticket"])) : createCommentVNode("v-if", true),
1126
+ createCommentVNode(" Approve/Reject: Only for customer support_ticket (not INTERNAL) "),
1127
+ currentSupportTicket.value.approval_status !== "INTERNAL" ? (openBlock(), createBlock(ApproveRejectActions_default, {
1128
+ key: 1,
1129
+ support_ticket: currentSupportTicket.value,
1130
+ onUpdate: handleWorkflowUpdate
1131
+ }, null, 8, ["support_ticket"])) : createCommentVNode("v-if", true),
1132
+ createCommentVNode(" Convert to Internal: Only for PENDING support_ticket "),
1133
+ currentSupportTicket.value.approval_status === "PENDING" ? (openBlock(), createBlock(ConvertToInternalWorkflow_default, {
1134
+ key: 2,
1135
+ support_ticket: currentSupportTicket.value,
1136
+ onUpdate: handleWorkflowUpdate
1137
+ }, null, 8, ["support_ticket"])) : createCommentVNode("v-if", true),
1138
+ createCommentVNode(" Convert to Customer: Only for INTERNAL tasks that aren't cancelled or deployed "),
1139
+ currentSupportTicket.value.approval_status === "INTERNAL" && currentSupportTicket.value.dev_lifecycle !== "CANCELLED" && currentSupportTicket.value.dev_lifecycle !== "DEPLOYED" ? (openBlock(), createBlock(ConvertToCustomerWorkflow_default, {
1140
+ key: 3,
1141
+ support_ticket: currentSupportTicket.value,
1142
+ onUpdate: handleWorkflowUpdate
1143
+ }, null, 8, ["support_ticket"])) : createCommentVNode("v-if", true),
1144
+ createCommentVNode(" Cancel Internal Task: Only for INTERNAL tasks that aren't already cancelled or deployed "),
1145
+ currentSupportTicket.value.approval_status === "INTERNAL" && currentSupportTicket.value.dev_lifecycle !== "CANCELLED" && currentSupportTicket.value.dev_lifecycle !== "DEPLOYED" ? (openBlock(), createBlock(CancelInternalTaskWorkflow_default, {
1146
+ key: 4,
1147
+ support_ticket: currentSupportTicket.value,
1148
+ onUpdate: handleWorkflowUpdate
1149
+ }, null, 8, ["support_ticket"])) : createCommentVNode("v-if", true),
1150
+ createCommentVNode(" Reactivate Internal Task: Only for terminal INTERNAL tasks (CANCELLED or DEPLOYED) "),
1151
+ currentSupportTicket.value.approval_status === "INTERNAL" && (currentSupportTicket.value.dev_lifecycle === "CANCELLED" || currentSupportTicket.value.dev_lifecycle === "DEPLOYED") ? (openBlock(), createBlock(ReactivateInternalTaskWorkflow_default, {
1152
+ key: 5,
1153
+ support_ticket: currentSupportTicket.value,
1154
+ onUpdate: handleWorkflowUpdate
1155
+ }, null, 8, ["support_ticket"])) : createCommentVNode("v-if", true),
1156
+ createCommentVNode(" Danger Zone - Always show section "),
1157
+ currentSupportTicket.value ? (openBlock(), createBlock(ZiniaContainer_default, { key: 6 }, {
1158
+ default: withCtx(() => [
1159
+ _cache[6] || (_cache[6] = createElementVNode("h3", { class: "card-title text-error" }, "Danger Zone", -1)),
1160
+ createCommentVNode(" Show delete button if backend says ticket can be deleted "),
1161
+ currentSupportTicket.value.can_delete ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [_cache[4] || (_cache[4] = createElementVNode("p", { class: "text-sm text-base-content/70 mb-4" }, " Permanently delete this support ticket. This action cannot be undone. ", -1)), createElementVNode("button", {
1162
+ onClick: openDeleteModal,
1163
+ class: "btn btn-error btn-sm",
1164
+ disabled: unref(isDeleting)
1165
+ }, " Delete Support Ticket ", 8, _hoisted_6)], 64)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [createCommentVNode(" Show message if backend says ticket cannot be deleted "), _cache[5] || (_cache[5] = createElementVNode("div", { class: "alert alert-info" }, [createElementVNode("svg", {
1166
+ xmlns: "http://www.w3.org/2000/svg",
1167
+ fill: "none",
1168
+ viewBox: "0 0 24 24",
1169
+ class: "stroke-current shrink-0 w-6 h-6"
1170
+ }, [createElementVNode("path", {
1171
+ "stroke-linecap": "round",
1172
+ "stroke-linejoin": "round",
1173
+ "stroke-width": "2",
1174
+ d: "M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
1175
+ })]), createElementVNode("span", null, " This ticket cannot be deleted because it has been charged to the customer. Use the archive feature instead if you need to hide it from the active list. ")], -1))], 64))
1176
+ ]),
1177
+ _: 1
1178
+ })) : createCommentVNode("v-if", true)
1179
+ ])) : createCommentVNode("v-if", true),
1180
+ createCommentVNode(" Delete Confirmation Modal "),
1181
+ createElementVNode("dialog", { class: normalizeClass([{ "modal modal-open": showDeleteModal.value }, "modal"]) }, [createElementVNode("div", _hoisted_7, [
1182
+ createCommentVNode(" Warning Icon "),
1183
+ _cache[9] || (_cache[9] = createElementVNode("div", { class: "flex items-center justify-center w-16 h-16 mx-auto mb-4 bg-error/10 rounded-full" }, [createElementVNode("svg", {
1184
+ xmlns: "http://www.w3.org/2000/svg",
1185
+ class: "w-8 h-8 text-error",
1186
+ fill: "none",
1187
+ viewBox: "0 0 24 24",
1188
+ stroke: "currentColor"
1189
+ }, [createElementVNode("path", {
1190
+ "stroke-linecap": "round",
1191
+ "stroke-linejoin": "round",
1192
+ "stroke-width": "2",
1193
+ d: "M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16.5c-.77.833.192 2.5 1.732 2.5z"
1194
+ })])], -1)),
1195
+ createCommentVNode(" Modal Title "),
1196
+ _cache[10] || (_cache[10] = createElementVNode("h3", { class: "text-lg font-bold text-center mb-2" }, "Delete Support Ticket", -1)),
1197
+ createCommentVNode(" Modal Content "),
1198
+ createElementVNode("div", _hoisted_8, [
1199
+ _cache[7] || (_cache[7] = createElementVNode("p", { class: "text-base-content/80 mb-2" }, " Are you sure you want to delete this support ticket? ", -1)),
1200
+ currentSupportTicket.value ? (openBlock(), createElementBlock("div", _hoisted_9, [
1201
+ createElementVNode("p", _hoisted_10, toDisplayString(currentSupportTicket.value.title || "Untitled Ticket"), 1),
1202
+ createElementVNode("p", _hoisted_11, toDisplayString(currentSupportTicket.value.requester_name || "No Requester"), 1),
1203
+ createElementVNode("div", _hoisted_12, [currentSupportTicket.value.type ? (openBlock(), createBlock(SupportTicketTypeBadge_default, {
1204
+ key: 0,
1205
+ type: currentSupportTicket.value.type,
1206
+ size: "sm"
1207
+ }, null, 8, ["type"])) : (openBlock(), createElementBlock("span", _hoisted_13, "No Type"))])
1208
+ ])) : createCommentVNode("v-if", true),
1209
+ _cache[8] || (_cache[8] = createElementVNode("p", { class: "text-sm text-error font-medium" }, "This action cannot be undone.", -1))
1210
+ ]),
1211
+ createCommentVNode(" Modal Actions "),
1212
+ createElementVNode("div", _hoisted_14, [createElementVNode("button", {
1213
+ onClick: closeDeleteModal,
1214
+ class: "btn btn-outline",
1215
+ disabled: unref(isDeleting)
1216
+ }, " Cancel ", 8, _hoisted_15), createElementVNode("button", {
1217
+ onClick: confirmDelete,
1218
+ class: "btn btn-error",
1219
+ disabled: unref(isDeleting)
1220
+ }, [unref(isDeleting) ? (openBlock(), createElementBlock("span", _hoisted_17)) : createCommentVNode("v-if", true), createTextVNode(" " + toDisplayString(unref(isDeleting) ? "Deleting..." : "Delete Support Ticket"), 1)], 8, _hoisted_16)])
1221
+ ]), createElementVNode("form", {
1222
+ method: "dialog",
1223
+ class: "modal-backdrop",
1224
+ onClick: closeDeleteModal
1225
+ }, [..._cache[11] || (_cache[11] = [createElementVNode("button", { type: "button" }, "close", -1)])])], 2)
1226
+ ], 64);
1227
+ };
1228
+ }
1229
+ });
1230
+ var StaffSupportTicketWorkflowTab_default = _sfc_main;
1231
+
1232
+ //#endregion
1233
+ export { CompleteSupportTicketForm_default as a, CustomerCreditBalance_default as c, ConvertToCustomerWorkflow_default as i, SupportTicketDevLifecycleBadge_default as l, ReactivateInternalTaskWorkflow_default as n, CancelInternalTaskWorkflow_default as o, ConvertToInternalWorkflow_default as r, ApproveRejectActions_default as s, StaffSupportTicketWorkflowTab_default as t, SupportTicketApprovalBadge_default as u };
1234
+ //# sourceMappingURL=StaffSupportTicketWorkflowTab-DmVTPzxS.js.map