@dragonmastery/dragoncore-vue 0.0.16 → 0.0.18

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/dist/{ChangePasswordPage-BXPuAPAw.js → ChangePasswordPage-D2Ci00Sh.js} +1 -1
  2. package/dist/{ChangePasswordPage-BXPuAPAw.js.map → ChangePasswordPage-D2Ci00Sh.js.map} +1 -1
  3. package/dist/{ChangePasswordPage-D4rzAT2e.js → ChangePasswordPage-DqnWhaUa.js} +1 -1
  4. package/dist/CreateTeamForm-LadKAxsM.js +32 -0
  5. package/dist/CreateTeamMemberForm-eWL__TEt.js +32 -0
  6. package/dist/{CreateUserPage-25iC5JNs.js → CreateUserPage-DbT_l32W.js} +1 -1
  7. package/dist/{CreateUserPage-25iC5JNs.js.map → CreateUserPage-DbT_l32W.js.map} +1 -1
  8. package/dist/CreateUserPage-cduuWl9g.js +6 -0
  9. package/dist/CreditBalanceDashboard-CgRRO6MD.js +32 -0
  10. package/dist/CreditManagement-BBb_Xumq.js +32 -0
  11. package/dist/CustomerCreateSupportTicketForm-yfyeXr0V.js +32 -0
  12. package/dist/{CustomerSupportTicketDetailPage-DDMwp3lY.js → CustomerSupportTicketDetailPage-CthS9akm.js} +4 -4
  13. package/dist/{CustomerSupportTicketDetailPage-DDMwp3lY.js.map → CustomerSupportTicketDetailPage-CthS9akm.js.map} +1 -1
  14. package/dist/CustomerSupportTicketList-Zzsg1FtO.js +32 -0
  15. package/dist/{CustomerSupportTicketParent-BItQs6qz.js → CustomerSupportTicketParent-CqR8lF7r.js} +2 -2
  16. package/dist/{CustomerSupportTicketParent-0TLLQujw.js → CustomerSupportTicketParent-iBV1KRKL.js} +3 -3
  17. package/dist/{CustomerSupportTicketParent-0TLLQujw.js.map → CustomerSupportTicketParent-iBV1KRKL.js.map} +1 -1
  18. package/dist/CustomerSupportTicketSuccess-BPyydSLQ.js +32 -0
  19. package/dist/EditTeamForm-D0wZKYm2.js +32 -0
  20. package/dist/{EditTeamMemberForm-y4Klbm2x.js → EditTeamMemberForm-Cy8nzoUb.js} +1 -1
  21. package/dist/{EditTeamMemberForm-y4Klbm2x.js.map → EditTeamMemberForm-Cy8nzoUb.js.map} +1 -1
  22. package/dist/{EditTeamMemberForm-poMUw7tK.js → EditTeamMemberForm-JuRGiWOn.js} +1 -1
  23. package/dist/{EditUserPage-DFMiGciD.js → EditUserPage-CIRqNko-.js} +2 -2
  24. package/dist/{EditUserPage-DFMiGciD.js.map → EditUserPage-CIRqNko-.js.map} +1 -1
  25. package/dist/{TeamNotesTab-CpGM8HXg.js → EditUserPage-Dl6d3Cuh.js} +2 -2
  26. package/dist/{ForgotPassword-DYN5QAho.js → ForgotPassword-CJg_buPl.js} +10 -6
  27. package/dist/ForgotPassword-CJg_buPl.js.map +1 -0
  28. package/dist/{ForgotPassword-Cq1lKwSI.js → ForgotPassword-rSN-8EC4.js} +1 -1
  29. package/dist/{LoginForm-Bv4pzTYW.js → LoginForm-DyHmiC1I.js} +14 -14
  30. package/dist/LoginForm-DyHmiC1I.js.map +1 -0
  31. package/dist/{LoginForm-DLdl5qLw.js → LoginForm-YCzdrekw.js} +1 -1
  32. package/dist/{Logout-7daBTqXu.js → Logout-C6pWyTIm.js} +9 -6
  33. package/dist/Logout-C6pWyTIm.js.map +1 -0
  34. package/dist/{Logout-DukqZAYW.js → Logout-Ctc8b-B0.js} +1 -1
  35. package/dist/{MfaSetup-Drj1hQJ6.js → MfaSetup-D80HhwEz.js} +12 -7
  36. package/dist/MfaSetup-D80HhwEz.js.map +1 -0
  37. package/dist/{MfaSetup-C6Pku6P_.js → MfaSetup-xNmNjSh1.js} +2 -2
  38. package/dist/{MfaVerify-DMvK-ius.js → MfaVerify-BEd-f6oV.js} +9 -7
  39. package/dist/MfaVerify-BEd-f6oV.js.map +1 -0
  40. package/dist/{MfaVerify-CeTPsWRU.js → MfaVerify-C0COXH_W.js} +2 -2
  41. package/dist/ResetPassword-4HLdgM7s.js +92 -0
  42. package/dist/ResetPassword-4HLdgM7s.js.map +1 -0
  43. package/dist/ResetPassword-BCzMTXpT.js +7 -0
  44. package/dist/{SavedFiltersPage-BnRm3u1G.js → SavedFiltersPage-p0qGRIuN.js} +23 -22
  45. package/dist/{SavedFiltersPage-BnRm3u1G.js.map → SavedFiltersPage-p0qGRIuN.js.map} +1 -1
  46. package/dist/{Signup-DkImN_pp.js → Signup-Ct0m0x78.js} +17 -10
  47. package/dist/Signup-Ct0m0x78.js.map +1 -0
  48. package/dist/{Signup-pBflBiRz.js → Signup-DNEklGpK.js} +1 -1
  49. package/dist/StaffCreateSupportTicketForm-CxpKnqCq.js +32 -0
  50. package/dist/{StaffSupportTicketDetailPage-pCzgt0bn.js → StaffSupportTicketDetailPage-TaAPQARa.js} +6 -6
  51. package/dist/{StaffSupportTicketDetailPage-pCzgt0bn.js.map → StaffSupportTicketDetailPage-TaAPQARa.js.map} +1 -1
  52. package/dist/StaffSupportTicketList-BuKBTk2v.js +32 -0
  53. package/dist/{StaffSupportTicketParent-Hj4m2xeF.js → StaffSupportTicketParent-KYzy4eb4.js} +3 -3
  54. package/dist/{StaffSupportTicketParent-Hj4m2xeF.js.map → StaffSupportTicketParent-KYzy4eb4.js.map} +1 -1
  55. package/dist/{StaffSupportTicketParent-BqMBB52c.js → StaffSupportTicketParent-Lkn-5u7C.js} +2 -2
  56. package/dist/StaffSupportTicketSuccess-BD1Xsnx1.js +32 -0
  57. package/dist/{SupportStaffPage-BmcE-1-G.js → SupportStaffPage-D_YsHZZa.js} +3 -3
  58. package/dist/{SupportStaffPage-BmcE-1-G.js.map → SupportStaffPage-D_YsHZZa.js.map} +1 -1
  59. package/dist/{SupportTicketDevLifecycleBadge-Ba-Rm6QW.js → SupportTicketDevLifecycleBadge-B2NysMAj.js} +1 -1
  60. package/dist/{SupportTicketDevLifecycleBadge-Ba-Rm6QW.js.map → SupportTicketDevLifecycleBadge-B2NysMAj.js.map} +1 -1
  61. package/dist/{SupportTicketMaintenancePage-DbH9gLlG.js → SupportTicketMaintenancePage-CpK1esq2.js} +1 -1
  62. package/dist/{SupportTicketMaintenancePage-DbH9gLlG.js.map → SupportTicketMaintenancePage-CpK1esq2.js.map} +1 -1
  63. package/dist/TeamAttachmentsTab-DA_MBYj8.js +32 -0
  64. package/dist/{TeamHistoryTab-B3DvaIzC.js → TeamHistoryTab-BQ-eXtiw.js} +2 -2
  65. package/dist/{TeamHistoryTab-B3DvaIzC.js.map → TeamHistoryTab-BQ-eXtiw.js.map} +1 -1
  66. package/dist/TeamHistoryTab-lz2ouNyP.js +4 -0
  67. package/dist/TeamList-T3mZJTzq.js +32 -0
  68. package/dist/TeamMemberList-BW4qqzC1.js +32 -0
  69. package/dist/TeamMemberParent-Wcht0pIz.js +32 -0
  70. package/dist/{TeamNotesTab-CXKv0UF9.js → TeamNotesTab-Dj12Q2gD.js} +2 -2
  71. package/dist/{TeamNotesTab-CXKv0UF9.js.map → TeamNotesTab-Dj12Q2gD.js.map} +1 -1
  72. package/dist/{EditUserPage-CG9qOvLb.js → TeamNotesTab-aGD8O49y.js} +2 -2
  73. package/dist/TeamParent-BkhaJwud.js +32 -0
  74. package/dist/{TimelineNoteInput-hpCxzQjP.js → TimelineNoteInput-DGDgyGe-.js} +1 -1
  75. package/dist/{TimelineNoteInput-hpCxzQjP.js.map → TimelineNoteInput-DGDgyGe-.js.map} +1 -1
  76. package/dist/UserListPage-C9zUjaOK.js +4 -0
  77. package/dist/{UserListPage-DtftDtVo.js → UserListPage-D-IdlsHK.js} +2 -2
  78. package/dist/{UserListPage-DtftDtVo.js.map → UserListPage-D-IdlsHK.js.map} +1 -1
  79. package/dist/{UserProfilePage-Ex-rpoTJ.js → UserProfilePage-D52_Q5yf.js} +1 -1
  80. package/dist/{UserProfilePage-1UWJUhqk.js → UserProfilePage-DMwDVgXa.js} +1 -1
  81. package/dist/{UserProfilePage-1UWJUhqk.js.map → UserProfilePage-DMwDVgXa.js.map} +1 -1
  82. package/dist/{VerifyEmail-tkPdmmBN.js → VerifyEmail-5thal4d_.js} +1 -1
  83. package/dist/{VerifyEmail-De72yrDX.js → VerifyEmail-CHfTzrHg.js} +9 -6
  84. package/dist/VerifyEmail-CHfTzrHg.js.map +1 -0
  85. package/dist/{VerifyEmailRequired-BMnPXJzY.js → VerifyEmailRequired-BCKREd_C.js} +8 -3
  86. package/dist/VerifyEmailRequired-BCKREd_C.js.map +1 -0
  87. package/dist/ViewTeam-g7WhYvsR.js +32 -0
  88. package/dist/ViewTeamMember-ByCSsl5k.js +32 -0
  89. package/dist/{convertToLocalDateTime-DOSGtMn8.js → convertToLocalDateTime-mKs5eC9T.js} +1 -1
  90. package/dist/{convertToLocalDateTime-DOSGtMn8.js.map → convertToLocalDateTime-mKs5eC9T.js.map} +1 -1
  91. package/dist/{displayIdFormatter-B1ZKgofu.js → displayIdFormatter-rSbbsHIX.js} +1 -1
  92. package/dist/{displayIdFormatter-B1ZKgofu.js.map → displayIdFormatter-rSbbsHIX.js.map} +1 -1
  93. package/dist/{extractRpcErrorMessage-C_UbKgHL.js → extractRpcErrorMessage-pP3v8kKE.js} +1 -1
  94. package/dist/{extractRpcErrorMessage-C_UbKgHL.js.map → extractRpcErrorMessage-pP3v8kKE.js.map} +1 -1
  95. package/dist/index.d.ts +49 -12
  96. package/dist/index.js +27 -25
  97. package/dist/{mfaSchema-DN655dny.js → mfaSchema-_vbG9jiT.js} +1 -1
  98. package/dist/{mfaSchema-DN655dny.js.map → mfaSchema-_vbG9jiT.js.map} +1 -1
  99. package/dist/{src-eLdX-D-O.js → src-B5eswi_J.js} +393 -441
  100. package/dist/src-B5eswi_J.js.map +1 -0
  101. package/dist/{useBreadcrumbs-DmgSucoe.js → useBreadcrumbs-B-W-miq6.js} +1 -1
  102. package/dist/{useBreadcrumbs-DmgSucoe.js.map → useBreadcrumbs-B-W-miq6.js.map} +1 -1
  103. package/dist/useReturnUrl-BBoPnDR3.js +51 -0
  104. package/dist/useReturnUrl-BBoPnDR3.js.map +1 -0
  105. package/package.json +1 -1
  106. package/dist/CreateTeamForm-CkjGTLz_.js +0 -31
  107. package/dist/CreateTeamMemberForm-CVpIyvAR.js +0 -31
  108. package/dist/CreateUserPage-BvsE7tFH.js +0 -6
  109. package/dist/CreditBalanceDashboard-B4ql-qT9.js +0 -31
  110. package/dist/CreditManagement-D99fYSac.js +0 -31
  111. package/dist/CustomerCreateSupportTicketForm-eMNpLn4_.js +0 -31
  112. package/dist/CustomerSupportTicketList-DnE-0wkZ.js +0 -31
  113. package/dist/CustomerSupportTicketSuccess-CBqqfJVd.js +0 -31
  114. package/dist/EditTeamForm-DhuxhKvO.js +0 -31
  115. package/dist/ForgotPassword-DYN5QAho.js.map +0 -1
  116. package/dist/LoginForm-Bv4pzTYW.js.map +0 -1
  117. package/dist/Logout-7daBTqXu.js.map +0 -1
  118. package/dist/MfaSetup-Drj1hQJ6.js.map +0 -1
  119. package/dist/MfaVerify-DMvK-ius.js.map +0 -1
  120. package/dist/ResetPassword-Bl34xbJ7.js +0 -31
  121. package/dist/Signup-DkImN_pp.js.map +0 -1
  122. package/dist/StaffCreateSupportTicketForm-Cy3zALqx.js +0 -31
  123. package/dist/StaffSupportTicketList-CdsRKYEj.js +0 -31
  124. package/dist/StaffSupportTicketSuccess-DS52WQ4o.js +0 -31
  125. package/dist/TeamAttachmentsTab-mB4y2I62.js +0 -31
  126. package/dist/TeamHistoryTab-B5DOTCUd.js +0 -4
  127. package/dist/TeamList-CRc3XZ2k.js +0 -31
  128. package/dist/TeamMemberList-DcJ0EKv0.js +0 -31
  129. package/dist/TeamMemberParent-BrDpy4QM.js +0 -31
  130. package/dist/TeamParent-dplHxTlz.js +0 -31
  131. package/dist/UserListPage-mOMo6rE7.js +0 -4
  132. package/dist/VerifyEmail-De72yrDX.js.map +0 -1
  133. package/dist/VerifyEmailRequired-BMnPXJzY.js.map +0 -1
  134. package/dist/ViewTeam-B9L8tANd.js +0 -31
  135. package/dist/ViewTeamMember-DKwVCMp7.js +0 -31
  136. package/dist/src-eLdX-D-O.js.map +0 -1
  137. /package/dist/{Appearance-C3WguxT-.js → Appearance-CohgRf-_.js} +0 -0
  138. /package/dist/{TeamMembersTab-DTJxmb-M.js → TeamMembersTab-CpE9BaCi.js} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"TeamNotesTab-CXKv0UF9.js","names":["variables: NoteFiltersDto"],"sources":["../src/slices/note/noteUpdateMetadata.ts","../src/slices/note/components/EditNoteModal.vue","../src/slices/note/noteFormMetadata.ts","../src/slices/note/noteRowSchema.ts","../src/slices/note/components/NoteList.vue","../src/slices/team/TeamNotesTab.vue"],"sourcesContent":["import { withMetadata } from '@dragonmastery/zinia-forms-core';\nimport { NoteUpdateSchema } from '@dragonmastery/dragoncore-shared';\n\nexport const noteUpdateMetadata = withMetadata(\n NoteUpdateSchema.pick({ body: true, tag: true }),\n 'noteUpdateForm',\n {\n body: {\n label: 'Note',\n placeholder: 'Enter your note here...',\n inputType: 'textarea',\n helpText: 'Update the note content',\n },\n tag: {\n label: 'Tag',\n inputType: 'combobox',\n helpText: 'Optional tag to categorize this note',\n },\n },\n);\n","<template>\n <dialog ref=\"modal\" class=\"modal\">\n <div class=\"modal-box\">\n <h3 class=\"font-bold text-lg mb-4\">Edit Note</h3>\n\n <ZiniaForm\n @handle-submit=\"handleSubmit\"\n @success=\"handleSuccess\"\n @error=\"handleError\"\n title=\"\"\n subtitle=\"\"\n >\n <zinia.TagField :select-options=\"form.extraData.tag || []\" :allow-create=\"true\" />\n <zinia.BodyField />\n\n <!-- Show visibility status (read-only) -->\n <div class=\"form-control\">\n <label class=\"label\">\n <span class=\"label-text\">Visibility</span>\n <span class=\"badge\" :class=\"isInternalNote ? 'badge-warning' : 'badge-info'\">\n {{ isInternalNote ? 'Internal' : 'External' }}\n </span>\n </label>\n </div>\n\n <div v-if=\"form.submitError\" class=\"alert alert-error mt-2\">\n <span>{{ form.submitError }}</span>\n </div>\n\n <div class=\"flex justify-end gap-2 mt-6\">\n <button type=\"button\" class=\"btn btn-ghost\" @click=\"closeModal\">Cancel</button>\n <ZiniaSubmitButton submitText=\"Update Note\" submittingText=\"Updating...\" />\n </div>\n\n <ZiniaFormErrorsSummary title=\"Please fix the following errors:\" />\n </ZiniaForm>\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 { useForm } from '@dragonmastery/zinia-forms-core';\nimport { ref, watch } from 'vue';\nimport { toast } from 'vue3-toastify';\nimport { useMutation } from '../../../composables/useMutation';\nimport { useQuery } from '../../../composables/useQuery';\nimport type { NoteRow } from '../noteRowSchema';\nimport { noteUpdateMetadata } from '../noteUpdateMetadata';\n\ninterface Props {\n note: NoteRow | null;\n isOpen: boolean;\n}\n\ninterface Emits {\n (e: 'close'): void;\n (e: 'success'): void;\n}\n\nconst props = defineProps<Props>();\nconst emit = defineEmits<Emits>();\n\nconst modal = ref<HTMLDialogElement>();\n\n// Internal note toggle state\nconst isInternalNote = ref(false);\n\n// Fetch note tags for combobox\nconst {\n data: noteTagsData,\n loading: noteTagsLoading,\n error: noteTagsError,\n refetch: refetchNoteTags,\n} = useQuery((api) => api.notes.getNoteTags());\n\n// Load note tags for combobox options\nconst loadNoteTags = async () => {\n // Wait for query to complete\n while (noteTagsLoading.value) {\n await new Promise((resolve) => setTimeout(resolve, 100));\n }\n\n if (noteTagsError.value) {\n return [];\n }\n\n const tags = noteTagsData.value || [];\n\n return tags.map((tag: string) => ({\n value: tag,\n label: tag,\n }));\n};\n\nconst {\n form,\n zinia,\n ZiniaForm,\n ZiniaSubmitButton,\n ZiniaFormErrorsSummary,\n clearSavedFormState,\n refreshFormData,\n} = useForm(noteUpdateMetadata, {\n storeName: `edit-note-form-${props.note?.id || 'new'}`,\n persistToLocalStorage: false,\n renderStyle: 'daisy_ui',\n dataLoaders: {\n tag: loadNoteTags,\n },\n fetchData: async () => {\n if (!props.note) {\n return { body: '', tag: null };\n }\n return {\n body: props.note.body || '',\n tag: props.note.tag || null,\n };\n },\n});\n\nconst { mutate: updateNote } = useMutation(\n (api, input: { id: string; body: string; tag?: string | null }) =>\n api.notes.updateNote(input),\n {\n invalidate: /^notes?:/,\n onSuccess: () => {\n // Refetch tags to include any new tags\n refetchNoteTags();\n },\n },\n);\n\nconst handleSubmit = async (formData: any) => {\n if (!props.note) {\n throw new Error('No note selected for editing');\n }\n\n const response = await updateNote({\n id: props.note.id,\n body: formData.body,\n tag: formData.tag || null,\n });\n\n if (!response) {\n throw new Error('Failed to update note');\n }\n\n return response;\n};\n\nconst handleSuccess = async () => {\n clearSavedFormState();\n refreshFormData(); // Reset form to initial state\n toast.success('Note updated successfully!');\n emit('success');\n closeModal();\n};\n\nconst handleError = (error: Error | unknown) => {\n form.setSubmitError(error instanceof Error ? error.message : 'An unknown error occurred');\n};\n\nconst closeModal = () => {\n emit('close');\n};\n\n// Watch for modal open/close\nwatch(\n () => props.isOpen,\n (isOpen) => {\n if (isOpen && modal.value) {\n modal.value.showModal();\n } else if (!isOpen && modal.value) {\n modal.value.close();\n // Reset form when modal closes\n refreshFormData();\n }\n },\n);\n\n// Watch for note changes to refresh form data\nwatch(\n () => props.note,\n () => {\n if (props.note && props.isOpen) {\n form.setValue('body', props.note.body || '');\n form.setValue('tag', props.note.tag || null);\n isInternalNote.value = props.note.is_internal || false;\n }\n },\n { immediate: true },\n);\n</script>\n","import { withMetadata } from '@dragonmastery/zinia-forms-core';\nimport { NoteCreateSchema } from '@dragonmastery/dragoncore-shared';\n\nexport const noteCreateMetadata = withMetadata(\n NoteCreateSchema.pick({ body: true, is_internal: true, tag: true }),\n 'noteCreateForm',\n {\n body: {\n label: 'Note',\n placeholder: 'Enter your note here...',\n inputType: 'textarea',\n helpText: 'Add a note about this record',\n },\n is_internal: {\n label: 'Internal Note',\n helpText: 'Check this box to make this note visible only to staff',\n },\n tag: {\n label: 'Tag',\n inputType: 'combobox',\n helpText: 'Optional tag to categorize this note',\n },\n },\n);\n","import { withMetadata } from '@dragonmastery/zinia-forms-core';\nimport { NoteReadSchema } from '@dragonmastery/dragoncore-shared';\nimport { z } from 'zod';\n\nexport const noteRowSchemaWithMetadata = withMetadata(NoteReadSchema, 'noteRowSchema', {\n body: { label: 'Note' },\n tag: { label: 'Tag', sortable: true },\n is_internal: { label: 'Visibility', sortable: true },\n created_at: { label: 'Created', sortable: true },\n created_by: { label: 'Created By', sortable: true },\n updated_at: { label: 'Updated', sortable: true },\n});\n\nexport type NoteRow = z.infer<typeof NoteReadSchema>;\n","<template>\n <div class=\"space-y-6\">\n <!-- Add Note Form -->\n <div class=\"mt-4\">\n <ZiniaForm\n @handle-submit=\"handleSubmit\"\n @success=\"handleSuccess\"\n @error=\"handleError\"\n title=\"\"\n subtitle=\"\"\n >\n <zinia.TagField :select-options=\"form.extraData.tag || []\" :allow-create=\"true\" />\n <zinia.BodyField />\n\n <div v-if=\"form.submitError\" class=\"alert alert-error mt-2\">\n <span>{{ form.submitError }}</span>\n </div>\n\n <div class=\"flex justify-end mt-6\">\n <ZiniaSubmitButton submitText=\"Add Note\" submittingText=\"Adding...\" />\n </div>\n\n <ZiniaFormErrorsSummary title=\"Please fix the following errors:\" />\n </ZiniaForm>\n </div>\n\n <!-- Notes Table -->\n <ZiniaDataTable>\n <template #cell-created_by=\"{ row }\">\n {{ row.created_by_display_name ?? row.created_by ?? '-' }}\n </template>\n <template #cell-created_at=\"{ row }\">\n {{ formatSystemTimestamp(row.created_at) }}\n </template>\n\n <template #cell-tag=\"{ row }\">\n {{ row.tag || '-' }}\n </template>\n\n <template #cell-updated_at=\"{ row }\">\n {{ row.updated_at ? formatSystemTimestamp(row.updated_at) : '-' }}\n </template>\n\n <template #cell-body=\"{ row }\">\n <div class=\"whitespace-pre-wrap\">\n {{ row.body || 'No content' }}\n </div>\n </template>\n </ZiniaDataTable>\n\n <!-- Edit Modal -->\n <EditNoteModal\n :note=\"selectedNote\"\n :is-open=\"isEditModalOpen\"\n @close=\"closeEditModal\"\n @success=\"handleEditSuccess\"\n />\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { executeWithAuth } from '../../../composables/useRpcAuth';\nimport { getRefreshTokenHandler } from '../../../utils/EnhancedRefreshTokenHandler';\nimport { useMutation } from '../../../composables/useMutation';\nimport { useQuery } from '../../../composables/useQuery';\nimport { formatSystemTimestamp } from '../../../utils/convertToLocalDateTime';\nimport EditNoteModal from './EditNoteModal.vue';\nimport { noteCreateMetadata } from '../noteFormMetadata';\nimport { noteRowSchemaWithMetadata, type NoteRow } from '../noteRowSchema';\nimport { ActionIcons, useCursorDataTable, useForm } from '@dragonmastery/zinia-forms-core';\nimport { OPERATORS, type NoteFiltersDto } from '@dragonmastery/dragoncore-shared';\nimport { computed, ref, watch } from 'vue';\nimport { toast } from 'vue3-toastify';\n\ninterface Props {\n recordId: string;\n recordType: string;\n mode?: 'customer' | 'internal';\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n mode: 'customer',\n});\n\n// Edit modal state\nconst selectedNote = ref<NoteRow | null>(null);\nconst isEditModalOpen = ref(false);\n\n// Computed properties for component intelligence\nconst isInternalNote = computed(() => {\n // Determine internal state based on mode\n return props.mode === 'internal';\n});\n\n// Query filters state\nconst queryFilters = ref<NoteFiltersDto>({\n record_id: { operator: OPERATORS.EQUALS, value: props.recordId },\n record_type: { operator: OPERATORS.EQUALS, value: props.recordType as any },\n});\n\n// Pagination token for breadcrumb navigation\nconst currentPaginationToken = ref<string | undefined | null>();\n\n// Fetch note tags for filter and form\nconst {\n data: noteTagsData,\n loading: noteTagsLoading,\n error: noteTagsError,\n refetch: refetchNoteTags,\n} = useQuery((api) => api.notes.getNoteTags());\n\n// Load note tags for filter options and form combobox\n// This function reads from noteTagsData.value, which is reactive\n// When refetchNoteTags() is called, noteTagsData.value updates\n// The next time this function is called (when filter dropdown opens), it will get fresh data\nconst loadNoteTags = async () => {\n // If query is loading, wait for it to complete to ensure we have fresh data\n while (noteTagsLoading.value) {\n await new Promise((resolve) => setTimeout(resolve, 100));\n }\n\n if (noteTagsError.value) {\n return [];\n }\n\n const tags = noteTagsData.value || [];\n\n return tags.map((tag: string) => ({\n value: tag,\n label: tag,\n }));\n};\n\n// Form setup\nconst { form, zinia, ZiniaForm, ZiniaSubmitButton, ZiniaFormErrorsSummary, refreshFormData } =\n useForm(noteCreateMetadata, {\n storeName: `note-form-${props.recordId}`,\n persistToLocalStorage: false,\n renderStyle: 'daisy_ui',\n dataLoaders: {\n tag: loadNoteTags,\n },\n fetchData: async () => ({\n body: '',\n tag: null,\n is_internal: isInternalNote.value,\n }),\n });\n\n// Data table configuration\nconst { ZiniaDataTable, refresh } = useCursorDataTable(noteRowSchemaWithMetadata, {\n fetchData: async ({ cursor, pageSize, sort, filters, search }) => {\n // Build query variables\n const variables: NoteFiltersDto = {\n first: pageSize,\n sortBy: sort?.field ? (sort.field as string) : 'created_at',\n sortDirection: (sort?.direction === 'asc' ? 'asc' : 'desc') as any,\n ...(cursor ? { after: cursor } : {}),\n ...(currentPaginationToken.value\n ? { paginationToken: currentPaginationToken.value }\n : {}),\n ...(search ? { search } : {}),\n record_id: { operator: OPERATORS.EQUALS, value: props.recordId },\n record_type: { operator: OPERATORS.EQUALS, value: props.recordType as any },\n ...filters,\n };\n\n // Apply visibility filter based on mode\n if (props.mode === 'customer') {\n variables.is_internal = { operator: OPERATORS.EQUALS, value: false };\n } else if (props.mode === 'internal') {\n variables.is_internal = { operator: OPERATORS.EQUALS, value: true };\n }\n // For 'all' mode, no filter is applied (shows everything)\n\n // Update query filters and execute\n queryFilters.value = variables;\n const result = await executeWithAuth(\n async (api) => {\n return await api.notes.getNotes(variables);\n },\n { refreshTokenHandler: getRefreshTokenHandler() },\n );\n currentPaginationToken.value = result?.pageInfo?.paginationToken;\n\n // Return paginated data\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\n columns: {\n created_by: {\n label: 'Created By',\n field: 'created_by',\n sortable: true,\n verticalAlign: 'top',\n },\n updated_at: {\n label: 'Updated',\n field: 'updated_at',\n sortable: true,\n verticalAlign: 'top',\n },\n tag: {\n label: 'Tag',\n field: 'tag',\n sortable: true,\n filterable: true,\n filterType: 'select',\n filterOptionsLoader: loadNoteTags,\n verticalAlign: 'top',\n },\n body: {\n label: 'Note',\n field: 'body',\n sortable: false,\n },\n },\n\n // Action buttons\n actions: {\n column: {\n verticalAlign: 'top',\n },\n items: [\n {\n key: 'edit',\n icon: ActionIcons.edit,\n size: 'xs',\n variant: 'primary',\n type: 'button',\n onClick: (row: NoteRow) => openEditModal(row),\n },\n ],\n },\n\n // Pagination settings\n pagination: {\n pageSize: 25,\n },\n});\n\n// Mutations\nconst { mutate: createNote } = useMutation((api, input: any) => api.notes.createNote(input), {\n invalidate: /^notes?:/,\n onSuccess: () => {\n // Refetch tags to include any new tags\n refetchNoteTags();\n },\n});\n\n// Form handlers\nconst handleSubmit = async (formData: any) => {\n const result = await createNote({\n record_id: props.recordId,\n record_type: props.recordType,\n body: formData.body,\n tag: formData.tag || null,\n is_internal: isInternalNote.value,\n });\n refresh();\n return result;\n};\n\nconst handleSuccess = async () => {\n refreshFormData();\n toast.success('Note added successfully!');\n refresh();\n};\n\nconst handleError = (error: Error | unknown) => {\n form.setSubmitError(error instanceof Error ? error.message : 'An unknown error occurred');\n};\n\n// Edit modal handlers\nconst openEditModal = (note: NoteRow) => {\n selectedNote.value = note;\n isEditModalOpen.value = true;\n};\n\nconst closeEditModal = () => {\n isEditModalOpen.value = false;\n selectedNote.value = null;\n};\n\nconst handleEditSuccess = async () => {\n // Refetch tags to include any new tags from the updated note\n await refetchNoteTags();\n // Refresh the data table to show updated note\n refresh();\n};\n\n// Watch for changes in recordId or recordType to refresh the data table\nwatch(\n () => [props.recordId, props.recordType],\n () => {\n if (props.recordId && props.recordType) {\n refresh();\n }\n },\n);\n\n// Watch for changes in noteTagsData to refresh form's data loaders\n// This ensures the create note form's tag combobox gets updated options\nwatch(\n noteTagsData,\n async () => {\n // Reload the tag data loader to refresh form.extraData.tag\n if (form.extraData && form.extraData.tag !== undefined) {\n const newTags = await loadNoteTags();\n form.extraData.tag = newTags;\n }\n },\n { deep: true },\n);\n</script>\n","<template>\n <NoteList :recordId=\"team_id\" recordType=\"team\" mode=\"customer\" />\n</template>\n\n<script setup lang=\"ts\">\nimport NoteList from '../note/components/NoteList.vue';\nimport { useRoute } from 'vue-router';\n\nconst route = useRoute();\nconst team_id = route.params.id as string;\n</script>\n"],"mappings":"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"}
