@dragonmastery/dragoncore-vue 0.0.28 → 0.0.30

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 (166) hide show
  1. package/dist/{ChangePasswordPage-C7rqJfii.js → ChangePasswordPage-D1LGJ02W.js} +1 -1
  2. package/dist/{ChangePasswordPage-nr0B06HB.js → ChangePasswordPage-Dy8lFUcI.js} +1 -1
  3. package/dist/{ChangePasswordPage-nr0B06HB.js.map → ChangePasswordPage-Dy8lFUcI.js.map} +1 -1
  4. package/dist/{ConsentFlowStep-DstxorHZ.js → ConsentFlowStep-DsVhXa91.js} +2 -2
  5. package/dist/{ConsentFlowStep-DstxorHZ.js.map → ConsentFlowStep-DsVhXa91.js.map} +1 -1
  6. package/dist/{ConsentRequired-ELUidmNv.js → ConsentRequired-B3eLxJgx.js} +3 -3
  7. package/dist/{ConsentRequired-ELUidmNv.js.map → ConsentRequired-B3eLxJgx.js.map} +1 -1
  8. package/dist/CreateTeamForm-5V_ks5Ie.js +12 -0
  9. package/dist/{CreateTeamForm-DRfZ74on.js → CreateTeamForm-B7MsOsiV.js} +4 -4
  10. package/dist/{CreateTeamForm-DRfZ74on.js.map → CreateTeamForm-B7MsOsiV.js.map} +1 -1
  11. package/dist/{CreateTeamMemberForm-CSF-tD6B.js → CreateTeamMemberForm-CayF2tIJ.js} +5 -5
  12. package/dist/{CreateTeamMemberForm-ITp4XFn9.js → CreateTeamMemberForm-DeUyXnVa.js} +4 -4
  13. package/dist/{CreateTeamMemberForm-ITp4XFn9.js.map → CreateTeamMemberForm-DeUyXnVa.js.map} +1 -1
  14. package/dist/{CreditBalanceDashboard-BRY56-9w.js → CreditBalanceDashboard-CoIEyZWh.js} +2 -2
  15. package/dist/{CreditBalanceDashboard-BRY56-9w.js.map → CreditBalanceDashboard-CoIEyZWh.js.map} +1 -1
  16. package/dist/{CreditBalanceDashboard-CwXWREgJ.js → CreditBalanceDashboard-D_TsFlTp.js} +5 -5
  17. package/dist/{CreditManagement-D-bsc1US.js → CreditManagement-CCyU_yja.js} +2 -2
  18. package/dist/{CreditManagement-D-bsc1US.js.map → CreditManagement-CCyU_yja.js.map} +1 -1
  19. package/dist/{CreditManagement-BAuzw-NE.js → CreditManagement-CdkqQM7F.js} +5 -5
  20. package/dist/{CreditTransactionHistory-plIaRscn.js → CreditTransactionHistory-UPg9uDNy.js} +3 -3
  21. package/dist/{CreditTransactionHistory-plIaRscn.js.map → CreditTransactionHistory-UPg9uDNy.js.map} +1 -1
  22. package/dist/{CustomerCreateSupportTicketForm-D72blvMU.js → CustomerCreateSupportTicketForm-CiTTUqtW.js} +5 -5
  23. package/dist/{CustomerCreateSupportTicketForm-Co6C_P5o.js → CustomerCreateSupportTicketForm-DFH1JtlA.js} +3 -3
  24. package/dist/{CustomerCreateSupportTicketForm-Co6C_P5o.js.map → CustomerCreateSupportTicketForm-DFH1JtlA.js.map} +1 -1
  25. package/dist/{CustomerSupportTicketDetailPage-CUkf9swo.js → CustomerSupportTicketDetailPage-DAwiE2t6.js} +5 -5
  26. package/dist/{CustomerSupportTicketDetailPage-CUkf9swo.js.map → CustomerSupportTicketDetailPage-DAwiE2t6.js.map} +1 -1
  27. package/dist/CustomerSupportTicketList-CKZl8jxx.js +64 -0
  28. package/dist/{CustomerSupportTicketParent-D19kei4H.js → CustomerSupportTicketParent-D3Gj4Hel.js} +2 -2
  29. package/dist/{CustomerSupportTicketParent-BaKfkSlU.js → CustomerSupportTicketParent-rl4Ym8oa.js} +3 -3
  30. package/dist/{CustomerSupportTicketParent-BaKfkSlU.js.map → CustomerSupportTicketParent-rl4Ym8oa.js.map} +1 -1
  31. package/dist/{CustomerSupportTicketSuccess-DVqoR5-o.js → CustomerSupportTicketSuccess-BEhFZgtn.js} +2 -2
  32. package/dist/{CustomerSupportTicketSuccess-DVqoR5-o.js.map → CustomerSupportTicketSuccess-BEhFZgtn.js.map} +1 -1
  33. package/dist/{CustomerSupportTicketSuccess-B87Zth-g.js → CustomerSupportTicketSuccess-BJO2xsQR.js} +4 -4
  34. package/dist/{DefaultReferralTeamPage-BHail7YF.js → DefaultReferralTeamPage-D3UIrIZK.js} +103 -63
  35. package/dist/DefaultReferralTeamPage-D3UIrIZK.js.map +1 -0
  36. package/dist/EditTeamForm-Bf4rSgQg.js +12 -0
  37. package/dist/{EditTeamForm-BEOkUaKG.js → EditTeamForm-C1_-p3lZ.js} +4 -4
  38. package/dist/{EditTeamForm-BEOkUaKG.js.map → EditTeamForm-C1_-p3lZ.js.map} +1 -1
  39. package/dist/{EditTeamMemberForm-CIqEjFF8.js → EditTeamMemberForm-Bh6zVNyJ.js} +3 -3
  40. package/dist/{EditTeamMemberForm-Fyf8Zxfh.js → EditTeamMemberForm-D9cofrUM.js} +3 -3
  41. package/dist/{EditTeamMemberForm-Fyf8Zxfh.js.map → EditTeamMemberForm-D9cofrUM.js.map} +1 -1
  42. package/dist/{EditUserPage-D3AWaHT2.js → EditUserPage-CQgp-08o.js} +1 -1
  43. package/dist/{EditUserPage-BBzGmOrx.js → EditUserPage-CwsO8naT.js} +2 -2
  44. package/dist/{EditUserPage-BBzGmOrx.js.map → EditUserPage-CwsO8naT.js.map} +1 -1
  45. package/dist/{ExternalLinkIcon-FidcmNOa.js → ExternalLinkIcon-BKVV5Gjm.js} +1 -1
  46. package/dist/{ExternalLinkIcon-FidcmNOa.js.map → ExternalLinkIcon-BKVV5Gjm.js.map} +1 -1
  47. package/dist/{FieldsetSection-CH1jAwcc.js → FieldsetSection-Br_sygWW.js} +1 -1
  48. package/dist/{FieldsetSection-CH1jAwcc.js.map → FieldsetSection-Br_sygWW.js.map} +1 -1
  49. package/dist/{LoginForm-p2fJiTtw.js → LoginForm-CFADKiln.js} +1 -1
  50. package/dist/{LoginForm-D1Mx2vAY.js → LoginForm-CSMHsZrq.js} +1 -1
  51. package/dist/{LoginForm-D1Mx2vAY.js.map → LoginForm-CSMHsZrq.js.map} +1 -1
  52. package/dist/{RecordVersionViewer-NLn1gVys.js → RecordVersionViewer-DKIdX_BX.js} +1 -1
  53. package/dist/{RecordVersionViewer-NLn1gVys.js.map → RecordVersionViewer-DKIdX_BX.js.map} +1 -1
  54. package/dist/{SavedFiltersPage-CvBKztlD.js → SavedFiltersPage-Cz01ZeHx.js} +44 -44
  55. package/dist/{SavedFiltersPage-CvBKztlD.js.map → SavedFiltersPage-Cz01ZeHx.js.map} +1 -1
  56. package/dist/{Signup-BCVZZCR_.js → Signup-CkhRQErA.js} +14 -4
  57. package/dist/Signup-CkhRQErA.js.map +1 -0
  58. package/dist/{Signup-CJrY4IK-.js → Signup-cOvXCtJj.js} +1 -1
  59. package/dist/{SignupConsentFlow-clxBjJlU.js → SignupConsentFlow-CKMFsnf5.js} +16 -8
  60. package/dist/SignupConsentFlow-CKMFsnf5.js.map +1 -0
  61. package/dist/{SignupRequirementsPage-CohJluxQ.js → SignupRequirementsPage-33z--rhH.js} +4 -4
  62. package/dist/{SignupRequirementsPage-CohJluxQ.js.map → SignupRequirementsPage-33z--rhH.js.map} +1 -1
  63. package/dist/{StaffCreateSupportTicketForm-Cm595v_4.js → StaffCreateSupportTicketForm-BtR-Aowv.js} +4 -4
  64. package/dist/{StaffCreateSupportTicketForm-Cm595v_4.js.map → StaffCreateSupportTicketForm-BtR-Aowv.js.map} +1 -1
  65. package/dist/{StaffCreateSupportTicketForm-DBhhJyXE.js → StaffCreateSupportTicketForm-D7ctCaXe.js} +5 -5
  66. package/dist/{StaffSupportTicketDetailPage-B63QXyum.js → StaffSupportTicketDetailPage-LqnNfU34.js} +7 -7
  67. package/dist/{StaffSupportTicketDetailPage-B63QXyum.js.map → StaffSupportTicketDetailPage-LqnNfU34.js.map} +1 -1
  68. package/dist/StaffSupportTicketList-GyzlONKe.js +64 -0
  69. package/dist/{StaffSupportTicketParent-yoC-_Lku.js → StaffSupportTicketParent-DPvdLUii.js} +3 -3
  70. package/dist/{StaffSupportTicketParent-yoC-_Lku.js.map → StaffSupportTicketParent-DPvdLUii.js.map} +1 -1
  71. package/dist/{StaffSupportTicketParent-ByUwsYGx.js → StaffSupportTicketParent-Dyybqx74.js} +2 -2
  72. package/dist/{StaffSupportTicketSuccess-DgULDGIj.js → StaffSupportTicketSuccess-B3N-RMoT.js} +2 -2
  73. package/dist/{StaffSupportTicketSuccess-DgULDGIj.js.map → StaffSupportTicketSuccess-B3N-RMoT.js.map} +1 -1
  74. package/dist/{StaffSupportTicketSuccess-DKzJs74k.js → StaffSupportTicketSuccess-DvonYilY.js} +4 -4
  75. package/dist/{SupportStaffPage-CkFLlle4.js → SupportStaffPage-geoITTqt.js} +3 -3
  76. package/dist/{SupportStaffPage-CkFLlle4.js.map → SupportStaffPage-geoITTqt.js.map} +1 -1
  77. package/dist/{SupportTicketDevLifecycleBadge-BYKZjEv6.js → SupportTicketDevLifecycleBadge-D8-Cv1Np.js} +1 -1
  78. package/dist/{SupportTicketDevLifecycleBadge-BYKZjEv6.js.map → SupportTicketDevLifecycleBadge-D8-Cv1Np.js.map} +1 -1
  79. package/dist/TeamAttachmentsTab-ChP4DaUP.js +64 -0
  80. package/dist/{TeamHistoryTab-p3hDxCc3.js → TeamHistoryTab-CxzA4u_G.js} +3 -3
  81. package/dist/{TeamHistoryTab-p3hDxCc3.js.map → TeamHistoryTab-CxzA4u_G.js.map} +1 -1
  82. package/dist/TeamHistoryTab-wRpRizDE.js +6 -0
  83. package/dist/{TeamList-gppM0GOD.js → TeamList-_SsqJicG.js} +3 -3
  84. package/dist/{TeamList-gppM0GOD.js.map → TeamList-_SsqJicG.js.map} +1 -1
  85. package/dist/TeamList-cp8Pa2xg.js +8 -0
  86. package/dist/TeamMemberList-B16SuLwM.js +7 -0
  87. package/dist/{TeamMemberList-D0-dM5kI.js → TeamMemberList-BYUANoBg.js} +3 -3
  88. package/dist/{TeamMemberList-D0-dM5kI.js.map → TeamMemberList-BYUANoBg.js.map} +1 -1
  89. package/dist/{TeamMemberParent-C9OEziOK.js → TeamMemberParent-BJl8nBmP.js} +4 -4
  90. package/dist/{TeamMemberParent-CJGWXjuM.js → TeamMemberParent-DmYcHU3n.js} +3 -3
  91. package/dist/{TeamMemberParent-CJGWXjuM.js.map → TeamMemberParent-DmYcHU3n.js.map} +1 -1
  92. package/dist/{TeamNotesTab-BnkgZd-5.js → TeamNotesTab-BQN9niw-.js} +1 -1
  93. package/dist/{TeamNotesTab-DPw9YEwK.js → TeamNotesTab-Cego-QT3.js} +2 -2
  94. package/dist/{TeamNotesTab-DPw9YEwK.js.map → TeamNotesTab-Cego-QT3.js.map} +1 -1
  95. package/dist/{TeamParent-YPtenk3l.js → TeamParent-BUnqP-dr.js} +3 -3
  96. package/dist/{TeamParent-YPtenk3l.js.map → TeamParent-BUnqP-dr.js.map} +1 -1
  97. package/dist/TeamParent-BseZ6Zoi.js +11 -0
  98. package/dist/{TimelineNoteInput-DXZhcUkH.js → TimelineNoteInput-BBZv3X4p.js} +2 -2
  99. package/dist/{TimelineNoteInput-DXZhcUkH.js.map → TimelineNoteInput-BBZv3X4p.js.map} +1 -1
  100. package/dist/{TimelineSystemEvent-Ch1sZiyO.js → TimelineSystemEvent-D5fkhkZT.js} +1 -1
  101. package/dist/{TimelineSystemEvent-Ch1sZiyO.js.map → TimelineSystemEvent-D5fkhkZT.js.map} +1 -1
  102. package/dist/UserListPage-BABli3QG.js +5 -0
  103. package/dist/{UserListPage-A0_eNpQ1.js → UserListPage-CDMSZpXK.js} +2 -2
  104. package/dist/{UserListPage-A0_eNpQ1.js.map → UserListPage-CDMSZpXK.js.map} +1 -1
  105. package/dist/{UserProfilePage-FNLYK9kj.js → UserProfilePage-BYitd7QV.js} +1 -1
  106. package/dist/{UserProfilePage-FNLYK9kj.js.map → UserProfilePage-BYitd7QV.js.map} +1 -1
  107. package/dist/{UserProfilePage-BWK97ODt.js → UserProfilePage-Dmxp7oqP.js} +1 -1
  108. package/dist/ViewTeam-rLNxVgS2.js +8 -0
  109. package/dist/{ViewTeam-CRmIplCt.js → ViewTeam-ttqX2In8.js} +131 -32
  110. package/dist/ViewTeam-ttqX2In8.js.map +1 -0
  111. package/dist/ViewTeamMember-B5U8kZBw.js +7 -0
  112. package/dist/{ViewTeamMember-Cf5yXdv6.js → ViewTeamMember-DqWZ3F_h.js} +4 -4
  113. package/dist/{ViewTeamMember-Cf5yXdv6.js.map → ViewTeamMember-DqWZ3F_h.js.map} +1 -1
  114. package/dist/{ZiniaContainer-BV6sojLa.js → ZiniaContainer-BPIfQOc7.js} +1 -1
  115. package/dist/{ZiniaContainer-BV6sojLa.js.map → ZiniaContainer-BPIfQOc7.js.map} +1 -1
  116. package/dist/{convertToLocalDateTime-C13-PrSA.js → convertToLocalDateTime-BKBxm2Rc.js} +1 -1
  117. package/dist/{convertToLocalDateTime-C13-PrSA.js.map → convertToLocalDateTime-BKBxm2Rc.js.map} +1 -1
  118. package/dist/{customerSupportTicketRoutes-Cy4fp4wx.js → customerSupportTicketRoutes-C-DKBy5g.js} +8 -8
  119. package/dist/{customerSupportTicketRoutes-Cy4fp4wx.js.map → customerSupportTicketRoutes-C-DKBy5g.js.map} +1 -1
  120. package/dist/{displayIdFormatter-Cr-QaEk1.js → displayIdFormatter-Ca4Al9iB.js} +1 -1
  121. package/dist/{displayIdFormatter-Cr-QaEk1.js.map → displayIdFormatter-Ca4Al9iB.js.map} +1 -1
  122. package/dist/{extractRpcErrorMessage-CAaeVysa.js → extractRpcErrorMessage-Df8-CJGV.js} +1 -1
  123. package/dist/{extractRpcErrorMessage-CAaeVysa.js.map → extractRpcErrorMessage-Df8-CJGV.js.map} +1 -1
  124. package/dist/index.d.ts +114 -92
  125. package/dist/index.js +48 -47
  126. package/dist/{saved_filter-jeZd2rlb.js → saved_filter-C2N9l_a9.js} +3 -3
  127. package/dist/{saved_filter-jeZd2rlb.js.map → saved_filter-C2N9l_a9.js.map} +1 -1
  128. package/dist/{signupConsentStorage-Ct4ZuKi-.js → signupConsentStorage-pWSoHuhO.js} +10 -2
  129. package/dist/signupConsentStorage-pWSoHuhO.js.map +1 -0
  130. package/dist/{src-zjaOyP9b.js → src-C8B9TJiH.js} +31 -26
  131. package/dist/src-C8B9TJiH.js.map +1 -0
  132. package/dist/{staffSupportTicketRoutes-L4CU5dcu.js → staffSupportTicketRoutes-CyMecWpC.js} +8 -8
  133. package/dist/{staffSupportTicketRoutes-L4CU5dcu.js.map → staffSupportTicketRoutes-CyMecWpC.js.map} +1 -1
  134. package/dist/{teamMemberMetadata-DX0W-B7p.js → teamMemberMetadata-C4urCwBU.js} +1 -1
  135. package/dist/{teamMemberMetadata-DX0W-B7p.js.map → teamMemberMetadata-C4urCwBU.js.map} +1 -1
  136. package/dist/{teamMetadata-26Mwjb2i.js → teamMetadata-NTjPt89L.js} +1 -1
  137. package/dist/{teamMetadata-26Mwjb2i.js.map → teamMetadata-NTjPt89L.js.map} +1 -1
  138. package/dist/{teamRoutes-CtNcFZjR.js → teamRoutes-CFDsHPkd.js} +12 -12
  139. package/dist/{teamRoutes-CtNcFZjR.js.map → teamRoutes-CFDsHPkd.js.map} +1 -1
  140. package/dist/{team_memberRoutes-Cxgte_vj.js → team_memberRoutes-BgjY9Kwq.js} +7 -7
  141. package/dist/{team_memberRoutes-Cxgte_vj.js.map → team_memberRoutes-BgjY9Kwq.js.map} +1 -1
  142. package/dist/{useBreadcrumbs-DIqU5AAp.js → useBreadcrumbs-CPWXm0hm.js} +1 -1
  143. package/dist/{useBreadcrumbs-DIqU5AAp.js.map → useBreadcrumbs-CPWXm0hm.js.map} +1 -1
  144. package/dist/{userAuthorized-klLUHGxT.js → userAuthorized-3RiCDXxr.js} +1 -1
  145. package/dist/{userAuthorized-klLUHGxT.js.map → userAuthorized-3RiCDXxr.js.map} +1 -1
  146. package/package.json +2 -2
  147. package/dist/CreateTeamForm-CmVZdqOQ.js +0 -12
  148. package/dist/CustomerSupportTicketList-CB_Y1lVj.js +0 -64
  149. package/dist/DefaultReferralTeamPage-BHail7YF.js.map +0 -1
  150. package/dist/EditTeamForm-DhutyI9c.js +0 -12
  151. package/dist/Signup-BCVZZCR_.js.map +0 -1
  152. package/dist/SignupConsentFlow-clxBjJlU.js.map +0 -1
  153. package/dist/StaffSupportTicketList-2TbMweMK.js +0 -64
  154. package/dist/TeamAttachmentsTab-D0SJplvU.js +0 -64
  155. package/dist/TeamHistoryTab-BSEOYC_5.js +0 -6
  156. package/dist/TeamList-DU6CFPUY.js +0 -8
  157. package/dist/TeamMemberList-uwSe9zdv.js +0 -7
  158. package/dist/TeamParent-CuASTHKr.js +0 -11
  159. package/dist/UserListPage-CjpxiETO.js +0 -5
  160. package/dist/ViewTeam-Bvvfik4P.js +0 -8
  161. package/dist/ViewTeam-CRmIplCt.js.map +0 -1
  162. package/dist/ViewTeamMember-DtQCZU-X.js +0 -7
  163. package/dist/signupConsentStorage-Ct4ZuKi-.js.map +0 -1
  164. package/dist/src-zjaOyP9b.js.map +0 -1
  165. /package/dist/{Appearance-CHCv4Fd1.js → Appearance-BhzkZJOL.js} +0 -0
  166. /package/dist/{TeamMembersTab-CeOJAhhR.js → TeamMembersTab-D7y2nV__.js} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"TimelineSystemEvent-Ch1sZiyO.js","names":["priorityConfig: Record<SupportTicketPriority, PriorityBadgeConfig>","typeConfig: Record<SupportTicketType, TypeBadgeConfig>","approvalConfig: Record<SupportTicketApproval, ApprovalBadgeConfig>","relative: string"],"sources":["../src/slices/support_ticket/utils/creditValueFormatter.ts","../src/slices/support_ticket/shared/SupportTicketPriorityBadge.vue","../src/slices/support_ticket/shared/SupportTicketTypeBadge.vue","../src/slices/support_ticket/shared/SupportTicketApprovalBadge.vue","../src/slices/support_ticket/utils/formatTicketDate.ts","../src/slices/support_ticket/shared/TimelineItem.vue","../src/slices/support_ticket/shared/TimelineSystemEvent.vue"],"sourcesContent":["import type { SupportTicketApproval } from '@dragonmastery/dragoncore-shared';\n\n/**\n * Helper function to check if credit value is empty\n */\nfunction isCreditValueEmpty(value: string | null | undefined): boolean {\n return value === null || value === undefined || value.trim() === '';\n}\n\n/**\n * Core credit formatting logic\n */\nfunction formatCreditValueCore(creditValue: string | null | undefined): string {\n // Use same logic as backend formatter\n if (isCreditValueEmpty(creditValue)) {\n return 'TBD';\n }\n\n const trimmed = creditValue!.trim();\n const num = parseFloat(trimmed);\n\n // Explicit zero is valid - preserve it (same as backend)\n if (num === 0) {\n return '0';\n }\n\n // Remove trailing zeros for non-zero values (same as backend)\n // Examples: \"100.00\" -> \"100\", \"9.50\" -> \"9.5\", \"123.45\" -> \"123.45\"\n return trimmed.replace(/\\.?0+$/, '');\n}\n\n/**\n * Formats credit value for staff views (includes internal ticket logic)\n *\n * @param creditValue - The credit value from the database\n * @param approvalStatus - The approval status to determine display logic\n * @returns Formatted string for display\n *\n * @example\n * formatStaffCreditValue(\"5.50\", \"PENDING\") // \"5.5\"\n * formatStaffCreditValue(\"10\", \"INTERNAL\") // \"N/A\"\n */\nexport function formatStaffCreditValue(\n creditValue: string | null | undefined,\n approvalStatus?: SupportTicketApproval,\n): string {\n // Internal tickets don't use credits\n if (approvalStatus === 'INTERNAL') {\n return 'N/A';\n }\n\n return formatCreditValueCore(creditValue);\n}\n\n/**\n * Formats credit value for customer views (status-based logic)\n *\n * @param creditValue - The credit value from the database\n * @param status - The computed status from the customer query\n * @returns Formatted string for display\n *\n * @example\n * formatCustomerCreditValue(\"5.50\", \"PENDING\") // \"5.5\"\n * formatCustomerCreditValue(\"5.50\", \"FOLLOWUP\") // \"5.5\"\n */\nexport function formatCustomerCreditValue(creditValue: string | null | undefined): string {\n // Note: Internal tickets (status would be different) are handled by backend\n // Customers don't see internal tickets, so we don't need to check for INTERNAL here\n return formatCreditValueCore(creditValue);\n}\n","<template>\n <div :class=\"badgeClasses\" :aria-label=\"ariaLabel\" role=\"status\">\n {{ displayText }}\n </div>\n</template>\n\n<script setup lang=\"ts\">\n/**\n * SupportTicketPriorityBadge - A reusable Vue component for displaying support ticket priority\n * as color-coded badges with consistent DaisyUI styling and accessibility features.\n *\n * @example\n * <SupportTicketPriorityBadge :priority=\"'HIGH'\" size=\"md\" />\n * <SupportTicketPriorityBadge :priority=\"'CRITICAL'\" size=\"sm\" variant=\"outline\" />\n */\nimport type { SupportTicketPriority } from '@dragonmastery/dragoncore-shared';\nimport { computed } from 'vue';\n\n/**\n * Props for the SupportTicketPriorityBadge component\n */\ninterface Props {\n /** The support ticket priority to display */\n priority: SupportTicketPriority;\n /** Size of the badge - defaults to 'md' */\n size?: 'sm' | 'md' | 'lg';\n /** Visual variant of the badge - defaults to 'default' */\n variant?: 'default' | 'outline';\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n size: 'md',\n variant: 'default',\n});\n\n/**\n * Configuration for each priority badge\n */\ninterface PriorityBadgeConfig {\n /** DaisyUI badge color class */\n color: string;\n /** Display text for the badge */\n text: string;\n /** Accessibility label for screen readers */\n ariaLabel: string;\n}\n\nconst priorityConfig: Record<SupportTicketPriority, PriorityBadgeConfig> = {\n LOW: {\n color: 'badge-neutral',\n text: 'Low',\n ariaLabel: 'Priority: Low priority',\n },\n MEDIUM: {\n color: 'badge-neutral',\n text: 'Medium',\n ariaLabel: 'Priority: Medium priority',\n },\n HIGH: {\n color: 'badge-neutral',\n text: 'High',\n ariaLabel: 'Priority: High priority',\n },\n CRITICAL: {\n color: 'badge-neutral',\n text: 'Critical',\n ariaLabel: 'Priority: Critical priority',\n },\n};\n\nconst getPriorityConfig = (priority: SupportTicketPriority): PriorityBadgeConfig => {\n const config = priorityConfig[priority];\n if (!config) {\n return {\n color: 'badge-neutral',\n text: priority || 'Unknown',\n ariaLabel: `Priority: ${priority || 'Unknown priority'}`,\n };\n }\n return config;\n};\n\nconst config = computed(() => getPriorityConfig(props.priority));\n\nconst badgeClasses = computed(() => {\n const baseClasses = ['badge', 'text-xs'];\n\n // Add color class\n baseClasses.push(config.value.color);\n\n // Add size class with responsive text sizing\n if (props.size === 'sm') {\n baseClasses.push('badge-sm', 'text-xs');\n } else if (props.size === 'lg') {\n baseClasses.push('badge-lg', 'text-sm');\n } else {\n // md size - responsive text\n baseClasses.push('text-xs', 'sm:text-sm');\n }\n\n // Add variant class\n if (props.variant === 'outline') {\n baseClasses.push('badge-outline');\n }\n\n return baseClasses.join(' ');\n});\n\nconst displayText = computed(() => config.value.text);\nconst ariaLabel = computed(() => config.value.ariaLabel);\n</script>\n","<template>\n <div :class=\"badgeClasses\" :aria-label=\"ariaLabel\" role=\"status\">\n {{ displayText }}\n </div>\n</template>\n\n<script setup lang=\"ts\">\n/**\n * SupportTicketTypeBadge - A reusable Vue component for displaying support ticket type\n * as color-coded badges with consistent DaisyUI styling and accessibility features.\n *\n * @example\n * <SupportTicketTypeBadge :type=\"'BUG'\" size=\"md\" />\n * <SupportTicketTypeBadge :type=\"'FEATURE_REQUEST'\" size=\"sm\" variant=\"outline\" />\n */\nimport type { SupportTicketType } from '@dragonmastery/dragoncore-shared';\nimport { computed } from 'vue';\n\n/**\n * Props for the SupportTicketTypeBadge component\n */\ninterface Props {\n /** The support ticket type to display */\n type: SupportTicketType;\n /** Size of the badge - defaults to 'md' */\n size?: 'sm' | 'md' | 'lg';\n /** Visual variant of the badge - defaults to 'default' */\n variant?: 'default' | 'outline';\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n size: 'md',\n variant: 'default',\n});\n\n/**\n * Configuration for each type badge\n */\ninterface TypeBadgeConfig {\n /** DaisyUI badge color class */\n color: string;\n /** Display text for the badge */\n text: string;\n /** Accessibility label for screen readers */\n ariaLabel: string;\n}\n\nconst typeConfig: Record<SupportTicketType, TypeBadgeConfig> = {\n BUG: {\n color: 'badge-neutral',\n text: 'Bug',\n ariaLabel: 'Type: Bug report requiring fix',\n },\n FEATURE_REQUEST: {\n color: 'badge-neutral',\n text: 'Feature',\n ariaLabel: 'Type: New feature request',\n },\n IMPROVEMENT: {\n color: 'badge-neutral',\n text: 'Improvement',\n ariaLabel: 'Type: Enhancement to existing feature',\n },\n OPERATIONAL: {\n color: 'badge-neutral',\n text: 'Ops',\n ariaLabel: 'Type: Operational/admin work',\n },\n};\n\nconst getTypeConfig = (type: SupportTicketType): TypeBadgeConfig => {\n const config = typeConfig[type];\n if (!config) {\n return {\n color: 'badge-neutral',\n text: type || 'Unknown',\n ariaLabel: `Type: ${type || 'Unknown type'}`,\n };\n }\n return config;\n};\n\nconst config = computed(() => getTypeConfig(props.type));\n\nconst badgeClasses = computed(() => {\n const baseClasses = ['badge', 'text-xs'];\n\n // Add color class\n baseClasses.push(config.value.color);\n\n // Add size class with responsive text sizing\n if (props.size === 'sm') {\n baseClasses.push('badge-sm', 'text-xs');\n } else if (props.size === 'lg') {\n baseClasses.push('badge-lg', 'text-sm');\n } else {\n // md size - responsive text\n baseClasses.push('text-xs', 'sm:text-sm');\n }\n\n // Add variant class\n if (props.variant === 'outline') {\n baseClasses.push('badge-outline');\n }\n\n return baseClasses.join(' ');\n});\n\nconst displayText = computed(() => config.value.text);\nconst ariaLabel = computed(() => config.value.ariaLabel);\n</script>\n","<template>\n <div :class=\"badgeClasses\" :aria-label=\"ariaLabel\" role=\"status\">\n {{ displayText }}\n </div>\n</template>\n\n<script setup lang=\"ts\">\n/**\n * SupportTicketApprovalBadge - A reusable Vue component for displaying support ticket approval status\n * as color-coded badges with consistent DaisyUI styling and accessibility features.\n *\n * @example\n * <SupportTicketApprovalBadge :approvalStatus=\"'PENDING'\" size=\"md\" />\n * <SupportTicketApprovalBadge :approvalStatus=\"'APPROVED'\" size=\"sm\" variant=\"outline\" />\n */\nimport type { SupportTicketApproval } from '@dragonmastery/dragoncore-shared';\nimport { computed } from 'vue';\n\n/**\n * Props for the SupportTicketApprovalBadge component\n */\ninterface Props {\n /** The support ticket approval status to display */\n approvalStatus: SupportTicketApproval;\n /** Size of the badge - defaults to 'md' */\n size?: 'sm' | 'md' | 'lg';\n /** Visual variant of the badge - defaults to 'default' */\n variant?: 'default' | 'outline';\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n size: 'md',\n variant: 'default',\n});\n\n/**\n * Configuration for each approval status badge\n */\ninterface ApprovalBadgeConfig {\n /** DaisyUI badge color class */\n color: string;\n /** Display text for the badge */\n text: string;\n /** Accessibility label for screen readers */\n ariaLabel: string;\n}\n\nconst approvalConfig: Record<SupportTicketApproval, ApprovalBadgeConfig> = {\n PENDING: {\n color: 'badge-warning',\n text: 'Pending',\n ariaLabel: 'Approval: Awaiting staff decision',\n },\n APPROVED: {\n color: 'badge-success',\n text: 'Approved',\n ariaLabel: 'Approval: Approved by staff',\n },\n REJECTED: {\n color: 'badge-error',\n text: 'Rejected',\n ariaLabel: 'Approval: Rejected by staff',\n },\n INTERNAL: {\n color: 'badge-info',\n text: 'Internal',\n ariaLabel: 'Approval: Internal staff ticket',\n },\n};\n\nconst getApprovalConfig = (approvalStatus: SupportTicketApproval): ApprovalBadgeConfig => {\n const config = approvalConfig[approvalStatus];\n if (!config) {\n return {\n color: 'badge-neutral',\n text: approvalStatus || 'Unknown',\n ariaLabel: `Approval: ${approvalStatus || 'Unknown status'}`,\n };\n }\n return config;\n};\n\nconst config = computed(() => getApprovalConfig(props.approvalStatus));\n\nconst badgeClasses = computed(() => {\n const baseClasses = ['badge', 'text-xs'];\n\n // Add color class\n baseClasses.push(config.value.color);\n\n // Add size class with responsive text sizing\n if (props.size === 'sm') {\n baseClasses.push('badge-sm', 'text-xs');\n } else if (props.size === 'lg') {\n baseClasses.push('badge-lg', 'text-sm');\n } else {\n // md size - responsive text\n baseClasses.push('text-xs', 'sm:text-sm');\n }\n\n // Add variant class\n if (props.variant === 'outline') {\n baseClasses.push('badge-outline');\n }\n\n return baseClasses.join(' ');\n});\n\nconst displayText = computed(() => config.value.text);\nconst ariaLabel = computed(() => config.value.ariaLabel);\n</script>\n","/**\n * Takes an ISO date string and returns:\n * - formatted: \"Jan 15, 2025\"\n * - relative: \"3 days ago\" / \"2 hours ago\" / \"just now\"\n * - localTime: \"2:30 PM\" (user's local time)\n */\nexport function formatTicketDate(isoString: string): {\n formatted: string;\n relative: string;\n localTime: string;\n} {\n const date = new Date(isoString);\n if (isNaN(date.getTime())) {\n return { formatted: isoString, relative: '', localTime: '' };\n }\n\n const formatted = date.toLocaleDateString(undefined, {\n year: 'numeric',\n month: 'short',\n day: 'numeric',\n });\n\n const localTime = date.toLocaleTimeString(undefined, {\n hour: 'numeric',\n minute: '2-digit',\n });\n\n const now = new Date();\n const diffMs = now.getTime() - date.getTime();\n const diffSec = Math.floor(diffMs / 1000);\n const diffMin = Math.floor(diffSec / 60);\n const diffHour = Math.floor(diffMin / 60);\n const diffDay = Math.floor(diffHour / 24);\n\n let relative: string;\n if (Math.abs(diffSec) < 60) {\n relative = 'just now';\n } else if (diffSec < 0) {\n const sec = Math.abs(diffSec);\n const min = Math.floor(sec / 60);\n const hr = Math.floor(min / 60);\n const day = Math.floor(hr / 24);\n if (min < 60) relative = `in ${min} minute${min === 1 ? '' : 's'}`;\n else if (hr < 24) relative = `in ${hr} hour${hr === 1 ? '' : 's'}`;\n else relative = `in ${day} day${day === 1 ? '' : 's'}`;\n } else if (diffMin < 60) {\n relative = diffMin === 1 ? '1 minute ago' : `${diffMin} minutes ago`;\n } else if (diffHour < 24) {\n relative = diffHour === 1 ? '1 hour ago' : `${diffHour} hours ago`;\n } else if (diffDay < 30) {\n relative = diffDay === 1 ? '1 day ago' : `${diffDay} days ago`;\n } else {\n const diffWeeks = Math.floor(diffDay / 7);\n const diffMonths = Math.floor(diffDay / 30);\n if (diffWeeks < 4) {\n relative = diffWeeks === 1 ? '1 week ago' : `${diffWeeks} weeks ago`;\n } else if (diffMonths < 12) {\n relative = diffMonths === 1 ? '1 month ago' : `${diffMonths} months ago`;\n } else {\n const diffYears = Math.floor(diffMonths / 12);\n relative = diffYears === 1 ? '1 year ago' : `${diffYears} years ago`;\n }\n }\n\n return { formatted, relative, localTime };\n}\n","<template>\n <div\n :class=\"[\n 'card card-bordered p-4 w-full',\n variant === 'internal'\n ? 'bg-warning/10 border-warning/30'\n : 'bg-base-100',\n ]\"\n >\n <div class=\"flex items-center gap-2 mb-3 flex-wrap\">\n <span\n v-if=\"variant === 'internal'\"\n class=\"badge badge-warning badge-sm gap-1 shrink-0\"\n aria-label=\"Internal note\"\n >\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-3.5 h-3.5\"\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 Internal\n </span>\n <span\n v-else\n class=\"w-6 h-6 rounded-full bg-primary text-primary-content text-xs flex items-center justify-center shrink-0\"\n aria-hidden=\"true\"\n >\n {{ authorInitial }}\n </span>\n <span class=\"font-semibold text-sm\">{{ authorName }}</span>\n <span class=\"text-base-content/50 text-sm\">· {{ relativeTime }}</span>\n </div>\n <div class=\"text-sm text-base-content break-words whitespace-pre-wrap\">\n <slot />\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport { formatTicketDate } from '../utils/formatTicketDate';\n\ninterface Props {\n authorName: string;\n createdAt: string;\n variant: 'customer' | 'internal';\n}\n\nconst props = defineProps<Props>();\n\nconst authorInitial = computed(() => {\n const name = props.authorName?.trim() || '?';\n return name.charAt(0).toUpperCase();\n});\n\nconst relativeTime = computed(() => {\n return props.createdAt ? formatTicketDate(props.createdAt).relative : '';\n});\n</script>\n","<template>\n <div class=\"py-2 flex items-start gap-2 text-sm\">\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 text-base-content/30 shrink-0 mt-0.5\"\n aria-hidden=\"true\"\n >\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n d=\"M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.324.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 011.37.49l1.296 2.247a1.125 1.125 0 01-.26 1.431l-1.003.827c-.293.24-.438.613-.431.992a6.759 6.759 0 010 .255c-.007.378.138.75.43.99l1.005.828c.424.35.534.954.26 1.43l-1.298 2.247a1.125 1.125 0 01-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.57 6.57 0 01-.22.128c-.331.183-.581.495-.644.869l-.213 1.28c-.09.543-.56.941-1.11.941h-2.594c-.55 0-1.02-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 01-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 01-1.369-.49l-1.297-2.247a1.125 1.125 0 01.26-1.431l1.004-.827c.292-.24.437-.613.43-.992a6.932 6.932 0 010-.255c.007-.378-.138-.75-.43-.99l-1.004-.828a1.125 1.125 0 01-.26-1.43l1.297-2.247a1.125 1.125 0 011.37-.491l1.216.456c.356.133.751.072 1.076-.124a6.57 6.57 0 01.22-.128c.332-.183.582-.495.644-.869l.214-1.281z\"\n />\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n d=\"M15 12a3 3 0 11-6 0 3 3 0 016 0z\"\n />\n </svg>\n <div class=\"flex-1 min-w-0 space-y-0.5\">\n <div class=\"flex flex-wrap items-baseline gap-x-2 gap-y-1\">\n <span class=\"text-base-content/60 font-medium\">{{ author }}</span>\n <span class=\"text-base-content/40 text-xs\" aria-hidden=\"true\">·</span>\n <span class=\"font-semibold text-base-content\">{{ displayAction }}</span>\n <template v-if=\"type\">\n <span class=\"text-base-content/40 text-xs\" aria-hidden=\"true\">·</span>\n <span\n class=\"badge badge-sm badge-outline border-base-content/20 text-base-content/80 font-normal px-1.5 py-0 capitalize\"\n >\n {{ type }}\n </span>\n </template>\n <template v-if=\"changes && changes.length > 1\">\n <template v-if=\"details\">\n <span class=\"text-base-content/40 text-xs\" aria-hidden=\"true\">·</span>\n <span class=\"text-base-content/70\">{{ details }}</span>\n </template>\n </template>\n <template v-else-if=\"hasChangeDetails\">\n <span class=\"text-base-content/40 text-xs\" aria-hidden=\"true\">·</span>\n <span class=\"text-base-content/70\">\n <template v-if=\"detailsPrefix\">{{ detailsPrefix }} </template>\n <template v-if=\"oldValue != null && newValue != null\">\n <span class=\"line-through text-base-content/50\">{{ oldValue }}</span>\n <span class=\"mx-1 text-base-content/40\">→</span>\n <span>{{ newValue }}</span>\n </template>\n <template v-else-if=\"displayDetails\">{{ displayDetails }}</template>\n </span>\n </template>\n </div>\n <ul\n v-if=\"changes && changes.length > 1\"\n class=\"mt-1.5 ml-6 list-disc list-inside text-base-content/70 text-sm space-y-0.5\"\n >\n <li v-for=\"(change, i) in changes\" :key=\"i\">\n <span class=\"italic text-base-content/60\">{{ change.action }}:</span>\n <template v-if=\"change.oldValue != null && change.newValue != null\">\n <span class=\"line-through text-base-content/50 ml-1\">{{ change.oldValue }}</span>\n <span class=\"mx-1 text-base-content/40\">→</span>\n <span>{{ change.newValue }}</span>\n </template>\n <template v-else-if=\"change.newValue != null\">\n <span class=\"ml-1\">{{ change.newValue }}</span>\n </template>\n </li>\n </ul>\n <div class=\"text-base-content/40 text-xs\">\n <button\n type=\"button\"\n class=\"cursor-pointer hover:text-base-content/60 hover:underline focus:outline-none focus:underline\"\n :title=\"fullDateTime\"\n @click=\"showFull = !showFull\"\n >\n {{ displayTime }}\n </button>\n </div>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, ref } from 'vue';\nimport { formatTicketDate } from '../utils/formatTicketDate';\n\ninterface SystemEventChange {\n action: string;\n oldValue: string | null;\n newValue: string | null;\n fieldName?: string;\n}\n\ninterface Props {\n author: string;\n message: string;\n timestamp: string;\n action?: string;\n type?: string | null;\n details?: string | null;\n oldValue?: string | null;\n newValue?: string | null;\n changes?: SystemEventChange[];\n}\n\nconst props = defineProps<Props>();\nconst showFull = ref(false);\n\nconst displayAction = computed(() => props.action ?? props.message);\nconst displayDetails = computed(() => {\n if (props.details) return props.details;\n if (props.oldValue != null && props.newValue != null) {\n return `${props.oldValue} → ${props.newValue}`;\n }\n return props.newValue ?? null;\n});\nconst hasChangeDetails = computed(\n () =>\n (props.oldValue != null && props.newValue != null) ||\n props.details != null ||\n props.newValue != null,\n);\nconst detailsPrefix = computed(() => {\n if (!props.details || (props.oldValue == null && props.newValue == null)) return null;\n if (props.details.includes(' · ')) {\n const parts = props.details.split(' · ');\n return parts.length > 1 ? parts[0]! : null;\n }\n return props.details;\n});\n\n/** Use relative time when within ~18 hours, otherwise full date and time */\nconst RECENT_THRESHOLD_HOURS = 18;\n\nconst shortTime = computed(() => {\n if (!props.timestamp) return '';\n const { relative, formatted, localTime } = formatTicketDate(props.timestamp);\n const dateTime = [formatted, localTime].filter(Boolean).join(', ');\n if (!relative && !dateTime) return '';\n const date = new Date(props.timestamp);\n const hoursAgo = (Date.now() - date.getTime()) / (1000 * 60 * 60);\n const isRecent = hoursAgo >= 0 && hoursAgo < RECENT_THRESHOLD_HOURS;\n return isRecent ? relative : dateTime;\n});\n\nconst fullDateTime = computed(() => {\n if (!props.timestamp) return '';\n const { formatted, localTime } = formatTicketDate(props.timestamp);\n return [formatted, localTime].filter(Boolean).join(', ');\n});\n\nconst displayTime = computed(() =>\n showFull.value ? fullDateTime.value : shortTime.value,\n);\n</script>\n"],"mappings":"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"}
