@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.
- package/LICENSE +75 -0
- package/dist/AppLink-CHMMrSFI.js +54 -0
- package/dist/AppLink-CHMMrSFI.js.map +1 -0
- package/dist/Appearance-BfPdKMXw.js +70 -0
- package/dist/Appearance-BfPdKMXw.js.map +1 -0
- package/dist/Appearance-C3WguxT-.js +3 -0
- package/dist/ChangePasswordPage-Btu5lf-r.js +86 -0
- package/dist/ChangePasswordPage-Btu5lf-r.js.map +1 -0
- package/dist/ChangePasswordPage-mBBuQMkT.js +6 -0
- package/dist/CreateTeamForm-n2ut93vM.js +43 -0
- package/dist/CreateTeamMemberForm-CcH3AxNL.js +43 -0
- package/dist/CreateUserPage-CDrGuW9B.js +6 -0
- package/dist/CreateUserPage-Cmx8xjjv.js +76 -0
- package/dist/CreateUserPage-Cmx8xjjv.js.map +1 -0
- package/dist/CreditBalanceDashboard-DLz0ioP3.js +43 -0
- package/dist/CreditManagement-D3q5S-qc.js +43 -0
- package/dist/CustomerCreateSupportTicketForm-Ci7QYkG-.js +43 -0
- package/dist/CustomerEditSupportTicketForm-Dd5ZB74k.js +159 -0
- package/dist/CustomerEditSupportTicketForm-Dd5ZB74k.js.map +1 -0
- package/dist/CustomerEditSupportTicketForm-lLchVjnw.js +9 -0
- package/dist/CustomerSupportTicketAttachmentsTab-gBrVO97t.js +43 -0
- package/dist/CustomerSupportTicketCustomerNotesTab-D0jhzbOY.js +8 -0
- package/dist/CustomerSupportTicketCustomerNotesTab-D1aa9It7.js +23 -0
- package/dist/CustomerSupportTicketCustomerNotesTab-D1aa9It7.js.map +1 -0
- package/dist/CustomerSupportTicketHistoryTab-BNTf8EZq.js +6 -0
- package/dist/CustomerSupportTicketHistoryTab-CFYN_Sa4.js +17 -0
- package/dist/CustomerSupportTicketHistoryTab-CFYN_Sa4.js.map +1 -0
- package/dist/CustomerSupportTicketList-BkOzFxMP.js +6 -0
- package/dist/CustomerSupportTicketList-C2nUPawb.js +166 -0
- package/dist/CustomerSupportTicketList-C2nUPawb.js.map +1 -0
- package/dist/CustomerSupportTicketParent-2mONd9kL.js +66 -0
- package/dist/CustomerSupportTicketParent-2mONd9kL.js.map +1 -0
- package/dist/CustomerSupportTicketParent-N8ko1yFE.js +7 -0
- package/dist/CustomerSupportTicketSuccess-w_-9NXT4.js +43 -0
- package/dist/CustomerViewSupportTicket-CVwNH0lS.js +11 -0
- package/dist/CustomerViewSupportTicket-tZkxragu.js +363 -0
- package/dist/CustomerViewSupportTicket-tZkxragu.js.map +1 -0
- package/dist/EditTeamForm-BioqiTWE.js +43 -0
- package/dist/EditTeamMemberForm-DCq0Gsn_.js +7 -0
- package/dist/EditTeamMemberForm-ru4WgLz-.js +169 -0
- package/dist/EditTeamMemberForm-ru4WgLz-.js.map +1 -0
- package/dist/EditUserPage-BxJ5QvIM.js +112 -0
- package/dist/EditUserPage-BxJ5QvIM.js.map +1 -0
- package/dist/EditUserPage-XOBuxUxd.js +7 -0
- package/dist/FieldsetSection-CsHN38_o.js +27 -0
- package/dist/FieldsetSection-CsHN38_o.js.map +1 -0
- package/dist/ForgotPassword-CpqvcSFg.js +7 -0
- package/dist/ForgotPassword-CqhenzUG.js +73 -0
- package/dist/ForgotPassword-CqhenzUG.js.map +1 -0
- package/dist/InlineAttachments-I39rOvip.js +1351 -0
- package/dist/InlineAttachments-I39rOvip.js.map +1 -0
- package/dist/LoginForm-AM0qkfbU.js +7 -0
- package/dist/LoginForm-_PZ51Uwe.js +116 -0
- package/dist/LoginForm-_PZ51Uwe.js.map +1 -0
- package/dist/Logout-BMjiqHnS.js +38 -0
- package/dist/Logout-BMjiqHnS.js.map +1 -0
- package/dist/Logout-BfiBjlaH.js +6 -0
- package/dist/NoteList-C0hRPNMO.js +497 -0
- package/dist/NoteList-C0hRPNMO.js.map +1 -0
- package/dist/NotificationEmailsPage-BjRqtW95.js +141 -0
- package/dist/NotificationEmailsPage-BjRqtW95.js.map +1 -0
- package/dist/NotificationEmailsPage-bx-9rg3x.js +7 -0
- package/dist/ResetPassword-BQLkR9TZ.js +43 -0
- package/dist/Signup-CnCcQlB8.js +7 -0
- package/dist/Signup-c2-_yMOM.js +106 -0
- package/dist/Signup-c2-_yMOM.js.map +1 -0
- package/dist/StaffCreateSupportTicketForm-ChVFDJdA.js +43 -0
- package/dist/StaffEditSupportTicketForm-DY1Zkf5k.js +9 -0
- package/dist/StaffEditSupportTicketForm-DuUKuIGg.js +263 -0
- package/dist/StaffEditSupportTicketForm-DuUKuIGg.js.map +1 -0
- package/dist/StaffSupportTicketAttachmentsTab-DpDXsHXP.js +43 -0
- package/dist/StaffSupportTicketCustomerNotesTab-CusqQV2-.js +23 -0
- package/dist/StaffSupportTicketCustomerNotesTab-CusqQV2-.js.map +1 -0
- package/dist/StaffSupportTicketCustomerNotesTab-rbJHJ0_V.js +8 -0
- package/dist/StaffSupportTicketHistoryTab-D24myEm3.js +17 -0
- package/dist/StaffSupportTicketHistoryTab-D24myEm3.js.map +1 -0
- package/dist/StaffSupportTicketHistoryTab-nmVma5vp.js +6 -0
- package/dist/StaffSupportTicketInternalNotesTab-D8HM--dp.js +23 -0
- package/dist/StaffSupportTicketInternalNotesTab-D8HM--dp.js.map +1 -0
- package/dist/StaffSupportTicketInternalNotesTab-DihYd5XI.js +8 -0
- package/dist/StaffSupportTicketList-DelptSmK.js +43 -0
- package/dist/StaffSupportTicketParent-BCrj3ckV.js +7 -0
- package/dist/StaffSupportTicketParent-Cx1buQZw.js +66 -0
- package/dist/StaffSupportTicketParent-Cx1buQZw.js.map +1 -0
- package/dist/StaffSupportTicketSuccess-BYxtY5wZ.js +43 -0
- package/dist/StaffSupportTicketWorkflowTab-BrDDBeK9.js +9 -0
- package/dist/StaffSupportTicketWorkflowTab-DmVTPzxS.js +1234 -0
- package/dist/StaffSupportTicketWorkflowTab-DmVTPzxS.js.map +1 -0
- package/dist/SupportTicketHistoryTab-CLMopA7a.js +220 -0
- package/dist/SupportTicketHistoryTab-CLMopA7a.js.map +1 -0
- package/dist/SupportTicketStatusBadge-YdZzjvkh.js +163 -0
- package/dist/SupportTicketStatusBadge-YdZzjvkh.js.map +1 -0
- package/dist/TeamAttachmentsTab-BxUpTWYh.js +43 -0
- package/dist/TeamHistoryTab-CUCT9MRG.js +5 -0
- package/dist/TeamHistoryTab-gB3H2KZv.js +219 -0
- package/dist/TeamHistoryTab-gB3H2KZv.js.map +1 -0
- package/dist/TeamList-By6pzWm5.js +43 -0
- package/dist/TeamMemberList-CYV9fWEb.js +43 -0
- package/dist/TeamMemberParent-CVvGqpxD.js +43 -0
- package/dist/TeamMembersTab-4gmnP9sD.js +21 -0
- package/dist/TeamMembersTab-4gmnP9sD.js.map +1 -0
- package/dist/TeamMembersTab-CpE9BaCi.js +3 -0
- package/dist/TeamNotesTab-pfXTDhg6.js +23 -0
- package/dist/TeamNotesTab-pfXTDhg6.js.map +1 -0
- package/dist/TeamNotesTab-u4cDC67X.js +8 -0
- package/dist/TeamParent-BxT1KubK.js +43 -0
- package/dist/UserListPage-DsQdH2Sm.js +4 -0
- package/dist/UserListPage-WU56KiWj.js +153 -0
- package/dist/UserListPage-WU56KiWj.js.map +1 -0
- package/dist/UserProfilePage-B73JhjUu.js +7 -0
- package/dist/UserProfilePage-BtLUY1kt.js +125 -0
- package/dist/UserProfilePage-BtLUY1kt.js.map +1 -0
- package/dist/ViewTeam-DzX-obEl.js +43 -0
- package/dist/ViewTeamMember-PF6S_4Pb.js +43 -0
- package/dist/ZiniaContainer-C7c7Vwkh.js +18 -0
- package/dist/ZiniaContainer-C7c7Vwkh.js.map +1 -0
- package/dist/convertToLocalDateTime-D4IoNvRj.js +111 -0
- package/dist/convertToLocalDateTime-D4IoNvRj.js.map +1 -0
- package/dist/creditValueFormatter-DftEzu8d.js +128 -0
- package/dist/creditValueFormatter-DftEzu8d.js.map +1 -0
- package/dist/displayIdFormatter-Dz900Awr.js +13 -0
- package/dist/displayIdFormatter-Dz900Awr.js.map +1 -0
- package/dist/index.d.ts +6068 -0
- package/dist/index.js +45 -0
- package/dist/src-o5fMIo5_.js +6649 -0
- package/dist/src-o5fMIo5_.js.map +1 -0
- package/dist/useBreadcrumbs-DmgSucoe.js +41 -0
- package/dist/useBreadcrumbs-DmgSucoe.js.map +1 -0
- package/dist/useMutation-CFwe7H9j.js +50 -0
- package/dist/useMutation-CFwe7H9j.js.map +1 -0
- package/dist/useQuery-p7oJO7OD.js +107 -0
- package/dist/useQuery-p7oJO7OD.js.map +1 -0
- package/dist/useQueryCache-ByayvZgZ.js +254 -0
- package/dist/useQueryCache-ByayvZgZ.js.map +1 -0
- package/dist/useRpcAuth-BLlRSHy8.js +722 -0
- package/dist/useRpcAuth-BLlRSHy8.js.map +1 -0
- package/package.json +62 -0
- package/src/daisyui.css +63 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StaffSupportTicketWorkflowTab-DmVTPzxS.js","names":["approvalConfig: Record<SupportTicketApproval, ApprovalBadgeConfig>","devLifecycleConfig: Record<SupportTicketDevLifecycle, DevLifecycleBadgeConfig>"],"sources":["../src/slices/support_ticket/components/SupportTicketApprovalBadge.vue","../src/slices/support_ticket/components/SupportTicketDevLifecycleBadge.vue","../src/slices/support_ticket/staff/components/CustomerCreditBalance.vue","../src/slices/support_ticket/staff/components/ApproveRejectActions.vue","../src/slices/support_ticket/staff/components/CancelInternalTaskWorkflow.vue","../src/slices/support_ticket/staff/components/CompleteSupportTicketForm.vue","../src/slices/support_ticket/staff/components/ConvertToCustomerWorkflow.vue","../src/slices/support_ticket/staff/components/ConvertToInternalWorkflow.vue","../src/slices/support_ticket/staff/components/ReactivateInternalTaskWorkflow.vue","../src/slices/support_ticket/staff/StaffSupportTicketWorkflowTab.vue"],"sourcesContent":["<template>\n <div :class=\"badgeClasses\" :aria-label=\"ariaLabel\" role=\"status\">\n {{ displayText }}\n </div>\n</template>\n\n<script setup lang=\"ts\">\n/**\n * SupportTicketApprovalBadge - A reusable Vue component for displaying support ticket approval status\n * as color-coded badges with consistent DaisyUI styling and accessibility features.\n *\n * @example\n * <SupportTicketApprovalBadge :approvalStatus=\"'PENDING'\" size=\"md\" />\n * <SupportTicketApprovalBadge :approvalStatus=\"'APPROVED'\" size=\"sm\" variant=\"outline\" />\n */\nimport type { SupportTicketApproval } from '@dragonmastery/dragoncore-shared';\nimport { computed } from 'vue';\n\n/**\n * Props for the SupportTicketApprovalBadge component\n */\ninterface Props {\n /** The support ticket approval status to display */\n approvalStatus: SupportTicketApproval;\n /** Size of the badge - defaults to 'md' */\n size?: 'sm' | 'md' | 'lg';\n /** Visual variant of the badge - defaults to 'default' */\n variant?: 'default' | 'outline';\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n size: 'md',\n variant: 'default',\n});\n\n/**\n * Configuration for each approval status badge\n */\ninterface ApprovalBadgeConfig {\n /** DaisyUI badge color class */\n color: string;\n /** Display text for the badge */\n text: string;\n /** Accessibility label for screen readers */\n ariaLabel: string;\n}\n\nconst approvalConfig: Record<SupportTicketApproval, ApprovalBadgeConfig> = {\n PENDING: {\n color: 'badge-warning',\n text: 'Pending',\n ariaLabel: 'Approval: Awaiting staff decision',\n },\n APPROVED: {\n color: 'badge-success',\n text: 'Approved',\n ariaLabel: 'Approval: Approved by staff',\n },\n REJECTED: {\n color: 'badge-error',\n text: 'Rejected',\n ariaLabel: 'Approval: Rejected by staff',\n },\n INTERNAL: {\n color: 'badge-info',\n text: 'Internal',\n ariaLabel: 'Approval: Internal staff ticket',\n },\n};\n\nconst getApprovalConfig = (approvalStatus: SupportTicketApproval): ApprovalBadgeConfig => {\n const config = approvalConfig[approvalStatus];\n if (!config) {\n return {\n color: 'badge-neutral',\n text: approvalStatus || 'Unknown',\n ariaLabel: `Approval: ${approvalStatus || 'Unknown status'}`,\n };\n }\n return config;\n};\n\nconst config = computed(() => getApprovalConfig(props.approvalStatus));\n\nconst badgeClasses = computed(() => {\n const baseClasses = ['badge', 'text-xs'];\n\n // Add color class\n baseClasses.push(config.value.color);\n\n // Add size class with responsive text sizing\n if (props.size === 'sm') {\n baseClasses.push('badge-sm', 'text-xs');\n } else if (props.size === 'lg') {\n baseClasses.push('badge-lg', 'text-sm');\n } else {\n // md size - responsive text\n baseClasses.push('text-xs', 'sm:text-sm');\n }\n\n // Add variant class\n if (props.variant === 'outline') {\n baseClasses.push('badge-outline');\n }\n\n return baseClasses.join(' ');\n});\n\nconst displayText = computed(() => config.value.text);\nconst ariaLabel = computed(() => config.value.ariaLabel);\n</script>\n","<template>\n <div :class=\"badgeClasses\" :aria-label=\"ariaLabel\" role=\"status\">\n {{ displayText }}\n </div>\n</template>\n\n<script setup lang=\"ts\">\n/**\n * SupportTicketDevLifecycleBadge - A reusable Vue component for displaying support ticket dev lifecycle\n * as color-coded badges with consistent DaisyUI styling and accessibility features.\n *\n * @example\n * <SupportTicketDevLifecycleBadge :devLifecycle=\"'DEVELOPMENT'\" size=\"md\" />\n * <SupportTicketDevLifecycleBadge :devLifecycle=\"'TESTING'\" size=\"sm\" variant=\"outline\" />\n */\nimport type { SupportTicketDevLifecycle } from '@dragonmastery/dragoncore-shared';\nimport { computed } from 'vue';\n\n/**\n * Props for the SupportTicketDevLifecycleBadge component\n */\ninterface Props {\n /** The support ticket dev lifecycle to display */\n devLifecycle: SupportTicketDevLifecycle;\n /** Size of the badge - defaults to 'md' */\n size?: 'sm' | 'md' | 'lg';\n /** Visual variant of the badge - defaults to 'default' */\n variant?: 'default' | 'outline';\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n size: 'md',\n variant: 'default',\n});\n\n/**\n * Configuration for each dev lifecycle badge\n */\ninterface DevLifecycleBadgeConfig {\n /** DaisyUI badge color class */\n color: string;\n /** Display text for the badge */\n text: string;\n /** Accessibility label for screen readers */\n ariaLabel: string;\n}\n\nconst devLifecycleConfig: Record<SupportTicketDevLifecycle, DevLifecycleBadgeConfig> = {\n PENDING: {\n color: 'badge-neutral',\n text: 'Pending',\n ariaLabel: 'Dev Stage: Pending',\n },\n BACKLOG: {\n color: 'badge-info',\n text: 'Backlog',\n ariaLabel: 'Dev Stage: In backlog',\n },\n PLANNING: {\n color: 'badge-info',\n text: 'Planning',\n ariaLabel: 'Dev Stage: Planning phase',\n },\n DEVELOPMENT: {\n color: 'badge-secondary',\n text: 'Dev',\n ariaLabel: 'Dev Stage: In development',\n },\n CODE_REVIEW: {\n color: 'badge-secondary',\n text: 'Review',\n ariaLabel: 'Dev Stage: Code review',\n },\n TESTING: {\n color: 'badge-warning',\n text: 'Testing',\n ariaLabel: 'Dev Stage: Testing phase',\n },\n STAGING: {\n color: 'badge-warning',\n text: 'Staging',\n ariaLabel: 'Dev Stage: On staging',\n },\n PO_APPROVAL: {\n color: 'badge-warning',\n text: 'PO Review',\n ariaLabel: 'Dev Stage: Awaiting PO approval',\n },\n DEPLOYED: {\n color: 'badge-success',\n text: 'Live',\n ariaLabel: 'Dev Stage: Deployed to production',\n },\n CANCELLED: {\n color: 'badge-error',\n text: 'Cancelled',\n ariaLabel: 'Dev Stage: Cancelled',\n },\n};\n\nconst getDevLifecycleConfig = (\n devLifecycle: SupportTicketDevLifecycle,\n): DevLifecycleBadgeConfig => {\n const config = devLifecycleConfig[devLifecycle];\n if (!config) {\n return {\n color: 'badge-neutral',\n text: devLifecycle || 'Unknown',\n ariaLabel: `Dev Stage: ${devLifecycle || 'Unknown stage'}`,\n };\n }\n return config;\n};\n\nconst config = computed(() => getDevLifecycleConfig(props.devLifecycle));\n\nconst badgeClasses = computed(() => {\n const baseClasses = ['badge', 'text-xs'];\n\n // Add color class\n baseClasses.push(config.value.color);\n\n // Add size class with responsive text sizing\n if (props.size === 'sm') {\n baseClasses.push('badge-sm', 'text-xs');\n } else if (props.size === 'lg') {\n baseClasses.push('badge-lg', 'text-sm');\n } else {\n // md size - responsive text\n baseClasses.push('text-xs', 'sm:text-sm');\n }\n\n // Add variant class\n if (props.variant === 'outline') {\n baseClasses.push('badge-outline');\n }\n\n return baseClasses.join(' ');\n});\n\nconst displayText = computed(() => config.value.text);\nconst ariaLabel = computed(() => config.value.ariaLabel);\n</script>\n","<template>\n <div>\n <!-- Loading State -->\n <div v-if=\"loading\" class=\"flex items-center gap-2\">\n <span class=\"loading loading-spinner loading-sm\"></span>\n <span class=\"text-sm\">Loading customer balance...</span>\n </div>\n\n <!-- Error State -->\n <div v-else-if=\"error\" class=\"alert alert-error alert-sm\">\n <span class=\"text-xs\">Failed to load customer balance</span>\n </div>\n\n <!-- Balance Display -->\n <div v-else-if=\"creditBalance\" class=\"space-y-2\">\n <div class=\"grid grid-cols-2 gap-2 text-sm\">\n <div>\n <span class=\"text-base-content/60\">Monthly:</span>\n <span class=\"font-bold ml-2\">{{\n formatStaffCreditValue(creditBalance.monthly)\n }}</span>\n </div>\n <div>\n <span class=\"text-base-content/60\">Rollover:</span>\n <span class=\"font-bold ml-2\">{{\n formatStaffCreditValue(creditBalance.rollover)\n }}</span>\n </div>\n </div>\n <div\n class=\"flex items-center justify-between p-2 rounded\"\n :class=\"{\n 'bg-success/20': totalAvailable > 0,\n 'bg-error/20': totalAvailable === 0,\n }\"\n >\n <span class=\"text-sm font-medium\">Total Available:</span>\n <span\n class=\"font-bold\"\n :class=\"{\n 'text-success': totalAvailable > 0,\n 'text-error': totalAvailable === 0,\n }\"\n >{{ formatStaffCreditValue(totalAvailable.toString()) }}</span\n >\n </div>\n\n <!-- Warning if no balance -->\n <div v-if=\"totalAvailable === 0\" class=\"alert alert-warning alert-sm\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n class=\"stroke-current shrink-0 h-4 w-4\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n >\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"2\"\n 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\"\n />\n </svg>\n <span class=\"text-xs\">Customer has insufficient credits</span>\n </div>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { useQuery } from '../../../../composables/useQuery';\nimport { computed } from 'vue';\nimport { formatStaffCreditValue } from '../../utils/creditValueFormatter';\n\n// Since there's only one customer in the system, admins see the same global balance\nconst { data, loading, error } = useQuery((api) => api.customer.getCreditBalance(), {\n staleTime: 2 * 60 * 1000,\n});\n\nconst creditBalance = computed(() => data.value ?? null);\n\nconst totalAvailable = computed(() => {\n if (!creditBalance.value) return 0;\n const monthly = parseFloat(creditBalance.value.monthly) || 0;\n const rollover = parseFloat(creditBalance.value.rollover) || 0;\n return monthly + rollover;\n});\n</script>\n","<template>\n <!-- Approve/Reject Section (PENDING only) -->\n <ZiniaContainer v-if=\"props.support_ticket.approval_status === 'PENDING'\">\n <h3 class=\"card-title text-base sm:text-lg\">Approve or Reject</h3>\n\n <div\n v-if=\"\n formatStaffCreditValue(\n props.support_ticket.credit_value,\n props.support_ticket.approval_status,\n ) === 'TBD'\n \"\n class=\"alert alert-warning py-2\"\n >\n <div>\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n class=\"stroke-current shrink-0 h-5 w-5\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n >\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"2\"\n 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\"\n />\n </svg>\n <span class=\"text-xs sm:text-sm\">You must set an estimate before approving</span>\n </div>\n </div>\n\n <div v-else class=\"space-y-3\">\n <div class=\"alert alert-info py-2\">\n <div>\n <span class=\"text-xs sm:text-sm\"\n >Estimate:\n {{\n formatStaffCreditValue(\n props.support_ticket.credit_value,\n props.support_ticket.approval_status,\n )\n }}\n credits</span\n >\n </div>\n </div>\n\n <!-- Show Customer's Credit Balance -->\n <div class=\"bg-base-100 rounded-lg p-3\">\n <h4 class=\"text-xs sm:text-sm font-medium mb-2\">Customer Balance Check</h4>\n <CustomerCreditBalance />\n </div>\n </div>\n\n <div class=\"flex flex-col sm:flex-row gap-2 sm:gap-3 justify-end mt-4\">\n <button\n class=\"btn btn-error btn-outline w-full sm:w-auto order-2 sm:order-1\"\n @click.prevent=\"showRejectModal\"\n :disabled=\"isApproving || isRejecting\"\n >\n <span v-if=\"isRejecting\" class=\"loading loading-spinner loading-sm mr-2\"></span>\n {{ isRejecting ? 'Rejecting...' : 'Reject' }}\n </button>\n <button\n class=\"btn btn-success w-full sm:w-auto order-1 sm:order-2\"\n @click.prevent=\"showApproveModal\"\n :disabled=\"\n formatStaffCreditValue(\n props.support_ticket.credit_value,\n props.support_ticket.approval_status,\n ) === 'TBD' ||\n isApproving ||\n isRejecting\n \"\n >\n <span v-if=\"isApproving\" class=\"loading loading-spinner loading-sm mr-2\"></span>\n {{ isApproving ? 'Approving...' : 'Approve & Deduct' }}\n </button>\n </div>\n\n <div v-if=\"error\" class=\"alert alert-error mt-2 py-2\">\n <span class=\"text-sm\">{{ error }}</span>\n </div>\n </ZiniaContainer>\n\n <!-- Revert Section (APPROVED/REJECTED only) -->\n <ZiniaContainer\n v-else-if=\"\n props.support_ticket.approval_status === 'APPROVED' ||\n props.support_ticket.approval_status === 'REJECTED'\n \"\n >\n <h3 class=\"card-title text-base sm:text-lg\">Revert Decision</h3>\n\n <div class=\"alert alert-warning py-2\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n class=\"stroke-current shrink-0 h-5 w-5\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n >\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"2\"\n 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\"\n />\n </svg>\n <div class=\"text-xs sm:text-sm\">\n <div class=\"font-medium mb-1\">Admin Action Required</div>\n <div>\n This support ticket is currently\n <span class=\"font-semibold\">{{ props.support_ticket.approval_status }}</span\n >. You can revert it back to PENDING status.\n </div>\n </div>\n </div>\n\n <div\n v-if=\"\n formatStaffCreditValue(\n props.support_ticket.credit_value,\n props.support_ticket.approval_status,\n ) !== 'TBD' &&\n formatStaffCreditValue(\n props.support_ticket.credit_value,\n props.support_ticket.approval_status,\n ) !== 'N/A'\n \"\n class=\"alert alert-info py-2\"\n >\n <div class=\"text-xs sm:text-sm\">\n Credits:\n {{\n formatStaffCreditValue(\n props.support_ticket.credit_value,\n props.support_ticket.approval_status,\n )\n }}\n will be refunded to customer\n </div>\n </div>\n\n <div class=\"flex mt-4\">\n <button\n class=\"btn btn-warning w-full sm:w-auto\"\n @click.prevent=\"showRevertModal\"\n :disabled=\"isReverting\"\n >\n <span v-if=\"isReverting\" class=\"loading loading-spinner loading-sm mr-2\"></span>\n {{ isReverting ? 'Reverting...' : 'Revert to PENDING' }}\n </button>\n </div>\n\n <div v-if=\"error\" class=\"alert alert-error mt-2 py-2\">\n <span class=\"text-sm\">{{ error }}</span>\n </div>\n </ZiniaContainer>\n\n <!-- Confirmation Modal -->\n <dialog ref=\"confirmModal\" class=\"modal\">\n <div class=\"modal-box\">\n <h3 class=\"font-bold text-lg\">{{ modalTitle }}</h3>\n <p class=\"py-4 whitespace-pre-line\">{{ modalMessage }}</p>\n <div class=\"modal-action\">\n <button class=\"btn btn-ghost\" @click=\"closeModal\">Cancel</button>\n <button class=\"btn\" :class=\"modalButtonClass\" @click=\"() => modalCallback?.()\">\n {{ modalButtonText }}\n </button>\n </div>\n </div>\n <form method=\"dialog\" class=\"modal-backdrop\">\n <button @click=\"closeModal\">close</button>\n </form>\n </dialog>\n</template>\n\n<script setup lang=\"ts\">\nimport ZiniaContainer from '../../../../components/ui/ZiniaContainer.vue';\nimport { useMutation } from '../../../../composables/useMutation';\nimport type { StaffSupportTicketReadDto } from '@dragonmastery/dragoncore-shared';\nimport { ref } from 'vue';\nimport { toast } from 'vue3-toastify';\nimport { formatStaffCreditValue } from '../../utils/creditValueFormatter';\nimport CustomerCreditBalance from './CustomerCreditBalance.vue';\n\ntype SupportTicket = StaffSupportTicketReadDto;\n\nconst props = defineProps<{ support_ticket: SupportTicket }>();\nconst emit = defineEmits(['update']);\n\nconst error = ref<string | null>(null);\nconst confirmModal = ref<HTMLDialogElement | null>(null);\nconst modalTitle = ref('');\nconst modalMessage = ref('');\nconst modalButtonText = ref('');\nconst modalButtonClass = ref('');\nconst modalCallback = ref<(() => Promise<void>) | null>(null);\n\nconst { mutate: approveSupportTicket, loading: isApproving } = useMutation(\n (api, input: { id: string }) => api.supportTickets.approveTicket(input),\n { invalidate: /^support-tickets?:/ },\n);\nconst { mutate: rejectSupportTicket, loading: isRejecting } = useMutation(\n (api, input: { id: string }) => api.supportTickets.rejectTicket(input),\n { invalidate: /^support-tickets?:/ },\n);\nconst { mutate: revertSupportTicket, loading: isReverting } = useMutation(\n (api, input: { id: string }) => api.supportTickets.revertTicket(input),\n { invalidate: /^support-tickets?:/ },\n);\n\nconst showApproveModal = () => {\n const creditDisplay = formatStaffCreditValue(\n props.support_ticket.credit_value,\n props.support_ticket.approval_status,\n );\n const credits =\n creditDisplay === 'TBD' || creditDisplay === 'N/A' ? 0 : parseFloat(creditDisplay);\n modalTitle.value = 'Approve Support Ticket?';\n modalMessage.value =\n `This will:\\n\\n` +\n `• Deduct ${credits.toFixed(2)} credits from customer\\n` +\n `• Lock the support ticket item\\n` +\n `• Start development workflow\\n\\n` +\n `This action cannot be undone.`;\n modalButtonText.value = 'Approve & Deduct';\n modalButtonClass.value = 'btn-success';\n modalCallback.value = handleApprove;\n confirmModal.value?.showModal();\n};\n\nconst showRejectModal = () => {\n modalTitle.value = 'Reject Support Ticket?';\n modalMessage.value =\n `This will:\\n\\n` +\n `• Reject this support ticket request\\n` +\n `• Lock the support ticket item\\n` +\n `• No credits will be deducted\\n\\n` +\n `The customer will be notified.`;\n modalButtonText.value = 'Reject';\n modalButtonClass.value = 'btn-error';\n modalCallback.value = handleReject;\n confirmModal.value?.showModal();\n};\n\nconst showRevertModal = () => {\n modalTitle.value = 'Revert Support Ticket to PENDING?';\n const creditDisplay = formatStaffCreditValue(\n props.support_ticket.credit_value,\n props.support_ticket.approval_status,\n );\n const hasCredits = creditDisplay !== 'TBD' && creditDisplay !== 'N/A';\n modalMessage.value =\n `This will:\\n\\n` +\n `• Change status back to PENDING\\n` +\n `• Unlock the support ticket item\\n` +\n (hasCredits ? `• Refund ${creditDisplay} credits to customer\\n` : '') +\n `• Allow the customer to edit again\\n\\n` +\n `Are you sure you want to revert this decision?`;\n modalButtonText.value = 'Revert to PENDING';\n modalButtonClass.value = 'btn-warning';\n modalCallback.value = handleRevert;\n confirmModal.value?.showModal();\n};\n\nconst closeModal = () => {\n confirmModal.value?.close();\n modalCallback.value = null;\n};\n\nconst handleApprove = async () => {\n error.value = null;\n closeModal();\n\n try {\n const response = await approveSupportTicket({ id: props.support_ticket.id });\n\n toast.success(\n `Support Ticket approved! ${formatStaffCreditValue(props.support_ticket.credit_value, props.support_ticket.approval_status)} credits deducted.`,\n );\n\n emit('update', response);\n } catch (e) {\n const errorMessage = e instanceof Error ? e.message : 'An unknown error occurred.';\n error.value = errorMessage;\n toast.error(errorMessage);\n }\n};\n\nconst handleReject = async () => {\n error.value = null;\n closeModal();\n\n try {\n const response = await rejectSupportTicket({ id: props.support_ticket.id });\n\n toast.info('Support Ticket rejected.');\n\n emit('update', response);\n } catch (e) {\n const errorMessage = e instanceof Error ? e.message : 'An unknown error occurred.';\n error.value = errorMessage;\n toast.error(errorMessage);\n }\n};\n\nconst handleRevert = async () => {\n error.value = null;\n closeModal();\n\n try {\n const response = await revertSupportTicket({ id: props.support_ticket.id });\n\n const creditDisplay = formatStaffCreditValue(\n props.support_ticket.credit_value,\n props.support_ticket.approval_status,\n );\n const refundMessage =\n creditDisplay !== 'TBD' && creditDisplay !== 'N/A'\n ? ` ${creditDisplay} credits refunded.`\n : '';\n\n toast.success(`Support Ticket reverted to PENDING.${refundMessage}`);\n\n emit('update', response);\n } catch (e) {\n const errorMessage = e instanceof Error ? e.message : 'An unknown error occurred.';\n error.value = errorMessage;\n toast.error(errorMessage);\n }\n};\n</script>\n","<template>\n <!-- Cancel Internal Task Section (INTERNAL only, not CANCELLED) -->\n <ZiniaContainer\n v-if=\"\n props.support_ticket.approval_status === 'INTERNAL' &&\n props.support_ticket.dev_lifecycle !== 'CANCELLED'\n \"\n >\n <h3 class=\"card-title text-base sm:text-lg\">Cancel Internal Task</h3>\n\n <div class=\"alert alert-warning py-2\">\n <div class=\"flex flex-col gap-2\">\n <span class=\"font-semibold text-sm\">What happens when you cancel:</span>\n <ul class=\"text-xs sm:text-sm space-y-1 ml-4 list-disc\">\n <li>Sets dev lifecycle to CANCELLED</li>\n <li>Records completion timestamp</li>\n <li>Task is marked as terminal state</li>\n <li>No credit impact (internal tasks have no credits)</li>\n </ul>\n </div>\n </div>\n\n <div class=\"flex justify-end mt-4\">\n <button\n class=\"btn btn-error w-full sm:w-auto\"\n @click.prevent=\"showCancelModal\"\n :disabled=\"isCancelling\"\n >\n <span v-if=\"isCancelling\" class=\"loading loading-spinner loading-sm mr-2\"></span>\n {{ isCancelling ? 'Cancelling...' : 'Cancel Internal Task' }}\n </button>\n </div>\n\n <div v-if=\"error\" class=\"alert alert-error mt-2 py-2\">\n <span class=\"text-sm\">{{ error }}</span>\n </div>\n </ZiniaContainer>\n\n <!-- Confirmation Modal -->\n <dialog ref=\"confirmModal\" class=\"modal\">\n <div class=\"modal-box\">\n <h3 class=\"font-bold text-lg\">{{ modalTitle }}</h3>\n <p class=\"py-4 whitespace-pre-line\">{{ modalMessage }}</p>\n <div class=\"modal-action\">\n <button class=\"btn btn-ghost\" @click=\"closeModal\">Cancel</button>\n <button class=\"btn btn-error\" @click=\"() => modalCallback?.()\">\n {{ modalButtonText }}\n </button>\n </div>\n </div>\n <form method=\"dialog\" class=\"modal-backdrop\">\n <button @click=\"closeModal\">close</button>\n </form>\n </dialog>\n</template>\n\n<script setup lang=\"ts\">\nimport ZiniaContainer from '../../../../components/ui/ZiniaContainer.vue';\nimport { useMutation } from '../../../../composables/useMutation';\nimport type { StaffSupportTicketReadDto } from '@dragonmastery/dragoncore-shared';\nimport { ref } from 'vue';\nimport { toast } from 'vue3-toastify';\n\ntype SupportTicket = StaffSupportTicketReadDto;\n\nconst props = defineProps<{ support_ticket: SupportTicket }>();\nconst emit = defineEmits(['update']);\n\nconst error = ref<string | null>(null);\nconst confirmModal = ref<HTMLDialogElement | null>(null);\nconst modalTitle = ref('');\nconst modalMessage = ref('');\nconst modalButtonText = ref('');\nconst modalCallback = ref<(() => Promise<void>) | null>(null);\n\nconst { mutate: cancelInternalTask, loading: isCancelling } = useMutation(\n (api, input: { id: string }) => api.supportTickets.cancelInternalTask(input),\n { invalidate: /^support-tickets?:/ },\n);\n\nconst showCancelModal = () => {\n modalTitle.value = 'Cancel Internal Task?';\n modalMessage.value =\n `This will:\\n\\n` +\n `• Set dev lifecycle to CANCELLED\\n` +\n `• Record completion timestamp\\n` +\n `• Mark task as complete (terminal state)\\n\\n` +\n `This action cannot be undone. The task will remain in the system as cancelled.`;\n modalButtonText.value = 'Cancel Task';\n modalCallback.value = handleCancel;\n confirmModal.value?.showModal();\n};\n\nconst handleCancel = async () => {\n error.value = null;\n try {\n const result = await cancelInternalTask({ id: props.support_ticket.id });\n\n toast.success('✅ Internal task cancelled successfully');\n closeModal();\n emit('update', result);\n } catch (err) {\n error.value = err instanceof Error ? err.message : 'Failed to cancel task';\n toast.error(`❌ ${error.value}`);\n }\n};\n\nconst closeModal = () => {\n confirmModal.value?.close();\n};\n</script>\n","<template>\n <ZiniaForm\n v-if=\"\n ['APPROVED', 'INTERNAL'].includes(props.support_ticket.approval_status) && !isCompleted\n \"\n @handleSubmit=\"handleComplete\"\n @success=\"handleSuccess\"\n @error=\"handleError\"\n >\n <h3 class=\"card-title text-base sm:text-lg\">Complete Support Ticket</h3>\n <p class=\"text-xs sm:text-sm text-base-content/70 mb-4\">\n Customer was charged\n <span class=\"font-semibold\">{{\n formatStaffCreditValue(\n props.support_ticket.credit_value,\n props.support_ticket.approval_status,\n )\n }}</span>\n credits\n </p>\n\n <!-- Delivered Value Field -->\n <zinia.DeliveredValueField\n label=\"Actual Effort Delivered\"\n placeholder=\"100.00\"\n hint=\"How much effort did it actually take?\"\n />\n\n <!-- Variance Indicator -->\n <div\n v-if=\"\n form.values.delivered_value &&\n formatStaffCreditValue(\n props.support_ticket.credit_value,\n props.support_ticket.approval_status,\n ) !== 'TBD' &&\n formatStaffCreditValue(\n props.support_ticket.credit_value,\n props.support_ticket.approval_status,\n ) !== 'N/A'\n \"\n class=\"alert py-2\"\n :class=\"getComparisonClass()\"\n >\n <span class=\"text-xs sm:text-sm\">{{ getComparisonMessage() }}</span>\n </div>\n\n <ZiniaSubmitButton submitText=\"Mark as Completed\" submittingText=\"Completing...\" />\n </ZiniaForm>\n\n <ZiniaContainer v-else-if=\"isCompleted\">\n <h3 class=\"card-title text-success text-base sm:text-lg\">✅ Completed</h3>\n\n <div class=\"grid grid-cols-2 gap-2 sm:gap-4 mt-2\">\n <div class=\"bg-base-100 p-3 rounded-lg\">\n <div class=\"text-xs text-base-content/70\">Customer Charged</div>\n <div class=\"text-lg sm:text-xl font-bold text-primary\">\n {{\n formatStaffCreditValue(\n props.support_ticket.credit_value,\n props.support_ticket.approval_status,\n )\n }}\n </div>\n <div class=\"text-xs text-base-content/60\">Fixed price</div>\n </div>\n\n <div class=\"bg-base-100 p-3 rounded-lg\">\n <div class=\"text-xs text-base-content/70\">Actual Effort</div>\n <div class=\"text-lg sm:text-xl font-bold\" :class=\"getActualClass()\">\n {{ props.support_ticket.delivered_value ?? 'N/A' }}\n </div>\n <div class=\"text-xs text-base-content/60\">\n {{ getVarianceLabel() }}\n </div>\n </div>\n </div>\n </ZiniaContainer>\n</template>\n\n<script setup lang=\"ts\">\nimport { useMutation } from '../../../../composables/useMutation';\nimport {\n CompleteSupportTicketSchema,\n type StaffSupportTicketReadDto,\n} from '@dragonmastery/dragoncore-shared';\nimport ZiniaContainer from '../../../../components/ui/ZiniaContainer.vue';\nimport { useForm, withMetadata } from '@dragonmastery/zinia-forms-core';\nimport { computed } from 'vue';\nimport { toast } from 'vue3-toastify';\nimport { formatStaffCreditValue } from '../../utils/creditValueFormatter';\n\ntype SupportTicket = StaffSupportTicketReadDto;\n\nconst props = defineProps<{ support_ticket: SupportTicket }>();\nconst emit = defineEmits(['update']);\n\n// Use shared schema for completing support_ticket\n// Note: We only need delivered_value field (id is handled by mutation)\nconst completeSupportTicketFormSchema = CompleteSupportTicketSchema.pick({\n delivered_value: true,\n});\n\nconst completeSupportTicketSchemaWithMetadata = withMetadata(\n completeSupportTicketFormSchema,\n 'completeSupportTicketSchema',\n {\n delivered_value: {\n inputType: 'text',\n placeholder: '100.00',\n },\n },\n);\n\n// Initialize form with estimate as default\nconst { form, zinia, ZiniaSubmitButton, ZiniaForm } = useForm(\n completeSupportTicketSchemaWithMetadata,\n {\n storeName: `complete-support_ticket-${props.support_ticket.id}`,\n persistToLocalStorage: false,\n renderStyle: 'daisy_ui',\n initialValues: {\n delivered_value:\n formatStaffCreditValue(\n props.support_ticket.credit_value,\n props.support_ticket.approval_status,\n ) === 'TBD' ||\n formatStaffCreditValue(\n props.support_ticket.credit_value,\n props.support_ticket.approval_status,\n ) === 'N/A'\n ? '0.00'\n : formatStaffCreditValue(\n props.support_ticket.credit_value,\n props.support_ticket.approval_status,\n ),\n },\n },\n);\n\nconst { mutate: completeSupportTicket } = useMutation(\n (api, input: { id: string; delivered_value: string }) =>\n api.supportTickets.completeTicket(input),\n { invalidate: /^support-tickets?:/ },\n);\n\nconst isCompleted = computed(() => props.support_ticket.status === 'COMPLETED');\n\nconst getComparisonClass = () => {\n const creditDisplay = formatStaffCreditValue(\n props.support_ticket.credit_value,\n props.support_ticket.approval_status,\n );\n if (!form.values.delivered_value || creditDisplay === 'TBD' || creditDisplay === 'N/A')\n return '';\n const actual = parseFloat(form.values.delivered_value);\n const final = parseFloat(creditDisplay);\n if (isNaN(actual) || isNaN(final)) return '';\n\n if (actual > final) return 'alert-warning';\n if (actual === final) return 'alert-success';\n return 'alert-info';\n};\n\nconst getComparisonMessage = () => {\n const creditDisplay = formatStaffCreditValue(\n props.support_ticket.credit_value,\n props.support_ticket.approval_status,\n );\n if (!form.values.delivered_value || creditDisplay === 'TBD' || creditDisplay === 'N/A')\n return '';\n const actual = parseFloat(form.values.delivered_value);\n const final = parseFloat(creditDisplay);\n if (isNaN(actual) || isNaN(final)) return '';\n\n const variance = (((actual - final) / final) * 100).toFixed(1);\n\n if (actual > final) {\n return `📈 Took ${(actual - final).toFixed(2)} more effort (+${variance}%)`;\n } else if (actual === final) {\n return '🎯 Exactly on estimate!';\n } else {\n return `📉 Took ${(final - actual).toFixed(2)} less effort (${variance}%)`;\n }\n};\n\nconst getActualClass = () => {\n const creditDisplay = formatStaffCreditValue(\n props.support_ticket.credit_value,\n props.support_ticket.approval_status,\n );\n if (\n !props.support_ticket.delivered_value ||\n creditDisplay === 'TBD' ||\n creditDisplay === 'N/A'\n )\n return '';\n const actual = parseFloat(props.support_ticket.delivered_value);\n const final = parseFloat(creditDisplay);\n if (isNaN(actual) || isNaN(final)) return '';\n\n if (actual > final) return 'text-warning';\n if (actual === final) return 'text-success';\n return 'text-info';\n};\n\nconst getVarianceLabel = () => {\n const creditDisplay = formatStaffCreditValue(\n props.support_ticket.credit_value,\n props.support_ticket.approval_status,\n );\n if (\n !props.support_ticket.delivered_value ||\n creditDisplay === 'TBD' ||\n creditDisplay === 'N/A'\n )\n return 'Work performed';\n const actual = parseFloat(props.support_ticket.delivered_value);\n const final = parseFloat(creditDisplay);\n if (isNaN(actual) || isNaN(final)) return 'Work performed';\n\n const diff = actual - final;\n const variance = ((diff / final) * 100).toFixed(1);\n\n if (diff > 0) return `+${variance}% over estimate`;\n if (diff < 0) return `${variance}% under estimate`;\n return 'On target';\n};\n\n// Handle form submission\nconst handleComplete = async (formData: { delivered_value: string }) => {\n const response = await completeSupportTicket({\n id: props.support_ticket.id,\n delivered_value: formData.delivered_value,\n });\n\n if (!response) {\n throw new Error('Failed to complete support ticket');\n }\n\n return response;\n};\n\n// Handle successful submission\nconst handleSuccess = () => {\n toast.success('SupportTicket marked as completed!', {});\n emit('update');\n};\n\n// Handle submission error\nconst handleError = (error: Error | unknown) => {\n const errorMessage = error instanceof Error ? error.message : 'An unknown error occurred.';\n toast.error(errorMessage);\n};\n</script>\n","<template>\n <!-- Convert to Customer SupportTicket Section (INTERNAL only) -->\n <ZiniaContainer v-if=\"props.support_ticket.approval_status === 'INTERNAL'\">\n <h3 class=\"card-title text-base sm:text-lg\">Convert to Customer SupportTicket</h3>\n\n <div class=\"alert alert-info py-2\">\n <div class=\"flex flex-col gap-2\">\n <span class=\"font-semibold text-sm\">What happens when you convert:</span>\n <ul class=\"text-xs sm:text-sm space-y-1 ml-4 list-disc\">\n <li>Changes status from internal task to customer support_ticket</li>\n <li>Requires approval workflow (goes to PENDING)</li>\n <li>Clears dev lifecycle (back to planning)</li>\n <li>Staff must set credit estimate before approval</li>\n </ul>\n </div>\n </div>\n\n <div class=\"flex justify-end mt-4\">\n <button\n class=\"btn btn-primary w-full sm:w-auto\"\n @click.prevent=\"showConvertModal\"\n :disabled=\"isConverting\"\n >\n <span v-if=\"isConverting\" class=\"loading loading-spinner loading-sm mr-2\"></span>\n {{ isConverting ? 'Converting...' : 'Convert to Customer SupportTicket' }}\n </button>\n </div>\n\n <div v-if=\"error\" class=\"alert alert-error mt-2 py-2\">\n <span class=\"text-sm\">{{ error }}</span>\n </div>\n </ZiniaContainer>\n\n <!-- Confirmation Modal -->\n <dialog ref=\"confirmModal\" class=\"modal\">\n <div class=\"modal-box\">\n <h3 class=\"font-bold text-lg\">{{ modalTitle }}</h3>\n <p class=\"py-4 whitespace-pre-line\">{{ modalMessage }}</p>\n <div class=\"modal-action\">\n <button class=\"btn btn-ghost\" @click=\"closeModal\">Cancel</button>\n <button class=\"btn btn-primary\" @click=\"() => modalCallback?.()\">\n {{ modalButtonText }}\n </button>\n </div>\n </div>\n <form method=\"dialog\" class=\"modal-backdrop\">\n <button @click=\"closeModal\">close</button>\n </form>\n </dialog>\n</template>\n\n<script setup lang=\"ts\">\nimport ZiniaContainer from '../../../../components/ui/ZiniaContainer.vue';\nimport { useMutation } from '../../../../composables/useMutation';\nimport type { StaffSupportTicketReadDto } from '@dragonmastery/dragoncore-shared';\nimport { ref } from 'vue';\nimport { toast } from 'vue3-toastify';\n\nconst props = defineProps<{ support_ticket: StaffSupportTicketReadDto }>();\nconst emit = defineEmits(['update']);\n\nconst error = ref<string | null>(null);\nconst confirmModal = ref<HTMLDialogElement | null>(null);\nconst modalTitle = ref('');\nconst modalMessage = ref('');\nconst modalButtonText = ref('');\nconst modalCallback = ref<(() => Promise<void>) | null>(null);\n\nconst { mutate: convertToCustomer, loading: isConverting } = useMutation(\n (api, input: { id: string }) => api.supportTickets.convertToCustomer(input.id),\n { invalidate: /^support-tickets?:/ },\n);\n\nconst showConvertModal = () => {\n modalTitle.value = 'Convert to Customer Support Ticket?';\n modalMessage.value =\n `This will:\\n\\n` +\n `• Change status to PENDING\\n` +\n `• Require approval workflow\\n` +\n `• Clear dev lifecycle stage\\n` +\n `• Reset to planning phase\\n\\n` +\n `You'll need to set a credit estimate before the support ticket can be approved.`;\n modalButtonText.value = 'Convert to Customer Support Ticket';\n modalCallback.value = handleConvert;\n confirmModal.value?.showModal();\n};\n\nconst handleConvert = async () => {\n error.value = null;\n try {\n const result = await convertToCustomer({ id: props.support_ticket.id });\n\n toast.success('✅ Converted to customer support ticket successfully');\n closeModal();\n emit('update', result);\n } catch (err) {\n error.value = err instanceof Error ? err.message : 'Failed to convert';\n toast.error(`❌ ${error.value}`);\n }\n};\n\nconst closeModal = () => {\n confirmModal.value?.close();\n};\n</script>\n","<template>\n <!-- Convert to Internal Section (PENDING only) -->\n <ZiniaContainer v-if=\"props.support_ticket.approval_status === 'PENDING'\">\n <h3 class=\"card-title text-base sm:text-lg\">Convert to Internal Task</h3>\n\n <div class=\"alert alert-info py-2\">\n <div class=\"flex flex-col gap-2\">\n <span class=\"font-semibold text-sm\">What happens when you convert:</span>\n <ul class=\"text-xs sm:text-sm space-y-1 ml-4 list-disc\">\n <li>Changes status from customer support_ticket to internal task</li>\n <li>Bypasses approval workflow entirely</li>\n <li>Automatically clears any credit estimates (internal tasks = no credits)</li>\n <li>Can start development immediately</li>\n </ul>\n </div>\n </div>\n\n <div class=\"flex justify-end mt-4\">\n <button\n class=\"btn btn-primary w-full sm:w-auto\"\n @click.prevent=\"showConvertModal\"\n :disabled=\"isConverting\"\n >\n <span v-if=\"isConverting\" class=\"loading loading-spinner loading-sm mr-2\"></span>\n {{ isConverting ? 'Converting...' : 'Convert to Internal Task' }}\n </button>\n </div>\n\n <div v-if=\"error\" class=\"alert alert-error mt-2 py-2\">\n <span class=\"text-sm\">{{ error }}</span>\n </div>\n </ZiniaContainer>\n\n <!-- Confirmation Modal -->\n <dialog ref=\"confirmModal\" class=\"modal\">\n <div class=\"modal-box\">\n <h3 class=\"font-bold text-lg\">{{ modalTitle }}</h3>\n <p class=\"py-4 whitespace-pre-line\">{{ modalMessage }}</p>\n <div class=\"modal-action\">\n <button class=\"btn btn-ghost\" @click=\"closeModal\">Cancel</button>\n <button class=\"btn btn-primary\" @click=\"() => modalCallback?.()\">\n {{ modalButtonText }}\n </button>\n </div>\n </div>\n <form method=\"dialog\" class=\"modal-backdrop\">\n <button @click=\"closeModal\">close</button>\n </form>\n </dialog>\n</template>\n\n<script setup lang=\"ts\">\nimport ZiniaContainer from '../../../../components/ui/ZiniaContainer.vue';\nimport { useMutation } from '../../../../composables/useMutation';\nimport type { StaffSupportTicketReadDto } from '@dragonmastery/dragoncore-shared';\nimport { ref } from 'vue';\nimport { toast } from 'vue3-toastify';\n\ntype SupportTicket = StaffSupportTicketReadDto;\n\nconst props = defineProps<{ support_ticket: SupportTicket }>();\nconst emit = defineEmits(['update']);\n\nconst error = ref<string | null>(null);\nconst confirmModal = ref<HTMLDialogElement | null>(null);\nconst modalTitle = ref('');\nconst modalMessage = ref('');\nconst modalButtonText = ref('');\nconst modalCallback = ref<(() => Promise<void>) | null>(null);\n\nconst { mutate: convertToInternal, loading: isConverting } = useMutation(\n (api, input: { id: string }) => api.supportTickets.convertToInternal(input.id),\n { invalidate: /^support-tickets?:/ },\n);\n\nconst showConvertModal = () => {\n const hasCredits =\n props.support_ticket.credit_value && parseFloat(props.support_ticket.credit_value) > 0;\n\n modalTitle.value = 'Convert to Internal Task?';\n modalMessage.value =\n `This will:\\n\\n` +\n `• Change status to INTERNAL\\n` +\n `• Bypass customer approval workflow\\n` +\n (hasCredits ? `• Clear ${props.support_ticket.credit_value} credit estimate\\n` : '') +\n `• Set dev lifecycle to BACKLOG\\n` +\n `• Allow immediate development start\\n\\n` +\n `This change can be useful for converting customer ideas into internal improvements.`;\n modalButtonText.value = 'Convert to Internal';\n modalCallback.value = handleConvert;\n confirmModal.value?.showModal();\n};\n\nconst handleConvert = async () => {\n error.value = null;\n try {\n const result = await convertToInternal({ id: props.support_ticket.id });\n\n toast.success('✅ Converted to internal task successfully');\n closeModal();\n emit('update', result);\n } catch (err) {\n error.value = err instanceof Error ? err.message : 'Failed to convert';\n toast.error(`❌ ${error.value}`);\n }\n};\n\nconst closeModal = () => {\n confirmModal.value?.close();\n};\n</script>\n","<template>\n <!-- Reactivate Terminal Internal Task Section (INTERNAL + CANCELLED or DEPLOYED) -->\n <ZiniaContainer\n v-if=\"\n props.support_ticket.approval_status === 'INTERNAL' &&\n (props.support_ticket.dev_lifecycle === 'CANCELLED' ||\n props.support_ticket.dev_lifecycle === 'DEPLOYED')\n \"\n >\n <h3 class=\"card-title text-base sm:text-lg\">Reopen Internal Task</h3>\n\n <div class=\"alert alert-info py-2\">\n <div class=\"flex flex-col gap-2\">\n <span class=\"font-semibold text-sm\">What happens when you reopen:</span>\n <ul class=\"text-xs sm:text-sm space-y-1 ml-4 list-disc\">\n <li v-if=\"props.support_ticket.dev_lifecycle === 'CANCELLED'\">\n Sets dev lifecycle to BACKLOG (fresh start)\n </li>\n <li v-else>Sets dev lifecycle to PO_APPROVAL (ready for review/fixes)</li>\n <li>Clears completion timestamp</li>\n <li>Task becomes active again</li>\n <li>You can resume work or make additional changes</li>\n </ul>\n </div>\n </div>\n\n <div class=\"flex justify-end mt-4\">\n <button\n class=\"btn btn-success w-full sm:w-auto\"\n @click.prevent=\"showReactivateModal\"\n :disabled=\"isReactivating\"\n >\n <span v-if=\"isReactivating\" class=\"loading loading-spinner loading-sm mr-2\"></span>\n {{ isReactivating ? 'Reopening...' : 'Reopen Task' }}\n </button>\n </div>\n\n <div v-if=\"error\" class=\"alert alert-error mt-2 py-2\">\n <span class=\"text-sm\">{{ error }}</span>\n </div>\n </ZiniaContainer>\n\n <!-- Confirmation Modal -->\n <dialog ref=\"confirmModal\" class=\"modal\">\n <div class=\"modal-box\">\n <h3 class=\"font-bold text-lg\">{{ modalTitle }}</h3>\n <p class=\"py-4 whitespace-pre-line\">{{ modalMessage }}</p>\n <div class=\"modal-action\">\n <button class=\"btn btn-ghost\" @click=\"closeModal\">Cancel</button>\n <button class=\"btn btn-success\" @click=\"() => modalCallback?.()\">\n {{ modalButtonText }}\n </button>\n </div>\n </div>\n <form method=\"dialog\" class=\"modal-backdrop\">\n <button @click=\"closeModal\">close</button>\n </form>\n </dialog>\n</template>\n\n<script setup lang=\"ts\">\nimport ZiniaContainer from '../../../../components/ui/ZiniaContainer.vue';\nimport { useMutation } from '../../../../composables/useMutation';\nimport type { StaffSupportTicketReadDto } from '@dragonmastery/dragoncore-shared';\nimport { ref } from 'vue';\nimport { toast } from 'vue3-toastify';\n\ntype SupportTicket = StaffSupportTicketReadDto;\n\nconst props = defineProps<{ support_ticket: SupportTicket }>();\nconst emit = defineEmits(['update']);\n\nconst error = ref<string | null>(null);\nconst confirmModal = ref<HTMLDialogElement | null>(null);\nconst modalTitle = ref('');\nconst modalMessage = ref('');\nconst modalButtonText = ref('');\nconst modalCallback = ref<(() => Promise<void>) | null>(null);\n\nconst { mutate: reactivateInternalTask, loading: isReactivating } = useMutation(\n (api, input: { id: string }) => api.supportTickets.reactivateInternalTask(input),\n { invalidate: /^support-tickets?:/ },\n);\n\nconst showReactivateModal = () => {\n const isCancelled = props.support_ticket.dev_lifecycle === 'CANCELLED';\n const targetState = isCancelled ? 'BACKLOG' : 'PO_APPROVAL';\n\n modalTitle.value = `Reopen ${isCancelled ? 'Cancelled' : 'Deployed'} Task?`;\n modalMessage.value =\n `This will:\\n\\n` +\n `• Set dev lifecycle to ${targetState}\\n` +\n `• Clear completion timestamp\\n` +\n `• Resume task as active\\n\\n` +\n (isCancelled\n ? `Task will restart from backlog for fresh planning.`\n : `Task will go to PO approval stage for review/fixes.`);\n modalButtonText.value = 'Reopen Task';\n modalCallback.value = handleReactivate;\n confirmModal.value?.showModal();\n};\n\nconst handleReactivate = async () => {\n error.value = null;\n try {\n const result = await reactivateInternalTask({ id: props.support_ticket.id });\n\n toast.success('✅ Internal task reopened successfully');\n closeModal();\n emit('update', result);\n } catch (err) {\n error.value = err instanceof Error ? err.message : 'Failed to reactivate task';\n toast.error(`❌ ${error.value}`);\n }\n};\n\nconst closeModal = () => {\n confirmModal.value?.close();\n};\n</script>\n","<template>\n <div v-if=\"isLoading\" class=\"flex justify-center items-center p-8\">\n <span class=\"loading loading-spinner loading-lg\"></span>\n </div>\n\n <div v-else-if=\"error\" class=\"alert alert-error mb-4\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n class=\"stroke-current shrink-0 h-6 w-6\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n >\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"2\"\n d=\"M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z\"\n />\n </svg>\n <span>{{ error.message }}</span>\n </div>\n\n <!-- Deleting State -->\n <div v-else-if=\"isDeleting\" class=\"max-w-7xl mx-auto p-6\">\n <div class=\"flex flex-col items-center justify-center p-16\">\n <div class=\"loading loading-spinner loading-lg mb-4\"></div>\n <p class=\"text-lg mb-2\">Deleting support ticket...</p>\n <p class=\"text-sm text-base-content/70\">This may take a moment</p>\n </div>\n </div>\n\n <div v-else-if=\"currentSupportTicket\" class=\"space-y-6\">\n <!-- Status Badge -->\n <ZiniaContainer>\n <h3 class=\"card-title\">Current Status</h3>\n <div class=\"flex gap-4 items-center\">\n <SupportTicketApprovalBadge\n :approvalStatus=\"currentSupportTicket.approval_status\"\n size=\"lg\"\n />\n <SupportTicketDevLifecycleBadge\n v-if=\"currentSupportTicket.dev_lifecycle\"\n :devLifecycle=\"currentSupportTicket.dev_lifecycle\"\n size=\"lg\"\n />\n <div v-if=\"currentSupportTicket.is_locked\" class=\"badge badge-lg badge-warning\">\n 🔒 LOCKED\n </div>\n </div>\n </ZiniaContainer>\n\n <!-- Complete: For both APPROVED and INTERNAL (not cancelled or already deployed) -->\n <CompleteSupportTicketForm\n v-if=\"\n currentSupportTicket.dev_lifecycle !== 'CANCELLED' &&\n currentSupportTicket.dev_lifecycle !== 'DEPLOYED'\n \"\n :support_ticket=\"currentSupportTicket\"\n @update=\"handleWorkflowUpdate\"\n />\n\n <!-- Approve/Reject: Only for customer support_ticket (not INTERNAL) -->\n <ApproveRejectActions\n v-if=\"currentSupportTicket.approval_status !== 'INTERNAL'\"\n :support_ticket=\"currentSupportTicket\"\n @update=\"handleWorkflowUpdate\"\n />\n\n <!-- Convert to Internal: Only for PENDING support_ticket -->\n <ConvertToInternalWorkflow\n v-if=\"currentSupportTicket.approval_status === 'PENDING'\"\n :support_ticket=\"currentSupportTicket\"\n @update=\"handleWorkflowUpdate\"\n />\n\n <!-- Convert to Customer: Only for INTERNAL tasks that aren't cancelled or deployed -->\n <ConvertToCustomerWorkflow\n v-if=\"\n currentSupportTicket.approval_status === 'INTERNAL' &&\n currentSupportTicket.dev_lifecycle !== 'CANCELLED' &&\n currentSupportTicket.dev_lifecycle !== 'DEPLOYED'\n \"\n :support_ticket=\"currentSupportTicket\"\n @update=\"handleWorkflowUpdate\"\n />\n\n <!-- Cancel Internal Task: Only for INTERNAL tasks that aren't already cancelled or deployed -->\n <CancelInternalTaskWorkflow\n v-if=\"\n currentSupportTicket.approval_status === 'INTERNAL' &&\n currentSupportTicket.dev_lifecycle !== 'CANCELLED' &&\n currentSupportTicket.dev_lifecycle !== 'DEPLOYED'\n \"\n :support_ticket=\"currentSupportTicket\"\n @update=\"handleWorkflowUpdate\"\n />\n\n <!-- Reactivate Internal Task: Only for terminal INTERNAL tasks (CANCELLED or DEPLOYED) -->\n <ReactivateInternalTaskWorkflow\n v-if=\"\n currentSupportTicket.approval_status === 'INTERNAL' &&\n (currentSupportTicket.dev_lifecycle === 'CANCELLED' ||\n currentSupportTicket.dev_lifecycle === 'DEPLOYED')\n \"\n :support_ticket=\"currentSupportTicket\"\n @update=\"handleWorkflowUpdate\"\n />\n\n <!-- Danger Zone - Always show section -->\n <ZiniaContainer v-if=\"currentSupportTicket\">\n <h3 class=\"card-title text-error\">Danger Zone</h3>\n\n <!-- Show delete button if backend says ticket can be deleted -->\n <template v-if=\"currentSupportTicket.can_delete\">\n <p class=\"text-sm text-base-content/70 mb-4\">\n Permanently delete this support ticket. This action cannot be undone.\n </p>\n <button @click=\"openDeleteModal\" class=\"btn btn-error btn-sm\" :disabled=\"isDeleting\">\n Delete Support Ticket\n </button>\n </template>\n\n <!-- Show message if backend says ticket cannot be deleted -->\n <template v-else>\n <div class=\"alert alert-info\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n class=\"stroke-current shrink-0 w-6 h-6\"\n >\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"2\"\n d=\"M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z\"\n ></path>\n </svg>\n <span>\n This ticket cannot be deleted because it has been charged to the customer. Use the\n archive feature instead if you need to hide it from the active list.\n </span>\n </div>\n </template>\n </ZiniaContainer>\n </div>\n\n <!-- Delete Confirmation Modal -->\n <dialog :class=\"{ 'modal modal-open': showDeleteModal }\" class=\"modal\">\n <div class=\"modal-box\">\n <!-- Warning Icon -->\n <div\n class=\"flex items-center justify-center w-16 h-16 mx-auto mb-4 bg-error/10 rounded-full\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n class=\"w-8 h-8 text-error\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke=\"currentColor\"\n >\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n stroke-width=\"2\"\n 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\"\n />\n </svg>\n </div>\n\n <!-- Modal Title -->\n <h3 class=\"text-lg font-bold text-center mb-2\">Delete Support Ticket</h3>\n\n <!-- Modal Content -->\n <div class=\"text-center mb-6\">\n <p class=\"text-base-content/80 mb-2\">\n Are you sure you want to delete this support ticket?\n </p>\n <div v-if=\"currentSupportTicket\" class=\"bg-base-200 p-3 rounded-lg mb-3\">\n <p class=\"font-semibold\">\n {{ currentSupportTicket.title || 'Untitled Ticket' }}\n </p>\n <p class=\"text-sm text-base-content/70\">\n {{ currentSupportTicket.requester_name || 'No Requester' }}\n </p>\n <div class=\"text-sm text-base-content/70\">\n <SupportTicketTypeBadge\n v-if=\"currentSupportTicket.type\"\n :type=\"currentSupportTicket.type\"\n size=\"sm\"\n />\n <span v-else>No Type</span>\n </div>\n </div>\n <p class=\"text-sm text-error font-medium\">This action cannot be undone.</p>\n </div>\n\n <!-- Modal Actions -->\n <div class=\"modal-action justify-center gap-3\">\n <button @click=\"closeDeleteModal\" class=\"btn btn-outline\" :disabled=\"isDeleting\">\n Cancel\n </button>\n <button @click=\"confirmDelete\" class=\"btn btn-error\" :disabled=\"isDeleting\">\n <span v-if=\"isDeleting\" class=\"loading loading-spinner loading-sm\"></span>\n {{ isDeleting ? 'Deleting...' : 'Delete Support Ticket' }}\n </button>\n </div>\n </div>\n <form method=\"dialog\" class=\"modal-backdrop\" @click=\"closeDeleteModal\">\n <button type=\"button\">close</button>\n </form>\n </dialog>\n</template>\n\n<script setup lang=\"ts\">\nimport ZiniaContainer from '../../../components/ui/ZiniaContainer.vue';\nimport { useMutation } from '../../../composables/useMutation';\nimport type { StaffSupportTicketReadDto } from '@dragonmastery/dragoncore-shared';\nimport { computed, inject, ref } from 'vue';\nimport { useRoute, useRouter } from 'vue-router';\nimport { toast } from 'vue3-toastify';\nimport SupportTicketApprovalBadge from '../components/SupportTicketApprovalBadge.vue';\nimport SupportTicketDevLifecycleBadge from '../components/SupportTicketDevLifecycleBadge.vue';\nimport SupportTicketTypeBadge from '../components/SupportTicketTypeBadge.vue';\nimport ApproveRejectActions from './components/ApproveRejectActions.vue';\nimport CancelInternalTaskWorkflow from './components/CancelInternalTaskWorkflow.vue';\nimport CompleteSupportTicketForm from './components/CompleteSupportTicketForm.vue';\nimport ConvertToCustomerWorkflow from './components/ConvertToCustomerWorkflow.vue';\nimport ConvertToInternalWorkflow from './components/ConvertToInternalWorkflow.vue';\nimport ReactivateInternalTaskWorkflow from './components/ReactivateInternalTaskWorkflow.vue';\n\ninterface Props {\n ticket: StaffSupportTicketReadDto | null;\n isLoading?: boolean;\n error?: Error | null;\n}\n\nconst props = defineProps<Props>();\n\nconst route = useRoute();\nconst router = useRouter();\nconst support_ticket_id = route.params.id as string;\n\n// Inject refresh function from parent\nconst refreshTicket = inject<() => Promise<void>>('refreshTicket');\n\nconst currentSupportTicket = computed(() => {\n return props.ticket ? { ...props.ticket, __typename: 'AdminSupportTicket' as const } : null;\n});\n\n// Delete modal state\nconst showDeleteModal = ref(false);\n\n// Delete mutation\nconst { mutate: deleteSupportTicket, loading: isDeleting } = useMutation(\n (api, input: { id: string }) => api.supportTickets.deleteTicket(input.id),\n { invalidate: /^support-tickets?:/ },\n);\n\nconst handleWorkflowUpdate = async () => {\n // Call parent's refresh function to refetch data\n if (refreshTicket) {\n await refreshTicket();\n }\n};\n\n// Delete functions\nfunction openDeleteModal() {\n showDeleteModal.value = true;\n}\n\nfunction closeDeleteModal() {\n showDeleteModal.value = false;\n}\n\nasync function confirmDelete() {\n closeDeleteModal(); // Close modal immediately to show loading on main content\n\n try {\n await deleteSupportTicket({ id: support_ticket_id });\n\n await router.push({ name: 'StaffSupportTicketList' });\n toast.success('Support ticket deleted successfully');\n } catch (err) {\n const errorMsg = err instanceof Error ? err.message : 'Failed to delete support ticket';\n // Check for APPROVED ticket error\n if (errorMsg.includes('Cannot delete approved tickets')) {\n toast.error(errorMsg);\n } else {\n toast.error('Failed to delete support ticket');\n }\n console.error(err);\n }\n // Note: Don't reset isDeleting on success since we're navigating away\n}\n</script>\n"],"mappings":"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"}
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import { r as executeWithAuth, s as getRefreshTokenHandler } from "./useRpcAuth-BLlRSHy8.js";
|
|
2
|
+
import { t as ZiniaContainer_default } from "./ZiniaContainer-C7c7Vwkh.js";
|
|
3
|
+
import { t as formatSystemTimestamp } from "./convertToLocalDateTime-D4IoNvRj.js";
|
|
4
|
+
import { Fragment, createCommentVNode, createElementBlock, createElementVNode, createVNode, defineComponent, normalizeClass, openBlock, ref, renderList, toDisplayString, unref, withCtx } from "vue";
|
|
5
|
+
import { useRoute } from "vue-router";
|
|
6
|
+
import { recordVersionSchema } from "@dragonmastery/dragoncore-shared";
|
|
7
|
+
import { useCursorDataTable, withMetadata } from "@dragonmastery/zinia-forms-core";
|
|
8
|
+
|
|
9
|
+
//#region src/slices/support_ticket/recordVersionRowSchema.ts
|
|
10
|
+
const recordVersionRowSchemaWithMetadata = withMetadata(recordVersionSchema, "recordVersionRowSchema", {
|
|
11
|
+
operation: {
|
|
12
|
+
label: "Operation",
|
|
13
|
+
sortable: true
|
|
14
|
+
},
|
|
15
|
+
recorded_at: {
|
|
16
|
+
label: "Date",
|
|
17
|
+
sortable: true
|
|
18
|
+
},
|
|
19
|
+
auth_username: {
|
|
20
|
+
label: "User",
|
|
21
|
+
sortable: true
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
//#endregion
|
|
26
|
+
//#region src/slices/support_ticket/components/SupportTicketHistoryTab.vue
|
|
27
|
+
const _hoisted_1 = { class: "mt-2" };
|
|
28
|
+
const _hoisted_2 = { class: "space-y-3" };
|
|
29
|
+
const _hoisted_3 = { class: "flex flex-col sm:flex-row sm:items-center gap-2" };
|
|
30
|
+
const _hoisted_4 = { class: "flex items-center gap-2" };
|
|
31
|
+
const _hoisted_5 = { class: "flex flex-col sm:flex-row sm:items-center gap-1 sm:gap-2 text-xs" };
|
|
32
|
+
const _hoisted_6 = { class: "text-base-content/70" };
|
|
33
|
+
const _hoisted_7 = { class: "text-base-content/60" };
|
|
34
|
+
const _hoisted_8 = ["onClick"];
|
|
35
|
+
const _hoisted_9 = {
|
|
36
|
+
key: 0,
|
|
37
|
+
class: "mt-3"
|
|
38
|
+
};
|
|
39
|
+
const _hoisted_10 = { key: 0 };
|
|
40
|
+
const _hoisted_11 = { class: "bg-base-200 rounded-lg p-3 text-sm" };
|
|
41
|
+
const _hoisted_12 = { class: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-2" };
|
|
42
|
+
const _hoisted_13 = { class: "text-xs font-medium text-base-content/70 mb-1" };
|
|
43
|
+
const _hoisted_14 = { class: "text-xs font-mono text-base-content" };
|
|
44
|
+
const _hoisted_15 = {
|
|
45
|
+
key: 0,
|
|
46
|
+
class: "text-base-content/50 italic"
|
|
47
|
+
};
|
|
48
|
+
const _hoisted_16 = { key: 1 };
|
|
49
|
+
const _hoisted_17 = { key: 1 };
|
|
50
|
+
const _hoisted_18 = { class: "space-y-2" };
|
|
51
|
+
const _hoisted_19 = { class: "flex items-center justify-between mb-1" };
|
|
52
|
+
const _hoisted_20 = { class: "font-medium text-xs text-base-content" };
|
|
53
|
+
const _hoisted_21 = { class: "grid grid-cols-1 md:grid-cols-2 gap-2" };
|
|
54
|
+
const _hoisted_22 = { class: "bg-error/10 border border-error/20 rounded p-1 text-xs" };
|
|
55
|
+
const _hoisted_23 = {
|
|
56
|
+
key: 0,
|
|
57
|
+
class: "text-base-content/50 italic"
|
|
58
|
+
};
|
|
59
|
+
const _hoisted_24 = {
|
|
60
|
+
key: 1,
|
|
61
|
+
class: "font-mono"
|
|
62
|
+
};
|
|
63
|
+
const _hoisted_25 = { class: "bg-success/10 border border-success/20 rounded p-1 text-xs" };
|
|
64
|
+
const _hoisted_26 = {
|
|
65
|
+
key: 0,
|
|
66
|
+
class: "text-base-content/50 italic"
|
|
67
|
+
};
|
|
68
|
+
const _hoisted_27 = {
|
|
69
|
+
key: 1,
|
|
70
|
+
class: "font-mono"
|
|
71
|
+
};
|
|
72
|
+
const _hoisted_28 = { key: 2 };
|
|
73
|
+
const _hoisted_29 = { class: "bg-error/10 rounded p-2 text-xs font-mono" };
|
|
74
|
+
const _hoisted_30 = { class: "whitespace-pre-wrap" };
|
|
75
|
+
const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
76
|
+
__name: "SupportTicketHistoryTab",
|
|
77
|
+
setup(__props) {
|
|
78
|
+
const support_ticket_id = useRoute().params.id;
|
|
79
|
+
const expandedItems = ref(/* @__PURE__ */ new Set());
|
|
80
|
+
const { ZiniaDataTable } = useCursorDataTable(recordVersionRowSchemaWithMetadata, {
|
|
81
|
+
fetchData: async ({ cursor, pageSize, sort, filters }) => {
|
|
82
|
+
const input = {
|
|
83
|
+
record_id: support_ticket_id,
|
|
84
|
+
record_type: "support_ticket",
|
|
85
|
+
filters: {
|
|
86
|
+
first: pageSize,
|
|
87
|
+
...cursor ? { after: cursor } : {},
|
|
88
|
+
sortBy: sort?.field || "recorded_at",
|
|
89
|
+
sortDirection: sort?.direction || "desc",
|
|
90
|
+
...filters
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
const result = await executeWithAuth(async (api) => {
|
|
94
|
+
return await api.recordVersions.listRecordVersionsPaginated(input.record_id, input.record_type, input.filters);
|
|
95
|
+
}, { refreshTokenHandler: getRefreshTokenHandler() });
|
|
96
|
+
return {
|
|
97
|
+
data: result.items || [],
|
|
98
|
+
hasNextPage: result.pageInfo?.hasNextPage ?? false,
|
|
99
|
+
hasPreviousPage: result.pageInfo?.hasPreviousPage ?? false,
|
|
100
|
+
prevPageCursor: result.pageInfo?.prevPageCursor ?? void 0,
|
|
101
|
+
nextPageCursor: result.pageInfo?.nextPageCursor ?? void 0
|
|
102
|
+
};
|
|
103
|
+
},
|
|
104
|
+
columns: { operation: {
|
|
105
|
+
label: "",
|
|
106
|
+
field: "operation"
|
|
107
|
+
} },
|
|
108
|
+
pagination: { pageSize: 25 }
|
|
109
|
+
});
|
|
110
|
+
const toggleDetails = (itemId) => {
|
|
111
|
+
if (expandedItems.value.has(itemId)) expandedItems.value.delete(itemId);
|
|
112
|
+
else expandedItems.value.add(itemId);
|
|
113
|
+
};
|
|
114
|
+
const formatOperation = (operation) => {
|
|
115
|
+
switch (operation) {
|
|
116
|
+
case "insert": return "Created";
|
|
117
|
+
case "update": return "Updated";
|
|
118
|
+
case "delete": return "Deleted";
|
|
119
|
+
default: return operation;
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
const formatRecordData = (recordData) => {
|
|
123
|
+
if (!recordData) return "No data";
|
|
124
|
+
try {
|
|
125
|
+
return JSON.stringify(JSON.parse(recordData), null, 2);
|
|
126
|
+
} catch {
|
|
127
|
+
return recordData;
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
function getCreatedFields(record) {
|
|
131
|
+
if (!record) return [];
|
|
132
|
+
try {
|
|
133
|
+
const createdData = JSON.parse(record);
|
|
134
|
+
const fields = [];
|
|
135
|
+
for (const [name, value] of Object.entries(createdData)) fields.push({
|
|
136
|
+
name,
|
|
137
|
+
value
|
|
138
|
+
});
|
|
139
|
+
return fields;
|
|
140
|
+
} catch (error) {
|
|
141
|
+
console.error("Error parsing record data:", error);
|
|
142
|
+
return [];
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
function getChangedFields(record, oldRecord) {
|
|
146
|
+
if (!record || !oldRecord) return [];
|
|
147
|
+
try {
|
|
148
|
+
const changedFields = JSON.parse(record);
|
|
149
|
+
const oldData = JSON.parse(oldRecord);
|
|
150
|
+
const changes = [];
|
|
151
|
+
for (const [field, newValue] of Object.entries(changedFields)) {
|
|
152
|
+
const oldValue = oldData[field];
|
|
153
|
+
changes.push({
|
|
154
|
+
field,
|
|
155
|
+
oldValue,
|
|
156
|
+
newValue
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
return changes;
|
|
160
|
+
} catch (error) {
|
|
161
|
+
console.error("Error parsing record data:", error);
|
|
162
|
+
return [];
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
function formatFieldName(fieldName) {
|
|
166
|
+
return fieldName.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
167
|
+
}
|
|
168
|
+
function formatFieldValue(fieldName, value) {
|
|
169
|
+
if (value === null || value === void 0) return "No value";
|
|
170
|
+
if (fieldName.includes("_at") || fieldName.includes("At")) try {
|
|
171
|
+
return formatSystemTimestamp(value);
|
|
172
|
+
} catch {
|
|
173
|
+
return String(value);
|
|
174
|
+
}
|
|
175
|
+
if (typeof value === "boolean") return value ? "Yes" : "No";
|
|
176
|
+
if (fieldName.includes("status") || fieldName.includes("Status")) return String(value).replace(/_/g, " ").toUpperCase();
|
|
177
|
+
return String(value);
|
|
178
|
+
}
|
|
179
|
+
return (_ctx, _cache) => {
|
|
180
|
+
return openBlock(), createElementBlock("div", _hoisted_1, [createVNode(ZiniaContainer_default, null, {
|
|
181
|
+
default: withCtx(() => [createVNode(unref(ZiniaDataTable), null, {
|
|
182
|
+
"cell-operation": withCtx(({ row }) => [createElementVNode("div", _hoisted_2, [
|
|
183
|
+
createCommentVNode(" Operation Badge "),
|
|
184
|
+
createElementVNode("div", _hoisted_3, [createElementVNode("div", _hoisted_4, [createElementVNode("span", { class: normalizeClass(["badge badge-xs", {
|
|
185
|
+
"badge-success": row.operation === "insert",
|
|
186
|
+
"badge-warning": row.operation === "update",
|
|
187
|
+
"badge-error": row.operation === "delete"
|
|
188
|
+
}]) }, toDisplayString(formatOperation(row.operation)), 3)]), createElementVNode("div", _hoisted_5, [
|
|
189
|
+
createElementVNode("span", _hoisted_6, toDisplayString(unref(formatSystemTimestamp)(row.recorded_at)), 1),
|
|
190
|
+
createElementVNode("span", _hoisted_7, " by " + toDisplayString(row.auth_username || "Unknown"), 1),
|
|
191
|
+
createElementVNode("button", {
|
|
192
|
+
class: "btn btn-primary btn-xs",
|
|
193
|
+
onClick: ($event) => toggleDetails(row.id)
|
|
194
|
+
}, toDisplayString(expandedItems.value.has(row.id) ? "Hide Details" : "View Details"), 9, _hoisted_8)
|
|
195
|
+
])]),
|
|
196
|
+
createCommentVNode(" Details based on operation type "),
|
|
197
|
+
expandedItems.value.has(row.id) ? (openBlock(), createElementBlock("div", _hoisted_9, [row.operation === "insert" ? (openBlock(), createElementBlock("div", _hoisted_10, [_cache[0] || (_cache[0] = createElementVNode("h4", { class: "font-medium text-sm text-base-content/80 mb-2" }, "Created Record", -1)), createElementVNode("div", _hoisted_11, [createElementVNode("div", _hoisted_12, [(openBlock(true), createElementBlock(Fragment, null, renderList(getCreatedFields(row.record), (field) => {
|
|
198
|
+
return openBlock(), createElementBlock("div", {
|
|
199
|
+
key: field.name,
|
|
200
|
+
class: "flex flex-col"
|
|
201
|
+
}, [createElementVNode("span", _hoisted_13, toDisplayString(formatFieldName(field.name)), 1), createElementVNode("span", _hoisted_14, [field.value === null || field.value === void 0 ? (openBlock(), createElementBlock("span", _hoisted_15, "No value")) : (openBlock(), createElementBlock("span", _hoisted_16, toDisplayString(formatFieldValue(field.name, field.value)), 1))])]);
|
|
202
|
+
}), 128))])])])) : row.operation === "update" ? (openBlock(), createElementBlock("div", _hoisted_17, [_cache[4] || (_cache[4] = createElementVNode("h4", { class: "font-medium text-sm text-base-content/80 mb-2" }, "Changes Made", -1)), createElementVNode("div", _hoisted_18, [(openBlock(true), createElementBlock(Fragment, null, renderList(getChangedFields(row.record, row.old_record), (change) => {
|
|
203
|
+
return openBlock(), createElementBlock("div", {
|
|
204
|
+
key: change.field,
|
|
205
|
+
class: "border border-base-300 rounded p-2 bg-base-50"
|
|
206
|
+
}, [createElementVNode("div", _hoisted_19, [createElementVNode("h5", _hoisted_20, toDisplayString(formatFieldName(change.field)), 1), _cache[1] || (_cache[1] = createElementVNode("span", { class: "badge badge-xs badge-warning" }, "Updated", -1))]), createElementVNode("div", _hoisted_21, [createElementVNode("div", null, [_cache[2] || (_cache[2] = createElementVNode("div", { class: "text-xs font-medium text-base-content/70 mb-1" }, " Previous ", -1)), createElementVNode("div", _hoisted_22, [change.oldValue === null ? (openBlock(), createElementBlock("span", _hoisted_23, "No value")) : (openBlock(), createElementBlock("span", _hoisted_24, toDisplayString(formatFieldValue(change.field, change.oldValue)), 1))])]), createElementVNode("div", null, [_cache[3] || (_cache[3] = createElementVNode("div", { class: "text-xs font-medium text-base-content/70 mb-1" }, "New", -1)), createElementVNode("div", _hoisted_25, [change.newValue === null ? (openBlock(), createElementBlock("span", _hoisted_26, "No value")) : (openBlock(), createElementBlock("span", _hoisted_27, toDisplayString(formatFieldValue(change.field, change.newValue)), 1))])])])]);
|
|
207
|
+
}), 128))])])) : row.operation === "delete" ? (openBlock(), createElementBlock("div", _hoisted_28, [_cache[5] || (_cache[5] = createElementVNode("h4", { class: "font-medium text-sm text-base-content/80 mb-2" }, "Deleted Record", -1)), createElementVNode("div", _hoisted_29, [createElementVNode("pre", _hoisted_30, toDisplayString(formatRecordData(row.old_record)), 1)])])) : createCommentVNode("v-if", true)])) : createCommentVNode("v-if", true)
|
|
208
|
+
])]),
|
|
209
|
+
_: 1
|
|
210
|
+
})]),
|
|
211
|
+
_: 1
|
|
212
|
+
})]);
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
var SupportTicketHistoryTab_default = _sfc_main;
|
|
217
|
+
|
|
218
|
+
//#endregion
|
|
219
|
+
export { SupportTicketHistoryTab_default as t };
|
|
220
|
+
//# sourceMappingURL=SupportTicketHistoryTab-CLMopA7a.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SupportTicketHistoryTab-CLMopA7a.js","names":["fields: Array<{ name: string; value: any }>","changes: Array<{ field: string; oldValue: any; newValue: any }>"],"sources":["../src/slices/support_ticket/recordVersionRowSchema.ts","../src/slices/support_ticket/components/SupportTicketHistoryTab.vue"],"sourcesContent":["import { withMetadata } from '@dragonmastery/zinia-forms-core';\nimport { recordVersionSchema } from '@dragonmastery/dragoncore-shared';\nimport { z } from 'zod';\n\nexport const recordVersionRowSchemaWithMetadata = withMetadata(\n recordVersionSchema,\n 'recordVersionRowSchema',\n {\n operation: {\n label: 'Operation',\n sortable: true,\n },\n recorded_at: {\n label: 'Date',\n sortable: true,\n },\n auth_username: {\n label: 'User',\n sortable: true,\n },\n },\n);\n\nexport type RecordVersionRow = z.infer<typeof recordVersionSchema>;\n","<template>\n <div class=\"mt-2\">\n <ZiniaContainer>\n <ZiniaDataTable>\n <!-- Custom cell templates -->\n <template #cell-operation=\"{ row }\">\n <div class=\"space-y-3\">\n <!-- Operation Badge -->\n <div class=\"flex flex-col sm:flex-row sm:items-center gap-2\">\n <div class=\"flex items-center gap-2\">\n <span\n class=\"badge badge-xs\"\n :class=\"{\n 'badge-success': row.operation === 'insert',\n 'badge-warning': row.operation === 'update',\n 'badge-error': row.operation === 'delete',\n }\"\n >\n {{ formatOperation(row.operation) }}\n </span>\n </div>\n <div class=\"flex flex-col sm:flex-row sm:items-center gap-1 sm:gap-2 text-xs\">\n <span class=\"text-base-content/70\">\n {{ formatSystemTimestamp(row.recorded_at) }}\n </span>\n <span class=\"text-base-content/60\">\n by {{ row.auth_username || 'Unknown' }}\n </span>\n <button class=\"btn btn-primary btn-xs\" @click=\"toggleDetails(row.id)\">\n {{ expandedItems.has(row.id) ? 'Hide Details' : 'View Details' }}\n </button>\n </div>\n </div>\n\n <!-- Details based on operation type -->\n <div v-if=\"expandedItems.has(row.id)\" class=\"mt-3\">\n <div v-if=\"row.operation === 'insert'\">\n <h4 class=\"font-medium text-sm text-base-content/80 mb-2\">Created Record</h4>\n <div class=\"bg-base-200 rounded-lg p-3 text-sm\">\n <div class=\"grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-2\">\n <div\n v-for=\"field in getCreatedFields(row.record)\"\n :key=\"field.name\"\n class=\"flex flex-col\"\n >\n <span class=\"text-xs font-medium text-base-content/70 mb-1\">\n {{ formatFieldName(field.name) }}\n </span>\n <span class=\"text-xs font-mono text-base-content\">\n <span\n v-if=\"field.value === null || field.value === undefined\"\n class=\"text-base-content/50 italic\"\n >No value</span\n >\n <span v-else>{{ formatFieldValue(field.name, field.value) }}</span>\n </span>\n </div>\n </div>\n </div>\n </div>\n\n <div v-else-if=\"row.operation === 'update'\">\n <h4 class=\"font-medium text-sm text-base-content/80 mb-2\">Changes Made</h4>\n <div class=\"space-y-2\">\n <div\n v-for=\"change in getChangedFields(row.record, row.old_record)\"\n :key=\"change.field\"\n class=\"border border-base-300 rounded p-2 bg-base-50\"\n >\n <div class=\"flex items-center justify-between mb-1\">\n <h5 class=\"font-medium text-xs text-base-content\">\n {{ formatFieldName(change.field) }}\n </h5>\n <span class=\"badge badge-xs badge-warning\">Updated</span>\n </div>\n <div class=\"grid grid-cols-1 md:grid-cols-2 gap-2\">\n <div>\n <div class=\"text-xs font-medium text-base-content/70 mb-1\">\n Previous\n </div>\n <div class=\"bg-error/10 border border-error/20 rounded p-1 text-xs\">\n <span\n v-if=\"change.oldValue === null\"\n class=\"text-base-content/50 italic\"\n >No value</span\n >\n <span v-else class=\"font-mono\">{{\n formatFieldValue(change.field, change.oldValue)\n }}</span>\n </div>\n </div>\n <div>\n <div class=\"text-xs font-medium text-base-content/70 mb-1\">New</div>\n <div\n class=\"bg-success/10 border border-success/20 rounded p-1 text-xs\"\n >\n <span\n v-if=\"change.newValue === null\"\n class=\"text-base-content/50 italic\"\n >No value</span\n >\n <span v-else class=\"font-mono\">{{\n formatFieldValue(change.field, change.newValue)\n }}</span>\n </div>\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <div v-else-if=\"row.operation === 'delete'\">\n <h4 class=\"font-medium text-sm text-base-content/80 mb-2\">Deleted Record</h4>\n <div class=\"bg-error/10 rounded p-2 text-xs font-mono\">\n <pre class=\"whitespace-pre-wrap\">{{ formatRecordData(row.old_record) }}</pre>\n </div>\n </div>\n </div>\n </div>\n </template>\n </ZiniaDataTable>\n </ZiniaContainer>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport ZiniaContainer from '../../../components/ui/ZiniaContainer.vue';\nimport { executeWithAuth } from '../../../composables/useRpcAuth';\nimport { getRefreshTokenHandler } from '../../../utils/EnhancedRefreshTokenHandler';\nimport { formatSystemTimestamp } from '../../../utils/convertToLocalDateTime';\nimport { useCursorDataTable } from '@dragonmastery/zinia-forms-core';\nimport { ref } from 'vue';\nimport { useRoute } from 'vue-router';\nimport { recordVersionRowSchemaWithMetadata } from '../recordVersionRowSchema';\n\n// Get support ticket ID from route\nconst route = useRoute();\nconst support_ticket_id = route.params.id as string;\n\n// Expanded items state\nconst expandedItems = ref(new Set<string>());\n\n// Data table configuration\nconst { ZiniaDataTable } = useCursorDataTable(recordVersionRowSchemaWithMetadata, {\n fetchData: async ({ cursor, pageSize, sort, filters }) => {\n // Build query variables for breadcrumb pagination\n const input = {\n record_id: support_ticket_id,\n record_type: 'support_ticket' as const,\n filters: {\n first: pageSize,\n ...(cursor ? { after: cursor } : {}),\n sortBy: sort?.field || 'recorded_at',\n sortDirection: (sort?.direction || 'desc') as 'asc' | 'desc',\n ...filters,\n },\n };\n\n // Call RPC endpoint\n const result = await executeWithAuth(\n async (api) => {\n return await api.recordVersions.listRecordVersionsPaginated(\n input.record_id,\n input.record_type,\n input.filters,\n );\n },\n { refreshTokenHandler: getRefreshTokenHandler() },\n );\n\n // Return paginated data with bidirectional navigation\n return {\n data: result.items || [],\n hasNextPage: result.pageInfo?.hasNextPage ?? false,\n hasPreviousPage: result.pageInfo?.hasPreviousPage ?? false,\n prevPageCursor: result.pageInfo?.prevPageCursor ?? undefined,\n nextPageCursor: result.pageInfo?.nextPageCursor ?? undefined,\n };\n },\n\n // Column configuration - only show operation column since everything is consolidated there\n columns: {\n operation: {\n label: '',\n field: 'operation',\n },\n },\n\n // Pagination settings\n pagination: {\n pageSize: 25,\n },\n});\n\n// Methods\nconst toggleDetails = (itemId: string) => {\n if (expandedItems.value.has(itemId)) {\n expandedItems.value.delete(itemId);\n } else {\n expandedItems.value.add(itemId);\n }\n};\n\nconst formatOperation = (operation: string) => {\n switch (operation) {\n case 'insert':\n return 'Created';\n case 'update':\n return 'Updated';\n case 'delete':\n return 'Deleted';\n default:\n return operation;\n }\n};\n\nconst formatRecordData = (recordData: string | null | undefined) => {\n if (!recordData) return 'No data';\n try {\n return JSON.stringify(JSON.parse(recordData), null, 2);\n } catch {\n return recordData;\n }\n};\n\nfunction getCreatedFields(record: string | null | undefined) {\n if (!record) return [];\n\n try {\n const createdData = JSON.parse(record);\n const fields: Array<{ name: string; value: any }> = [];\n\n for (const [name, value] of Object.entries(createdData)) {\n fields.push({ name, value });\n }\n\n return fields;\n } catch (error) {\n console.error('Error parsing record data:', error);\n return [];\n }\n}\n\nfunction getChangedFields(\n record: string | null | undefined,\n oldRecord: string | null | undefined,\n) {\n if (!record || !oldRecord) return [];\n\n try {\n const changedFields = JSON.parse(record);\n const oldData = JSON.parse(oldRecord);\n\n const changes: Array<{ field: string; oldValue: any; newValue: any }> = [];\n\n for (const [field, newValue] of Object.entries(changedFields)) {\n const oldValue = oldData[field];\n changes.push({ field, oldValue, newValue });\n }\n\n return changes;\n } catch (error) {\n console.error('Error parsing record data:', error);\n return [];\n }\n}\n\nfunction formatFieldName(fieldName: string): string {\n // Convert snake_case to Title Case\n return fieldName\n .split('_')\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(' ');\n}\n\nfunction formatFieldValue(fieldName: string, value: any): string {\n if (value === null || value === undefined) {\n return 'No value';\n }\n\n // Format dates\n if (fieldName.includes('_at') || fieldName.includes('At')) {\n try {\n return formatSystemTimestamp(value);\n } catch {\n return String(value);\n }\n }\n\n // Format booleans\n if (typeof value === 'boolean') {\n return value ? 'Yes' : 'No';\n }\n\n // Format enums/status fields\n if (fieldName.includes('status') || fieldName.includes('Status')) {\n return String(value).replace(/_/g, ' ').toUpperCase();\n }\n\n return String(value);\n}\n</script>\n"],"mappings":"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"}
|