1
+ {"version":3,"file":"TeamNotesTab-Dj12Q2gD.js","names":["variables: NoteFiltersDto"],"sources":["../src/slices/note/noteUpdateMetadata.ts","../src/slices/note/components/EditNoteModal.vue","../src/slices/note/noteFormMetadata.ts","../src/slices/note/noteRowSchema.ts","../src/slices/note/components/NoteList.vue","../src/slices/team/TeamNotesTab.vue"],"sourcesContent":["import { withMetadata } from '@dragonmastery/zinia-forms-core';\nimport { NoteUpdateSchema } from '@dragonmastery/dragoncore-shared';\n\nexport const noteUpdateMetadata = withMetadata(\n NoteUpdateSchema.pick({ body: true, tag: true }),\n 'noteUpdateForm',\n {\n body: {\n label: 'Note',\n placeholder: 'Enter your note here...',\n inputType: 'textarea',\n helpText: 'Update the note content',\n },\n tag: {\n label: 'Tag',\n inputType: 'combobox',\n helpText: 'Optional tag to categorize this note',\n },\n },\n);\n","<template>\n <dialog ref=\"modal\" class=\"modal\">\n <div class=\"modal-box\">\n <h3 class=\"font-bold text-lg mb-4\">Edit Note</h3>\n\n <ZiniaForm\n @handle-submit=\"handleSubmit\"\n @success=\"handleSuccess\"\n @error=\"handleError\"\n title=\"\"\n subtitle=\"\"\n >\n <zinia.TagField :select-options=\"form.extraData.tag || []\" :allow-create=\"true\" />\n <zinia.BodyField />\n\n <!-- Show visibility status (read-only) -->\n <div class=\"form-control\">\n <label class=\"label\">\n <span class=\"label-text\">Visibility</span>\n <span class=\"badge\" :class=\"isInternalNote ? 'badge-warning' : 'badge-info'\">\n {{ isInternalNote ? 'Internal' : 'External' }}\n </span>\n </label>\n </div>\n\n <div v-if=\"form.submitError\" class=\"alert alert-error mt-2\">\n <span>{{ form.submitError }}</span>\n </div>\n\n <div class=\"flex justify-end gap-2 mt-6\">\n <button type=\"button\" class=\"btn btn-ghost\" @click=\"closeModal\">Cancel</button>\n <ZiniaSubmitButton submitText=\"Update Note\" submittingText=\"Updating...\" />\n </div>\n\n <ZiniaFormErrorsSummary title=\"Please fix the following errors:\" />\n </ZiniaForm>\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 { useForm } from '@dragonmastery/zinia-forms-core';\nimport { ref, watch } from 'vue';\nimport { toast } from 'vue3-toastify';\nimport { useMutation } from '../../../composables/useMutation';\nimport { useQuery } from '../../../composables/useQuery';\nimport type { NoteRow } from '../noteRowSchema';\nimport { noteUpdateMetadata } from '../noteUpdateMetadata';\n\ninterface Props {\n note: NoteRow | null;\n isOpen: boolean;\n}\n\ninterface Emits {\n (e: 'close'): void;\n (e: 'success'): void;\n}\n\nconst props = defineProps<Props>();\nconst emit = defineEmits<Emits>();\n\nconst modal = ref<HTMLDialogElement>();\n\n// Internal note toggle state\nconst isInternalNote = ref(false);\n\n// Fetch note tags for combobox\nconst {\n data: noteTagsData,\n loading: noteTagsLoading,\n error: noteTagsError,\n refetch: refetchNoteTags,\n} = useQuery((api) => api.notes.getNoteTags());\n\n// Load note tags for combobox options\nconst loadNoteTags = async () => {\n // Wait for query to complete\n while (noteTagsLoading.value) {\n await new Promise((resolve) => setTimeout(resolve, 100));\n }\n\n if (noteTagsError.value) {\n return [];\n }\n\n const tags = noteTagsData.value || [];\n\n return tags.map((tag: string) => ({\n value: tag,\n label: tag,\n }));\n};\n\nconst {\n form,\n zinia,\n ZiniaForm,\n ZiniaSubmitButton,\n ZiniaFormErrorsSummary,\n clearSavedFormState,\n refreshFormData,\n} = useForm(noteUpdateMetadata, {\n storeName: `edit-note-form-${props.note?.id || 'new'}`,\n persistToLocalStorage: false,\n renderStyle: 'daisy_ui',\n dataLoaders: {\n tag: loadNoteTags,\n },\n fetchData: async () => {\n if (!props.note) {\n return { body: '', tag: null };\n }\n return {\n body: props.note.body || '',\n tag: props.note.tag || null,\n };\n },\n});\n\nconst { mutate: updateNote } = useMutation(\n (api, input: { id: string; body: string; tag?: string | null }) =>\n api.notes.updateNote(input),\n {\n invalidate: /^notes?:/,\n onSuccess: () => {\n // Refetch tags to include any new tags\n refetchNoteTags();\n },\n },\n);\n\nconst handleSubmit = async (formData: any) => {\n if (!props.note) {\n throw new Error('No note selected for editing');\n }\n\n const response = await updateNote({\n id: props.note.id,\n body: formData.body,\n tag: formData.tag || null,\n });\n\n if (!response) {\n throw new Error('Failed to update note');\n }\n\n return response;\n};\n\nconst handleSuccess = async () => {\n clearSavedFormState();\n refreshFormData(); // Reset form to initial state\n toast.success('Note updated successfully!');\n emit('success');\n closeModal();\n};\n\nconst handleError = (error: Error | unknown) => {\n form.setSubmitError(error instanceof Error ? error.message : 'An unknown error occurred');\n};\n\nconst closeModal = () => {\n emit('close');\n};\n\n// Watch for modal open/close\nwatch(\n () => props.isOpen,\n (isOpen) => {\n if (isOpen && modal.value) {\n modal.value.showModal();\n } else if (!isOpen && modal.value) {\n modal.value.close();\n // Reset form when modal closes\n refreshFormData();\n }\n },\n);\n\n// Watch for note changes to refresh form data\nwatch(\n () => props.note,\n () => {\n if (props.note && props.isOpen) {\n form.setValue('body', props.note.body || '');\n form.setValue('tag', props.note.tag || null);\n isInternalNote.value = props.note.is_internal || false;\n }\n },\n { immediate: true },\n);\n</script>\n","import { withMetadata } from '@dragonmastery/zinia-forms-core';\nimport { NoteCreateSchema } from '@dragonmastery/dragoncore-shared';\n\nexport const noteCreateMetadata = withMetadata(\n NoteCreateSchema.pick({ body: true, is_internal: true, tag: true }),\n 'noteCreateForm',\n {\n body: {\n label: 'Note',\n placeholder: 'Enter your note here...',\n inputType: 'textarea',\n helpText: 'Add a note about this record',\n },\n is_internal: {\n label: 'Internal Note',\n helpText: 'Check this box to make this note visible only to staff',\n },\n tag: {\n label: 'Tag',\n inputType: 'combobox',\n helpText: 'Optional tag to categorize this note',\n },\n },\n);\n","import { withMetadata } from '@dragonmastery/zinia-forms-core';\nimport { NoteReadSchema } from '@dragonmastery/dragoncore-shared';\nimport { z } from 'zod';\n\nexport const noteRowSchemaWithMetadata = withMetadata(NoteReadSchema, 'noteRowSchema', {\n body: { label: 'Note' },\n tag: { label: 'Tag', sortable: true },\n is_internal: { label: 'Visibility', sortable: true },\n created_at: { label: 'Created', sortable: true },\n created_by: { label: 'Created By', sortable: true },\n updated_at: { label: 'Updated', sortable: true },\n});\n\nexport type NoteRow = z.infer<typeof NoteReadSchema>;\n","<template>\n <div class=\"space-y-6\">\n <!-- Add Note Form -->\n <div class=\"mt-4\">\n <ZiniaForm\n @handle-submit=\"handleSubmit\"\n @success=\"handleSuccess\"\n @error=\"handleError\"\n title=\"\"\n subtitle=\"\"\n >\n <zinia.TagField :select-options=\"form.extraData.tag || []\" :allow-create=\"true\" />\n <zinia.BodyField />\n\n <div v-if=\"form.submitError\" class=\"alert alert-error mt-2\">\n <span>{{ form.submitError }}</span>\n </div>\n\n <div class=\"flex justify-end mt-6\">\n <ZiniaSubmitButton submitText=\"Add Note\" submittingText=\"Adding...\" />\n </div>\n\n <ZiniaFormErrorsSummary title=\"Please fix the following errors:\" />\n </ZiniaForm>\n </div>\n\n <!-- Notes Table -->\n <ZiniaDataTable>\n <template #cell-created_by=\"{ row }\">\n {{ row.created_by_display_name ?? row.created_by ?? '-' }}\n </template>\n <template #cell-created_at=\"{ row }\">\n {{ formatSystemTimestamp(row.created_at) }}\n </template>\n\n <template #cell-tag=\"{ row }\">\n {{ row.tag || '-' }}\n </template>\n\n <template #cell-updated_at=\"{ row }\">\n {{ row.updated_at ? formatSystemTimestamp(row.updated_at) : '-' }}\n </template>\n\n <template #cell-body=\"{ row }\">\n <div class=\"whitespace-pre-wrap\">\n {{ row.body || 'No content' }}\n </div>\n </template>\n </ZiniaDataTable>\n\n <!-- Edit Modal -->\n <EditNoteModal\n :note=\"selectedNote\"\n :is-open=\"isEditModalOpen\"\n @close=\"closeEditModal\"\n @success=\"handleEditSuccess\"\n />\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { executeWithAuth } from '../../../composables/useRpcAuth';\nimport { getRefreshTokenHandler } from '../../../utils/EnhancedRefreshTokenHandler';\nimport { useMutation } from '../../../composables/useMutation';\nimport { useQuery } from '../../../composables/useQuery';\nimport { formatSystemTimestamp } from '../../../utils/convertToLocalDateTime';\nimport EditNoteModal from './EditNoteModal.vue';\nimport { noteCreateMetadata } from '../noteFormMetadata';\nimport { noteRowSchemaWithMetadata, type NoteRow } from '../noteRowSchema';\nimport { ActionIcons, useCursorDataTable, useForm } from '@dragonmastery/zinia-forms-core';\nimport { OPERATORS, type NoteFiltersDto } from '@dragonmastery/dragoncore-shared';\nimport { computed, ref, watch } from 'vue';\nimport { toast } from 'vue3-toastify';\n\ninterface Props {\n recordId: string;\n recordType: string;\n mode?: 'customer' | 'internal';\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n mode: 'customer',\n});\n\n// Edit modal state\nconst selectedNote = ref<NoteRow | null>(null);\nconst isEditModalOpen = ref(false);\n\n// Computed properties for component intelligence\nconst isInternalNote = computed(() => {\n // Determine internal state based on mode\n return props.mode === 'internal';\n});\n\n// Query filters state\nconst queryFilters = ref<NoteFiltersDto>({\n record_id: { operator: OPERATORS.EQUALS, value: props.recordId },\n record_type: { operator: OPERATORS.EQUALS, value: props.recordType as any },\n});\n\n// Pagination token for breadcrumb navigation\nconst currentPaginationToken = ref<string | undefined | null>();\n\n// Fetch note tags for filter and form\nconst {\n data: noteTagsData,\n loading: noteTagsLoading,\n error: noteTagsError,\n refetch: refetchNoteTags,\n} = useQuery((api) => api.notes.getNoteTags());\n\n// Load note tags for filter options and form combobox\n// This function reads from noteTagsData.value, which is reactive\n// When refetchNoteTags() is called, noteTagsData.value updates\n// The next time this function is called (when filter dropdown opens), it will get fresh data\nconst loadNoteTags = async () => {\n // If query is loading, wait for it to complete to ensure we have fresh data\n while (noteTagsLoading.value) {\n await new Promise((resolve) => setTimeout(resolve, 100));\n }\n\n if (noteTagsError.value) {\n return [];\n }\n\n const tags = noteTagsData.value || [];\n\n return tags.map((tag: string) => ({\n value: tag,\n label: tag,\n }));\n};\n\n// Form setup\nconst { form, zinia, ZiniaForm, ZiniaSubmitButton, ZiniaFormErrorsSummary, refreshFormData } =\n useForm(noteCreateMetadata, {\n storeName: `note-form-${props.recordId}`,\n persistToLocalStorage: false,\n renderStyle: 'daisy_ui',\n dataLoaders: {\n tag: loadNoteTags,\n },\n fetchData: async () => ({\n body: '',\n tag: null,\n is_internal: isInternalNote.value,\n }),\n });\n\n// Data table configuration\nconst { ZiniaDataTable, refresh } = useCursorDataTable(noteRowSchemaWithMetadata, {\n fetchData: async ({ cursor, pageSize, sort, filters, search }) => {\n // Build query variables\n const variables: NoteFiltersDto = {\n first: pageSize,\n sortBy: sort?.field ? (sort.field as string) : 'created_at',\n sortDirection: (sort?.direction === 'asc' ? 'asc' : 'desc') as any,\n ...(cursor ? { after: cursor } : {}),\n ...(currentPaginationToken.value\n ? { paginationToken: currentPaginationToken.value }\n : {}),\n ...(search ? { search } : {}),\n record_id: { operator: OPERATORS.EQUALS, value: props.recordId },\n record_type: { operator: OPERATORS.EQUALS, value: props.recordType as any },\n ...filters,\n };\n\n // Apply visibility filter based on mode\n if (props.mode === 'customer') {\n variables.is_internal = { operator: OPERATORS.EQUALS, value: false };\n } else if (props.mode === 'internal') {\n variables.is_internal = { operator: OPERATORS.EQUALS, value: true };\n }\n // For 'all' mode, no filter is applied (shows everything)\n\n // Update query filters and execute\n queryFilters.value = variables;\n const result = await executeWithAuth(\n async (api) => {\n return await api.notes.getNotes(variables);\n },\n { refreshTokenHandler: getRefreshTokenHandler() },\n );\n currentPaginationToken.value = result?.pageInfo?.paginationToken;\n\n // Return paginated data\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\n columns: {\n created_by: {\n label: 'Created By',\n field: 'created_by',\n sortable: true,\n verticalAlign: 'top',\n },\n updated_at: {\n label: 'Updated',\n field: 'updated_at',\n sortable: true,\n verticalAlign: 'top',\n },\n tag: {\n label: 'Tag',\n field: 'tag',\n sortable: true,\n filterable: true,\n filterType: 'select',\n filterOptionsLoader: loadNoteTags,\n verticalAlign: 'top',\n },\n body: {\n label: 'Note',\n field: 'body',\n sortable: false,\n },\n },\n\n // Action buttons\n actions: {\n column: {\n verticalAlign: 'top',\n },\n items: [\n {\n key: 'edit',\n icon: ActionIcons.edit,\n size: 'xs',\n variant: 'primary',\n type: 'button',\n onClick: (row: NoteRow) => openEditModal(row),\n },\n ],\n },\n\n // Pagination settings\n pagination: {\n pageSize: 25,\n },\n});\n\n// Mutations\nconst { mutate: createNote } = useMutation((api, input: any) => api.notes.createNote(input), {\n invalidate: /^notes?:/,\n onSuccess: () => {\n // Refetch tags to include any new tags\n refetchNoteTags();\n },\n});\n\n// Form handlers\nconst handleSubmit = async (formData: any) => {\n const result = await createNote({\n record_id: props.recordId,\n record_type: props.recordType,\n body: formData.body,\n tag: formData.tag || null,\n is_internal: isInternalNote.value,\n });\n refresh();\n return result;\n};\n\nconst handleSuccess = async () => {\n refreshFormData();\n toast.success('Note added successfully!');\n refresh();\n};\n\nconst handleError = (error: Error | unknown) => {\n form.setSubmitError(error instanceof Error ? error.message : 'An unknown error occurred');\n};\n\n// Edit modal handlers\nconst openEditModal = (note: NoteRow) => {\n selectedNote.value = note;\n isEditModalOpen.value = true;\n};\n\nconst closeEditModal = () => {\n isEditModalOpen.value = false;\n selectedNote.value = null;\n};\n\nconst handleEditSuccess = async () => {\n // Refetch tags to include any new tags from the updated note\n await refetchNoteTags();\n // Refresh the data table to show updated note\n refresh();\n};\n\n// Watch for changes in recordId or recordType to refresh the data table\nwatch(\n () => [props.recordId, props.recordType],\n () => {\n if (props.recordId && props.recordType) {\n refresh();\n }\n },\n);\n\n// Watch for changes in noteTagsData to refresh form's data loaders\n// This ensures the create note form's tag combobox gets updated options\nwatch(\n noteTagsData,\n async () => {\n // Reload the tag data loader to refresh form.extraData.tag\n if (form.extraData && form.extraData.tag !== undefined) {\n const newTags = await loadNoteTags();\n form.extraData.tag = newTags;\n }\n },\n { deep: true },\n);\n</script>\n","<template>\n <NoteList :recordId=\"team_id\" recordType=\"team\" mode=\"customer\" />\n</template>\n\n<script setup lang=\"ts\">\nimport NoteList from '../note/components/NoteList.vue';\nimport { useRoute } from 'vue-router';\n\nconst route = useRoute();\nconst team_id = route.params.id as string;\n</script>\n"],"mappings":"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"}
@@ -2,6 +2,6 @@ import "./useRpcAuth-SgNzCAPa.js";
2
2
  import "./useQueryCache-DIGf3fCM.js";