1
+ {"version":3,"file":"TimelineSystemEvent-D5fkhkZT.js","names":["priorityConfig: Record<SupportTicketPriority, PriorityBadgeConfig>","typeConfig: Record<SupportTicketType, TypeBadgeConfig>","approvalConfig: Record<SupportTicketApproval, ApprovalBadgeConfig>","relative: string"],"sources":["../src/slices/support_ticket/utils/creditValueFormatter.ts","../src/slices/support_ticket/shared/SupportTicketPriorityBadge.vue","../src/slices/support_ticket/shared/SupportTicketTypeBadge.vue","../src/slices/support_ticket/shared/SupportTicketApprovalBadge.vue","../src/slices/support_ticket/utils/formatTicketDate.ts","../src/slices/support_ticket/shared/TimelineItem.vue","../src/slices/support_ticket/shared/TimelineSystemEvent.vue"],"sourcesContent":["import type { SupportTicketApproval } from '@dragonmastery/dragoncore-shared';\n\n/**\n * Helper function to check if credit value is empty\n */\nfunction isCreditValueEmpty(value: string | null | undefined): boolean {\n return value === null || value === undefined || value.trim() === '';\n}\n\n/**\n * Core credit formatting logic\n */\nfunction formatCreditValueCore(creditValue: string | null | undefined): string {\n // Use same logic as backend formatter\n if (isCreditValueEmpty(creditValue)) {\n return 'TBD';\n }\n\n const trimmed = creditValue!.trim();\n const num = parseFloat(trimmed);\n\n // Explicit zero is valid - preserve it (same as backend)\n if (num === 0) {\n return '0';\n }\n\n // Remove trailing zeros for non-zero values (same as backend)\n // Examples: \"100.00\" -> \"100\", \"9.50\" -> \"9.5\", \"123.45\" -> \"123.45\"\n return trimmed.replace(/\\.?0+$/, '');\n}\n\n/**\n * Formats credit value for staff views (includes internal ticket logic)\n *\n * @param creditValue - The credit value from the database\n * @param approvalStatus - The approval status to determine display logic\n * @returns Formatted string for display\n *\n * @example\n * formatStaffCreditValue(\"5.50\", \"PENDING\") // \"5.5\"\n * formatStaffCreditValue(\"10\", \"INTERNAL\") // \"N/A\"\n */\nexport function formatStaffCreditValue(\n creditValue: string | null | undefined,\n approvalStatus?: SupportTicketApproval,\n): string {\n // Internal tickets don't use credits\n if (approvalStatus === 'INTERNAL') {\n return 'N/A';\n }\n\n return formatCreditValueCore(creditValue);\n}\n\n/**\n * Formats credit value for customer views (status-based logic)\n *\n * @param creditValue - The credit value from the database\n * @param status - The computed status from the customer query\n * @returns Formatted string for display\n *\n * @example\n * formatCustomerCreditValue(\"5.50\", \"PENDING\") // \"5.5\"\n * formatCustomerCreditValue(\"5.50\", \"FOLLOWUP\") // \"5.5\"\n */\nexport function formatCustomerCreditValue(creditValue: string | null | undefined): string {\n // Note: Internal tickets (status would be different) are handled by backend\n // Customers don't see internal tickets, so we don't need to check for INTERNAL here\n return formatCreditValueCore(creditValue);\n}\n","<template>\n <div :class=\"badgeClasses\" :aria-label=\"ariaLabel\" role=\"status\">\n {{ displayText }}\n </div>\n</template>\n\n<script setup lang=\"ts\">\n/**\n * SupportTicketPriorityBadge - A reusable Vue component for displaying support ticket priority\n * as color-coded badges with consistent DaisyUI styling and accessibility features.\n *\n * @example\n * <SupportTicketPriorityBadge :priority=\"'HIGH'\" size=\"md\" />\n * <SupportTicketPriorityBadge :priority=\"'CRITICAL'\" size=\"sm\" variant=\"outline\" />\n */\nimport type { SupportTicketPriority } from '@dragonmastery/dragoncore-shared';\nimport { computed } from 'vue';\n\n/**\n * Props for the SupportTicketPriorityBadge component\n */\ninterface Props {\n /** The support ticket priority to display */\n priority: SupportTicketPriority;\n /** Size of the badge - defaults to 'md' */\n size?: 'sm' | 'md' | 'lg';\n /** Visual variant of the badge - defaults to 'default' */\n variant?: 'default' | 'outline';\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n size: 'md',\n variant: 'default',\n});\n\n/**\n * Configuration for each priority badge\n */\ninterface PriorityBadgeConfig {\n /** DaisyUI badge color class */\n color: string;\n /** Display text for the badge */\n text: string;\n /** Accessibility label for screen readers */\n ariaLabel: string;\n}\n\nconst priorityConfig: Record<SupportTicketPriority, PriorityBadgeConfig> = {\n LOW: {\n color: 'badge-neutral',\n text: 'Low',\n ariaLabel: 'Priority: Low priority',\n },\n MEDIUM: {\n color: 'badge-neutral',\n text: 'Medium',\n ariaLabel: 'Priority: Medium priority',\n },\n HIGH: {\n color: 'badge-neutral',\n text: 'High',\n ariaLabel: 'Priority: High priority',\n },\n CRITICAL: {\n color: 'badge-neutral',\n text: 'Critical',\n ariaLabel: 'Priority: Critical priority',\n },\n};\n\nconst getPriorityConfig = (priority: SupportTicketPriority): PriorityBadgeConfig => {\n const config = priorityConfig[priority];\n if (!config) {\n return {\n color: 'badge-neutral',\n text: priority || 'Unknown',\n ariaLabel: `Priority: ${priority || 'Unknown priority'}`,\n };\n }\n return config;\n};\n\nconst config = computed(() => getPriorityConfig(props.priority));\n\nconst badgeClasses = computed(() => {\n const baseClasses = ['badge', 'text-xs'];\n\n // Add color class\n baseClasses.push(config.value.color);\n\n // Add size class with responsive text sizing\n if (props.size === 'sm') {\n baseClasses.push('badge-sm', 'text-xs');\n } else if (props.size === 'lg') {\n baseClasses.push('badge-lg', 'text-sm');\n } else {\n // md size - responsive text\n baseClasses.push('text-xs', 'sm:text-sm');\n }\n\n // Add variant class\n if (props.variant === 'outline') {\n baseClasses.push('badge-outline');\n }\n\n return baseClasses.join(' ');\n});\n\nconst displayText = computed(() => config.value.text);\nconst ariaLabel = computed(() => config.value.ariaLabel);\n</script>\n","<template>\n <div :class=\"badgeClasses\" :aria-label=\"ariaLabel\" role=\"status\">\n {{ displayText }}\n </div>\n</template>\n\n<script setup lang=\"ts\">\n/**\n * SupportTicketTypeBadge - A reusable Vue component for displaying support ticket type\n * as color-coded badges with consistent DaisyUI styling and accessibility features.\n *\n * @example\n * <SupportTicketTypeBadge :type=\"'BUG'\" size=\"md\" />\n * <SupportTicketTypeBadge :type=\"'FEATURE_REQUEST'\" size=\"sm\" variant=\"outline\" />\n */\nimport type { SupportTicketType } from '@dragonmastery/dragoncore-shared';\nimport { computed } from 'vue';\n\n/**\n * Props for the SupportTicketTypeBadge component\n */\ninterface Props {\n /** The support ticket type to display */\n type: SupportTicketType;\n /** Size of the badge - defaults to 'md' */\n size?: 'sm' | 'md' | 'lg';\n /** Visual variant of the badge - defaults to 'default' */\n variant?: 'default' | 'outline';\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n size: 'md',\n variant: 'default',\n});\n\n/**\n * Configuration for each type badge\n */\ninterface TypeBadgeConfig {\n /** DaisyUI badge color class */\n color: string;\n /** Display text for the badge */\n text: string;\n /** Accessibility label for screen readers */\n ariaLabel: string;\n}\n\nconst typeConfig: Record<SupportTicketType, TypeBadgeConfig> = {\n BUG: {\n color: 'badge-neutral',\n text: 'Bug',\n ariaLabel: 'Type: Bug report requiring fix',\n },\n FEATURE_REQUEST: {\n color: 'badge-neutral',\n text: 'Feature',\n ariaLabel: 'Type: New feature request',\n },\n IMPROVEMENT: {\n color: 'badge-neutral',\n text: 'Improvement',\n ariaLabel: 'Type: Enhancement to existing feature',\n },\n OPERATIONAL: {\n color: 'badge-neutral',\n text: 'Ops',\n ariaLabel: 'Type: Operational/admin work',\n },\n};\n\nconst getTypeConfig = (type: SupportTicketType): TypeBadgeConfig => {\n const config = typeConfig[type];\n if (!config) {\n return {\n color: 'badge-neutral',\n text: type || 'Unknown',\n ariaLabel: `Type: ${type || 'Unknown type'}`,\n };\n }\n return config;\n};\n\nconst config = computed(() => getTypeConfig(props.type));\n\nconst badgeClasses = computed(() => {\n const baseClasses = ['badge', 'text-xs'];\n\n // Add color class\n baseClasses.push(config.value.color);\n\n // Add size class with responsive text sizing\n if (props.size === 'sm') {\n baseClasses.push('badge-sm', 'text-xs');\n } else if (props.size === 'lg') {\n baseClasses.push('badge-lg', 'text-sm');\n } else {\n // md size - responsive text\n baseClasses.push('text-xs', 'sm:text-sm');\n }\n\n // Add variant class\n if (props.variant === 'outline') {\n baseClasses.push('badge-outline');\n }\n\n return baseClasses.join(' ');\n});\n\nconst displayText = computed(() => config.value.text);\nconst ariaLabel = computed(() => config.value.ariaLabel);\n</script>\n","<template>\n <div :class=\"badgeClasses\" :aria-label=\"ariaLabel\" role=\"status\">\n {{ displayText }}\n </div>\n</template>\n\n<script setup lang=\"ts\">\n/**\n * SupportTicketApprovalBadge - A reusable Vue component for displaying support ticket approval status\n * as color-coded badges with consistent DaisyUI styling and accessibility features.\n *\n * @example\n * <SupportTicketApprovalBadge :approvalStatus=\"'PENDING'\" size=\"md\" />\n * <SupportTicketApprovalBadge :approvalStatus=\"'APPROVED'\" size=\"sm\" variant=\"outline\" />\n */\nimport type { SupportTicketApproval } from '@dragonmastery/dragoncore-shared';\nimport { computed } from 'vue';\n\n/**\n * Props for the SupportTicketApprovalBadge component\n */\ninterface Props {\n /** The support ticket approval status to display */\n approvalStatus: SupportTicketApproval;\n /** Size of the badge - defaults to 'md' */\n size?: 'sm' | 'md' | 'lg';\n /** Visual variant of the badge - defaults to 'default' */\n variant?: 'default' | 'outline';\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n size: 'md',\n variant: 'default',\n});\n\n/**\n * Configuration for each approval status badge\n */\ninterface ApprovalBadgeConfig {\n /** DaisyUI badge color class */\n color: string;\n /** Display text for the badge */\n text: string;\n /** Accessibility label for screen readers */\n ariaLabel: string;\n}\n\nconst approvalConfig: Record<SupportTicketApproval, ApprovalBadgeConfig> = {\n PENDING: {\n color: 'badge-warning',\n text: 'Pending',\n ariaLabel: 'Approval: Awaiting staff decision',\n },\n APPROVED: {\n color: 'badge-success',\n text: 'Approved',\n ariaLabel: 'Approval: Approved by staff',\n },\n REJECTED: {\n color: 'badge-error',\n text: 'Rejected',\n ariaLabel: 'Approval: Rejected by staff',\n },\n INTERNAL: {\n color: 'badge-info',\n text: 'Internal',\n ariaLabel: 'Approval: Internal staff ticket',\n },\n};\n\nconst getApprovalConfig = (approvalStatus: SupportTicketApproval): ApprovalBadgeConfig => {\n const config = approvalConfig[approvalStatus];\n if (!config) {\n return {\n color: 'badge-neutral',\n text: approvalStatus || 'Unknown',\n ariaLabel: `Approval: ${approvalStatus || 'Unknown status'}`,\n };\n }\n return config;\n};\n\nconst config = computed(() => getApprovalConfig(props.approvalStatus));\n\nconst badgeClasses = computed(() => {\n const baseClasses = ['badge', 'text-xs'];\n\n // Add color class\n baseClasses.push(config.value.color);\n\n // Add size class with responsive text sizing\n if (props.size === 'sm') {\n baseClasses.push('badge-sm', 'text-xs');\n } else if (props.size === 'lg') {\n baseClasses.push('badge-lg', 'text-sm');\n } else {\n // md size - responsive text\n baseClasses.push('text-xs', 'sm:text-sm');\n }\n\n // Add variant class\n if (props.variant === 'outline') {\n baseClasses.push('badge-outline');\n }\n\n return baseClasses.join(' ');\n});\n\nconst displayText = computed(() => config.value.text);\nconst ariaLabel = computed(() => config.value.ariaLabel);\n</script>\n","/**\n * Takes an ISO date string and returns:\n * - formatted: \"Jan 15, 2025\"\n * - relative: \"3 days ago\" / \"2 hours ago\" / \"just now\"\n * - localTime: \"2:30 PM\" (user's local time)\n */\nexport function formatTicketDate(isoString: string): {\n formatted: string;\n relative: string;\n localTime: string;\n} {\n const date = new Date(isoString);\n if (isNaN(date.getTime())) {\n return { formatted: isoString, relative: '', localTime: '' };\n }\n\n const formatted = date.toLocaleDateString(undefined, {\n year: 'numeric',\n month: 'short',\n day: 'numeric',\n });\n\n const localTime = date.toLocaleTimeString(undefined, {\n hour: 'numeric',\n minute: '2-digit',\n });\n\n const now = new Date();\n const diffMs = now.getTime() - date.getTime();\n const diffSec = Math.floor(diffMs / 1000);\n const diffMin = Math.floor(diffSec / 60);\n const diffHour = Math.floor(diffMin / 60);\n const diffDay = Math.floor(diffHour / 24);\n\n let relative: string;\n if (Math.abs(diffSec) < 60) {\n relative = 'just now';\n } else if (diffSec < 0) {\n const sec = Math.abs(diffSec);\n const min = Math.floor(sec / 60);\n const hr = Math.floor(min / 60);\n const day = Math.floor(hr / 24);\n if (min < 60) relative = `in ${min} minute${min === 1 ? '' : 's'}`;\n else if (hr < 24) relative = `in ${hr} hour${hr === 1 ? '' : 's'}`;\n else relative = `in ${day} day${day === 1 ? '' : 's'}`;\n } else if (diffMin < 60) {\n relative = diffMin === 1 ? '1 minute ago' : `${diffMin} minutes ago`;\n } else if (diffHour < 24) {\n relative = diffHour === 1 ? '1 hour ago' : `${diffHour} hours ago`;\n } else if (diffDay < 30) {\n relative = diffDay === 1 ? '1 day ago' : `${diffDay} days ago`;\n } else {\n const diffWeeks = Math.floor(diffDay / 7);\n const diffMonths = Math.floor(diffDay / 30);\n if (diffWeeks < 4) {\n relative = diffWeeks === 1 ? '1 week ago' : `${diffWeeks} weeks ago`;\n } else if (diffMonths < 12) {\n relative = diffMonths === 1 ? '1 month ago' : `${diffMonths} months ago`;\n } else {\n const diffYears = Math.floor(diffMonths / 12);\n relative = diffYears === 1 ? '1 year ago' : `${diffYears} years ago`;\n }\n }\n\n return { formatted, relative, localTime };\n}\n","<template>\n <div\n :class=\"[\n 'card card-bordered p-4 w-full',\n variant === 'internal'\n ? 'bg-warning/10 border-warning/30'\n : 'bg-base-100',\n ]\"\n >\n <div class=\"flex items-center gap-2 mb-3 flex-wrap\">\n <span\n v-if=\"variant === 'internal'\"\n class=\"badge badge-warning badge-sm gap-1 shrink-0\"\n aria-label=\"Internal note\"\n >\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-3.5 h-3.5\"\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 Internal\n </span>\n <span\n v-else\n class=\"w-6 h-6 rounded-full bg-primary text-primary-content text-xs flex items-center justify-center shrink-0\"\n aria-hidden=\"true\"\n >\n {{ authorInitial }}\n </span>\n <span class=\"font-semibold text-sm\">{{ authorName }}</span>\n <span class=\"text-base-content/50 text-sm\">· {{ relativeTime }}</span>\n </div>\n <div class=\"text-sm text-base-content break-words whitespace-pre-wrap\">\n <slot />\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed } from 'vue';\nimport { formatTicketDate } from '../utils/formatTicketDate';\n\ninterface Props {\n authorName: string;\n createdAt: string;\n variant: 'customer' | 'internal';\n}\n\nconst props = defineProps<Props>();\n\nconst authorInitial = computed(() => {\n const name = props.authorName?.trim() || '?';\n return name.charAt(0).toUpperCase();\n});\n\nconst relativeTime = computed(() => {\n return props.createdAt ? formatTicketDate(props.createdAt).relative : '';\n});\n</script>\n","<template>\n <div class=\"py-2 flex items-start gap-2 text-sm\">\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 text-base-content/30 shrink-0 mt-0.5\"\n aria-hidden=\"true\"\n >\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n d=\"M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.324.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 011.37.49l1.296 2.247a1.125 1.125 0 01-.26 1.431l-1.003.827c-.293.24-.438.613-.431.992a6.759 6.759 0 010 .255c-.007.378.138.75.43.99l1.005.828c.424.35.534.954.26 1.43l-1.298 2.247a1.125 1.125 0 01-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.57 6.57 0 01-.22.128c-.331.183-.581.495-.644.869l-.213 1.28c-.09.543-.56.941-1.11.941h-2.594c-.55 0-1.02-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 01-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 01-1.369-.49l-1.297-2.247a1.125 1.125 0 01.26-1.431l1.004-.827c.292-.24.437-.613.43-.992a6.932 6.932 0 010-.255c.007-.378-.138-.75-.43-.99l-1.004-.828a1.125 1.125 0 01-.26-1.43l1.297-2.247a1.125 1.125 0 011.37-.491l1.216.456c.356.133.751.072 1.076-.124a6.57 6.57 0 01.22-.128c.332-.183.582-.495.644-.869l.214-1.281z\"\n />\n <path\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n d=\"M15 12a3 3 0 11-6 0 3 3 0 016 0z\"\n />\n </svg>\n <div class=\"flex-1 min-w-0 space-y-0.5\">\n <div class=\"flex flex-wrap items-baseline gap-x-2 gap-y-1\">\n <span class=\"text-base-content/60 font-medium\">{{ author }}</span>\n <span class=\"text-base-content/40 text-xs\" aria-hidden=\"true\">·</span>\n <span class=\"font-semibold text-base-content\">{{ displayAction }}</span>\n <template v-if=\"type\">\n <span class=\"text-base-content/40 text-xs\" aria-hidden=\"true\">·</span>\n <span\n class=\"badge badge-sm badge-outline border-base-content/20 text-base-content/80 font-normal px-1.5 py-0 capitalize\"\n >\n {{ type }}\n </span>\n </template>\n <template v-if=\"changes && changes.length > 1\">\n <template v-if=\"details\">\n <span class=\"text-base-content/40 text-xs\" aria-hidden=\"true\">·</span>\n <span class=\"text-base-content/70\">{{ details }}</span>\n </template>\n </template>\n <template v-else-if=\"hasChangeDetails\">\n <span class=\"text-base-content/40 text-xs\" aria-hidden=\"true\">·</span>\n <span class=\"text-base-content/70\">\n <template v-if=\"detailsPrefix\">{{ detailsPrefix }} </template>\n <template v-if=\"oldValue != null && newValue != null\">\n <span class=\"line-through text-base-content/50\">{{ oldValue }}</span>\n <span class=\"mx-1 text-base-content/40\">→</span>\n <span>{{ newValue }}</span>\n </template>\n <template v-else-if=\"displayDetails\">{{ displayDetails }}</template>\n </span>\n </template>\n </div>\n <ul\n v-if=\"changes && changes.length > 1\"\n class=\"mt-1.5 ml-6 list-disc list-inside text-base-content/70 text-sm space-y-0.5\"\n >\n <li v-for=\"(change, i) in changes\" :key=\"i\">\n <span class=\"italic text-base-content/60\">{{ change.action }}:</span>\n <template v-if=\"change.oldValue != null && change.newValue != null\">\n <span class=\"line-through text-base-content/50 ml-1\">{{ change.oldValue }}</span>\n <span class=\"mx-1 text-base-content/40\">→</span>\n <span>{{ change.newValue }}</span>\n </template>\n <template v-else-if=\"change.newValue != null\">\n <span class=\"ml-1\">{{ change.newValue }}</span>\n </template>\n </li>\n </ul>\n <div class=\"text-base-content/40 text-xs\">\n <button\n type=\"button\"\n class=\"cursor-pointer hover:text-base-content/60 hover:underline focus:outline-none focus:underline\"\n :title=\"fullDateTime\"\n @click=\"showFull = !showFull\"\n >\n {{ displayTime }}\n </button>\n </div>\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\nimport { computed, ref } from 'vue';\nimport { formatTicketDate } from '../utils/formatTicketDate';\n\ninterface SystemEventChange {\n action: string;\n oldValue: string | null;\n newValue: string | null;\n fieldName?: string;\n}\n\ninterface Props {\n author: string;\n message: string;\n timestamp: string;\n action?: string;\n type?: string | null;\n details?: string | null;\n oldValue?: string | null;\n newValue?: string | null;\n changes?: SystemEventChange[];\n}\n\nconst props = defineProps<Props>();\nconst showFull = ref(false);\n\nconst displayAction = computed(() => props.action ?? props.message);\nconst displayDetails = computed(() => {\n if (props.details) return props.details;\n if (props.oldValue != null && props.newValue != null) {\n return `${props.oldValue} → ${props.newValue}`;\n }\n return props.newValue ?? null;\n});\nconst hasChangeDetails = computed(\n () =>\n (props.oldValue != null && props.newValue != null) ||\n props.details != null ||\n props.newValue != null,\n);\nconst detailsPrefix = computed(() => {\n if (!props.details || (props.oldValue == null && props.newValue == null)) return null;\n if (props.details.includes(' · ')) {\n const parts = props.details.split(' · ');\n return parts.length > 1 ? parts[0]! : null;\n }\n return props.details;\n});\n\n/** Use relative time when within ~18 hours, otherwise full date and time */\nconst RECENT_THRESHOLD_HOURS = 18;\n\nconst shortTime = computed(() => {\n if (!props.timestamp) return '';\n const { relative, formatted, localTime } = formatTicketDate(props.timestamp);\n const dateTime = [formatted, localTime].filter(Boolean).join(', ');\n if (!relative && !dateTime) return '';\n const date = new Date(props.timestamp);\n const hoursAgo = (Date.now() - date.getTime()) / (1000 * 60 * 60);\n const isRecent = hoursAgo >= 0 && hoursAgo < RECENT_THRESHOLD_HOURS;\n return isRecent ? relative : dateTime;\n});\n\nconst fullDateTime = computed(() => {\n if (!props.timestamp) return '';\n const { formatted, localTime } = formatTicketDate(props.timestamp);\n return [formatted, localTime].filter(Boolean).join(', ');\n});\n\nconst displayTime = computed(() =>\n showFull.value ? fullDateTime.value : shortTime.value,\n);\n</script>\n"],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import "./useRpcAuth-CJtq1dqM.js";
2
+ import "./EnhancedRefreshTokenHandler-C6tZCcfX.js";
3
+ import { t as UserListPage_default } from "./UserListPage-CDMSZpXK.js";
4
+
5
+ export { UserListPage_default as default };
@@ -1,6 +1,6 @@
1
1
  import { r as executeWithAuth } from "./useRpcAuth-CJtq1dqM.js";
2
2
  import { r as getRefreshTokenHandler } from "./EnhancedRefreshTokenHandler-C6tZCcfX.js";
3
- import { t as formatSystemTimestamp } from "./convertToLocalDateTime-C13-PrSA.js";
3
+ import { t as formatSystemTimestamp } from "./convertToLocalDateTime-BKBxm2Rc.js";
4
4
  import { computed, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, normalizeClass, openBlock, resolveComponent, toDisplayString, unref, withCtx } from "vue";
5
5
  import { UserReadSchema } from "@dragonmastery/dragoncore-shared";
6
6
  import { useCursorDataTable, withMetadata } from "@dragonmastery/zinia-forms-core";
@@ -151,4 +151,4 @@ var UserListPage_default = _sfc_main;
151
151
 
152
152
  //#endregion
153
153
  export { userRowSchemaWithMetadata as n, UserTypeBadge_default as r, UserListPage_default as t };
154
- //# sourceMappingURL=UserListPage-A0_eNpQ1.js.map
154
+ //# sourceMappingURL=UserListPage-CDMSZpXK.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"UserListPage-A0_eNpQ1.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":";;;;;;;;;;;;;;;EAcA,MAAM,QAAQ;EAId,MAAM,aAAa;GACjB,UAAU;IACR,OAAO;IACP,SAAS;IACV;GACD,MAAM;IACJ,OAAO;IACP,SAAS;IACV;GACD,OAAO;IACL,OAAO;IACP,SAAS;IACV;GACD,aAAa;IACX,OAAO;IACP,SAAS;IACV;GACF;EAED,MAAM,YAAY,eAAe;AAC/B,UAAO,WAAW,MAAM,WAAW,SAAS,MAAM;IAClD;EAEF,MAAM,eAAe,eAAe;GAClC,MAAM,SAAS,WAAW,MAAM;GAChC,MAAM,cAAc,SAAS,MAAM;AAEnC,OAAI,CAAC,OACH,QAAO,GAAG,YAAY;AAGxB,UAAO,GAAG,YAAY,SAAS,OAAO;IACtC;;uBAjDA,mBAEO,QAAA,EAFD,OAAK,eAAA,CAAC,kBAAyB,aAAA,MAAY,CAAA,EAAA,kBAC5C,UAAA,MAAS,EAAA,EAAA;;;;;;;;ACEhB,MAAa,4BAA4B,aAAa,gBAAgB,iBAAiB;CACrF,UAAU,EAAE,OAAO,YAAY;CAC/B,OAAO,EAAE,OAAO,SAAS;CACzB,WAAW,EAAE,OAAO,QAAQ;CAC5B,gBAAgB,EAAE,OAAO,YAAY;CACrC,YAAY,EAAE,OAAO,WAAW;CACjC,CAAC;;;;;;;;ECsCF,MAAM,EAAE,mBAAmB,mBAAmB,2BAA2B;GACvE,WAAW,YAAY;AAmBrB,WAAO;KACL,OAnBY,MAAM,gBAClB,OAAO,QAAQ;AACb,aAAO,MAAM,IAAI,MAAM,WAAW;QAEpC,EAAE,qBAAqB,wBAAwB,EAAE,CAClD,EAGoC,KAAK,UAAU;MAClD,IAAI,KAAK;MACT,UAAU,KAAK;MACf,OAAO,KAAK;MACZ,gBAAgB,KAAK;MACrB,WAAW,KAAK;MAChB,YAAY,KAAK;MACjB,YAAY,KAAK,cAAc;MAChC,EAAE;KAID,aAAa;KACb,iBAAiB;KACjB,gBAAgB;KAChB,gBAAgB;KACjB;;GAIH,SAAS;IACP,UAAU;KAAE,OAAO;KAAY,OAAO;KAAY,UAAU;KAAM;IAClE,OAAO;KAAE,OAAO;KAAS,OAAO;KAAS,UAAU;KAAM;IACzD,WAAW;KAAE,OAAO;KAAQ,OAAO;KAAa,UAAU;KAAM;IAChE,gBAAgB;KACd,OAAO;KACP,OAAO;KACP,UAAU;KACX;IACD,YAAY;KAAE,OAAO;KAAW,OAAO;KAAc,UAAU;KAAM;IACtE;GAGD,SAAS,EACP,OAAO,CACL;IACE,KAAK;IACL,MAAM;IACN,MAAM;IACN,SAAS;IACT,MAAM;IACN,OAAO,QAAiB,gBAAgB,IAAI,GAAG;IAChD,CACF,EACF;GAED,YAAY,EACV,UAAU,KACX;GACF,CAAC;;;uBA1GA,mBAmCM,OAnCN,YAmCM;IAlCJ,mBAAA,kCAAsC;8BACtC,mBAEM,OAAA,EAFD,OAAM,0CAAwC,EAAA,CACjD,mBAAmD,MAAA,EAA/C,OAAM,sBAAoB,EAAC,kBAAe,CAAA;IAGhD,mBAAA,qBAAyB;IACzB,YA2BiB,MAAA,eAAA,EAAA,MAAA;KAzBJ,kBAAc,SACqB,EADjB,UAAG,CAC9B,YAA4C,uBAAA,EAA5B,aAAW,IAAI,WAAA,EAAA,MAAA,GAAA,CAAA,YAAA,CAAA,CAAA,CAAA;KAGtB,uBAAmB,SAMrB,EANyB,UAAG,CACnC,mBAKO,QAAA,EAJL,OAAK,eAAA,CAAC,kBACE,IAAI,iBAAc,kBAAA,cAAA,CAAA,EAAA,kBAEvB,IAAI,iBAAc,aAAA,eAAA,EAAA,EAAA,CAAA,CAAA;KAId,mBAAe,SACmB,EADf,UAAG,CAAA,gCAC5B,MAAA,sBAAqB,CAAC,IAAI,WAAU,CAAA,EAAA,EAAA,CAAA,CAAA;KAG9B,gBAAY,SAMP,EANW,UAAG,CAC5B,YAKc,wBAAA;MAJX,IAAE;OAAA,MAAA;OAAA,QAAA,EAAA,IAAoC,IAAI,IAAE;OAAA;MAC7C,OAAM;;6BAGR,CAAA,GAAA,OAAA,OAAA,OAAA,KAAA,CAAA,gBAFC,UAED,GAAA,CAAA,EAAA,CAAA"}
1
+ {"version":3,"file":"UserListPage-CDMSZpXK.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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"}
@@ -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-FNLYK9kj.js.map
170
+ //# sourceMappingURL=UserProfilePage-BYitd7QV.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"UserProfilePage-FNLYK9kj.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-BYitd7QV.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"}
@@ -3,6 +3,6 @@ import "./EnhancedRefreshTokenHandler-C6tZCcfX.js";
3
3
  import "./useQueryCache-alzaRWEb.js";
4
4
  import "./useMutation-BLNuJoYl.js";
5
5
  import "./useQuery-BzUGEOj0.js";
6
- import { t as UserProfilePage_default } from "./UserProfilePage-FNLYK9kj.js";
6
+ import { t as UserProfilePage_default } from "./UserProfilePage-BYitd7QV.js";
7
7
 
8
8
  export { UserProfilePage_default as default };
@@ -0,0 +1,8 @@
1
+ import "./useRpcAuth-CJtq1dqM.js";
2
+ import "./ZiniaContainer-BPIfQOc7.js";
3
+ import "./userAuthorized-3RiCDXxr.js";
4
+ import "./team_memberRoutes-BgjY9Kwq.js";
5
+ import "./teamRoutes-CFDsHPkd.js";
6
+ import { t as ViewTeam_default } from "./ViewTeam-ttqX2In8.js";
7
+
8
+ export { ViewTeam_default as default };
@@ -1,8 +1,9 @@
1
- import { t as ZiniaContainer_default } from "./ZiniaContainer-BV6sojLa.js";
2
- import { t as formatSystemTimestamp } from "./convertToLocalDateTime-C13-PrSA.js";
3
- import { t as teamPaths } from "./teamRoutes-CtNcFZjR.js";
4
- import { computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, openBlock, resolveComponent, toDisplayString, unref, withCtx } from "vue";
1
+ import { t as ZiniaContainer_default } from "./ZiniaContainer-BPIfQOc7.js";
2
+ import { t as formatSystemTimestamp } from "./convertToLocalDateTime-BKBxm2Rc.js";
3
+ import { t as teamPaths } from "./teamRoutes-CFDsHPkd.js";
4
+ import { computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, inject, openBlock, resolveComponent, toDisplayString, unref, withCtx } from "vue";
5
5
  import { useRoute } from "vue-router";
6
+ import { toast } from "vue3-toastify";
6
7
 
7
8
  //#region src/slices/team/ViewTeam.vue
8
9
  const _hoisted_1 = {
@@ -106,15 +107,34 @@ const _hoisted_40 = {
106
107
  class: "text-sm mt-2"
107
108
  };
108
109
  const _hoisted_41 = ["href"];
109
- const _hoisted_42 = { class: "mt-4 pt-4 border-t border-base-300 text-xs sm:text-sm text-base-content/50" };
110
- const _hoisted_43 = { class: "flex flex-col sm:flex-row sm:items-center gap-1 sm:gap-4" };
111
- const _hoisted_44 = { key: 0 };
112
- const _hoisted_45 = { key: 1 };
113
- const _hoisted_46 = {
110
+ const _hoisted_42 = {
111
+ key: 4,
112
+ class: "card bg-base-100 shadow-sm"
113
+ };
114
+ const _hoisted_43 = { class: "card-body" };
115
+ const _hoisted_44 = {
116
+ key: 0,
117
+ class: "mb-3"
118
+ };
119
+ const _hoisted_45 = { class: "flex items-center gap-2" };
120
+ const _hoisted_46 = { class: "flex-1 px-3 py-2 bg-base-200 rounded-lg text-sm font-mono break-all" };
121
+ const _hoisted_47 = { key: 1 };
122
+ const _hoisted_48 = { class: "flex items-center gap-2" };
123
+ const _hoisted_49 = { class: "flex-1 px-3 py-2 bg-base-200 rounded-lg text-sm font-mono break-all" };
124
+ const _hoisted_50 = {
125
+ key: 2,
126
+ class: "flex items-center gap-2"
127
+ };
128
+ const _hoisted_51 = { class: "flex-1 px-3 py-2 bg-base-200 rounded-lg text-sm font-mono" };
129
+ const _hoisted_52 = { class: "mt-4 pt-4 border-t border-base-300 text-xs sm:text-sm text-base-content/50" };
130
+ const _hoisted_53 = { class: "flex flex-col sm:flex-row sm:items-center gap-1 sm:gap-4" };
131
+ const _hoisted_54 = { key: 0 };
132
+ const _hoisted_55 = { key: 1 };
133
+ const _hoisted_56 = {
114
134
  key: 2,
115
135
  class: "text-xs"
116
136
  };
117
- const _hoisted_47 = { class: "flex flex-col sm:flex-row gap-3 justify-center mt-6" };
137
+ const _hoisted_57 = { class: "flex flex-col sm:flex-row gap-3 justify-center mt-6" };
118
138
  const _sfc_main = /* @__PURE__ */ defineComponent({
119
139
  __name: "ViewTeam",
120
140
  props: {
@@ -125,10 +145,29 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
125
145
  setup(__props) {
126
146
  const props = __props;
127
147
  const team_id = useRoute().params.id;
148
+ const referralAppBaseUrl = inject("referralAppBaseUrl") ?? "";
149
+ const referralMarketingBaseUrl = inject("referralMarketingBaseUrl") ?? "";
128
150
  const teamData = computed(() => props.team);
151
+ function buildRefLink(base) {
152
+ const tag = teamData.value?.referral_tag;
153
+ if (!tag) return "";
154
+ const b = base.trim().replace(/\/$/, "");
155
+ if (!b) return "";
156
+ return `${b}${b.includes("?") ? "&" : "?"}ref=${encodeURIComponent(tag)}`;
157
+ }
158
+ const referralAppLink = computed(() => buildRefLink(referralAppBaseUrl));
159
+ const referralMarketingLink = computed(() => buildRefLink(referralMarketingBaseUrl));
160
+ async function copyToClipboard(text, successMessage) {
161
+ try {
162
+ await navigator.clipboard.writeText(text);
163
+ toast.success(successMessage);
164
+ } catch {
165
+ toast.error("Failed to copy");
166
+ }
167
+ }
129
168
  return (_ctx, _cache) => {
130
169
  const _component_router_link = resolveComponent("router-link");
131
- return __props.isLoading ? (openBlock(), createElementBlock("div", _hoisted_1, [..._cache[0] || (_cache[0] = [createElementVNode("span", { class: "loading loading-spinner loading-lg" }, null, -1)])])) : __props.error ? (openBlock(), createElementBlock("div", _hoisted_2, [_cache[1] || (_cache[1] = createElementVNode("svg", {
170
+ return __props.isLoading ? (openBlock(), createElementBlock("div", _hoisted_1, [..._cache[3] || (_cache[3] = [createElementVNode("span", { class: "loading loading-spinner loading-lg" }, null, -1)])])) : __props.error ? (openBlock(), createElementBlock("div", _hoisted_2, [_cache[4] || (_cache[4] = createElementVNode("svg", {
132
171
  xmlns: "http://www.w3.org/2000/svg",
133
172
  class: "stroke-current shrink-0 h-6 w-6",
134
173
  fill: "none",
@@ -147,53 +186,113 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
147
186
  createCommentVNode(" Team Information Grid "),
148
187
  createElementVNode("div", _hoisted_11, [
149
188
  createCommentVNode(" Basic Information "),
150
- teamData.value.legal_name ? (openBlock(), createElementBlock("div", _hoisted_12, [createElementVNode("div", _hoisted_13, [_cache[3] || (_cache[3] = createElementVNode("h3", { class: "card-title text-base mb-3" }, "Basic Information", -1)), teamData.value.legal_name ? (openBlock(), createElementBlock("div", _hoisted_14, [_cache[2] || (_cache[2] = createElementVNode("span", { class: "font-medium text-base-content/70" }, "Legal Name:", -1)), createElementVNode("span", _hoisted_15, toDisplayString(teamData.value.legal_name), 1)])) : createCommentVNode("v-if", true)])])) : createCommentVNode("v-if", true),
189
+ teamData.value.legal_name ? (openBlock(), createElementBlock("div", _hoisted_12, [createElementVNode("div", _hoisted_13, [_cache[6] || (_cache[6] = createElementVNode("h3", { class: "card-title text-base mb-3" }, "Basic Information", -1)), teamData.value.legal_name ? (openBlock(), createElementBlock("div", _hoisted_14, [_cache[5] || (_cache[5] = createElementVNode("span", { class: "font-medium text-base-content/70" }, "Legal Name:", -1)), createElementVNode("span", _hoisted_15, toDisplayString(teamData.value.legal_name), 1)])) : createCommentVNode("v-if", true)])])) : createCommentVNode("v-if", true),
151
190
  createCommentVNode(" Contact Information "),
152
191
  teamData.value.contact_name || teamData.value.contact_email || teamData.value.contact_business_phone || teamData.value.contact_mobile_phone ? (openBlock(), createElementBlock("div", _hoisted_16, [createElementVNode("div", _hoisted_17, [
153
- _cache[9] || (_cache[9] = createElementVNode("h3", { class: "card-title text-base mb-3" }, "Contact Information", -1)),
154
- teamData.value.contact_name ? (openBlock(), createElementBlock("div", _hoisted_18, [_cache[4] || (_cache[4] = createElementVNode("span", { class: "font-medium text-base-content/70" }, "Name:", -1)), createElementVNode("span", _hoisted_19, toDisplayString(teamData.value.contact_name), 1)])) : createCommentVNode("v-if", true),
155
- teamData.value.contact_email ? (openBlock(), createElementBlock("div", _hoisted_20, [_cache[5] || (_cache[5] = createElementVNode("span", { class: "font-medium text-base-content/70" }, "Email:", -1)), createElementVNode("a", {
192
+ _cache[12] || (_cache[12] = createElementVNode("h3", { class: "card-title text-base mb-3" }, "Contact Information", -1)),
193
+ teamData.value.contact_name ? (openBlock(), createElementBlock("div", _hoisted_18, [_cache[7] || (_cache[7] = createElementVNode("span", { class: "font-medium text-base-content/70" }, "Name:", -1)), createElementVNode("span", _hoisted_19, toDisplayString(teamData.value.contact_name), 1)])) : createCommentVNode("v-if", true),
194
+ teamData.value.contact_email ? (openBlock(), createElementBlock("div", _hoisted_20, [_cache[8] || (_cache[8] = createElementVNode("span", { class: "font-medium text-base-content/70" }, "Email:", -1)), createElementVNode("a", {
156
195
  href: `mailto:${teamData.value.contact_email}`,
157
196
  class: "ml-2 link link-primary"
158
197
  }, toDisplayString(teamData.value.contact_email), 9, _hoisted_21)])) : createCommentVNode("v-if", true),
159
- teamData.value.contact_business_phone ? (openBlock(), createElementBlock("div", _hoisted_22, [_cache[6] || (_cache[6] = createElementVNode("span", { class: "font-medium text-base-content/70" }, "Business Phone:", -1)), createElementVNode("span", _hoisted_23, toDisplayString(teamData.value.contact_business_phone), 1)])) : createCommentVNode("v-if", true),
160
- teamData.value.contact_mobile_phone ? (openBlock(), createElementBlock("div", _hoisted_24, [_cache[7] || (_cache[7] = createElementVNode("span", { class: "font-medium text-base-content/70" }, "Mobile Phone:", -1)), createElementVNode("span", _hoisted_25, toDisplayString(teamData.value.contact_mobile_phone), 1)])) : createCommentVNode("v-if", true),
161
- teamData.value.contact_time_zone ? (openBlock(), createElementBlock("div", _hoisted_26, [_cache[8] || (_cache[8] = createElementVNode("span", { class: "font-medium text-base-content/70" }, "Time Zone:", -1)), createElementVNode("span", _hoisted_27, toDisplayString(teamData.value.contact_time_zone), 1)])) : createCommentVNode("v-if", true)
198
+ teamData.value.contact_business_phone ? (openBlock(), createElementBlock("div", _hoisted_22, [_cache[9] || (_cache[9] = createElementVNode("span", { class: "font-medium text-base-content/70" }, "Business Phone:", -1)), createElementVNode("span", _hoisted_23, toDisplayString(teamData.value.contact_business_phone), 1)])) : createCommentVNode("v-if", true),
199
+ teamData.value.contact_mobile_phone ? (openBlock(), createElementBlock("div", _hoisted_24, [_cache[10] || (_cache[10] = createElementVNode("span", { class: "font-medium text-base-content/70" }, "Mobile Phone:", -1)), createElementVNode("span", _hoisted_25, toDisplayString(teamData.value.contact_mobile_phone), 1)])) : createCommentVNode("v-if", true),
200
+ teamData.value.contact_time_zone ? (openBlock(), createElementBlock("div", _hoisted_26, [_cache[11] || (_cache[11] = createElementVNode("span", { class: "font-medium text-base-content/70" }, "Time Zone:", -1)), createElementVNode("span", _hoisted_27, toDisplayString(teamData.value.contact_time_zone), 1)])) : createCommentVNode("v-if", true)
162
201
  ])])) : createCommentVNode("v-if", true),
163
202
  createCommentVNode(" Address Information "),
164
203
  teamData.value.address_full || teamData.value.address_city || teamData.value.address_zip ? (openBlock(), createElementBlock("div", _hoisted_28, [createElementVNode("div", _hoisted_29, [
165
- _cache[13] || (_cache[13] = createElementVNode("h3", { class: "card-title text-base mb-3" }, "Address", -1)),
166
- teamData.value.address_full ? (openBlock(), createElementBlock("div", _hoisted_30, [_cache[10] || (_cache[10] = createElementVNode("span", { class: "font-medium text-base-content/70" }, "Address:", -1)), createElementVNode("span", _hoisted_31, toDisplayString(teamData.value.address_full), 1)])) : createCommentVNode("v-if", true),
167
- teamData.value.address_city ? (openBlock(), createElementBlock("div", _hoisted_32, [_cache[11] || (_cache[11] = createElementVNode("span", { class: "font-medium text-base-content/70" }, "City:", -1)), createElementVNode("span", _hoisted_33, toDisplayString(teamData.value.address_city), 1)])) : createCommentVNode("v-if", true),
168
- teamData.value.address_zip ? (openBlock(), createElementBlock("div", _hoisted_34, [_cache[12] || (_cache[12] = createElementVNode("span", { class: "font-medium text-base-content/70" }, "Zip:", -1)), createElementVNode("span", _hoisted_35, toDisplayString(teamData.value.address_zip), 1)])) : createCommentVNode("v-if", true)
204
+ _cache[16] || (_cache[16] = createElementVNode("h3", { class: "card-title text-base mb-3" }, "Address", -1)),
205
+ teamData.value.address_full ? (openBlock(), createElementBlock("div", _hoisted_30, [_cache[13] || (_cache[13] = createElementVNode("span", { class: "font-medium text-base-content/70" }, "Address:", -1)), createElementVNode("span", _hoisted_31, toDisplayString(teamData.value.address_full), 1)])) : createCommentVNode("v-if", true),
206
+ teamData.value.address_city ? (openBlock(), createElementBlock("div", _hoisted_32, [_cache[14] || (_cache[14] = createElementVNode("span", { class: "font-medium text-base-content/70" }, "City:", -1)), createElementVNode("span", _hoisted_33, toDisplayString(teamData.value.address_city), 1)])) : createCommentVNode("v-if", true),
207
+ teamData.value.address_zip ? (openBlock(), createElementBlock("div", _hoisted_34, [_cache[15] || (_cache[15] = createElementVNode("span", { class: "font-medium text-base-content/70" }, "Zip:", -1)), createElementVNode("span", _hoisted_35, toDisplayString(teamData.value.address_zip), 1)])) : createCommentVNode("v-if", true)
169
208
  ])])) : createCommentVNode("v-if", true),
170
209
  createCommentVNode(" Web Presence "),
171
210
  teamData.value.twitter_username || teamData.value.url ? (openBlock(), createElementBlock("div", _hoisted_36, [createElementVNode("div", _hoisted_37, [
172
- _cache[16] || (_cache[16] = createElementVNode("h3", { class: "card-title text-base mb-3" }, "Web Presence", -1)),
173
- teamData.value.twitter_username ? (openBlock(), createElementBlock("div", _hoisted_38, [_cache[14] || (_cache[14] = createElementVNode("span", { class: "font-medium text-base-content/70" }, "Twitter:", -1)), createElementVNode("span", _hoisted_39, "@" + toDisplayString(teamData.value.twitter_username), 1)])) : createCommentVNode("v-if", true),
174
- teamData.value.url ? (openBlock(), createElementBlock("div", _hoisted_40, [_cache[15] || (_cache[15] = createElementVNode("span", { class: "font-medium text-base-content/70" }, "URL:", -1)), createElementVNode("a", {
211
+ _cache[19] || (_cache[19] = createElementVNode("h3", { class: "card-title text-base mb-3" }, "Web Presence", -1)),
212
+ teamData.value.twitter_username ? (openBlock(), createElementBlock("div", _hoisted_38, [_cache[17] || (_cache[17] = createElementVNode("span", { class: "font-medium text-base-content/70" }, "Twitter:", -1)), createElementVNode("span", _hoisted_39, "@" + toDisplayString(teamData.value.twitter_username), 1)])) : createCommentVNode("v-if", true),
213
+ teamData.value.url ? (openBlock(), createElementBlock("div", _hoisted_40, [_cache[18] || (_cache[18] = createElementVNode("span", { class: "font-medium text-base-content/70" }, "URL:", -1)), createElementVNode("a", {
175
214
  href: teamData.value.url,
176
215
  target: "_blank",
177
216
  rel: "noopener noreferrer",
178
217
  class: "ml-2 link link-primary"
179
218
  }, toDisplayString(teamData.value.url), 9, _hoisted_41)])) : createCommentVNode("v-if", true)
219
+ ])])) : createCommentVNode("v-if", true),
220
+ createCommentVNode(" Referral Tag "),
221
+ teamData.value.referral_tag ? (openBlock(), createElementBlock("div", _hoisted_42, [createElementVNode("div", _hoisted_43, [
222
+ _cache[25] || (_cache[25] = createElementVNode("h3", { class: "card-title text-base mb-3" }, "Referral Tag", -1)),
223
+ _cache[26] || (_cache[26] = createElementVNode("p", { class: "text-sm text-base-content/70 mb-3" }, [
224
+ createTextVNode(" Share a link so referral events are routed to this team. The "),
225
+ createElementVNode("code", { class: "text-xs" }, "ref"),
226
+ createTextVNode(" parameter tags visitors for attribution. ")
227
+ ], -1)),
228
+ referralAppLink.value ? (openBlock(), createElementBlock("div", _hoisted_44, [_cache[21] || (_cache[21] = createElementVNode("div", { class: "text-xs font-medium text-base-content/60 mb-1" }, "App link (direct)", -1)), createElementVNode("div", _hoisted_45, [createElementVNode("code", _hoisted_46, toDisplayString(referralAppLink.value), 1), createElementVNode("button", {
229
+ type: "button",
230
+ class: "btn btn-sm btn-ghost shrink-0",
231
+ title: "Copy app link",
232
+ onClick: _cache[0] || (_cache[0] = ($event) => copyToClipboard(referralAppLink.value, "App link copied"))
233
+ }, [..._cache[20] || (_cache[20] = [createElementVNode("svg", {
234
+ xmlns: "http://www.w3.org/2000/svg",
235
+ class: "h-4 w-4",
236
+ fill: "none",
237
+ viewBox: "0 0 24 24",
238
+ stroke: "currentColor"
239
+ }, [createElementVNode("path", {
240
+ "stroke-linecap": "round",
241
+ "stroke-linejoin": "round",
242
+ "stroke-width": "2",
243
+ d: "M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"
244
+ })], -1)])])])])) : createCommentVNode("v-if", true),
245
+ referralMarketingLink.value ? (openBlock(), createElementBlock("div", _hoisted_47, [_cache[23] || (_cache[23] = createElementVNode("div", { class: "text-xs font-medium text-base-content/60 mb-1" }, "Marketing link", -1)), createElementVNode("div", _hoisted_48, [createElementVNode("code", _hoisted_49, toDisplayString(referralMarketingLink.value), 1), createElementVNode("button", {
246
+ type: "button",
247
+ class: "btn btn-sm btn-ghost shrink-0",
248
+ title: "Copy marketing link",
249
+ onClick: _cache[1] || (_cache[1] = ($event) => copyToClipboard(referralMarketingLink.value, "Marketing link copied"))
250
+ }, [..._cache[22] || (_cache[22] = [createElementVNode("svg", {
251
+ xmlns: "http://www.w3.org/2000/svg",
252
+ class: "h-4 w-4",
253
+ fill: "none",
254
+ viewBox: "0 0 24 24",
255
+ stroke: "currentColor"
256
+ }, [createElementVNode("path", {
257
+ "stroke-linecap": "round",
258
+ "stroke-linejoin": "round",
259
+ "stroke-width": "2",
260
+ d: "M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"
261
+ })], -1)])])])])) : createCommentVNode("v-if", true),
262
+ !referralAppLink.value && !referralMarketingLink.value ? (openBlock(), createElementBlock("div", _hoisted_50, [createElementVNode("code", _hoisted_51, toDisplayString(teamData.value.referral_tag), 1), createElementVNode("button", {
263
+ type: "button",
264
+ class: "btn btn-sm btn-ghost shrink-0",
265
+ title: "Copy tag",
266
+ onClick: _cache[2] || (_cache[2] = ($event) => copyToClipboard(teamData.value.referral_tag, "Referral tag copied"))
267
+ }, [..._cache[24] || (_cache[24] = [createElementVNode("svg", {
268
+ xmlns: "http://www.w3.org/2000/svg",
269
+ class: "h-4 w-4",
270
+ fill: "none",
271
+ viewBox: "0 0 24 24",
272
+ stroke: "currentColor"
273
+ }, [createElementVNode("path", {
274
+ "stroke-linecap": "round",
275
+ "stroke-linejoin": "round",
276
+ "stroke-width": "2",
277
+ d: "M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"
278
+ })], -1)])])])) : createCommentVNode("v-if", true)
180
279
  ])])) : createCommentVNode("v-if", true)
181
280
  ]),
182
281
  createCommentVNode(" Metadata "),
183
- createElementVNode("div", _hoisted_42, [createElementVNode("div", _hoisted_43, [
184
- teamData.value.created_by ? (openBlock(), createElementBlock("span", _hoisted_44, "Created by " + toDisplayString(teamData.value.created_by_display_name ?? teamData.value.created_by), 1)) : createCommentVNode("v-if", true),
185
- teamData.value.created_at ? (openBlock(), createElementBlock("span", _hoisted_45, " Created " + toDisplayString(unref(formatSystemTimestamp)(teamData.value.created_at)), 1)) : createCommentVNode("v-if", true),
186
- teamData.value.updated_at && teamData.value.updated_at !== teamData.value.created_at ? (openBlock(), createElementBlock("span", _hoisted_46, " Updated " + toDisplayString(unref(formatSystemTimestamp)(teamData.value.updated_at)), 1)) : createCommentVNode("v-if", true)
282
+ createElementVNode("div", _hoisted_52, [createElementVNode("div", _hoisted_53, [
283
+ teamData.value.created_by ? (openBlock(), createElementBlock("span", _hoisted_54, "Created by " + toDisplayString(teamData.value.created_by_display_name ?? teamData.value.created_by), 1)) : createCommentVNode("v-if", true),
284
+ teamData.value.created_at ? (openBlock(), createElementBlock("span", _hoisted_55, " Created " + toDisplayString(unref(formatSystemTimestamp)(teamData.value.created_at)), 1)) : createCommentVNode("v-if", true),
285
+ teamData.value.updated_at && teamData.value.updated_at !== teamData.value.created_at ? (openBlock(), createElementBlock("span", _hoisted_56, " Updated " + toDisplayString(unref(formatSystemTimestamp)(teamData.value.updated_at)), 1)) : createCommentVNode("v-if", true)
187
286
  ])]),
188
287
  createCommentVNode(" Action Buttons "),
189
- createElementVNode("div", _hoisted_47, [createVNode(_component_router_link, {
288
+ createElementVNode("div", _hoisted_57, [createVNode(_component_router_link, {
190
289
  to: {
191
290
  name: unref(teamPaths).edit.name,
192
291
  params: { id: unref(team_id) }
193
292
  },
194
293
  class: "btn btn-primary"
195
294
  }, {
196
- default: withCtx(() => [..._cache[17] || (_cache[17] = [createElementVNode("svg", {
295
+ default: withCtx(() => [..._cache[27] || (_cache[27] = [createElementVNode("svg", {
197
296
  xmlns: "http://www.w3.org/2000/svg",
198
297
  fill: "none",
199
298
  viewBox: "0 0 24 24",
@@ -217,4 +316,4 @@ var ViewTeam_default = _sfc_main;
217
316
 
218
317
  //#endregion
219
318
  export { ViewTeam_default as t };
220
- //# sourceMappingURL=ViewTeam-CRmIplCt.js.map
319
+ //# sourceMappingURL=ViewTeam-ttqX2In8.js.map