3
3
  import "./useMutation-DzRSXPB1.js";
4
4
  import "./useQuery-bvJabe9Q.js";
5
- import { t as EditUserPage_default } from "./EditUserPage-DFMiGciD.js";
5
+ import { t as TeamNotesTab_default } from "./TeamNotesTab-Dj12Q2gD.js";
6
6
 
7
- export { EditUserPage_default as default };
7
+ export { TeamNotesTab_default as default };
@@ -0,0 +1,32 @@
1
+ import "./useRpcAuth-SgNzCAPa.js";
2
+ import "./useQueryCache-DIGf3fCM.js";
3
+ import "./useMutation-DzRSXPB1.js";
4
+ import "./useQuery-bvJabe9Q.js";
5
+ import { ct as TeamParent_default } from "./src-B5eswi_J.js";
6
+ import "./AppLink-CHMMrSFI.js";
7
+ import "./TimelineSystemEvent-CBwUl5G8.js";
8
+ import "./TeamMembersTab-4gmnP9sD.js";
9
+ import "./Appearance-BfPdKMXw.js";
10
+ import "./useBreadcrumbs-B-W-miq6.js";
11
+ import "./EditTeamMemberForm-Cy8nzoUb.js";
12
+ import "./TeamHistoryTab-BQ-eXtiw.js";
13
+ import "./UserProfilePage-DMwDVgXa.js";
14
+ import "./ChangePasswordPage-D2Ci00Sh.js";
15
+ import "./TeamNotesTab-Dj12Q2gD.js";
16
+ import "./CustomerSupportTicketParent-iBV1KRKL.js";
17
+ import "./SupportTicketDevLifecycleBadge-B2NysMAj.js";
18
+ import "./StaffSupportTicketParent-KYzy4eb4.js";
19
+ import "./LoginForm-DyHmiC1I.js";
20
+ import "./Signup-Ct0m0x78.js";
21
+ import "./ForgotPassword-CJg_buPl.js";
22
+ import "./ResetPassword-4HLdgM7s.js";
23
+ import "./Logout-C6pWyTIm.js";
24
+ import "./mfaSchema-_vbG9jiT.js";
25
+ import "./MfaSetup-D80HhwEz.js";
26
+ import "./MfaVerify-BEd-f6oV.js";
27
+ import "./VerifyEmail-CHfTzrHg.js";
28
+ import "./UserListPage-D-IdlsHK.js";
29
+ import "./CreateUserPage-DbT_l32W.js";
30
+ import "./EditUserPage-CIRqNko-.js";
31
+
32
+ export { TeamParent_default as default };
@@ -510,4 +510,4 @@ var TimelineNoteInput_default = _sfc_main;
510
510
 
511
511
  //#endregion
512
512
  export { SupportTicketAttachmentsCollapsible_default as a, parseRecordVersions as i, MetadataField_default as n, ActionBannerAlert_default as r, TimelineNoteInput_default as t };
513
- //# sourceMappingURL=TimelineNoteInput-hpCxzQjP.js.map
513
+ //# sourceMappingURL=TimelineNoteInput-DGDgyGe-.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"TimelineNoteInput-hpCxzQjP.js","names":["events: SystemEvent[]","collectedChanges: Array<{\n action: string;\n oldValue: string | null;\n newValue: string | null;\n fieldName: string;\n }>","map: Record<AlertVariant, string>","copyTimeoutId: ReturnType<typeof setTimeout> | null"],"sources":["../src/slices/support_ticket/shared/SupportTicketAttachmentsCollapsible.vue","../src/slices/support_ticket/utils/parseRecordVersions.ts","../src/slices/support_ticket/shared/ActionBannerAlert.vue","../src/slices/support_ticket/shared/MetadataField.vue","../src/slices/support_ticket/shared/timelineNoteFormMetadata.ts","../src/slices/support_ticket/shared/TimelineNoteInput.vue"],"sourcesContent":["<template>\n <div v-if=\"recordId\" class=\"w-full\">\n <div class=\"collapse collapse-arrow bg-base-200\">\n <input type=\"checkbox\" v-model=\"attachmentsExpanded\" />\n <div class=\"collapse-title text-sm font-medium px-4 py-2 min-h-0\">\n <div class=\"flex items-center gap-2\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n class=\"h-4 w-4\"\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=\"M15.172 7l-6.586 6.586a2 2 0 102.828 2.828l6.414-6.586a4 4 0 00-5.656-5.656l-6.415 6.585a6 6 0 108.486 8.486L20.5 13\"\n />\n </svg>\n <span>Attachments ({{ attachmentsCount }})</span>\n </div>\n </div>\n <div class=\"collapse-content px-0\">\n <div class=\"px-4 pb-4\">\n <InlineAttachments\n :record-id=\"recordId\"\n :can-upload=\"editable && !locked\"\n :can-delete=\"editable && !locked\"\n @update:attachments-count=\"attachmentsCount = $event\"\n @uploaded=\"emit('uploaded')\"\n @deleted=\"emit('deleted')\"\n />\n </div>\n </div>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref } from 'vue';\nimport InlineAttachments from './InlineAttachments.vue';\n\nconst attachmentsCount = ref(0);\n\ninterface Props {\n recordId: string;\n locked: boolean;\n editable: boolean;\n}\n\ndefineProps<Props>();\n\nconst emit = defineEmits<{ uploaded: []; deleted: [] }>();\n\nconst attachmentsExpanded = ref(false);\n</script>\n","import {\n supportTicketNumberToPriority,\n type RecordVersionReadDto,\n} from '@dragonmastery/dragoncore-shared';\nimport { formatTicketDate } from './formatTicketDate';\n\nexport interface SystemEventChange {\n action: string;\n oldValue: string | null;\n newValue: string | null;\n fieldName?: string;\n}\n\nexport interface SystemEvent {\n id: string;\n timestamp: string;\n author: string;\n message: string;\n /** When set, used for structured display: action (italic) + type (badge) + details */\n action?: string;\n type?: string | null;\n details?: string | null;\n oldValue?: string | null;\n newValue?: string | null;\n fieldName?: string; // Field name that changed (for filtering)\n /** When multiple fields changed in same record version, grouped changes */\n changes?: SystemEventChange[];\n}\n\nconst SKIP_FIELDS = new Set(['updated_at', 'updated_by', 'id', 'display_id']);\n\n/** Fields that store user IDs - display names from lookup instead of raw IDs */\nconst USER_ID_FIELDS = new Set([\n 'assigned_to',\n 'created_by',\n 'updated_by',\n 'archived_by',\n 'deleted_by',\n]);\n\nfunction truncate(value: string, maxLength: number = 50): string {\n if (value.length <= maxLength) return value;\n return value.substring(0, maxLength) + '...';\n}\n\nfunction formatEnumValue(value: string): string {\n return value\n .split('_')\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join(' ');\n}\n\nfunction formatFieldValue(\n fieldName: string,\n value: unknown,\n truncateLong: boolean = false,\n displayMap?: Map<string, string>,\n): string {\n if (value === null || value === undefined) return '';\n if (typeof value === 'string' && /^\\d{4}-\\d{2}-\\d{2}/.test(value)) {\n return formatTicketDate(value).formatted;\n }\n if (typeof value === 'boolean') return value ? 'Yes' : 'No';\n // User ID fields: display name from lookup when available\n if (typeof value === 'string' && USER_ID_FIELDS.has(fieldName) && displayMap) {\n return displayMap.get(value) ?? value;\n }\n // Priority: DB stores number (1-4), record_versions may have legacy string or new number\n if (fieldName === 'priority') {\n if (typeof value === 'number') {\n return formatEnumValue(supportTicketNumberToPriority(value));\n }\n if (typeof value === 'string') return formatEnumValue(value);\n }\n if (typeof value === 'string') {\n if (\n fieldName.includes('status') ||\n fieldName.includes('type') ||\n fieldName.includes('lifecycle')\n ) {\n return formatEnumValue(value);\n }\n // Truncate title and description\n if (truncateLong && (fieldName === 'title' || fieldName === 'description')) {\n return truncate(value);\n }\n }\n return String(value);\n}\n\nfunction generateActionMessage(\n fieldName: string,\n oldValue: unknown,\n newValue: unknown,\n): string {\n switch (fieldName) {\n case 'assigned_to':\n if (oldValue === null || oldValue === undefined) return 'assigned to';\n return 'reassigned to';\n case 'title':\n return 'changed the title';\n case 'description':\n return 'updated the description';\n case 'type':\n return 'changed type';\n case 'priority':\n return 'changed priority';\n case 'approval_status':\n return 'changed status';\n case 'dev_lifecycle':\n return 'moved';\n case 'credit_value':\n if (oldValue === null || oldValue === undefined) return 'set credits';\n return 'changed credits';\n case 'delivered_value':\n if (oldValue === null || oldValue === undefined) return 'set delivered value';\n return 'changed delivered value';\n case 'start_at':\n if (oldValue === null || oldValue === undefined) return 'set start date';\n if (newValue === null || newValue === undefined) return 'cleared start date';\n return 'changed start date';\n case 'target_at':\n if (oldValue === null || oldValue === undefined) return 'set target date';\n if (newValue === null || newValue === undefined) return 'cleared target date';\n return 'changed target date';\n case 'completed_at':\n if (oldValue === null || oldValue === undefined) return 'marked as completed';\n if (newValue === null || newValue === undefined) return 'cleared completed date';\n return 'changed completed date';\n case 'locked_approval_at':\n if (\n oldValue === null ||\n (oldValue === undefined && newValue !== null && newValue !== undefined)\n ) {\n return 'locked the ticket';\n }\n return 'changed lock status';\n case 'archived_at':\n if (\n oldValue === null ||\n (oldValue === undefined && newValue !== null && newValue !== undefined)\n ) {\n return 'archived the ticket';\n }\n if (\n oldValue !== null &&\n oldValue !== undefined &&\n (newValue === null || newValue === undefined)\n ) {\n return 'unarchived the ticket';\n }\n return 'changed archive status';\n case 'requester_email':\n return 'changed requester email';\n case 'requester_name':\n return 'changed requester name';\n case 'attachment_added':\n return 'added attachment';\n case 'attachment_removed':\n return 'removed attachment';\n default:\n return `updated ${fieldName.replace(/_/g, ' ')}`;\n }\n}\n\nfunction parseRecord(recordJson: string | null | undefined): Record<string, unknown> | null {\n if (!recordJson) return null;\n try {\n return JSON.parse(recordJson);\n } catch {\n return null;\n }\n}\n\nexport function parseRecordVersions(\n versions: RecordVersionReadDto[],\n displayMap?: Map<string, string>,\n): SystemEvent[] {\n const events: SystemEvent[] = [];\n\n for (const version of versions) {\n const author = version.auth_username || 'Unknown';\n const timestamp = version.recorded_at;\n\n if (version.operation === 'insert') {\n events.push({\n id: `${version.id}-insert`,\n timestamp,\n author,\n message: 'created this ticket',\n action: 'created',\n type: 'ticket',\n });\n continue;\n }\n\n if (version.operation === 'update') {\n const oldRecord = parseRecord(version.old_record);\n const newRecord = parseRecord(version.record);\n\n if (!oldRecord || !newRecord) continue;\n\n const collectedChanges: Array<{\n action: string;\n oldValue: string | null;\n newValue: string | null;\n fieldName: string;\n }> = [];\n\n for (const [fieldName, newValue] of Object.entries(newRecord)) {\n if (SKIP_FIELDS.has(fieldName)) continue;\n\n const oldValue = oldRecord[fieldName];\n\n if (oldValue !== newValue) {\n const oldFormatted =\n oldValue !== null && oldValue !== undefined\n ? formatFieldValue(fieldName, oldValue, true, displayMap)\n : null;\n const newFormatted =\n newValue !== null && newValue !== undefined\n ? formatFieldValue(fieldName, newValue, true, displayMap)\n : null;\n\n const actionMsg = generateActionMessage(fieldName, oldValue, newValue);\n\n collectedChanges.push({\n action: actionMsg,\n oldValue: oldFormatted || null,\n newValue: newFormatted || null,\n fieldName,\n });\n }\n }\n\n if (collectedChanges.length > 0) {\n const primaryChange = collectedChanges[0]!;\n const details =\n primaryChange.oldValue != null && primaryChange.newValue != null\n ? `${primaryChange.oldValue} → ${primaryChange.newValue}`\n : primaryChange.newValue ?? null;\n\n events.push({\n id: version.id,\n timestamp,\n author,\n message: primaryChange.action,\n action: collectedChanges.length === 1 ? primaryChange.action : 'updated',\n type: 'ticket',\n details: collectedChanges.length === 1 ? details : null,\n oldValue: collectedChanges.length === 1 ? primaryChange.oldValue : undefined,\n newValue: collectedChanges.length === 1 ? primaryChange.newValue : undefined,\n fieldName: collectedChanges.length === 1 ? primaryChange.fieldName : undefined,\n changes:\n collectedChanges.length > 1\n ? collectedChanges.map((c) => ({\n action: c.action,\n oldValue: c.oldValue,\n newValue: c.newValue,\n fieldName: c.fieldName,\n }))\n : undefined,\n });\n }\n }\n }\n\n events.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());\n return events;\n}\n","<template>\n <div\n role=\"alert\"\n :class=\"[\n 'py-3 px-4 w-full rounded-lg border border-base-300 border-l-4 bg-base-200/60',\n variantBorderClass,\n ]\"\n >\n <!-- Mobile-first: stack vertically on small screens, row on desktop -->\n <div\n class=\"flex flex-col gap-3 sm:flex-row sm:items-center sm:gap-3\"\n >\n <div class=\"flex items-start gap-3 min-w-0\">\n <component :is=\"iconComponent\" v-if=\"icon\" class=\"shrink-0 w-5 h-5 opacity-90 mt-0.5\" />\n <span class=\"flex-1 min-w-0\">\n <slot />\n </span>\n </div>\n <div\n v-if=\"hasActions\"\n class=\"grid grid-cols-2 gap-2 sm:flex sm:flex-row sm:flex-wrap sm:ml-auto sm:shrink-0 sm:[&>*]:w-auto\"\n >\n <slot name=\"actions\" />\n </div>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, useSlots, h } from 'vue';\n\ntype AlertVariant = 'warning' | 'success' | 'error' | 'info' | 'neutral';\ntype IconType = 'lock' | 'clock' | 'info' | 'archive';\n\ninterface Props {\n variant: AlertVariant;\n icon?: IconType;\n}\n\nconst props = defineProps<Props>();\n\nconst slots = useSlots();\n\nconst variantBorderClass = computed(() => {\n const map: Record<AlertVariant, string> = {\n warning: 'border-l-warning',\n success: 'border-l-success',\n error: 'border-l-error',\n info: 'border-l-info',\n neutral: 'border-l-base-content/30',\n };\n return map[props.variant];\n});\n\nconst hasActions = computed(() => {\n const actionsSlot = slots.actions;\n if (!actionsSlot) return false;\n const vnodes = actionsSlot();\n return !!vnodes?.length;\n});\n\nconst iconComponent = computed(() => {\n if (!props.icon) return null;\n const icons = {\n lock: () =>\n h(\n 'svg',\n {\n xmlns: 'http://www.w3.org/2000/svg',\n fill: 'none',\n viewBox: '0 0 24 24',\n 'stroke-width': '1.5',\n stroke: 'currentColor',\n class: 'w-5 h-5',\n },\n [\n h('path', {\n 'stroke-linecap': 'round',\n 'stroke-linejoin': 'round',\n d: 'M16.5 10.5V6.75a4.5 4.5 0 10-9 0v3.75m-.75 11.25h10.5a2.25 2.25 0 002.25-2.25v-6.75a2.25 2.25 0 00-2.25-2.25H6.75a2.25 2.25 0 00-2.25 2.25v6.75a2.25 2.25 0 002.25 2.25z',\n }),\n ],\n ),\n clock: () =>\n h(\n 'svg',\n {\n xmlns: 'http://www.w3.org/2000/svg',\n fill: 'none',\n viewBox: '0 0 24 24',\n 'stroke-width': '1.5',\n stroke: 'currentColor',\n class: 'w-5 h-5',\n },\n [\n h('path', {\n 'stroke-linecap': 'round',\n 'stroke-linejoin': 'round',\n d: 'M12 6v6h4.5m4.5 0a9 9 0 11-18 0 9 9 0 0118 0z',\n }),\n ],\n ),\n info: () =>\n h(\n 'svg',\n {\n xmlns: 'http://www.w3.org/2000/svg',\n fill: 'none',\n viewBox: '0 0 24 24',\n 'stroke-width': '1.5',\n stroke: 'currentColor',\n class: 'w-5 h-5',\n },\n [\n h('path', {\n 'stroke-linecap': 'round',\n 'stroke-linejoin': 'round',\n d: 'M11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008H12V8.25z',\n }),\n ],\n ),\n archive: () =>\n h(\n 'svg',\n {\n xmlns: 'http://www.w3.org/2000/svg',\n fill: 'none',\n viewBox: '0 0 24 24',\n 'stroke-width': '1.5',\n stroke: 'currentColor',\n class: 'w-5 h-5',\n },\n [\n h('path', {\n 'stroke-linecap': 'round',\n 'stroke-linejoin': 'round',\n d: 'M20.25 7.5l-.625 10.632a2.25 2.25 0 01-2.247 2.118H6.622a2.25 2.25 0 01-2.247-2.118L3.75 7.5M10 11.25h4M3.375 7.5h17.25c.621 0 1.125-.504 1.125-1.125v-1.5c0-.621-.504-1.125-1.125-1.125H3.375c-.621 0-1.125.504-1.125 1.125v1.5c0 .621.504 1.125 1.125 1.125z',\n }),\n ],\n ),\n };\n return icons[props.icon] ?? null;\n});\n</script>\n","<template>\n <div class=\"flex flex-col\">\n <span class=\"text-xs font-semibold uppercase tracking-wide text-base-content/50 mb-0.5\">\n {{ label }}\n </span>\n <template v-if=\"hasContent\">\n <span\n v-if=\"copyable\"\n ref=\"valueRef\"\n role=\"button\"\n tabindex=\"0\"\n class=\"font-mono cursor-pointer select-all\"\n @click=\"handleCopy\"\n @keydown.enter=\"handleCopy\"\n @keydown.space.prevent=\"handleCopy\"\n >\n {{ copied ? 'Copied!' : undefined }}\n <template v-if=\"!copied\"><slot /></template>\n </span>\n <span v-else>\n <slot />\n </span>\n </template>\n <template v-else>\n <slot name=\"empty\">\n <span class=\"text-base-content/50 italic text-sm\">Not set</span>\n </slot>\n </template>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { Comment } from 'vue';\nimport { ref, computed, useSlots } from 'vue';\n\ninterface Props {\n label: string;\n copyable?: boolean;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n copyable: false,\n});\n\nconst slots = useSlots();\nconst valueRef = ref<HTMLSpanElement | null>(null);\nconst copied = ref(false);\nlet copyTimeoutId: ReturnType<typeof setTimeout> | null = null;\n\nconst hasContent = computed(() => {\n const defaultSlot = slots.default;\n if (!defaultSlot) return false;\n const vnodes = defaultSlot();\n if (!vnodes || !Array.isArray(vnodes)) return false;\n return vnodes.some((v) => v.type !== Comment);\n});\n\nasync function handleCopy() {\n if (!props.copyable) return;\n const text = valueRef.value?.textContent?.trim();\n if (!text) return;\n try {\n await navigator.clipboard.writeText(text);\n copied.value = true;\n if (copyTimeoutId) clearTimeout(copyTimeoutId);\n copyTimeoutId = setTimeout(() => {\n copied.value = false;\n copyTimeoutId = null;\n }, 1500);\n } catch {\n // ignore clipboard errors\n }\n}\n</script>\n","import { withMetadata } from '@dragonmastery/zinia-forms-core';\nimport { z } from 'zod';\n\n/** Schema for adding a comment/note on support ticket timeline. */\nconst TimelineNoteCreateSchema = z.object({\n body: z.string().min(1, 'Comment is required').trim(),\n is_internal: z.boolean().optional().default(false),\n});\n\nexport const timelineNoteCreateMetadata = withMetadata(\n TimelineNoteCreateSchema,\n 'timelineNoteCreateForm',\n {\n body: {\n label: 'Comment',\n placeholder: 'Add a comment...',\n inputType: 'textarea',\n },\n is_internal: {\n label: 'Internal Note',\n helpText: 'Internal notes are not visible to the customer',\n },\n },\n);\n\nexport type TimelineNoteCreateDto = z.infer<typeof TimelineNoteCreateSchema>;\n","<template>\n <div class=\"border-t border-base-200 pt-4 mt-4 w-full\">\n <template v-if=\"disabled\">\n <div class=\"bg-base-200/50 rounded-lg p-4 text-center\">\n <span class=\"text-base-content/50 text-sm inline-flex items-center gap-1.5\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke-width=\"1.5\"\n stroke=\"currentColor\"\n class=\"w-4 h-4\"\n >\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n d=\"M16.5 10.5V6.75a4.5 4.5 0 10-9 0v3.75m-.75 11.25h10.5a2.25 2.25 0 002.25-2.25v-6.75a2.25 2.25 0 00-2.25-2.25H6.75a2.25 2.25 0 00-2.25 2.25v6.75a2.25 2.25 0 002.25 2.25z\"\n />\n </svg>\n This ticket has been locked. You can no longer add comments.\n </span>\n </div>\n </template>\n <ZiniaForm\n v-else\n @handle-submit=\"handleSubmit\"\n @success=\"handleSuccess\"\n @error=\"handleError\"\n title=\"\"\n subtitle=\"\"\n >\n <div ref=\"formWrapperRef\" class=\"grid grid-cols-1 gap-4 w-full\" @keydown=\"handleKeydown\">\n <p\n v-if=\"showTypeToggle\"\n class=\"col-span-full text-xs mb-1\"\n :class=\"form.values.is_internal ? 'text-warning' : 'text-info'\"\n >\n {{\n form.values.is_internal\n ? '🔒 Internal — not visible to customer'\n : 'Visible to customer'\n }}\n </p>\n <div class=\"col-span-full\">\n <zinia.BodyField class=\"textarea w-full\" />\n </div>\n <div class=\"col-span-full flex flex-wrap gap-2 justify-between items-center\">\n <div v-if=\"showTypeToggle\" class=\"join\">\n <button\n type=\"button\"\n :class=\"[\n 'btn btn-sm join-item',\n !form.values.is_internal ? 'btn-info btn-active' : '',\n ]\"\n :disabled=\"form.isSubmitting\"\n @click=\"form.setValue('is_internal', false)\"\n >\n Customer Note\n </button>\n <button\n type=\"button\"\n :class=\"[\n 'btn btn-sm join-item',\n form.values.is_internal ? 'btn-warning btn-active' : '',\n ]\"\n :disabled=\"form.isSubmitting\"\n @click=\"form.setValue('is_internal', true)\"\n >\n Internal Note\n </button>\n </div>\n <div v-else></div>\n <ZiniaSubmitButton submitText=\"Comment\" submittingText=\"Adding...\" />\n </div>\n </div>\n </ZiniaForm>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { useForm } from '@dragonmastery/zinia-forms-core';\nimport { ref, watch } from 'vue';\nimport { timelineNoteCreateMetadata } from './timelineNoteFormMetadata';\n\ninterface Props {\n showTypeToggle: boolean;\n disabled: boolean;\n /** When provided, noteType is controlled (e.g. synced with URL query param) */\n noteType?: 'customer' | 'internal';\n /** Called when form submits with validated data. Must return a Promise. */\n onSubmit: (payload: { content: string; noteType: 'customer' | 'internal' }) => Promise<void>;\n}\n\nconst props = defineProps<Props>();\nconst formWrapperRef = ref<HTMLElement | null>(null);\n\nconst emit = defineEmits<{\n 'update:noteType': [value: 'customer' | 'internal'];\n}>();\n\nconst { form, zinia, ZiniaForm, ZiniaSubmitButton, refreshFormData } = useForm(\n timelineNoteCreateMetadata,\n {\n storeName: 'timeline-note-input',\n persistToLocalStorage: false,\n renderStyle: 'daisy_ui',\n fetchData: async () => ({\n body: '',\n is_internal: props.noteType === 'internal',\n }),\n },\n);\n\n// Sync form's is_internal when controlled noteType prop changes (e.g. from URL)\nwatch(\n () => props.noteType,\n (noteType) => {\n if (noteType !== undefined) {\n form.setValue('is_internal', noteType === 'internal');\n }\n },\n { immediate: true },\n);\n\n// Emit when user toggles note type (for URL sync in StaffTimeline)\nwatch(\n () => form.values.is_internal,\n (isInternal) => {\n if (props.showTypeToggle) {\n emit('update:noteType', isInternal ? 'internal' : 'customer');\n }\n },\n);\n\nfunction handleKeydown(e: KeyboardEvent) {\n if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') {\n e.preventDefault();\n const form = formWrapperRef.value?.closest('form');\n form?.requestSubmit();\n }\n}\n\nasync function handleSubmit(formData: { body: string; is_internal: boolean }) {\n await props.onSubmit({\n content: (formData.body ?? '').trim(),\n noteType: props.showTypeToggle && formData.is_internal ? 'internal' : 'customer',\n });\n}\n\nfunction handleSuccess() {\n refreshFormData();\n (document.activeElement as HTMLElement)?.blur();\n}\n\nfunction handleError(_error: Error | unknown) {\n // Form displays errors via ZiniaFormErrorsSummary\n}\n\nfunction reset() {\n refreshFormData();\n}\n\ndefineExpose({ reset });\n</script>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;EA2CA,MAAM,mBAAmB,IAAI,EAAE;EAU/B,MAAM,OAAO;EAEb,MAAM,sBAAsB,IAAI,MAAM;;UAtDzB,QAAA,YAAA,WAAA,EAAX,mBAmCM,OAnCN,cAmCM,CAlCJ,mBAiCM,OAjCN,cAiCM;mBAhCJ,mBAAuD,SAAA;KAAhD,MAAK;kEAAoB,oBAAmB,QAAA;qCAAnB,oBAAA,MAAmB,CAAA,CAAA;IACnD,mBAkBM,OAlBN,cAkBM,CAjBJ,mBAgBM,OAhBN,cAgBM,CAAA,OAAA,OAAA,OAAA,KAfJ,mBAaM,OAAA;KAZJ,OAAM;KACN,OAAM;KACN,MAAK;KACL,SAAQ;KACR,QAAO;QAEP,mBAKE,QAAA;KAJA,kBAAe;KACf,mBAAgB;KAChB,gBAAa;KACb,GAAE;eAGN,mBAAiD,QAAA,MAA3C,kBAAa,gBAAG,iBAAA,MAAgB,GAAG,KAAC,EAAA,CAAA,CAAA,CAAA,CAAA;IAG9C,mBAWM,OAXN,cAWM,CAVJ,mBASM,OATN,cASM,CARJ,YAOE,2BAAA;KANC,aAAW,QAAA;KACX,cAAY,QAAA,YAAQ,CAAK,QAAA;KACzB,cAAY,QAAA,YAAQ,CAAK,QAAA;KACzB,6BAAwB,OAAA,OAAA,OAAA,MAAA,WAAE,iBAAA,QAAmB;KAC7C,YAAQ,OAAA,OAAA,OAAA,MAAA,WAAE,KAAI,WAAA;KACd,WAAO,OAAA,OAAA,OAAA,MAAA,WAAE,KAAI,UAAA;;;;;;;;;;;;;;ACF1B,MAAM,cAAc,IAAI,IAAI;CAAC;CAAc;CAAc;CAAM;CAAa,CAAC;;AAG7E,MAAM,iBAAiB,IAAI,IAAI;CAC7B;CACA;CACA;CACA;CACA;CACD,CAAC;AAEF,SAAS,SAAS,OAAe,YAAoB,IAAY;AAC/D,KAAI,MAAM,UAAU,UAAW,QAAO;AACtC,QAAO,MAAM,UAAU,GAAG,UAAU,GAAG;;AAGzC,SAAS,gBAAgB,OAAuB;AAC9C,QAAO,MACJ,MAAM,IAAI,CACV,KAAK,SAAS,KAAK,OAAO,EAAE,CAAC,aAAa,GAAG,KAAK,MAAM,EAAE,CAAC,aAAa,CAAC,CACzE,KAAK,IAAI;;AAGd,SAAS,iBACP,WACA,OACA,eAAwB,OACxB,YACQ;AACR,KAAI,UAAU,QAAQ,UAAU,OAAW,QAAO;AAClD,KAAI,OAAO,UAAU,YAAY,qBAAqB,KAAK,MAAM,CAC/D,QAAO,iBAAiB,MAAM,CAAC;AAEjC,KAAI,OAAO,UAAU,UAAW,QAAO,QAAQ,QAAQ;AAEvD,KAAI,OAAO,UAAU,YAAY,eAAe,IAAI,UAAU,IAAI,WAChE,QAAO,WAAW,IAAI,MAAM,IAAI;AAGlC,KAAI,cAAc,YAAY;AAC5B,MAAI,OAAO,UAAU,SACnB,QAAO,gBAAgB,8BAA8B,MAAM,CAAC;AAE9D,MAAI,OAAO,UAAU,SAAU,QAAO,gBAAgB,MAAM;;AAE9D,KAAI,OAAO,UAAU,UAAU;AAC7B,MACE,UAAU,SAAS,SAAS,IAC5B,UAAU,SAAS,OAAO,IAC1B,UAAU,SAAS,YAAY,CAE/B,QAAO,gBAAgB,MAAM;AAG/B,MAAI,iBAAiB,cAAc,WAAW,cAAc,eAC1D,QAAO,SAAS,MAAM;;AAG1B,QAAO,OAAO,MAAM;;AAGtB,SAAS,sBACP,WACA,UACA,UACQ;AACR,SAAQ,WAAR;EACE,KAAK;AACH,OAAI,aAAa,QAAQ,aAAa,OAAW,QAAO;AACxD,UAAO;EACT,KAAK,QACH,QAAO;EACT,KAAK,cACH,QAAO;EACT,KAAK,OACH,QAAO;EACT,KAAK,WACH,QAAO;EACT,KAAK,kBACH,QAAO;EACT,KAAK,gBACH,QAAO;EACT,KAAK;AACH,OAAI,aAAa,QAAQ,aAAa,OAAW,QAAO;AACxD,UAAO;EACT,KAAK;AACH,OAAI,aAAa,QAAQ,aAAa,OAAW,QAAO;AACxD,UAAO;EACT,KAAK;AACH,OAAI,aAAa,QAAQ,aAAa,OAAW,QAAO;AACxD,OAAI,aAAa,QAAQ,aAAa,OAAW,QAAO;AACxD,UAAO;EACT,KAAK;AACH,OAAI,aAAa,QAAQ,aAAa,OAAW,QAAO;AACxD,OAAI,aAAa,QAAQ,aAAa,OAAW,QAAO;AACxD,UAAO;EACT,KAAK;AACH,OAAI,aAAa,QAAQ,aAAa,OAAW,QAAO;AACxD,OAAI,aAAa,QAAQ,aAAa,OAAW,QAAO;AACxD,UAAO;EACT,KAAK;AACH,OACE,aAAa,QACZ,aAAa,UAAa,aAAa,QAAQ,aAAa,OAE7D,QAAO;AAET,UAAO;EACT,KAAK;AACH,OACE,aAAa,QACZ,aAAa,UAAa,aAAa,QAAQ,aAAa,OAE7D,QAAO;AAET,OACE,aAAa,QACb,aAAa,WACZ,aAAa,QAAQ,aAAa,QAEnC,QAAO;AAET,UAAO;EACT,KAAK,kBACH,QAAO;EACT,KAAK,iBACH,QAAO;EACT,KAAK,mBACH,QAAO;EACT,KAAK,qBACH,QAAO;EACT,QACE,QAAO,WAAW,UAAU,QAAQ,MAAM,IAAI;;;AAIpD,SAAS,YAAY,YAAuE;AAC1F,KAAI,CAAC,WAAY,QAAO;AACxB,KAAI;AACF,SAAO,KAAK,MAAM,WAAW;SACvB;AACN,SAAO;;;AAIX,SAAgB,oBACd,UACA,YACe;CACf,MAAMA,SAAwB,EAAE;AAEhC,MAAK,MAAM,WAAW,UAAU;EAC9B,MAAM,SAAS,QAAQ,iBAAiB;EACxC,MAAM,YAAY,QAAQ;AAE1B,MAAI,QAAQ,cAAc,UAAU;AAClC,UAAO,KAAK;IACV,IAAI,GAAG,QAAQ,GAAG;IAClB;IACA;IACA,SAAS;IACT,QAAQ;IACR,MAAM;IACP,CAAC;AACF;;AAGF,MAAI,QAAQ,cAAc,UAAU;GAClC,MAAM,YAAY,YAAY,QAAQ,WAAW;GACjD,MAAM,YAAY,YAAY,QAAQ,OAAO;AAE7C,OAAI,CAAC,aAAa,CAAC,UAAW;GAE9B,MAAMC,mBAKD,EAAE;AAEP,QAAK,MAAM,CAAC,WAAW,aAAa,OAAO,QAAQ,UAAU,EAAE;AAC7D,QAAI,YAAY,IAAI,UAAU,CAAE;IAEhC,MAAM,WAAW,UAAU;AAE3B,QAAI,aAAa,UAAU;KACzB,MAAM,eACJ,aAAa,QAAQ,aAAa,SAC9B,iBAAiB,WAAW,UAAU,MAAM,WAAW,GACvD;KACN,MAAM,eACJ,aAAa,QAAQ,aAAa,SAC9B,iBAAiB,WAAW,UAAU,MAAM,WAAW,GACvD;KAEN,MAAM,YAAY,sBAAsB,WAAW,UAAU,SAAS;AAEtE,sBAAiB,KAAK;MACpB,QAAQ;MACR,UAAU,gBAAgB;MAC1B,UAAU,gBAAgB;MAC1B;MACD,CAAC;;;AAIN,OAAI,iBAAiB,SAAS,GAAG;IAC/B,MAAM,gBAAgB,iBAAiB;IACvC,MAAM,UACJ,cAAc,YAAY,QAAQ,cAAc,YAAY,OACxD,GAAG,cAAc,SAAS,KAAK,cAAc,aAC7C,cAAc,YAAY;AAEhC,WAAO,KAAK;KACV,IAAI,QAAQ;KACZ;KACA;KACA,SAAS,cAAc;KACvB,QAAQ,iBAAiB,WAAW,IAAI,cAAc,SAAS;KAC/D,MAAM;KACN,SAAS,iBAAiB,WAAW,IAAI,UAAU;KACnD,UAAU,iBAAiB,WAAW,IAAI,cAAc,WAAW;KACnE,UAAU,iBAAiB,WAAW,IAAI,cAAc,WAAW;KACnE,WAAW,iBAAiB,WAAW,IAAI,cAAc,YAAY;KACrE,SACE,iBAAiB,SAAS,IACtB,iBAAiB,KAAK,OAAO;MAC3B,QAAQ,EAAE;MACV,UAAU,EAAE;MACZ,UAAU,EAAE;MACZ,WAAW,EAAE;MACd,EAAE,GACH;KACP,CAAC;;;;AAKR,QAAO,MAAM,GAAG,MAAM,IAAI,KAAK,EAAE,UAAU,CAAC,SAAS,GAAG,IAAI,KAAK,EAAE,UAAU,CAAC,SAAS,CAAC;AACxF,QAAO;;;;;;;;;;;;;;;;;;;ECrOT,MAAM,QAAQ;EAEd,MAAM,QAAQ,UAAU;EAExB,MAAM,qBAAqB,eAAe;AAQxC,UAP0C;IACxC,SAAS;IACT,SAAS;IACT,OAAO;IACP,MAAM;IACN,SAAS;IACV,CACU,MAAM;IACjB;EAEF,MAAM,aAAa,eAAe;GAChC,MAAM,cAAc,MAAM;AAC1B,OAAI,CAAC,YAAa,QAAO;AAEzB,UAAO,CAAC,CADO,aAAa,EACX;IACjB;EAEF,MAAM,gBAAgB,eAAe;AACnC,OAAI,CAAC,MAAM,KAAM,QAAO;AA+ExB,UA9Ec;IACZ,YACE,EACE,OACA;KACE,OAAO;KACP,MAAM;KACN,SAAS;KACT,gBAAgB;KAChB,QAAQ;KACR,OAAO;KACR,EACD,CACE,EAAE,QAAQ;KACR,kBAAkB;KAClB,mBAAmB;KACnB,GAAG;KACJ,CAAC,CACH,CACF;IACH,aACE,EACE,OACA;KACE,OAAO;KACP,MAAM;KACN,SAAS;KACT,gBAAgB;KAChB,QAAQ;KACR,OAAO;KACR,EACD,CACE,EAAE,QAAQ;KACR,kBAAkB;KAClB,mBAAmB;KACnB,GAAG;KACJ,CAAC,CACH,CACF;IACH,YACE,EACE,OACA;KACE,OAAO;KACP,MAAM;KACN,SAAS;KACT,gBAAgB;KAChB,QAAQ;KACR,OAAO;KACR,EACD,CACE,EAAE,QAAQ;KACR,kBAAkB;KAClB,mBAAmB;KACnB,GAAG;KACJ,CAAC,CACH,CACF;IACH,eACE,EACE,OACA;KACE,OAAO;KACP,MAAM;KACN,SAAS;KACT,gBAAgB;KAChB,QAAQ;KACR,OAAO;KACR,EACD,CACE,EAAE,QAAQ;KACR,kBAAkB;KAClB,mBAAmB;KACnB,GAAG;KACJ,CAAC,CACH,CACF;IACJ,CACY,MAAM,SAAS;IAC5B;;uBA7IA,mBAwBM,OAAA;IAvBJ,MAAK;IACJ,OAAK,eAAA,CAAA,gFAAgG,mBAAA,MAAA,CAAA;OAKtG,mBAAA,oEAAwE,EACxE,mBAeM,OAfN,cAeM,CAZJ,mBAKM,OALN,cAKM,CAJiC,QAAA,QAAA,WAAA,EAArC,YAAwF,wBAAxE,cAAA,MAAa,EAAA;;IAAc,OAAM;2CACjD,mBAEO,QAFP,cAEO,CADL,WAAQ,KAAA,QAAA,UAAA,CAAA,CAAA,CAAA,CAAA,EAIJ,WAAA,SAAA,WAAA,EADR,mBAKM,OALN,cAKM,CADJ,WAAuB,KAAA,QAAA,UAAA,CAAA,CAAA,IAAA,mBAAA,QAAA,KAAA,CAAA,CAAA,CAAA;;;;;;;;;;;;;;;;;;;;;;ECkB/B,MAAM,QAAQ;EAId,MAAM,QAAQ,UAAU;EACxB,MAAM,WAAW,IAA4B,KAAK;EAClD,MAAM,SAAS,IAAI,MAAM;EACzB,IAAIE,gBAAsD;EAE1D,MAAM,aAAa,eAAe;GAChC,MAAM,cAAc,MAAM;AAC1B,OAAI,CAAC,YAAa,QAAO;GACzB,MAAM,SAAS,aAAa;AAC5B,OAAI,CAAC,UAAU,CAAC,MAAM,QAAQ,OAAO,CAAE,QAAO;AAC9C,UAAO,OAAO,MAAM,MAAM,EAAE,SAAS,QAAQ;IAC7C;EAEF,eAAe,aAAa;AAC1B,OAAI,CAAC,MAAM,SAAU;GACrB,MAAM,OAAO,SAAS,OAAO,aAAa,MAAM;AAChD,OAAI,CAAC,KAAM;AACX,OAAI;AACF,UAAM,UAAU,UAAU,UAAU,KAAK;AACzC,WAAO,QAAQ;AACf,QAAI,cAAe,cAAa,cAAc;AAC9C,oBAAgB,iBAAiB;AAC/B,YAAO,QAAQ;AACf,qBAAgB;OACf,KAAK;WACF;;;uBApER,mBA2BM,OA3BN,cA2BM,CA1BJ,mBAEO,QAFP,cAEO,gBADF,QAAA,MAAK,EAAA,EAAA,EAEM,WAAA,SAAA,WAAA,EAAhB,mBAiBW,UAAA,EAAA,KAAA,GAAA,EAAA,CAfD,QAAA,YAAA,WAAA,EADR,mBAYO,QAAA;;aAVD;IAAJ,KAAI;IACJ,MAAK;IACL,UAAS;IACT,OAAM;IACL,SAAO;IACP,WAAO,CAAA,SAAQ,YAAU,CAAA,QAAA,CAAA,EAAA,SAAA,cACF,YAAU,CAAA,UAAA,CAAA,EAAA,CAAA,QAAA,CAAA,CAAA;uCAE/B,OAAA,QAAM,YAAe,OAAS,GAAG,KACpC,EAAA,EAAA,CAAiB,OAAA,QAAQ,WAAQ,KAAA,QAAA,WAAA,EAAA,KAAA,GAAA,CAAA,GAAA,mBAAA,QAAA,KAAA,CAAA,EAAA,IAAA,aAAA,KAAA,WAAA,EAEnC,mBAEO,QAAA,cAAA,CADL,WAAQ,KAAA,QAAA,UAAA,CAAA,CAAA,EAAA,SAIV,WAEO,KAAA,QAAA,SAAA,EAAA,KAAA,GAAA,QAAA,CAAA,OAAA,OAAA,OAAA,KADL,mBAAgE,QAAA,EAA1D,OAAM,uCAAqC,EAAC,WAAO,GAAA,EAAA,CAAA,CAAA,CAAA;;;;;;;;;ACrBjE,MAAM,2BAA2B,EAAE,OAAO;CACxC,MAAM,EAAE,QAAQ,CAAC,IAAI,GAAG,sBAAsB,CAAC,MAAM;CACrD,aAAa,EAAE,SAAS,CAAC,UAAU,CAAC,QAAQ,MAAM;CACnD,CAAC;AAEF,MAAa,6BAA6B,aACxC,0BACA,0BACA;CACE,MAAM;EACJ,OAAO;EACP,aAAa;EACb,WAAW;EACZ;CACD,aAAa;EACX,OAAO;EACP,UAAU;EACX;CACF,CACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;ECsED,MAAM,QAAQ;EACd,MAAM,iBAAiB,IAAwB,KAAK;EAEpD,MAAM,OAAO;EAIb,MAAM,EAAE,MAAM,OAAO,WAAW,mBAAmB,oBAAoB,QACrE,4BACA;GACE,WAAW;GACX,uBAAuB;GACvB,aAAa;GACb,WAAW,aAAa;IACtB,MAAM;IACN,aAAa,MAAM,aAAa;IACjC;GACF,CACF;AAGD,cACQ,MAAM,WACX,aAAa;AACZ,OAAI,aAAa,OACf,MAAK,SAAS,eAAe,aAAa,WAAW;KAGzD,EAAE,WAAW,MAAM,CACpB;AAGD,cACQ,KAAK,OAAO,cACjB,eAAe;AACd,OAAI,MAAM,eACR,MAAK,mBAAmB,aAAa,aAAa,WAAW;IAGlE;EAED,SAAS,cAAc,GAAkB;AACvC,QAAK,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,SAAS;AACjD,MAAE,gBAAgB;AAElB,KADa,eAAe,OAAO,QAAQ,OAAO,GAC5C,eAAe;;;EAIzB,eAAe,aAAa,UAAkD;AAC5E,SAAM,MAAM,SAAS;IACnB,UAAU,SAAS,QAAQ,IAAI,MAAM;IACrC,UAAU,MAAM,kBAAkB,SAAS,cAAc,aAAa;IACvE,CAAC;;EAGJ,SAAS,gBAAgB;AACvB,oBAAiB;AAChB,YAAS,eAA+B,MAAM;;EAGjD,SAAS,YAAY,QAAyB;EAI9C,SAAS,QAAQ;AACf,oBAAiB;;AAGnB,WAAa,EAAE,OAAO,CAAC;;uBAjKrB,mBA2EM,OA3EN,YA2EM,CA1EY,QAAA,YAAA,WAAA,EACd,mBAkBM,OAlBN,YAkBM,CAAA,GAAA,OAAA,OAAA,OAAA,KAAA,CAjBJ,mBAgBO,QAAA,EAhBD,OAAM,iEAA+D,EAAA,CACzE,mBAaM,OAAA;IAZJ,OAAM;IACN,MAAK;IACL,SAAQ;IACR,gBAAa;IACb,QAAO;IACP,OAAM;OAEN,mBAIE,QAAA;IAHA,kBAAe;IACf,mBAAgB;IAChB,GAAE;yBAEA,iEAER,CAAA,2BAGJ,YAoDY,MAAA,UAAA,EAAA;;IAlDT,gBAAe;IACf,WAAS;IACT,SAAO;IACR,OAAM;IACN,UAAS;;2BA6CH,CA3CN,mBA2CM,OAAA;cA3CG;KAAJ,KAAI;KAAiB,OAAM;KAAiC,WAAS;;KAEhE,QAAA,kBAAA,WAAA,EADR,mBAUI,KAAA;;MARF,OAAK,eAAA,CAAC,8BACE,MAAA,KAAI,CAAC,OAAO,cAAW,iBAAA,YAAA,CAAA;wBAG7B,MAAA,KAAI,CAAC,OAAO,cAAA,0CAAA,sBAAA;KAKhB,mBAEM,OAFN,YAEM,CADJ,YAA2C,MAAA,MAAA,CAAA,WAAA,EAA1B,OAAM,mBAAiB,CAAA,CAAA,CAAA;KAE1C,mBA2BM,OA3BN,YA2BM,CA1BO,QAAA,kBAAA,WAAA,EAAX,mBAuBM,OAvBN,YAuBM,CAtBJ,mBAUS,UAAA;MATP,MAAK;MACJ,OAAK,eAAA,CAAA,wBAAA,CAA6D,MAAA,KAAI,CAAC,OAAO,cAAW,wBAAA,GAAA,CAAA;MAIzF,UAAU,MAAA,KAAI,CAAC;MACf,SAAK,OAAA,OAAA,OAAA,MAAA,WAAE,MAAA,KAAI,CAAC,SAAQ,eAAA,MAAA;QACtB,mBAED,IAAA,WAAA,EACA,mBAUS,UAAA;MATP,MAAK;MACJ,OAAK,eAAA,CAAA,wBAA4D,MAAA,KAAI,CAAC,OAAO,cAAW,2BAAA,GAAA,CAAA;MAIxF,UAAU,MAAA,KAAI,CAAC;MACf,SAAK,OAAA,OAAA,OAAA,MAAA,WAAE,MAAA,KAAI,CAAC,SAAQ,eAAA,KAAA;QACtB,mBAED,IAAA,WAAA,CAAA,CAAA,KAAA,WAAA,EAEF,mBAAkB,OAAA,WAAA,GAClB,YAAqE,MAAA,kBAAA,EAAA;MAAlD,YAAW;MAAU,gBAAe"}
1
+ {"version":3,"file":"TimelineNoteInput-DGDgyGe-.js","names":["events: SystemEvent[]","collectedChanges: Array<{\n action: string;\n oldValue: string | null;\n newValue: string | null;\n fieldName: string;\n }>","map: Record<AlertVariant, string>","copyTimeoutId: ReturnType<typeof setTimeout> | null"],"sources":["../src/slices/support_ticket/shared/SupportTicketAttachmentsCollapsible.vue","../src/slices/support_ticket/utils/parseRecordVersions.ts","../src/slices/support_ticket/shared/ActionBannerAlert.vue","../src/slices/support_ticket/shared/MetadataField.vue","../src/slices/support_ticket/shared/timelineNoteFormMetadata.ts","../src/slices/support_ticket/shared/TimelineNoteInput.vue"],"sourcesContent":["<template>\n <div v-if=\"recordId\" class=\"w-full\">\n <div class=\"collapse collapse-arrow bg-base-200\">\n <input type=\"checkbox\" v-model=\"attachmentsExpanded\" />\n <div class=\"collapse-title text-sm font-medium px-4 py-2 min-h-0\">\n <div class=\"flex items-center gap-2\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n class=\"h-4 w-4\"\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=\"M15.172 7l-6.586 6.586a2 2 0 102.828 2.828l6.414-6.586a4 4 0 00-5.656-5.656l-6.415 6.585a6 6 0 108.486 8.486L20.5 13\"\n />\n </svg>\n <span>Attachments ({{ attachmentsCount }})</span>\n </div>\n </div>\n <div class=\"collapse-content px-0\">\n <div class=\"px-4 pb-4\">\n <InlineAttachments\n :record-id=\"recordId\"\n :can-upload=\"editable && !locked\"\n :can-delete=\"editable && !locked\"\n @update:attachments-count=\"attachmentsCount = $event\"\n @uploaded=\"emit('uploaded')\"\n @deleted=\"emit('deleted')\"\n />\n </div>\n </div>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { ref } from 'vue';\nimport InlineAttachments from './InlineAttachments.vue';\n\nconst attachmentsCount = ref(0);\n\ninterface Props {\n recordId: string;\n locked: boolean;\n editable: boolean;\n}\n\ndefineProps<Props>();\n\nconst emit = defineEmits<{ uploaded: []; deleted: [] }>();\n\nconst attachmentsExpanded = ref(false);\n</script>\n","import {\n supportTicketNumberToPriority,\n type RecordVersionReadDto,\n} from '@dragonmastery/dragoncore-shared';\nimport { formatTicketDate } from './formatTicketDate';\n\nexport interface SystemEventChange {\n action: string;\n oldValue: string | null;\n newValue: string | null;\n fieldName?: string;\n}\n\nexport interface SystemEvent {\n id: string;\n timestamp: string;\n author: string;\n message: string;\n /** When set, used for structured display: action (italic) + type (badge) + details */\n action?: string;\n type?: string | null;\n details?: string | null;\n oldValue?: string | null;\n newValue?: string | null;\n fieldName?: string; // Field name that changed (for filtering)\n /** When multiple fields changed in same record version, grouped changes */\n changes?: SystemEventChange[];\n}\n\nconst SKIP_FIELDS = new Set(['updated_at', 'updated_by', 'id', 'display_id']);\n\n/** Fields that store user IDs - display names from lookup instead of raw IDs */\nconst USER_ID_FIELDS = new Set([\n 'assigned_to',\n 'created_by',\n 'updated_by',\n 'archived_by',\n 'deleted_by',\n]);\n\nfunction truncate(value: string, maxLength: number = 50): string {\n if (value.length <= maxLength) return value;\n return value.substring(0, maxLength) + '...';\n}\n\nfunction formatEnumValue(value: string): string {\n return value\n .split('_')\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())\n .join(' ');\n}\n\nfunction formatFieldValue(\n fieldName: string,\n value: unknown,\n truncateLong: boolean = false,\n displayMap?: Map<string, string>,\n): string {\n if (value === null || value === undefined) return '';\n if (typeof value === 'string' && /^\\d{4}-\\d{2}-\\d{2}/.test(value)) {\n return formatTicketDate(value).formatted;\n }\n if (typeof value === 'boolean') return value ? 'Yes' : 'No';\n // User ID fields: display name from lookup when available\n if (typeof value === 'string' && USER_ID_FIELDS.has(fieldName) && displayMap) {\n return displayMap.get(value) ?? value;\n }\n // Priority: DB stores number (1-4), record_versions may have legacy string or new number\n if (fieldName === 'priority') {\n if (typeof value === 'number') {\n return formatEnumValue(supportTicketNumberToPriority(value));\n }\n if (typeof value === 'string') return formatEnumValue(value);\n }\n if (typeof value === 'string') {\n if (\n fieldName.includes('status') ||\n fieldName.includes('type') ||\n fieldName.includes('lifecycle')\n ) {\n return formatEnumValue(value);\n }\n // Truncate title and description\n if (truncateLong && (fieldName === 'title' || fieldName === 'description')) {\n return truncate(value);\n }\n }\n return String(value);\n}\n\nfunction generateActionMessage(\n fieldName: string,\n oldValue: unknown,\n newValue: unknown,\n): string {\n switch (fieldName) {\n case 'assigned_to':\n if (oldValue === null || oldValue === undefined) return 'assigned to';\n return 'reassigned to';\n case 'title':\n return 'changed the title';\n case 'description':\n return 'updated the description';\n case 'type':\n return 'changed type';\n case 'priority':\n return 'changed priority';\n case 'approval_status':\n return 'changed status';\n case 'dev_lifecycle':\n return 'moved';\n case 'credit_value':\n if (oldValue === null || oldValue === undefined) return 'set credits';\n return 'changed credits';\n case 'delivered_value':\n if (oldValue === null || oldValue === undefined) return 'set delivered value';\n return 'changed delivered value';\n case 'start_at':\n if (oldValue === null || oldValue === undefined) return 'set start date';\n if (newValue === null || newValue === undefined) return 'cleared start date';\n return 'changed start date';\n case 'target_at':\n if (oldValue === null || oldValue === undefined) return 'set target date';\n if (newValue === null || newValue === undefined) return 'cleared target date';\n return 'changed target date';\n case 'completed_at':\n if (oldValue === null || oldValue === undefined) return 'marked as completed';\n if (newValue === null || newValue === undefined) return 'cleared completed date';\n return 'changed completed date';\n case 'locked_approval_at':\n if (\n oldValue === null ||\n (oldValue === undefined && newValue !== null && newValue !== undefined)\n ) {\n return 'locked the ticket';\n }\n return 'changed lock status';\n case 'archived_at':\n if (\n oldValue === null ||\n (oldValue === undefined && newValue !== null && newValue !== undefined)\n ) {\n return 'archived the ticket';\n }\n if (\n oldValue !== null &&\n oldValue !== undefined &&\n (newValue === null || newValue === undefined)\n ) {\n return 'unarchived the ticket';\n }\n return 'changed archive status';\n case 'requester_email':\n return 'changed requester email';\n case 'requester_name':\n return 'changed requester name';\n case 'attachment_added':\n return 'added attachment';\n case 'attachment_removed':\n return 'removed attachment';\n default:\n return `updated ${fieldName.replace(/_/g, ' ')}`;\n }\n}\n\nfunction parseRecord(recordJson: string | null | undefined): Record<string, unknown> | null {\n if (!recordJson) return null;\n try {\n return JSON.parse(recordJson);\n } catch {\n return null;\n }\n}\n\nexport function parseRecordVersions(\n versions: RecordVersionReadDto[],\n displayMap?: Map<string, string>,\n): SystemEvent[] {\n const events: SystemEvent[] = [];\n\n for (const version of versions) {\n const author = version.auth_username || 'Unknown';\n const timestamp = version.recorded_at;\n\n if (version.operation === 'insert') {\n events.push({\n id: `${version.id}-insert`,\n timestamp,\n author,\n message: 'created this ticket',\n action: 'created',\n type: 'ticket',\n });\n continue;\n }\n\n if (version.operation === 'update') {\n const oldRecord = parseRecord(version.old_record);\n const newRecord = parseRecord(version.record);\n\n if (!oldRecord || !newRecord) continue;\n\n const collectedChanges: Array<{\n action: string;\n oldValue: string | null;\n newValue: string | null;\n fieldName: string;\n }> = [];\n\n for (const [fieldName, newValue] of Object.entries(newRecord)) {\n if (SKIP_FIELDS.has(fieldName)) continue;\n\n const oldValue = oldRecord[fieldName];\n\n if (oldValue !== newValue) {\n const oldFormatted =\n oldValue !== null && oldValue !== undefined\n ? formatFieldValue(fieldName, oldValue, true, displayMap)\n : null;\n const newFormatted =\n newValue !== null && newValue !== undefined\n ? formatFieldValue(fieldName, newValue, true, displayMap)\n : null;\n\n const actionMsg = generateActionMessage(fieldName, oldValue, newValue);\n\n collectedChanges.push({\n action: actionMsg,\n oldValue: oldFormatted || null,\n newValue: newFormatted || null,\n fieldName,\n });\n }\n }\n\n if (collectedChanges.length > 0) {\n const primaryChange = collectedChanges[0]!;\n const details =\n primaryChange.oldValue != null && primaryChange.newValue != null\n ? `${primaryChange.oldValue} → ${primaryChange.newValue}`\n : primaryChange.newValue ?? null;\n\n events.push({\n id: version.id,\n timestamp,\n author,\n message: primaryChange.action,\n action: collectedChanges.length === 1 ? primaryChange.action : 'updated',\n type: 'ticket',\n details: collectedChanges.length === 1 ? details : null,\n oldValue: collectedChanges.length === 1 ? primaryChange.oldValue : undefined,\n newValue: collectedChanges.length === 1 ? primaryChange.newValue : undefined,\n fieldName: collectedChanges.length === 1 ? primaryChange.fieldName : undefined,\n changes:\n collectedChanges.length > 1\n ? collectedChanges.map((c) => ({\n action: c.action,\n oldValue: c.oldValue,\n newValue: c.newValue,\n fieldName: c.fieldName,\n }))\n : undefined,\n });\n }\n }\n }\n\n events.sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());\n return events;\n}\n","<template>\n <div\n role=\"alert\"\n :class=\"[\n 'py-3 px-4 w-full rounded-lg border border-base-300 border-l-4 bg-base-200/60',\n variantBorderClass,\n ]\"\n >\n <!-- Mobile-first: stack vertically on small screens, row on desktop -->\n <div\n class=\"flex flex-col gap-3 sm:flex-row sm:items-center sm:gap-3\"\n >\n <div class=\"flex items-start gap-3 min-w-0\">\n <component :is=\"iconComponent\" v-if=\"icon\" class=\"shrink-0 w-5 h-5 opacity-90 mt-0.5\" />\n <span class=\"flex-1 min-w-0\">\n <slot />\n </span>\n </div>\n <div\n v-if=\"hasActions\"\n class=\"grid grid-cols-2 gap-2 sm:flex sm:flex-row sm:flex-wrap sm:ml-auto sm:shrink-0 sm:[&>*]:w-auto\"\n >\n <slot name=\"actions\" />\n </div>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, useSlots, h } from 'vue';\n\ntype AlertVariant = 'warning' | 'success' | 'error' | 'info' | 'neutral';\ntype IconType = 'lock' | 'clock' | 'info' | 'archive';\n\ninterface Props {\n variant: AlertVariant;\n icon?: IconType;\n}\n\nconst props = defineProps<Props>();\n\nconst slots = useSlots();\n\nconst variantBorderClass = computed(() => {\n const map: Record<AlertVariant, string> = {\n warning: 'border-l-warning',\n success: 'border-l-success',\n error: 'border-l-error',\n info: 'border-l-info',\n neutral: 'border-l-base-content/30',\n };\n return map[props.variant];\n});\n\nconst hasActions = computed(() => {\n const actionsSlot = slots.actions;\n if (!actionsSlot) return false;\n const vnodes = actionsSlot();\n return !!vnodes?.length;\n});\n\nconst iconComponent = computed(() => {\n if (!props.icon) return null;\n const icons = {\n lock: () =>\n h(\n 'svg',\n {\n xmlns: 'http://www.w3.org/2000/svg',\n fill: 'none',\n viewBox: '0 0 24 24',\n 'stroke-width': '1.5',\n stroke: 'currentColor',\n class: 'w-5 h-5',\n },\n [\n h('path', {\n 'stroke-linecap': 'round',\n 'stroke-linejoin': 'round',\n d: 'M16.5 10.5V6.75a4.5 4.5 0 10-9 0v3.75m-.75 11.25h10.5a2.25 2.25 0 002.25-2.25v-6.75a2.25 2.25 0 00-2.25-2.25H6.75a2.25 2.25 0 00-2.25 2.25v6.75a2.25 2.25 0 002.25 2.25z',\n }),\n ],\n ),\n clock: () =>\n h(\n 'svg',\n {\n xmlns: 'http://www.w3.org/2000/svg',\n fill: 'none',\n viewBox: '0 0 24 24',\n 'stroke-width': '1.5',\n stroke: 'currentColor',\n class: 'w-5 h-5',\n },\n [\n h('path', {\n 'stroke-linecap': 'round',\n 'stroke-linejoin': 'round',\n d: 'M12 6v6h4.5m4.5 0a9 9 0 11-18 0 9 9 0 0118 0z',\n }),\n ],\n ),\n info: () =>\n h(\n 'svg',\n {\n xmlns: 'http://www.w3.org/2000/svg',\n fill: 'none',\n viewBox: '0 0 24 24',\n 'stroke-width': '1.5',\n stroke: 'currentColor',\n class: 'w-5 h-5',\n },\n [\n h('path', {\n 'stroke-linecap': 'round',\n 'stroke-linejoin': 'round',\n d: 'M11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008H12V8.25z',\n }),\n ],\n ),\n archive: () =>\n h(\n 'svg',\n {\n xmlns: 'http://www.w3.org/2000/svg',\n fill: 'none',\n viewBox: '0 0 24 24',\n 'stroke-width': '1.5',\n stroke: 'currentColor',\n class: 'w-5 h-5',\n },\n [\n h('path', {\n 'stroke-linecap': 'round',\n 'stroke-linejoin': 'round',\n d: 'M20.25 7.5l-.625 10.632a2.25 2.25 0 01-2.247 2.118H6.622a2.25 2.25 0 01-2.247-2.118L3.75 7.5M10 11.25h4M3.375 7.5h17.25c.621 0 1.125-.504 1.125-1.125v-1.5c0-.621-.504-1.125-1.125-1.125H3.375c-.621 0-1.125.504-1.125 1.125v1.5c0 .621.504 1.125 1.125 1.125z',\n }),\n ],\n ),\n };\n return icons[props.icon] ?? null;\n});\n</script>\n","<template>\n <div class=\"flex flex-col\">\n <span class=\"text-xs font-semibold uppercase tracking-wide text-base-content/50 mb-0.5\">\n {{ label }}\n </span>\n <template v-if=\"hasContent\">\n <span\n v-if=\"copyable\"\n ref=\"valueRef\"\n role=\"button\"\n tabindex=\"0\"\n class=\"font-mono cursor-pointer select-all\"\n @click=\"handleCopy\"\n @keydown.enter=\"handleCopy\"\n @keydown.space.prevent=\"handleCopy\"\n >\n {{ copied ? 'Copied!' : undefined }}\n <template v-if=\"!copied\"><slot /></template>\n </span>\n <span v-else>\n <slot />\n </span>\n </template>\n <template v-else>\n <slot name=\"empty\">\n <span class=\"text-base-content/50 italic text-sm\">Not set</span>\n </slot>\n </template>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { Comment } from 'vue';\nimport { ref, computed, useSlots } from 'vue';\n\ninterface Props {\n label: string;\n copyable?: boolean;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n copyable: false,\n});\n\nconst slots = useSlots();\nconst valueRef = ref<HTMLSpanElement | null>(null);\nconst copied = ref(false);\nlet copyTimeoutId: ReturnType<typeof setTimeout> | null = null;\n\nconst hasContent = computed(() => {\n const defaultSlot = slots.default;\n if (!defaultSlot) return false;\n const vnodes = defaultSlot();\n if (!vnodes || !Array.isArray(vnodes)) return false;\n return vnodes.some((v) => v.type !== Comment);\n});\n\nasync function handleCopy() {\n if (!props.copyable) return;\n const text = valueRef.value?.textContent?.trim();\n if (!text) return;\n try {\n await navigator.clipboard.writeText(text);\n copied.value = true;\n if (copyTimeoutId) clearTimeout(copyTimeoutId);\n copyTimeoutId = setTimeout(() => {\n copied.value = false;\n copyTimeoutId = null;\n }, 1500);\n } catch {\n // ignore clipboard errors\n }\n}\n</script>\n","import { withMetadata } from '@dragonmastery/zinia-forms-core';\nimport { z } from 'zod';\n\n/** Schema for adding a comment/note on support ticket timeline. */\nconst TimelineNoteCreateSchema = z.object({\n body: z.string().min(1, 'Comment is required').trim(),\n is_internal: z.boolean().optional().default(false),\n});\n\nexport const timelineNoteCreateMetadata = withMetadata(\n TimelineNoteCreateSchema,\n 'timelineNoteCreateForm',\n {\n body: {\n label: 'Comment',\n placeholder: 'Add a comment...',\n inputType: 'textarea',\n },\n is_internal: {\n label: 'Internal Note',\n helpText: 'Internal notes are not visible to the customer',\n },\n },\n);\n\nexport type TimelineNoteCreateDto = z.infer<typeof TimelineNoteCreateSchema>;\n","<template>\n <div class=\"border-t border-base-200 pt-4 mt-4 w-full\">\n <template v-if=\"disabled\">\n <div class=\"bg-base-200/50 rounded-lg p-4 text-center\">\n <span class=\"text-base-content/50 text-sm inline-flex items-center gap-1.5\">\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n fill=\"none\"\n viewBox=\"0 0 24 24\"\n stroke-width=\"1.5\"\n stroke=\"currentColor\"\n class=\"w-4 h-4\"\n >\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n d=\"M16.5 10.5V6.75a4.5 4.5 0 10-9 0v3.75m-.75 11.25h10.5a2.25 2.25 0 002.25-2.25v-6.75a2.25 2.25 0 00-2.25-2.25H6.75a2.25 2.25 0 00-2.25 2.25v6.75a2.25 2.25 0 002.25 2.25z\"\n />\n </svg>\n This ticket has been locked. You can no longer add comments.\n </span>\n </div>\n </template>\n <ZiniaForm\n v-else\n @handle-submit=\"handleSubmit\"\n @success=\"handleSuccess\"\n @error=\"handleError\"\n title=\"\"\n subtitle=\"\"\n >\n <div ref=\"formWrapperRef\" class=\"grid grid-cols-1 gap-4 w-full\" @keydown=\"handleKeydown\">\n <p\n v-if=\"showTypeToggle\"\n class=\"col-span-full text-xs mb-1\"\n :class=\"form.values.is_internal ? 'text-warning' : 'text-info'\"\n >\n {{\n form.values.is_internal\n ? '🔒 Internal — not visible to customer'\n : 'Visible to customer'\n }}\n </p>\n <div class=\"col-span-full\">\n <zinia.BodyField class=\"textarea w-full\" />\n </div>\n <div class=\"col-span-full flex flex-wrap gap-2 justify-between items-center\">\n <div v-if=\"showTypeToggle\" class=\"join\">\n <button\n type=\"button\"\n :class=\"[\n 'btn btn-sm join-item',\n !form.values.is_internal ? 'btn-info btn-active' : '',\n ]\"\n :disabled=\"form.isSubmitting\"\n @click=\"form.setValue('is_internal', false)\"\n >\n Customer Note\n </button>\n <button\n type=\"button\"\n :class=\"[\n 'btn btn-sm join-item',\n form.values.is_internal ? 'btn-warning btn-active' : '',\n ]\"\n :disabled=\"form.isSubmitting\"\n @click=\"form.setValue('is_internal', true)\"\n >\n Internal Note\n </button>\n </div>\n <div v-else></div>\n <ZiniaSubmitButton submitText=\"Comment\" submittingText=\"Adding...\" />\n </div>\n </div>\n </ZiniaForm>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { useForm } from '@dragonmastery/zinia-forms-core';\nimport { ref, watch } from 'vue';\nimport { timelineNoteCreateMetadata } from './timelineNoteFormMetadata';\n\ninterface Props {\n showTypeToggle: boolean;\n disabled: boolean;\n /** When provided, noteType is controlled (e.g. synced with URL query param) */\n noteType?: 'customer' | 'internal';\n /** Called when form submits with validated data. Must return a Promise. */\n onSubmit: (payload: { content: string; noteType: 'customer' | 'internal' }) => Promise<void>;\n}\n\nconst props = defineProps<Props>();\nconst formWrapperRef = ref<HTMLElement | null>(null);\n\nconst emit = defineEmits<{\n 'update:noteType': [value: 'customer' | 'internal'];\n}>();\n\nconst { form, zinia, ZiniaForm, ZiniaSubmitButton, refreshFormData } = useForm(\n timelineNoteCreateMetadata,\n {\n storeName: 'timeline-note-input',\n persistToLocalStorage: false,\n renderStyle: 'daisy_ui',\n fetchData: async () => ({\n body: '',\n is_internal: props.noteType === 'internal',\n }),\n },\n);\n\n// Sync form's is_internal when controlled noteType prop changes (e.g. from URL)\nwatch(\n () => props.noteType,\n (noteType) => {\n if (noteType !== undefined) {\n form.setValue('is_internal', noteType === 'internal');\n }\n },\n { immediate: true },\n);\n\n// Emit when user toggles note type (for URL sync in StaffTimeline)\nwatch(\n () => form.values.is_internal,\n (isInternal) => {\n if (props.showTypeToggle) {\n emit('update:noteType', isInternal ? 'internal' : 'customer');\n }\n },\n);\n\nfunction handleKeydown(e: KeyboardEvent) {\n if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') {\n e.preventDefault();\n const form = formWrapperRef.value?.closest('form');\n form?.requestSubmit();\n }\n}\n\nasync function handleSubmit(formData: { body: string; is_internal: boolean }) {\n await props.onSubmit({\n content: (formData.body ?? '').trim(),\n noteType: props.showTypeToggle && formData.is_internal ? 'internal' : 'customer',\n });\n}\n\nfunction handleSuccess() {\n refreshFormData();\n (document.activeElement as HTMLElement)?.blur();\n}\n\nfunction handleError(_error: Error | unknown) {\n // Form displays errors via ZiniaFormErrorsSummary\n}\n\nfunction reset() {\n refreshFormData();\n}\n\ndefineExpose({ reset });\n</script>\n"],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import "./useRpcAuth-SgNzCAPa.js";
2
+ import { t as UserListPage_default } from "./UserListPage-D-IdlsHK.js";
3
+
4
+ export { UserListPage_default as default };
@@ -1,5 +1,5 @@
1
1
  import { r as executeWithAuth, s as getRefreshTokenHandler } from "./useRpcAuth-SgNzCAPa.js";
2
- import { t as formatSystemTimestamp } from "./convertToLocalDateTime-DOSGtMn8.js";
2
+ import { t as formatSystemTimestamp } from "./convertToLocalDateTime-mKs5eC9T.js";
3
3
  import { computed, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, normalizeClass, openBlock, resolveComponent, toDisplayString, unref, withCtx } from "vue";
4
4
  import { UserReadSchema } from "@dragonmastery/dragoncore-shared";
5
5
  import { useCursorDataTable, withMetadata } from "@dragonmastery/zinia-forms-core";
@@ -150,4 +150,4 @@ var UserListPage_default = _sfc_main;
150
150
 
151
151
  //#endregion
152
152
  export { userRowSchemaWithMetadata as n, UserTypeBadge_default as r, UserListPage_default as t };
153
- //# sourceMappingURL=UserListPage-DtftDtVo.js.map
153
+ //# sourceMappingURL=UserListPage-D-IdlsHK.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"UserListPage-DtftDtVo.js","names":["mappedUsers: UserRow[]"],"sources":["../src/slices/admin/components/UserTypeBadge.vue","../src/slices/admin/features/user_management/userRowSchema.ts","../src/slices/admin/features/user_management/UserListPage.vue"],"sourcesContent":["<template>\n <span class=\"badge badge-sm\" :class=\"badgeClasses\">\n {{ typeLabel }}\n </span>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed } from 'vue';\n\ninterface Props {\n userType: 'consumer' | 'lead' | 'staff' | 'super_admin';\n size?: 'xs' | 'sm' | 'md' | 'lg';\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n size: 'sm',\n});\n\nconst typeConfig = {\n consumer: {\n label: 'Consumer',\n variant: 'neutral',\n },\n lead: {\n label: 'Lead',\n variant: 'info',\n },\n staff: {\n label: 'Staff',\n variant: 'warning',\n },\n super_admin: {\n label: 'Admin',\n variant: 'error',\n },\n};\n\nconst typeLabel = computed(() => {\n return typeConfig[props.userType]?.label || props.userType;\n});\n\nconst badgeClasses = computed(() => {\n const config = typeConfig[props.userType];\n const baseClasses = `badge-${props.size}`;\n\n if (!config) {\n return `${baseClasses} badge-neutral`;\n }\n\n return `${baseClasses} badge-${config.variant}`;\n});\n</script>\n","import { withMetadata } from '@dragonmastery/zinia-forms-core';\nimport { UserReadSchema } from '@dragonmastery/dragoncore-shared';\nimport type { z } from 'zod';\n\nexport const userRowSchemaWithMetadata = withMetadata(UserReadSchema, 'userRowSchema', {\n username: { label: 'Username' },\n email: { label: 'Email' },\n user_type: { label: 'Role' },\n email_verified: { label: 'Verified' },\n created_at: { label: 'Created' },\n});\n\nexport type UserRow = z.infer<typeof UserReadSchema>;\n","<template>\n <div class=\"mt-2\">\n <!-- Header with title and actions -->\n <div class=\"flex justify-between items-center mb-4\">\n <h1 class=\"text-2xl font-bold\">User Management</h1>\n </div>\n\n <!-- Zinia Data Table -->\n <ZiniaDataTable>\n <!-- Custom cell templates -->\n <template #cell-user_type=\"{ row }\">\n <UserTypeBadge :user-type=\"row.user_type\" />\n </template>\n\n <template #cell-email_verified=\"{ row }\">\n <span\n class=\"badge badge-sm\"\n :class=\"row.email_verified ? 'badge-success' : 'badge-error'\"\n >\n {{ row.email_verified ? 'Verified' : 'Not Verified' }}\n </span>\n </template>\n\n <template #cell-created_at=\"{ row }\">\n {{ formatSystemTimestamp(row.created_at) }}\n </template>\n\n <template #cell-actions=\"{ row }\">\n <router-link\n :to=\"{ name: 'EditUser', params: { id: row.id } }\"\n class=\"btn btn-sm btn-primary\"\n >\n Edit\n </router-link>\n </template>\n </ZiniaDataTable>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { executeWithAuth } from '../../../../composables/useRpcAuth';\nimport { getRefreshTokenHandler } from '../../../../utils/EnhancedRefreshTokenHandler';\nimport { formatSystemTimestamp } from '../../../../utils/convertToLocalDateTime';\nimport { useCursorDataTable } from '@dragonmastery/zinia-forms-core';\nimport UserTypeBadge from '../../components/UserTypeBadge.vue';\nimport { userRowSchemaWithMetadata, type UserRow } from './userRowSchema';\n\n// Set up data table\nconst { ZiniaDataTable } = useCursorDataTable(userRowSchemaWithMetadata, {\n fetchData: async () => {\n const users = await executeWithAuth(\n async (api) => {\n return await api.users.listUsers();\n },\n { refreshTokenHandler: getRefreshTokenHandler() },\n );\n\n // Map response to UserRow format\n const mappedUsers: UserRow[] = users.map((user) => ({\n id: user.id,\n username: user.username,\n email: user.email,\n email_verified: user.email_verified,\n user_type: user.user_type,\n created_at: user.created_at,\n updated_at: user.updated_at ?? null,\n }));\n\n return {\n data: mappedUsers,\n hasNextPage: false,\n hasPreviousPage: false,\n prevPageCursor: undefined,\n nextPageCursor: undefined,\n };\n },\n\n // Column configuration\n columns: {\n username: { label: 'Username', field: 'username', sortable: true },\n email: { label: 'Email', field: 'email', sortable: true },\n user_type: { label: 'Role', field: 'user_type', sortable: true },\n email_verified: {\n label: 'Verified',\n field: 'email_verified',\n sortable: true,\n },\n created_at: { label: 'Created', field: 'created_at', sortable: true },\n },\n\n // Action buttons\n actions: {\n items: [\n {\n key: 'edit',\n icon: 'edit',\n size: 'xs',\n variant: 'primary',\n type: 'link',\n href: (row: UserRow) => `/admin/users/${row.id}/edit`,\n },\n ],\n },\n\n pagination: {\n pageSize: 100,\n },\n});\n</script>\n"],"mappings":"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"}
1
+ {"version":3,"file":"UserListPage-D-IdlsHK.js","names":["mappedUsers: UserRow[]"],"sources":["../src/slices/admin/components/UserTypeBadge.vue","../src/slices/admin/features/user_management/userRowSchema.ts","../src/slices/admin/features/user_management/UserListPage.vue"],"sourcesContent":["<template>\n <span class=\"badge badge-sm\" :class=\"badgeClasses\">\n {{ typeLabel }}\n </span>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed } from 'vue';\n\ninterface Props {\n userType: 'consumer' | 'lead' | 'staff' | 'super_admin';\n size?: 'xs' | 'sm' | 'md' | 'lg';\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n size: 'sm',\n});\n\nconst typeConfig = {\n consumer: {\n label: 'Consumer',\n variant: 'neutral',\n },\n lead: {\n label: 'Lead',\n variant: 'info',\n },\n staff: {\n label: 'Staff',\n variant: 'warning',\n },\n super_admin: {\n label: 'Admin',\n variant: 'error',\n },\n};\n\nconst typeLabel = computed(() => {\n return typeConfig[props.userType]?.label || props.userType;\n});\n\nconst badgeClasses = computed(() => {\n const config = typeConfig[props.userType];\n const baseClasses = `badge-${props.size}`;\n\n if (!config) {\n return `${baseClasses} badge-neutral`;\n }\n\n return `${baseClasses} badge-${config.variant}`;\n});\n</script>\n","import { withMetadata } from '@dragonmastery/zinia-forms-core';\nimport { UserReadSchema } from '@dragonmastery/dragoncore-shared';\nimport type { z } from 'zod';\n\nexport const userRowSchemaWithMetadata = withMetadata(UserReadSchema, 'userRowSchema', {\n username: { label: 'Username' },\n email: { label: 'Email' },\n user_type: { label: 'Role' },\n email_verified: { label: 'Verified' },\n created_at: { label: 'Created' },\n});\n\nexport type UserRow = z.infer<typeof UserReadSchema>;\n","<template>\n <div class=\"mt-2\">\n <!-- Header with title and actions -->\n <div class=\"flex justify-between items-center mb-4\">\n <h1 class=\"text-2xl font-bold\">User Management</h1>\n </div>\n\n <!-- Zinia Data Table -->\n <ZiniaDataTable>\n <!-- Custom cell templates -->\n <template #cell-user_type=\"{ row }\">\n <UserTypeBadge :user-type=\"row.user_type\" />\n </template>\n\n <template #cell-email_verified=\"{ row }\">\n <span\n class=\"badge badge-sm\"\n :class=\"row.email_verified ? 'badge-success' : 'badge-error'\"\n >\n {{ row.email_verified ? 'Verified' : 'Not Verified' }}\n </span>\n </template>\n\n <template #cell-created_at=\"{ row }\">\n {{ formatSystemTimestamp(row.created_at) }}\n </template>\n\n <template #cell-actions=\"{ row }\">\n <router-link\n :to=\"{ name: 'EditUser', params: { id: row.id } }\"\n class=\"btn btn-sm btn-primary\"\n >\n Edit\n </router-link>\n </template>\n </ZiniaDataTable>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { executeWithAuth } from '../../../../composables/useRpcAuth';\nimport { getRefreshTokenHandler } from '../../../../utils/EnhancedRefreshTokenHandler';\nimport { formatSystemTimestamp } from '../../../../utils/convertToLocalDateTime';\nimport { useCursorDataTable } from '@dragonmastery/zinia-forms-core';\nimport UserTypeBadge from '../../components/UserTypeBadge.vue';\nimport { userRowSchemaWithMetadata, type UserRow } from './userRowSchema';\n\n// Set up data table\nconst { ZiniaDataTable } = useCursorDataTable(userRowSchemaWithMetadata, {\n fetchData: async () => {\n const users = await executeWithAuth(\n async (api) => {\n return await api.users.listUsers();\n },\n { refreshTokenHandler: getRefreshTokenHandler() },\n );\n\n // Map response to UserRow format\n const mappedUsers: UserRow[] = users.map((user) => ({\n id: user.id,\n username: user.username,\n email: user.email,\n email_verified: user.email_verified,\n user_type: user.user_type,\n created_at: user.created_at,\n updated_at: user.updated_at ?? null,\n }));\n\n return {\n data: mappedUsers,\n hasNextPage: false,\n hasPreviousPage: false,\n prevPageCursor: undefined,\n nextPageCursor: undefined,\n };\n },\n\n // Column configuration\n columns: {\n username: { label: 'Username', field: 'username', sortable: true },\n email: { label: 'Email', field: 'email', sortable: true },\n user_type: { label: 'Role', field: 'user_type', sortable: true },\n email_verified: {\n label: 'Verified',\n field: 'email_verified',\n sortable: true,\n },\n created_at: { label: 'Created', field: 'created_at', sortable: true },\n },\n\n // Action buttons\n actions: {\n items: [\n {\n key: 'edit',\n icon: 'edit',\n size: 'xs',\n variant: 'primary',\n type: 'link',\n href: (row: UserRow) => `/admin/users/${row.id}/edit`,\n },\n ],\n },\n\n pagination: {\n pageSize: 100,\n },\n});\n</script>\n"],"mappings":"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"}
@@ -2,6 +2,6 @@ import "./useRpcAuth-SgNzCAPa.js";
2
2
  import "./useQueryCache-DIGf3fCM.js";
3
3
  import "./useMutation-DzRSXPB1.js";
4
4
  import "./useQuery-bvJabe9Q.js";
5
- import { t as UserProfilePage_default } from "./UserProfilePage-1UWJUhqk.js";
5
+ import { t as UserProfilePage_default } from "./UserProfilePage-DMwDVgXa.js";
6
6
 
7
7
  export { UserProfilePage_default as default };
@@ -167,4 +167,4 @@ var UserProfilePage_default = _sfc_main;
167
167
 
168
168
  //#endregion
169
169
  export { userProfileSchemaWithMetadata as n, UserProfilePage_default as t };
170
- //# sourceMappingURL=UserProfilePage-1UWJUhqk.js.map
170
+ //# sourceMappingURL=UserProfilePage-DMwDVgXa.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"UserProfilePage-1UWJUhqk.js","names":[],"sources":["../src/slices/user/features/user_profile/userProfileSchema.ts","../src/slices/user/features/user_profile/UserProfilePage.vue"],"sourcesContent":["import { withMetadata } from '@dragonmastery/zinia-forms-core';\nimport { UserProfileBaseSchema, UserProfileUpdateSchema } from '@dragonmastery/dragoncore-shared';\nimport { z } from 'zod';\n\n// Define the login form type\nexport type UserProfileForm = z.infer<typeof UserProfileBaseSchema>;\n\n// Enhance the schema with metadata\nexport const userProfileSchemaWithMetadata = withMetadata(\n UserProfileUpdateSchema,\n 'userProfileSchema',\n {\n first_name: {\n inputType: 'text',\n placeholder: 'Enter first name',\n helpText: 'Enter the first name',\n autocomplete: 'first-name',\n autofocus: true,\n },\n\n last_name: {\n inputType: 'text',\n placeholder: 'Enter last name',\n helpText: 'Enter the last name',\n autocomplete: 'last-name',\n },\n\n bio: {\n inputType: 'textarea',\n placeholder: 'Enter bio',\n helpText: 'Enter a short bio',\n },\n },\n);\n","<template>\n <div v-if=\"form.isLoading\" class=\"flex justify-center items-center p-8\">\n <span class=\"loading loading-spinner loading-lg\"></span>\n </div>\n <div v-else-if=\"form.loadError\" 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>{{ form.loadError }}</span>\n </div>\n <div v-else class=\"max-w-md mx-auto bg-base-200 p-6 rounded-xl shadow-md container\">\n <h1 class=\"text-2xl font-bold mb-6 text-center\">Update User Profile</h1>\n\n <!-- Email & verification status -->\n <div v-if=\"session.userSession?.user.email\" class=\"mb-6 p-4 rounded-lg bg-base-300\">\n <div class=\"flex items-center justify-between gap-2\">\n <div>\n <p class=\"text-sm text-base-content/70\">Email</p>\n <p class=\"font-medium\">{{ session.userSession.user.email }}</p>\n <p\n v-if=\"emailVerificationMode !== 'disabled'\"\n class=\"text-sm mt-1\"\n :class=\"session.userSession.user.email_verified ? 'text-success' : 'text-warning'\"\n >\n {{ session.userSession.user.email_verified ? 'Verified' : 'Not verified' }}\n </p>\n </div>\n <button\n v-if=\"\n emailVerificationMode !== 'disabled' &&\n !session.userSession.user.email_verified\n \"\n type=\"button\"\n class=\"btn btn-outline btn-sm\"\n :disabled=\"resendLoading\"\n @click=\"resendVerification\"\n >\n {{ resendLoading ? 'Sending...' : 'Resend verification' }}\n </button>\n </div>\n </div>\n\n <ZiniaForm @handle-submit=\"handleSubmit\" @success=\"handleSuccess\" @error=\"handleError\">\n <zinia.FirstNameField />\n <zinia.LastNameField />\n <zinia.BioField />\n\n <ZiniaSubmitButton submitText=\"Update\" submittingText=\"Updating...\" />\n </ZiniaForm>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport type { DragoncoreApi } from '@dragonmastery/dragoncore-shared';\nimport type { EmailVerificationApi } from '@dragonmastery/dragoncore-shared';\nimport type { UserProfileUpdateDto } from '@dragonmastery/dragoncore-shared';\nimport { useForm } from '@dragonmastery/zinia-forms-core';\nimport { ref } from 'vue';\nimport { toast } from 'vue3-toastify';\nimport { useEnv } from '../../../../composables/useEnv';\nimport { useMutation } from '../../../../composables/useMutation';\nimport { useQuery } from '../../../../composables/useQuery';\nimport { useUserSessionStore } from '../../../../composables/useUserSessionStore';\nimport { userProfileSchemaWithMetadata } from './userProfileSchema';\n\n//user session\nconst session = useUserSessionStore();\nconst { emailVerificationMode } = useEnv();\nconst resendLoading = ref(false);\n\nconst { mutate: resendMutate } = useMutation(\n (api, _input?: unknown) => {\n const verifyEmail = (api as DragoncoreApi).verifyEmail;\n if (!verifyEmail) throw new Error('Email verification is not configured');\n return (verifyEmail as EmailVerificationApi).resendVerificationEmail();\n },\n { skipAuthCheck: false },\n);\n\nconst resendVerification = async () => {\n try {\n resendLoading.value = true;\n const result = await resendMutate(undefined);\n if (result?.ok) {\n toast.success('Verification email sent. Please check your inbox.');\n await session.refreshToken();\n } else {\n toast.error('Failed to resend verification email.');\n }\n } catch (error) {\n toast.error(error instanceof Error ? error.message : 'Failed to resend');\n } finally {\n resendLoading.value = false;\n }\n};\n\n// fetch user profile data\nconst { data: userProfileData, loading: userProfileFetching } = useQuery(\n (api) => api.userProfiles.getCurrentUserProfile(),\n {\n enabled: !!session.userSession?.user.userId,\n staleTime: 5 * 60 * 1000,\n },\n);\n\n// Create a type-safe form using our schema with metadata\nconst { form, zinia, ZiniaForm, ZiniaSubmitButton } = useForm(userProfileSchemaWithMetadata, {\n storeName: 'user-profile-form',\n persistToLocalStorage: false,\n renderStyle: 'daisy_ui',\n fetchData: async () => {\n while (userProfileFetching.value) {\n await new Promise((resolve) => setTimeout(resolve, 100));\n }\n\n if (!userProfileData.value) {\n return {\n user_id: session.userSession?.user.userId || '',\n bio: '',\n first_name: '',\n last_name: '',\n };\n }\n\n return {\n user_id: userProfileData.value.user_id,\n bio: userProfileData.value.bio || '',\n first_name: userProfileData.value.first_name || '',\n last_name: userProfileData.value.last_name || '',\n };\n },\n});\n\nconst { mutate: updateUserProfile } = useMutation(\n (api, input: UserProfileUpdateDto) => api.userProfiles.updateUserProfile(input),\n { invalidate: /^user:profile/ },\n);\n\n// Handle form submission\nconst handleSubmit = async (data: UserProfileUpdateDto) => {\n if (!session.userSession?.user.userId) {\n throw new Error('User session not found');\n }\n\n const result = await updateUserProfile({\n user_id: session.userSession?.user.userId,\n first_name: data.first_name,\n last_name: data.last_name,\n bio: data.bio,\n });\n if (!result) throw new Error('Update user profile failed');\n\n return result;\n};\n\n// Handle success\nconst handleSuccess = (_data: any) => {\n toast.success('User profile updated successfully!');\n};\n\n// Handle error\nconst handleError = (error: any) => {\n toast.error(error.message || 'Update user profile failed');\n};\n</script>\n"],"mappings":"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"}
1
+ {"version":3,"file":"UserProfilePage-DMwDVgXa.js","names":[],"sources":["../src/slices/user/features/user_profile/userProfileSchema.ts","../src/slices/user/features/user_profile/UserProfilePage.vue"],"sourcesContent":["import { withMetadata } from '@dragonmastery/zinia-forms-core';\nimport { UserProfileBaseSchema, UserProfileUpdateSchema } from '@dragonmastery/dragoncore-shared';\nimport { z } from 'zod';\n\n// Define the login form type\nexport type UserProfileForm = z.infer<typeof UserProfileBaseSchema>;\n\n// Enhance the schema with metadata\nexport const userProfileSchemaWithMetadata = withMetadata(\n UserProfileUpdateSchema,\n 'userProfileSchema',\n {\n first_name: {\n inputType: 'text',\n placeholder: 'Enter first name',\n helpText: 'Enter the first name',\n autocomplete: 'first-name',\n autofocus: true,\n },\n\n last_name: {\n inputType: 'text',\n placeholder: 'Enter last name',\n helpText: 'Enter the last name',\n autocomplete: 'last-name',\n },\n\n bio: {\n inputType: 'textarea',\n placeholder: 'Enter bio',\n helpText: 'Enter a short bio',\n },\n },\n);\n","<template>\n <div v-if=\"form.isLoading\" class=\"flex justify-center items-center p-8\">\n <span class=\"loading loading-spinner loading-lg\"></span>\n </div>\n <div v-else-if=\"form.loadError\" 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>{{ form.loadError }}</span>\n </div>\n <div v-else class=\"max-w-md mx-auto bg-base-200 p-6 rounded-xl shadow-md container\">\n <h1 class=\"text-2xl font-bold mb-6 text-center\">Update User Profile</h1>\n\n <!-- Email & verification status -->\n <div v-if=\"session.userSession?.user.email\" class=\"mb-6 p-4 rounded-lg bg-base-300\">\n <div class=\"flex items-center justify-between gap-2\">\n <div>\n <p class=\"text-sm text-base-content/70\">Email</p>\n <p class=\"font-medium\">{{ session.userSession.user.email }}</p>\n <p\n v-if=\"emailVerificationMode !== 'disabled'\"\n class=\"text-sm mt-1\"\n :class=\"session.userSession.user.email_verified ? 'text-success' : 'text-warning'\"\n >\n {{ session.userSession.user.email_verified ? 'Verified' : 'Not verified' }}\n </p>\n </div>\n <button\n v-if=\"\n emailVerificationMode !== 'disabled' &&\n !session.userSession.user.email_verified\n \"\n type=\"button\"\n class=\"btn btn-outline btn-sm\"\n :disabled=\"resendLoading\"\n @click=\"resendVerification\"\n >\n {{ resendLoading ? 'Sending...' : 'Resend verification' }}\n </button>\n </div>\n </div>\n\n <ZiniaForm @handle-submit=\"handleSubmit\" @success=\"handleSuccess\" @error=\"handleError\">\n <zinia.FirstNameField />\n <zinia.LastNameField />\n <zinia.BioField />\n\n <ZiniaSubmitButton submitText=\"Update\" submittingText=\"Updating...\" />\n </ZiniaForm>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport type { DragoncoreApi } from '@dragonmastery/dragoncore-shared';\nimport type { EmailVerificationApi } from '@dragonmastery/dragoncore-shared';\nimport type { UserProfileUpdateDto } from '@dragonmastery/dragoncore-shared';\nimport { useForm } from '@dragonmastery/zinia-forms-core';\nimport { ref } from 'vue';\nimport { toast } from 'vue3-toastify';\nimport { useEnv } from '../../../../composables/useEnv';\nimport { useMutation } from '../../../../composables/useMutation';\nimport { useQuery } from '../../../../composables/useQuery';\nimport { useUserSessionStore } from '../../../../composables/useUserSessionStore';\nimport { userProfileSchemaWithMetadata } from './userProfileSchema';\n\n//user session\nconst session = useUserSessionStore();\nconst { emailVerificationMode } = useEnv();\nconst resendLoading = ref(false);\n\nconst { mutate: resendMutate } = useMutation(\n (api, _input?: unknown) => {\n const verifyEmail = (api as DragoncoreApi).verifyEmail;\n if (!verifyEmail) throw new Error('Email verification is not configured');\n return (verifyEmail as EmailVerificationApi).resendVerificationEmail();\n },\n { skipAuthCheck: false },\n);\n\nconst resendVerification = async () => {\n try {\n resendLoading.value = true;\n const result = await resendMutate(undefined);\n if (result?.ok) {\n toast.success('Verification email sent. Please check your inbox.');\n await session.refreshToken();\n } else {\n toast.error('Failed to resend verification email.');\n }\n } catch (error) {\n toast.error(error instanceof Error ? error.message : 'Failed to resend');\n } finally {\n resendLoading.value = false;\n }\n};\n\n// fetch user profile data\nconst { data: userProfileData, loading: userProfileFetching } = useQuery(\n (api) => api.userProfiles.getCurrentUserProfile(),\n {\n enabled: !!session.userSession?.user.userId,\n staleTime: 5 * 60 * 1000,\n },\n);\n\n// Create a type-safe form using our schema with metadata\nconst { form, zinia, ZiniaForm, ZiniaSubmitButton } = useForm(userProfileSchemaWithMetadata, {\n storeName: 'user-profile-form',\n persistToLocalStorage: false,\n renderStyle: 'daisy_ui',\n fetchData: async () => {\n while (userProfileFetching.value) {\n await new Promise((resolve) => setTimeout(resolve, 100));\n }\n\n if (!userProfileData.value) {\n return {\n user_id: session.userSession?.user.userId || '',\n bio: '',\n first_name: '',\n last_name: '',\n };\n }\n\n return {\n user_id: userProfileData.value.user_id,\n bio: userProfileData.value.bio || '',\n first_name: userProfileData.value.first_name || '',\n last_name: userProfileData.value.last_name || '',\n };\n },\n});\n\nconst { mutate: updateUserProfile } = useMutation(\n (api, input: UserProfileUpdateDto) => api.userProfiles.updateUserProfile(input),\n { invalidate: /^user:profile/ },\n);\n\n// Handle form submission\nconst handleSubmit = async (data: UserProfileUpdateDto) => {\n if (!session.userSession?.user.userId) {\n throw new Error('User session not found');\n }\n\n const result = await updateUserProfile({\n user_id: session.userSession?.user.userId,\n first_name: data.first_name,\n last_name: data.last_name,\n bio: data.bio,\n });\n if (!result) throw new Error('Update user profile failed');\n\n return result;\n};\n\n// Handle success\nconst handleSuccess = (_data: any) => {\n toast.success('User profile updated successfully!');\n};\n\n// Handle error\nconst handleError = (error: any) => {\n toast.error(error.message || 'Update user profile failed');\n};\n</script>\n"],"mappings":";;;;;;;;;AAQA,MAAa,gCAAgC,aAC3C,yBACA,qBACA;CACE,YAAY;EACV,WAAW;EACX,aAAa;EACb,UAAU;EACV,cAAc;EACd,WAAW;EACZ;CAED,WAAW;EACT,WAAW;EACX,aAAa;EACb,UAAU;EACV,cAAc;EACf;CAED,KAAK;EACH,WAAW;EACX,aAAa;EACb,UAAU;EACX;CACF,CACF;;;;;;;;;;;;;;;;;;;;;;;;;;EC2CD,MAAM,UAAU,qBAAqB;EACrC,MAAM,EAAE,0BAA0B,QAAQ;EAC1C,MAAM,gBAAgB,IAAI,MAAM;EAEhC,MAAM,EAAE,QAAQ,iBAAiB,aAC9B,KAAK,WAAqB;GACzB,MAAM,cAAe,IAAsB;AAC3C,OAAI,CAAC,YAAa,OAAM,IAAI,MAAM,uCAAuC;AACzE,UAAQ,YAAqC,yBAAyB;KAExE,EAAE,eAAe,OAAO,CACzB;EAED,MAAM,qBAAqB,YAAY;AACrC,OAAI;AACF,kBAAc,QAAQ;AAEtB,SADe,MAAM,aAAa,OAAU,GAChC,IAAI;AACd,WAAM,QAAQ,oDAAoD;AAClE,WAAM,QAAQ,cAAc;UAE5B,OAAM,MAAM,uCAAuC;YAE9C,OAAO;AACd,UAAM,MAAM,iBAAiB,QAAQ,MAAM,UAAU,mBAAmB;aAChE;AACR,kBAAc,QAAQ;;;EAK1B,MAAM,EAAE,MAAM,iBAAiB,SAAS,wBAAwB,UAC7D,QAAQ,IAAI,aAAa,uBAAuB,EACjD;GACE,SAAS,CAAC,CAAC,QAAQ,aAAa,KAAK;GACrC,WAAW,MAAS;GACrB,CACF;EAGD,MAAM,EAAE,MAAM,OAAO,WAAW,sBAAsB,QAAQ,+BAA+B;GAC3F,WAAW;GACX,uBAAuB;GACvB,aAAa;GACb,WAAW,YAAY;AACrB,WAAO,oBAAoB,MACzB,OAAM,IAAI,SAAS,YAAY,WAAW,SAAS,IAAI,CAAC;AAG1D,QAAI,CAAC,gBAAgB,MACnB,QAAO;KACL,SAAS,QAAQ,aAAa,KAAK,UAAU;KAC7C,KAAK;KACL,YAAY;KACZ,WAAW;KACZ;AAGH,WAAO;KACL,SAAS,gBAAgB,MAAM;KAC/B,KAAK,gBAAgB,MAAM,OAAO;KAClC,YAAY,gBAAgB,MAAM,cAAc;KAChD,WAAW,gBAAgB,MAAM,aAAa;KAC/C;;GAEJ,CAAC;EAEF,MAAM,EAAE,QAAQ,sBAAsB,aACnC,KAAK,UAAgC,IAAI,aAAa,kBAAkB,MAAM,EAC/E,EAAE,YAAY,iBAAiB,CAChC;EAGD,MAAM,eAAe,OAAO,SAA+B;AACzD,OAAI,CAAC,QAAQ,aAAa,KAAK,OAC7B,OAAM,IAAI,MAAM,yBAAyB;GAG3C,MAAM,SAAS,MAAM,kBAAkB;IACrC,SAAS,QAAQ,aAAa,KAAK;IACnC,YAAY,KAAK;IACjB,WAAW,KAAK;IAChB,KAAK,KAAK;IACX,CAAC;AACF,OAAI,CAAC,OAAQ,OAAM,IAAI,MAAM,6BAA6B;AAE1D,UAAO;;EAIT,MAAM,iBAAiB,UAAe;AACpC,SAAM,QAAQ,qCAAqC;;EAIrD,MAAM,eAAe,UAAe;AAClC,SAAM,MAAM,MAAM,WAAW,6BAA6B;;;UA3K/C,MAAA,KAAI,CAAC,aAAA,WAAA,EAAhB,mBAEM,OAFN,YAEM,CAAA,GAAA,OAAA,OAAA,OAAA,KAAA,CADJ,mBAAwD,QAAA,EAAlD,OAAM,sCAAoC,EAAA,MAAA,GAAA,CAAA,EAAA,CAAA,IAElC,MAAA,KAAI,CAAC,aAAA,WAAA,EAArB,mBAeM,OAfN,YAeM,CAAA,OAAA,OAAA,OAAA,KAdJ,mBAYM,OAAA;IAXJ,OAAM;IACN,OAAM;IACN,MAAK;IACL,SAAQ;OAER,mBAKE,QAAA;IAJA,kBAAe;IACf,mBAAgB;IAChB,gBAAa;IACb,GAAE;cAGN,mBAAiC,QAAA,MAAA,gBAAxB,MAAA,KAAI,CAAC,UAAS,EAAA,EAAA,CAAA,CAAA,KAAA,WAAA,EAEzB,mBAuCM,OAvCN,YAuCM;8BAtCJ,mBAAwE,MAAA,EAApE,OAAM,uCAAqC,EAAC,uBAAmB,GAAA;IAEnE,mBAAA,gCAAoC;IACzB,MAAA,QAAO,CAAC,aAAa,KAAK,SAAA,WAAA,EAArC,mBA0BM,OA1BN,YA0BM,CAzBJ,mBAwBM,OAxBN,YAwBM,CAvBJ,mBAUM,OAAA,MAAA;+BATJ,mBAAiD,KAAA,EAA9C,OAAM,gCAA8B,EAAC,SAAK,GAAA;KAC7C,mBAA+D,KAA/D,YAA+D,gBAArC,MAAA,QAAO,CAAC,YAAY,KAAK,MAAK,EAAA,EAAA;KAEhD,MAAA,sBAAqB,KAAA,cAAA,WAAA,EAD7B,mBAMI,KAAA;;MAJF,OAAK,eAAA,CAAC,gBACE,MAAA,QAAO,CAAC,YAAY,KAAK,iBAAc,iBAAA,eAAA,CAAA;wBAE5C,MAAA,QAAO,CAAC,YAAY,KAAK,iBAAc,aAAA,eAAA,EAAA,EAAA,IAAA,mBAAA,QAAA,KAAA;QAIzB,MAAA,sBAAqB,KAAA,cAAA,CAAgC,MAAA,QAAO,CAAC,YAAY,KAAK,kBAAA,WAAA,EADnG,mBAWS,UAAA;;KANP,MAAK;KACL,OAAM;KACL,UAAU,cAAA;KACV,SAAO;uBAEL,cAAA,QAAa,eAAA,sBAAA,EAAA,GAAA,WAAA,IAAA,mBAAA,QAAA,KAAA,CAAA,CAAA,CAAA,CAAA,IAAA,mBAAA,QAAA,KAAA;IAKtB,YAMY,MAAA,UAAA,EAAA;KANA,gBAAe;KAAe,WAAS;KAAgB,SAAO;;4BAChD;MAAxB,YAAwB,MAAA,MAAA,CAAA,eAAA;MACxB,YAAuB,MAAA,MAAA,CAAA,cAAA;MACvB,YAAkB,MAAA,MAAA,CAAA,SAAA;MAElB,YAAsE,MAAA,kBAAA,EAAA;OAAnD,YAAW;OAAS,gBAAe"}
@@ -2,6 +2,6 @@ import "./useRpcAuth-SgNzCAPa.js";
2
2
  import "./useQueryCache-DIGf3fCM.js";
3
3
  import "./useMutation-DzRSXPB1.js";
4
4
  import "./AppLink-CHMMrSFI.js";
5
- import { t as VerifyEmail_default } from "./VerifyEmail-De72yrDX.js";
5
+ import { t as VerifyEmail_default } from "./VerifyEmail-CHfTzrHg.js";
6
6
 
7
7
  export { VerifyEmail_default as default };
@@ -1,7 +1,8 @@
1
1
  import { l as useUserSessionStore, m as useEnv } from "./useRpcAuth-SgNzCAPa.js";
2
2
  import { t as useMutation } from "./useMutation-DzRSXPB1.js";
3
3
  import { t as AppLink_default } from "./AppLink-CHMMrSFI.js";
4
- import { createCommentVNode, createElementBlock, createElementVNode, createStaticVNode, createTextVNode, createVNode, defineComponent, onMounted, openBlock, ref, toDisplayString, withCtx } from "vue";
4
+ import { i as withReturnUrl } from "./useReturnUrl-BBoPnDR3.js";
5
+ import { computed, createCommentVNode, createElementBlock, createElementVNode, createStaticVNode, createTextVNode, createVNode, defineComponent, onMounted, openBlock, ref, toDisplayString, withCtx } from "vue";
5
6
  import { useRoute } from "vue-router";
6
7
  import { toast } from "vue3-toastify";
7
8
 
@@ -29,6 +30,8 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
29
30
  __name: "VerifyEmail",
30
31
  setup(__props) {
31
32
  const route = useRoute();
33
+ const returnUrl = computed(() => route.query.returnUrl);
34
+ const loginLink = computed(() => withReturnUrl("/auth/login", returnUrl.value));
32
35
  const sessionStore = useUserSessionStore();
33
36
  const { emailVerificationMode } = useEnv();
34
37
  const token = route.query.token ?? route.params.token;
@@ -102,24 +105,24 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
102
105
  createElementVNode("p", _hoisted_5, [
103
106
  _cache[2] || (_cache[2] = createTextVNode(" Your email has been verified. Switch back to your other tab to continue, or ", -1)),
104
107
  createVNode(AppLink_default, {
105
- to: "/auth/login",
108
+ to: loginLink.value,
106
109
  class: "link link-primary"
107
110
  }, {
108
111
  default: withCtx(() => [..._cache[1] || (_cache[1] = [createTextVNode("continue to login", -1)])]),
109
112
  _: 1
110
- }),
113
+ }, 8, ["to"]),
111
114
  _cache[3] || (_cache[3] = createTextVNode(". ", -1))
112
115
  ])
113
116
  ])) : (openBlock(), createElementBlock("div", _hoisted_6, [
114
117
  _cache[7] || (_cache[7] = createStaticVNode("<div class=\"w-14 h-14 rounded-full bg-error/20 flex items-center justify-center mx-auto\"><svg xmlns=\"http://www.w3.org/2000/svg\" class=\"w-7 h-7 text-error\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"12\" cy=\"12\" r=\"10\"></circle><line x1=\"15\" y1=\"9\" x2=\"9\" y2=\"15\"></line><line x1=\"9\" y1=\"9\" x2=\"15\" y2=\"15\"></line></svg></div><h3 class=\"text-lg font-semibold\">Verification failed</h3>", 2)),
115
118
  createElementVNode("p", _hoisted_7, toDisplayString(errorMessage.value), 1),
116
119
  createElementVNode("div", _hoisted_8, [createVNode(AppLink_default, {
117
- to: "/auth/login",
120
+ to: loginLink.value,
118
121
  class: "btn btn-outline btn-sm"
119
122
  }, {
120
123
  default: withCtx(() => [..._cache[6] || (_cache[6] = [createTextVNode("Back to login", -1)])]),
121
124
  _: 1
122
- }), verifyEmailApi.value ? (openBlock(), createElementBlock("button", {
125
+ }, 8, ["to"]), verifyEmailApi.value ? (openBlock(), createElementBlock("button", {
123
126
  key: 0,
124
127
  type: "button",
125
128
  class: "btn btn-ghost btn-sm",
@@ -134,4 +137,4 @@ var VerifyEmail_default = _sfc_main;
134
137
 
135
138
  //#endregion
136
139
  export { VerifyEmail_default as t };
137
- //# sourceMappingURL=VerifyEmail-De72yrDX.js.map
140
+ //# sourceMappingURL=VerifyEmail-CHfTzrHg.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VerifyEmail-CHfTzrHg.js","names":[],"sources":["../src/slices/auth/features/verify_email/VerifyEmail.vue"],"sourcesContent":["<template>\n <div class=\"card bg-base-100 shadow-lg border border-base-300 max-w-md mx-auto\">\n <div class=\"card-body p-4 sm:p-6 text-center\">\n <div v-if=\"status === 'loading'\" class=\"space-y-4\">\n <span class=\"loading loading-spinner loading-lg text-primary\"></span>\n <p class=\"text-sm text-base-content/70\">Verifying your email...</p>\n </div>\n <div v-else-if=\"status === 'success'\" class=\"space-y-4\">\n <div\n class=\"w-14 h-14 rounded-full bg-success/20 flex items-center justify-center mx-auto\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n class=\"w-7 h-7 text-success\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <polyline points=\"20 6 9 17 4 12\" />\n </svg>\n </div>\n <h3 class=\"text-lg font-semibold\">Email verified!</h3>\n <p class=\"text-sm text-base-content/70\">\n Your email has been verified. Switch back to your other tab to continue, or\n <AppLink :to=\"loginLink\" class=\"link link-primary\">continue to login</AppLink>.\n </p>\n </div>\n <div v-else class=\"space-y-4\">\n <div\n class=\"w-14 h-14 rounded-full bg-error/20 flex items-center justify-center mx-auto\"\n >\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n class=\"w-7 h-7 text-error\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <line x1=\"15\" y1=\"9\" x2=\"9\" y2=\"15\" />\n <line x1=\"9\" y1=\"9\" x2=\"15\" y2=\"15\" />\n </svg>\n </div>\n <h3 class=\"text-lg font-semibold\">Verification failed</h3>\n <p class=\"text-sm text-base-content/70\">{{ errorMessage }}</p>\n <div class=\"flex flex-col gap-2 items-center\">\n <AppLink :to=\"loginLink\" class=\"btn btn-outline btn-sm\">Back to login</AppLink>\n <button\n v-if=\"verifyEmailApi\"\n type=\"button\"\n class=\"btn btn-ghost btn-sm\"\n :disabled=\"resendLoading\"\n @click=\"resendVerification\"\n >\n {{ resendLoading ? 'Sending...' : 'Resend verification email' }}\n </button>\n </div>\n </div>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport AppLink from '../../../../components/AppLink.vue';\nimport { useEnv } from '../../../../composables/useEnv';\nimport { useMutation } from '../../../../composables/useMutation';\nimport { useUserSessionStore } from '../../../../composables/useUserSessionStore';\nimport { withReturnUrl } from '../../../../utils/useReturnUrl';\nimport type { DragoncoreApi } from '@dragonmastery/dragoncore-shared';\nimport type { EmailVerificationApi } from '@dragonmastery/dragoncore-shared';\nimport { computed, ref, onMounted } from 'vue';\nimport { useRoute } from 'vue-router';\nimport { toast } from 'vue3-toastify';\n\nconst AUTH_CHANNEL = 'auth';\n\nconst route = useRoute();\nconst returnUrl = computed(() => route.query.returnUrl as string | undefined);\nconst loginLink = computed(() => withReturnUrl('/auth/login', returnUrl.value));\nconst sessionStore = useUserSessionStore();\nconst { emailVerificationMode } = useEnv();\n\n// Support token from query (?token=xxx) or params (/verify-email/:token)\nconst token = (route.query.token ?? route.params.token) as string;\n\nconst status = ref<'loading' | 'success' | 'error'>('loading');\nconst errorMessage = ref<string>('');\nconst verifyEmailApi = ref<boolean>(false);\nconst resendLoading = ref(false);\n\nconst { mutate: verifyMutate } = useMutation(\n (api, tokenToVerify: string) => {\n const verifyEmail = (api as DragoncoreApi).verifyEmail;\n if (!verifyEmail) throw new Error('Email verification is not configured');\n return (verifyEmail as EmailVerificationApi).verifyEmail(tokenToVerify);\n },\n { skipAuthCheck: true },\n);\n\nconst { mutate: resendMutate } = useMutation(\n (api, _input?: unknown) => {\n const verifyEmail = (api as DragoncoreApi).verifyEmail;\n if (!verifyEmail) throw new Error('Email verification is not configured');\n return (verifyEmail as EmailVerificationApi).resendVerificationEmail();\n },\n { skipAuthCheck: false },\n);\n\nonMounted(async () => {\n if (!token) {\n status.value = 'error';\n errorMessage.value = 'No verification token provided.';\n return;\n }\n\n if (emailVerificationMode === 'disabled') {\n status.value = 'error';\n errorMessage.value = 'Email verification is not enabled for this application.';\n return;\n }\n\n try {\n const result = await verifyMutate(token);\n verifyEmailApi.value = true;\n if (result?.ok) {\n status.value = 'success';\n try {\n await sessionStore.refreshToken();\n } catch {\n // User may need to log in again; that's ok\n }\n const channel = new BroadcastChannel(AUTH_CHANNEL);\n channel.postMessage({ type: 'email_verified' });\n channel.close();\n } else {\n status.value = 'error';\n }\n } catch (error) {\n status.value = 'error';\n errorMessage.value = error instanceof Error ? error.message : 'Something went wrong. The link may have expired.';\n verifyEmailApi.value = true;\n }\n});\n\nconst resendVerification = async () => {\n try {\n resendLoading.value = true;\n const result = await resendMutate(undefined);\n if (result?.ok) {\n toast.success('Verification email sent. Please check your inbox.');\n } else {\n toast.error('Failed to resend verification email.');\n }\n } catch (error) {\n toast.error(error instanceof Error ? error.message : 'Failed to resend');\n } finally {\n resendLoading.value = false;\n }\n};\n</script>\n"],"mappings":"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"}