@ozdao/martyrs 0.2.492 → 0.2.494

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 (341) hide show
  1. package/dist/_virtual/index.cjs +4 -4
  2. package/dist/_virtual/index.js +4 -4
  3. package/dist/_virtual/index2.cjs +4 -4
  4. package/dist/_virtual/index2.js +4 -4
  5. package/dist/builder.cjs +53 -90
  6. package/dist/builder.js +54 -91
  7. package/dist/{crud-B-kQw3Z5.cjs → crud-JN_LFj01.cjs} +3 -0
  8. package/dist/{crud-Cwx5VlSm.js → crud-sE7GLPbj.js} +3 -0
  9. package/dist/globals.server.cjs +322 -3
  10. package/dist/globals.server.js +303 -1
  11. package/dist/{globals.verifier-D68mHEBl.cjs → globals.verifier-C0zj_LLo.cjs} +8 -1
  12. package/dist/{globals.verifier-CWFz5Gh2.js → globals.verifier-DFqKQ7hK.js} +8 -1
  13. package/dist/inventory.server.cjs +2 -2
  14. package/dist/inventory.server.js +2 -2
  15. package/dist/{main-SZQ1QjeP.js → main-CJm5myDI.js} +631 -607
  16. package/dist/{main-MzmGbSxs.cjs → main-DTaE01lg.cjs} +6 -6
  17. package/dist/martyrs/src/components/Calendar/Calendar.vue2.cjs +1 -1
  18. package/dist/martyrs/src/components/Calendar/Calendar.vue2.cjs.map +1 -1
  19. package/dist/martyrs/src/components/Calendar/Calendar.vue2.js +1 -1
  20. package/dist/martyrs/src/components/Calendar/Calendar.vue2.js.map +1 -1
  21. package/dist/martyrs/src/components/Feed/Feed.vue.cjs +33 -7
  22. package/dist/martyrs/src/components/Feed/Feed.vue.cjs.map +1 -1
  23. package/dist/martyrs/src/components/Feed/Feed.vue.js +33 -7
  24. package/dist/martyrs/src/components/Feed/Feed.vue.js.map +1 -1
  25. package/dist/martyrs/src/components/Field/{Field.vue2.cjs → Field.vue.cjs} +2 -2
  26. package/dist/martyrs/src/components/Field/{Field.vue2.js.map → Field.vue.cjs.map} +1 -1
  27. package/dist/martyrs/src/components/Field/{Field.vue2.js → Field.vue.js} +2 -2
  28. package/dist/martyrs/src/components/Field/Field.vue.js.map +1 -0
  29. package/dist/martyrs/src/components/FieldBig/FieldBig.vue.cjs +1 -1
  30. package/dist/martyrs/src/components/FieldBig/FieldBig.vue.js +1 -1
  31. package/dist/martyrs/src/components/FieldTags/FieldTags.vue.cjs +1 -1
  32. package/dist/martyrs/src/components/FieldTags/FieldTags.vue.js +1 -1
  33. package/dist/martyrs/src/components/Menu/{Menu.vue.cjs → Menu.vue2.cjs} +2 -2
  34. package/dist/martyrs/src/components/Menu/Menu.vue2.cjs.map +1 -0
  35. package/dist/martyrs/src/components/Menu/{Menu.vue.js → Menu.vue2.js} +2 -2
  36. package/dist/martyrs/src/components/Menu/Menu.vue2.js.map +1 -0
  37. package/dist/martyrs/src/components/Menu/MenuItem.vue.js +2 -2
  38. package/dist/martyrs/src/components/Menu/MenuItem.vue.js.map +1 -1
  39. package/dist/martyrs/src/components/PhotoViewer/PhotoViewer.vue.js +4 -4
  40. package/dist/martyrs/src/modules/auth/views/components/pages/EnterCode.vue.cjs +1 -1
  41. package/dist/martyrs/src/modules/auth/views/components/pages/EnterCode.vue.js +1 -1
  42. package/dist/martyrs/src/modules/auth/views/components/pages/EnterPassword.vue.cjs +1 -1
  43. package/dist/martyrs/src/modules/auth/views/components/pages/EnterPassword.vue.js +1 -1
  44. package/dist/martyrs/src/modules/auth/views/components/pages/Invite.vue.cjs +1 -1
  45. package/dist/martyrs/src/modules/auth/views/components/pages/Invite.vue.js +1 -1
  46. package/dist/martyrs/src/modules/auth/views/components/pages/Profile.vue.cjs +2 -2
  47. package/dist/martyrs/src/modules/auth/views/components/pages/Profile.vue.js +2 -2
  48. package/dist/martyrs/src/modules/auth/views/components/pages/ProfileEditProfile.vue.cjs +1 -1
  49. package/dist/martyrs/src/modules/auth/views/components/pages/ProfileEditProfile.vue.js +1 -1
  50. package/dist/martyrs/src/modules/auth/views/components/pages/ResetPassword.vue.cjs +1 -1
  51. package/dist/martyrs/src/modules/auth/views/components/pages/ResetPassword.vue.js +1 -1
  52. package/dist/martyrs/src/modules/auth/views/components/pages/SignIn.vue.cjs +1 -1
  53. package/dist/martyrs/src/modules/auth/views/components/pages/SignIn.vue.js +1 -1
  54. package/dist/martyrs/src/modules/auth/views/components/pages/SignUp.vue.cjs +1 -1
  55. package/dist/martyrs/src/modules/auth/views/components/pages/SignUp.vue.js +1 -1
  56. package/dist/martyrs/src/modules/auth/views/components/sections/ProfileEditCredentials.vue.cjs +1 -1
  57. package/dist/martyrs/src/modules/auth/views/components/sections/ProfileEditCredentials.vue.js +1 -1
  58. package/dist/martyrs/src/modules/community/components/pages/CreateBlogPost.vue.cjs +2 -2
  59. package/dist/martyrs/src/modules/community/components/pages/CreateBlogPost.vue.js +2 -2
  60. package/dist/martyrs/src/modules/constructor/components/elements/Card.vue.cjs +1 -1
  61. package/dist/martyrs/src/modules/constructor/components/elements/Card.vue.js +1 -1
  62. package/dist/martyrs/src/modules/constructor/components/elements/Embed.vue.cjs +1 -1
  63. package/dist/martyrs/src/modules/constructor/components/elements/Embed.vue.js +1 -1
  64. package/dist/martyrs/src/modules/events/components/pages/EditEvent.vue.cjs +1 -1
  65. package/dist/martyrs/src/modules/events/components/pages/EditEvent.vue.js +1 -1
  66. package/dist/martyrs/src/modules/events/components/pages/EditEventTickets.vue.cjs +1 -1
  67. package/dist/martyrs/src/modules/events/components/pages/EditEventTickets.vue.js +1 -1
  68. package/dist/martyrs/src/modules/events/components/pages/Event.vue.cjs +1 -1
  69. package/dist/martyrs/src/modules/events/components/pages/Event.vue.js +1 -1
  70. package/dist/martyrs/src/modules/gallery/components/sections/BackofficeGallery.vue.cjs +1 -1
  71. package/dist/martyrs/src/modules/gallery/components/sections/BackofficeGallery.vue.js +1 -1
  72. package/dist/martyrs/src/modules/globals/views/classes/globals.i18n.cjs +1 -1
  73. package/dist/martyrs/src/modules/globals/views/classes/globals.i18n.js +1 -1
  74. package/dist/martyrs/src/modules/globals/views/components/blocks/BlockSearch.vue.cjs +1 -1
  75. package/dist/martyrs/src/modules/globals/views/components/blocks/BlockSearch.vue.js +1 -1
  76. package/dist/martyrs/src/modules/globals/views/components/layouts/Client.vue.cjs +5 -1
  77. package/dist/martyrs/src/modules/globals/views/components/layouts/Client.vue.cjs.map +1 -1
  78. package/dist/martyrs/src/modules/globals/views/components/layouts/Client.vue.js +5 -1
  79. package/dist/martyrs/src/modules/globals/views/components/layouts/Client.vue.js.map +1 -1
  80. package/dist/martyrs/src/modules/icons/entities/IconTime.vue.cjs +2 -2
  81. package/dist/martyrs/src/modules/icons/entities/IconTime.vue.js +2 -2
  82. package/dist/martyrs/src/modules/icons/navigation/IconChevronLeft.vue.cjs +2 -2
  83. package/dist/martyrs/src/modules/icons/navigation/IconChevronLeft.vue.js +2 -2
  84. package/dist/martyrs/src/modules/icons/navigation/IconChevronRight.vue.cjs +2 -2
  85. package/dist/martyrs/src/modules/icons/navigation/IconChevronRight.vue.js +2 -2
  86. package/dist/martyrs/src/modules/icons/pages/IconsPage.vue.js +6 -6
  87. package/dist/martyrs/src/modules/icons/pages/IconsPage.vue.js.map +1 -1
  88. package/dist/martyrs/src/modules/inventory/components/forms/AdjustmentForm.vue.cjs +1 -1
  89. package/dist/martyrs/src/modules/inventory/components/forms/AdjustmentForm.vue.js +1 -1
  90. package/dist/martyrs/src/modules/inventory/components/forms/StockAlertsForm.vue.cjs +1 -1
  91. package/dist/martyrs/src/modules/inventory/components/forms/StockAlertsForm.vue.js +1 -1
  92. package/dist/martyrs/src/modules/inventory/components/pages/Inventory.vue.cjs +1 -1
  93. package/dist/martyrs/src/modules/inventory/components/pages/InventoryEdit.vue.cjs +1 -1
  94. package/dist/martyrs/src/modules/inventory/components/pages/InventoryEdit.vue.js +1 -1
  95. package/dist/martyrs/src/modules/music/components/cards/AlbumCard.vue.cjs +22 -15
  96. package/dist/martyrs/src/modules/music/components/cards/AlbumCard.vue.cjs.map +1 -1
  97. package/dist/martyrs/src/modules/music/components/cards/AlbumCard.vue.js +23 -16
  98. package/dist/martyrs/src/modules/music/components/cards/AlbumCard.vue.js.map +1 -1
  99. package/dist/martyrs/src/modules/music/components/cards/ArtistCard.vue.cjs +2 -2
  100. package/dist/martyrs/src/modules/music/components/cards/ArtistCard.vue.cjs.map +1 -1
  101. package/dist/martyrs/src/modules/music/components/cards/ArtistCard.vue.js +2 -2
  102. package/dist/martyrs/src/modules/music/components/cards/ArtistCard.vue.js.map +1 -1
  103. package/dist/martyrs/src/modules/music/components/cards/PlaylistCard.vue.cjs +31 -13
  104. package/dist/martyrs/src/modules/music/components/cards/PlaylistCard.vue.cjs.map +1 -1
  105. package/dist/martyrs/src/modules/music/components/cards/PlaylistCard.vue.js +33 -15
  106. package/dist/martyrs/src/modules/music/components/cards/PlaylistCard.vue.js.map +1 -1
  107. package/dist/martyrs/src/modules/music/components/cards/TrackListCard.vue.cjs +39 -22
  108. package/dist/martyrs/src/modules/music/components/cards/TrackListCard.vue.cjs.map +1 -1
  109. package/dist/martyrs/src/modules/music/components/cards/TrackListCard.vue.js +39 -22
  110. package/dist/martyrs/src/modules/music/components/cards/TrackListCard.vue.js.map +1 -1
  111. package/dist/martyrs/src/modules/music/components/forms/AlbumForm.vue.cjs +1 -1
  112. package/dist/martyrs/src/modules/music/components/forms/AlbumForm.vue.js +1 -1
  113. package/dist/martyrs/src/modules/music/components/forms/ArtistForm.vue.cjs +1 -1
  114. package/dist/martyrs/src/modules/music/components/forms/ArtistForm.vue.js +1 -1
  115. package/dist/martyrs/src/modules/music/components/forms/PlaylistForm.vue.cjs +385 -125
  116. package/dist/martyrs/src/modules/music/components/forms/PlaylistForm.vue.cjs.map +1 -1
  117. package/dist/martyrs/src/modules/music/components/forms/PlaylistForm.vue.js +391 -131
  118. package/dist/martyrs/src/modules/music/components/forms/PlaylistForm.vue.js.map +1 -1
  119. package/dist/martyrs/src/modules/music/components/forms/SearchForm.vue.cjs +24 -7
  120. package/dist/martyrs/src/modules/music/components/forms/SearchForm.vue.cjs.map +1 -1
  121. package/dist/martyrs/src/modules/music/components/forms/SearchForm.vue.js +25 -8
  122. package/dist/martyrs/src/modules/music/components/forms/SearchForm.vue.js.map +1 -1
  123. package/dist/martyrs/src/modules/music/components/forms/TrackForm.vue.cjs +99 -87
  124. package/dist/martyrs/src/modules/music/components/forms/TrackForm.vue.cjs.map +1 -1
  125. package/dist/martyrs/src/modules/music/components/forms/TrackForm.vue.js +111 -99
  126. package/dist/martyrs/src/modules/music/components/forms/TrackForm.vue.js.map +1 -1
  127. package/dist/martyrs/src/modules/music/components/layouts/MusicBottomPlayer.vue.cjs +21 -0
  128. package/dist/martyrs/src/modules/music/components/layouts/MusicBottomPlayer.vue.cjs.map +1 -0
  129. package/dist/martyrs/src/modules/music/components/layouts/MusicBottomPlayer.vue.js +21 -0
  130. package/dist/martyrs/src/modules/music/components/layouts/MusicBottomPlayer.vue.js.map +1 -0
  131. package/dist/martyrs/src/modules/music/components/pages/Album.vue.cjs +442 -210
  132. package/dist/martyrs/src/modules/music/components/pages/Album.vue.cjs.map +1 -1
  133. package/dist/martyrs/src/modules/music/components/pages/Album.vue.js +445 -213
  134. package/dist/martyrs/src/modules/music/components/pages/Album.vue.js.map +1 -1
  135. package/dist/martyrs/src/modules/music/components/pages/Artist.vue.cjs +92 -117
  136. package/dist/martyrs/src/modules/music/components/pages/Artist.vue.cjs.map +1 -1
  137. package/dist/martyrs/src/modules/music/components/pages/Artist.vue.js +93 -118
  138. package/dist/martyrs/src/modules/music/components/pages/Artist.vue.js.map +1 -1
  139. package/dist/martyrs/src/modules/music/components/pages/MusicHome.vue.cjs +72 -113
  140. package/dist/martyrs/src/modules/music/components/pages/MusicHome.vue.cjs.map +1 -1
  141. package/dist/martyrs/src/modules/music/components/pages/MusicHome.vue.js +78 -119
  142. package/dist/martyrs/src/modules/music/components/pages/MusicHome.vue.js.map +1 -1
  143. package/dist/martyrs/src/modules/music/components/pages/MusicLibrary.vue.cjs +15 -12
  144. package/dist/martyrs/src/modules/music/components/pages/MusicLibrary.vue.cjs.map +1 -1
  145. package/dist/martyrs/src/modules/music/components/pages/MusicLibrary.vue.js +15 -12
  146. package/dist/martyrs/src/modules/music/components/pages/MusicLibrary.vue.js.map +1 -1
  147. package/dist/martyrs/src/modules/music/components/pages/Playlist.vue.cjs +558 -429
  148. package/dist/martyrs/src/modules/music/components/pages/Playlist.vue.cjs.map +1 -1
  149. package/dist/martyrs/src/modules/music/components/pages/Playlist.vue.js +560 -431
  150. package/dist/martyrs/src/modules/music/components/pages/Playlist.vue.js.map +1 -1
  151. package/dist/martyrs/src/modules/music/components/pages/SearchResults.vue.cjs +146 -284
  152. package/dist/martyrs/src/modules/music/components/pages/SearchResults.vue.cjs.map +1 -1
  153. package/dist/martyrs/src/modules/music/components/pages/SearchResults.vue.js +149 -287
  154. package/dist/martyrs/src/modules/music/components/pages/SearchResults.vue.js.map +1 -1
  155. package/dist/martyrs/src/modules/music/components/pages/Track.vue.cjs +460 -63
  156. package/dist/martyrs/src/modules/music/components/pages/Track.vue.cjs.map +1 -1
  157. package/dist/martyrs/src/modules/music/components/pages/Track.vue.js +462 -65
  158. package/dist/martyrs/src/modules/music/components/pages/Track.vue.js.map +1 -1
  159. package/dist/martyrs/src/modules/music/components/player/MusicPlayer.vue.cjs +126 -136
  160. package/dist/martyrs/src/modules/music/components/player/MusicPlayer.vue.cjs.map +1 -1
  161. package/dist/martyrs/src/modules/music/components/player/MusicPlayer.vue.js +129 -139
  162. package/dist/martyrs/src/modules/music/components/player/MusicPlayer.vue.js.map +1 -1
  163. package/dist/martyrs/src/modules/music/components/player/TrackProgress.vue.cjs +18 -15
  164. package/dist/martyrs/src/modules/music/components/player/TrackProgress.vue.cjs.map +1 -1
  165. package/dist/martyrs/src/modules/music/components/player/TrackProgress.vue.js +18 -15
  166. package/dist/martyrs/src/modules/music/components/player/TrackProgress.vue.js.map +1 -1
  167. package/dist/martyrs/src/modules/music/components/player/VolumeControl.vue.cjs +28 -23
  168. package/dist/martyrs/src/modules/music/components/player/VolumeControl.vue.cjs.map +1 -1
  169. package/dist/martyrs/src/modules/music/components/player/VolumeControl.vue.js +29 -24
  170. package/dist/martyrs/src/modules/music/components/player/VolumeControl.vue.js.map +1 -1
  171. package/dist/martyrs/src/modules/music/music.client.cjs +3 -6
  172. package/dist/martyrs/src/modules/music/music.client.cjs.map +1 -1
  173. package/dist/martyrs/src/modules/music/music.client.js +9 -12
  174. package/dist/martyrs/src/modules/music/music.client.js.map +1 -1
  175. package/dist/martyrs/src/modules/music/router/music.cjs +27 -1
  176. package/dist/martyrs/src/modules/music/router/music.cjs.map +1 -1
  177. package/dist/martyrs/src/modules/music/router/music.js +27 -1
  178. package/dist/martyrs/src/modules/music/router/music.js.map +1 -1
  179. package/dist/martyrs/src/modules/music/store/artists.cjs +6 -4
  180. package/dist/martyrs/src/modules/music/store/artists.cjs.map +1 -1
  181. package/dist/martyrs/src/modules/music/store/artists.js +6 -4
  182. package/dist/martyrs/src/modules/music/store/artists.js.map +1 -1
  183. package/dist/martyrs/src/modules/music/store/player.cjs +5 -0
  184. package/dist/martyrs/src/modules/music/store/player.cjs.map +1 -1
  185. package/dist/martyrs/src/modules/music/store/player.js +5 -0
  186. package/dist/martyrs/src/modules/music/store/player.js.map +1 -1
  187. package/dist/martyrs/src/modules/music/store/tracks.cjs +22 -0
  188. package/dist/martyrs/src/modules/music/store/tracks.cjs.map +1 -1
  189. package/dist/martyrs/src/modules/music/store/tracks.js +22 -0
  190. package/dist/martyrs/src/modules/music/store/tracks.js.map +1 -1
  191. package/dist/martyrs/src/modules/orders/components/blocks/CardOrderBackoffice.vue.js +2 -2
  192. package/dist/martyrs/src/modules/orders/components/pages/OrderBackoffice.vue.js +2 -2
  193. package/dist/martyrs/src/modules/orders/components/pages/OrderCreateBackoffice.vue.cjs +1 -1
  194. package/dist/martyrs/src/modules/orders/components/pages/OrderCreateBackoffice.vue.js +1 -1
  195. package/dist/martyrs/src/modules/orders/components/sections/FormAddCustomer.vue.cjs +1 -1
  196. package/dist/martyrs/src/modules/orders/components/sections/FormAddCustomer.vue.js +1 -1
  197. package/dist/martyrs/src/modules/orders/components/sections/FormCustomerDetails.vue.cjs +1 -1
  198. package/dist/martyrs/src/modules/orders/components/sections/FormCustomerDetails.vue.js +1 -1
  199. package/dist/martyrs/src/modules/orders/components/sections/FormDelivery.vue.cjs +1 -1
  200. package/dist/martyrs/src/modules/orders/components/sections/FormDelivery.vue.js +1 -1
  201. package/dist/martyrs/src/modules/organizations/components/blocks/CardOrganization.vue.js +2 -2
  202. package/dist/martyrs/src/modules/organizations/components/pages/DepartmentEdit.vue.cjs +1 -1
  203. package/dist/martyrs/src/modules/organizations/components/pages/DepartmentEdit.vue.js +1 -1
  204. package/dist/martyrs/src/modules/organizations/components/pages/Members.vue.cjs +1 -1
  205. package/dist/martyrs/src/modules/organizations/components/pages/Members.vue.js +1 -1
  206. package/dist/martyrs/src/modules/organizations/components/pages/Organization.vue.cjs +1 -1
  207. package/dist/martyrs/src/modules/organizations/components/pages/Organization.vue.js +1 -1
  208. package/dist/martyrs/src/modules/organizations/components/pages/OrganizationBackoffice.vue.cjs +1 -1
  209. package/dist/martyrs/src/modules/organizations/components/pages/OrganizationBackoffice.vue.js +1 -1
  210. package/dist/martyrs/src/modules/organizations/components/pages/OrganizationEdit.vue.cjs +1 -1
  211. package/dist/martyrs/src/modules/organizations/components/pages/OrganizationEdit.vue.js +1 -1
  212. package/dist/martyrs/src/modules/organizations/components/sections/Documents.vue.cjs +1 -1
  213. package/dist/martyrs/src/modules/organizations/components/sections/Documents.vue.js +1 -1
  214. package/dist/martyrs/src/modules/organizations/components/sections/MembersAdd.vue.cjs +1 -1
  215. package/dist/martyrs/src/modules/organizations/components/sections/MembersAdd.vue.js +1 -1
  216. package/dist/martyrs/src/modules/organizations/components/sections/Organizations.vue.cjs +1 -1
  217. package/dist/martyrs/src/modules/organizations/components/sections/Organizations.vue.js +1 -1
  218. package/dist/martyrs/src/modules/organizations/router/organizations.cjs +1 -1
  219. package/dist/martyrs/src/modules/organizations/router/organizations.js +1 -1
  220. package/dist/martyrs/src/modules/pages/views/components/blocks/CardPage.vue.cjs +1 -1
  221. package/dist/martyrs/src/modules/pages/views/components/blocks/CardPage.vue.js +1 -1
  222. package/dist/martyrs/src/modules/pages/views/components/pages/PageEdit.vue.cjs +1 -1
  223. package/dist/martyrs/src/modules/pages/views/components/pages/PageEdit.vue.js +1 -1
  224. package/dist/martyrs/src/modules/products/components/pages/CategoryEdit.vue.cjs +1 -1
  225. package/dist/martyrs/src/modules/products/components/pages/CategoryEdit.vue.js +1 -1
  226. package/dist/martyrs/src/modules/products/components/pages/ProductEdit.vue.cjs +1 -1
  227. package/dist/martyrs/src/modules/products/components/pages/ProductEdit.vue.js +1 -1
  228. package/dist/martyrs/src/modules/products/components/sections/EditAttributes.vue.cjs +1 -1
  229. package/dist/martyrs/src/modules/products/components/sections/EditAttributes.vue.js +1 -1
  230. package/dist/martyrs/src/modules/products/components/sections/EditDiscounts.vue.cjs +1 -1
  231. package/dist/martyrs/src/modules/products/components/sections/EditDiscounts.vue.js +1 -1
  232. package/dist/martyrs/src/modules/products/components/sections/EditVariants.vue.cjs +1 -1
  233. package/dist/martyrs/src/modules/products/components/sections/EditVariants.vue.js +1 -1
  234. package/dist/martyrs/src/modules/rents/views/components/pages/Gant/GanttBar.vue.cjs +4 -3
  235. package/dist/martyrs/src/modules/rents/views/components/pages/Gant/GanttBar.vue.cjs.map +1 -1
  236. package/dist/martyrs/src/modules/rents/views/components/pages/Gant/GanttBar.vue.js +4 -3
  237. package/dist/martyrs/src/modules/rents/views/components/pages/Gant/GanttBar.vue.js.map +1 -1
  238. package/dist/martyrs/src/modules/rents/views/components/pages/Gant/GanttChart.vue.cjs +37 -70
  239. package/dist/martyrs/src/modules/rents/views/components/pages/Gant/GanttChart.vue.cjs.map +1 -1
  240. package/dist/martyrs/src/modules/rents/views/components/pages/Gant/GanttChart.vue.js +38 -71
  241. package/dist/martyrs/src/modules/rents/views/components/pages/Gant/GanttChart.vue.js.map +1 -1
  242. package/dist/martyrs/src/modules/rents/views/components/pages/Gant/GanttToolbar.vue.cjs +2 -1
  243. package/dist/martyrs/src/modules/rents/views/components/pages/Gant/GanttToolbar.vue.cjs.map +1 -1
  244. package/dist/martyrs/src/modules/rents/views/components/pages/Gant/GanttToolbar.vue.js +6 -5
  245. package/dist/martyrs/src/modules/rents/views/components/pages/Gant/GanttToolbar.vue.js.map +1 -1
  246. package/dist/martyrs/src/modules/rents/views/components/pages/Rents.vue.cjs +45 -52
  247. package/dist/martyrs/src/modules/rents/views/components/pages/Rents.vue.cjs.map +1 -1
  248. package/dist/martyrs/src/modules/rents/views/components/pages/Rents.vue.js +46 -53
  249. package/dist/martyrs/src/modules/rents/views/components/pages/Rents.vue.js.map +1 -1
  250. package/dist/martyrs/src/modules/rents/views/components/pages/RentsEdit.vue.cjs +1 -1
  251. package/dist/martyrs/src/modules/rents/views/components/pages/RentsEdit.vue.js +1 -1
  252. package/dist/martyrs/src/modules/spots/components/blocks/SpotMemberModify.vue.cjs +1 -1
  253. package/dist/martyrs/src/modules/spots/components/blocks/SpotMemberModify.vue.js +1 -1
  254. package/dist/martyrs/src/modules/spots/components/layouts/Spots.vue.cjs +1 -1
  255. package/dist/martyrs/src/modules/spots/components/layouts/Spots.vue.js +1 -1
  256. package/dist/martyrs/src/modules/spots/components/pages/SpotEdit.vue.cjs +1 -1
  257. package/dist/martyrs/src/modules/spots/components/pages/SpotEdit.vue.js +1 -1
  258. package/dist/martyrs/src/modules/spots/components/sections/WorktimeEdit.vue.cjs +1 -1
  259. package/dist/martyrs/src/modules/spots/components/sections/WorktimeEdit.vue.js +1 -1
  260. package/dist/martyrs/src/modules/wallet/views/components/blocks/CardDeposit.vue.cjs +1 -1
  261. package/dist/martyrs/src/modules/wallet/views/components/blocks/CardDeposit.vue.js +1 -1
  262. package/dist/martyrs/src/modules/wallet/views/components/blocks/CryptoDeposit.vue.cjs +1 -1
  263. package/dist/martyrs/src/modules/wallet/views/components/blocks/CryptoDeposit.vue.js +1 -1
  264. package/dist/martyrs.cjs.js +1 -1
  265. package/dist/martyrs.css +1 -1
  266. package/dist/martyrs.es.js +1 -1
  267. package/dist/music.server.cjs +124 -31
  268. package/dist/music.server.js +124 -31
  269. package/dist/organizations.server.cjs +1 -1
  270. package/dist/organizations.server.js +1 -1
  271. package/dist/products.server.cjs +2 -2
  272. package/dist/products.server.js +2 -2
  273. package/dist/rents.server.cjs +3 -3
  274. package/dist/rents.server.js +3 -3
  275. package/dist/style.css +373 -80
  276. package/dist/{web-D7lZjuC0.js → web-Dkk0_7TA.js} +1 -1
  277. package/dist/{web-D-YZ9KHz.cjs → web-stVkXd0l.cjs} +1 -1
  278. package/package.json +1 -1
  279. package/src/builder/modes/ssr.prod.js +21 -5
  280. package/src/builder/rspack/rspack.config.spa.client.js +0 -44
  281. package/src/builder/rspack/rspack.config.ssr.client.js +40 -40
  282. package/src/components/Calendar/Calendar.vue +378 -377
  283. package/src/components/Feed/Feed.vue +28 -2
  284. package/src/modules/globals/controllers/classes/crud/crud.policies.js +5 -0
  285. package/src/modules/globals/controllers/classes/globals.validator.js +8 -1
  286. package/src/modules/globals/views/components/layouts/Client.vue +7 -0
  287. package/src/modules/music/README.md +8 -0
  288. package/src/modules/music/components/SidebarMusic.vue +6 -9
  289. package/src/modules/music/components/cards/AlbumCard.vue +20 -14
  290. package/src/modules/music/components/cards/ArtistCard.vue +1 -1
  291. package/src/modules/music/components/cards/PlaylistCard.vue +31 -11
  292. package/src/modules/music/components/cards/TrackListCard.vue +24 -13
  293. package/src/modules/music/components/forms/PlaylistForm.vue +417 -107
  294. package/src/modules/music/components/forms/SearchForm.vue +31 -8
  295. package/src/modules/music/components/forms/TrackForm.vue +50 -32
  296. package/src/modules/music/components/layouts/MusicBottomPlayer.vue +17 -0
  297. package/src/modules/music/components/pages/Album.vue +373 -186
  298. package/src/modules/music/components/pages/Artist.vue +54 -94
  299. package/src/modules/music/components/pages/MusicHome.vue +59 -56
  300. package/src/modules/music/components/pages/MusicLibrary.vue +13 -11
  301. package/src/modules/music/components/pages/Playlist.vue +495 -379
  302. package/src/modules/music/components/pages/SearchResults.vue +185 -313
  303. package/src/modules/music/components/pages/Track.vue +363 -69
  304. package/src/modules/music/components/player/MusicPlayer.vue +368 -97
  305. package/src/modules/music/components/player/TrackProgress.vue +76 -22
  306. package/src/modules/music/components/player/VolumeControl.vue +61 -28
  307. package/src/modules/music/controllers/search.controller.js +3 -0
  308. package/src/modules/music/controllers/stream.controller.js +11 -3
  309. package/src/modules/music/middlewares/playlists.verifier.js +1 -1
  310. package/src/modules/music/music.client.js +3 -6
  311. package/src/modules/music/music.server.js +8 -4
  312. package/src/modules/music/router/music.js +8 -1
  313. package/src/modules/music/routes/albums.routes.js +37 -5
  314. package/src/modules/music/routes/artists.routes.js +14 -4
  315. package/src/modules/music/routes/genres.routes.js +5 -1
  316. package/src/modules/music/routes/playlists.routes.js +42 -9
  317. package/src/modules/music/routes/tracks.routes.js +27 -2
  318. package/src/modules/music/store/artists.js +6 -2
  319. package/src/modules/music/store/player.js +6 -0
  320. package/src/modules/music/store/tracks.js +31 -0
  321. package/src/modules/music/websocket/streaming.handler.js +7 -1
  322. package/src/modules/rents/controllers/services/rents.services.js +2 -2
  323. package/src/modules/rents/views/components/pages/Gant/GanttBar.vue +4 -3
  324. package/src/modules/rents/views/components/pages/Gant/GanttChart.vue +42 -40
  325. package/src/modules/rents/views/components/pages/Gant/GanttToolbar.vue +3 -1
  326. package/src/modules/rents/views/components/pages/Rents.vue +60 -56
  327. package/dist/globals.websocket-DzvdIBf6.js +0 -306
  328. package/dist/globals.websocket-k6_B1T7k.cjs +0 -322
  329. package/dist/martyrs/src/components/Field/Field.vue2.cjs.map +0 -1
  330. package/dist/martyrs/src/components/Menu/Menu.vue.cjs.map +0 -1
  331. package/dist/martyrs/src/components/Menu/Menu.vue.js.map +0 -1
  332. package/dist/martyrs/src/modules/music/components/cards/TrackCard.vue.cjs +0 -69
  333. package/dist/martyrs/src/modules/music/components/cards/TrackCard.vue.cjs.map +0 -1
  334. package/dist/martyrs/src/modules/music/components/cards/TrackCard.vue.js +0 -69
  335. package/dist/martyrs/src/modules/music/components/cards/TrackCard.vue.js.map +0 -1
  336. package/dist/martyrs/src/modules/music/components/layouts/MusicLayout.vue.cjs +0 -104
  337. package/dist/martyrs/src/modules/music/components/layouts/MusicLayout.vue.cjs.map +0 -1
  338. package/dist/martyrs/src/modules/music/components/layouts/MusicLayout.vue.js +0 -104
  339. package/dist/martyrs/src/modules/music/components/layouts/MusicLayout.vue.js.map +0 -1
  340. package/src/modules/music/components/cards/TrackCard.vue +0 -86
  341. package/src/modules/music/components/layouts/MusicLayout.vue +0 -83
@@ -1,167 +1,427 @@
1
- import { reactive, createElementBlock, openBlock, createElementVNode, withModifiers, createVNode, createBlock, withCtx, createTextVNode } from "vue";
2
- import Field from "../../../../components/Field/Field.vue2.js";
3
- import _sfc_main$1 from "../../../../components/Radio/Radio.vue.js";
4
- import _sfc_main$4 from "../../../../components/Button/Button.vue.js";
5
- import _sfc_main$3 from "../../../../components/UploadImage/UploadImage.vue.js";
6
- import Media from "../../../../components/Media/Media.vue.js";
7
- import _sfc_main$2 from "../../../icons/entities/IconMusic.vue.js";
8
- import { state } from "../../../auth/views/store/auth.js";
9
- import { actions } from "../../store/playlists.js";
10
- const _hoisted_1 = { class: "playlist-form" };
11
- const _hoisted_2 = { class: "form-group mn-b-medium" };
12
- const _hoisted_3 = { class: "form-group mn-b-medium" };
13
- const _hoisted_4 = { class: "form-group mn-b-medium" };
14
- const _hoisted_5 = { class: "flex gap-small" };
15
- const _hoisted_6 = { class: "form-group mn-b-medium" };
16
- const _hoisted_7 = { class: "playlist-cover-upload flex gap-medium" };
17
- const _hoisted_8 = { class: "playlist-cover-preview bg-dark-transp-25 radius-small o-hidden" };
18
- const _hoisted_9 = {
19
- key: 1,
20
- class: "w-10r h-10r flex-center flex"
1
+ import { reactive, ref, watch, computed, onMounted, createElementBlock, openBlock, createElementVNode, toDisplayString, withModifiers, createVNode, withCtx, createCommentVNode, createTextVNode } from "vue";
2
+ import { useRouter, useRoute } from "vue-router";
3
+ import Field from "../../../../components/Field/Field.vue.js";
4
+ import _sfc_main$2 from "../../../../components/Block/Block.vue.js";
5
+ import _sfc_main$5 from "../../../../components/Button/Button.vue.js";
6
+ import _sfc_main$4 from "../../../../components/Radio/Radio.vue.js";
7
+ import _sfc_main$1 from "../../../../components/UploadImage/UploadImage.vue.js";
8
+ import _sfc_main$3 from "../../../icons/navigation/IconCross.vue.js";
9
+ import BlockMultiselect from "../../../globals/views/components/blocks/BlockMultiselect.vue.js";
10
+ import { actions as actions$1 } from "../../store/playlists.js";
11
+ import { state, actions } from "../../store/tracks.js";
12
+ import { actions as actions$2 } from "../../../globals/views/store/globals.js";
13
+ import { state as state$1 } from "../../../auth/views/store/auth.js";
14
+ const _hoisted_1 = { class: "pd-medium" };
15
+ const _hoisted_2 = { class: "h2 mn-b-medium" };
16
+ const _hoisted_3 = { class: "bg-light pd-medium radius-medium" };
17
+ const _hoisted_4 = { class: "mn-b-medium" };
18
+ const _hoisted_5 = { class: "flex-nowrap flex-v-center flex gap-thin" };
19
+ const _hoisted_6 = ["onClick", "disabled"];
20
+ const _hoisted_7 = ["onClick", "disabled"];
21
+ const _hoisted_8 = { class: "flex-1" };
22
+ const _hoisted_9 = { class: "t-medium" };
23
+ const _hoisted_10 = { class: "t-small t-transp" };
24
+ const _hoisted_11 = { key: 0 };
25
+ const _hoisted_12 = {
26
+ key: 2,
27
+ class: "t-small t-transp"
21
28
  };
22
- const _hoisted_10 = { class: "form-actions t-right" };
29
+ const _hoisted_13 = ["onClick"];
30
+ const _hoisted_14 = { class: "flex-nowrap flex-v-center flex" };
31
+ const _hoisted_15 = { class: "w-100" };
32
+ const _hoisted_16 = { class: "t-medium" };
33
+ const _hoisted_17 = { class: "t-small t-transp" };
34
+ const _hoisted_18 = { key: 0 };
35
+ const _hoisted_19 = {
36
+ key: 0,
37
+ class: "t-small t-transp mn-l-small"
38
+ };
39
+ const _hoisted_20 = {
40
+ key: 0,
41
+ class: "t-small t-transp mn-t-small"
42
+ };
43
+ const _hoisted_21 = { class: "bg-light pd-medium radius-medium" };
44
+ const _hoisted_22 = { class: "mn-b-medium" };
45
+ const _hoisted_23 = { class: "flex gap-medium" };
46
+ const _hoisted_24 = { class: "mn-b-medium" };
47
+ const _hoisted_25 = { class: "flex gap-medium" };
48
+ const _hoisted_26 = { class: "flex flex-justify-between" };
23
49
  const _sfc_main = {
24
50
  __name: "PlaylistForm",
25
- emits: ["created", "cancel"],
26
- setup(__props, { emit: __emit }) {
27
- const emit = __emit;
28
- const form = reactive({
51
+ props: {
52
+ editMode: {
53
+ type: Boolean,
54
+ default: false
55
+ },
56
+ url: {
57
+ type: String,
58
+ default: ""
59
+ }
60
+ },
61
+ setup(__props) {
62
+ const props = __props;
63
+ const router = useRouter();
64
+ useRoute();
65
+ const playlist = reactive({
29
66
  title: "",
30
67
  description: "",
31
- isPublic: true,
32
68
  coverUrl: "",
33
- isCollaborative: false,
34
- tracks: []
69
+ tracks: [],
70
+ url: "",
71
+ isPublic: true,
72
+ isCollaborative: false
73
+ });
74
+ const validation = reactive({
75
+ title: false,
76
+ description: false
77
+ });
78
+ const urlManuallySet = ref(false);
79
+ const generateSlug = (text) => {
80
+ if (!text) return "";
81
+ return text.toLowerCase().replace(/[^a-z0-9\s-]/g, "").replace(/\s+/g, "-").replace(/-+/g, "-").trim("-");
82
+ };
83
+ watch(() => playlist.title, (newTitle) => {
84
+ if (!urlManuallySet.value && !props.editMode) {
85
+ playlist.url = generateSlug(newTitle);
86
+ }
87
+ });
88
+ watch(() => playlist.url, (newUrl, oldUrl) => {
89
+ if (newUrl !== generateSlug(playlist.title)) {
90
+ urlManuallySet.value = true;
91
+ }
92
+ });
93
+ const totalDuration = computed(() => {
94
+ return playlist.tracks.reduce((sum, track) => sum + (track.duration || 0), 0);
35
95
  });
36
- const validationErrors = reactive({});
96
+ const formatDuration = (seconds) => {
97
+ if (!seconds) return "0:00";
98
+ const hours = Math.floor(seconds / 3600);
99
+ const minutes = Math.floor(seconds % 3600 / 60);
100
+ const secs = seconds % 60;
101
+ if (hours > 0) {
102
+ return `${hours}:${minutes.toString().padStart(2, "0")}:${secs.toString().padStart(2, "0")}`;
103
+ }
104
+ return `${minutes}:${secs.toString().padStart(2, "0")}`;
105
+ };
106
+ const moveTrack = (index, direction) => {
107
+ const newIndex = direction === "up" ? index - 1 : index + 1;
108
+ if (newIndex < 0 || newIndex >= playlist.tracks.length) return;
109
+ const tracks = [...playlist.tracks];
110
+ [tracks[index], tracks[newIndex]] = [tracks[newIndex], tracks[index]];
111
+ playlist.tracks = tracks;
112
+ };
113
+ const fetchPlaylist = async () => {
114
+ if (!props.url) return;
115
+ try {
116
+ const fetchedPlaylist = await actions$1.fetchPlaylistByUrl(props.url);
117
+ if (!fetchedPlaylist) {
118
+ actions$2.setError({
119
+ message: "Playlist not found"
120
+ });
121
+ return;
122
+ }
123
+ Object.assign(playlist, {
124
+ title: fetchedPlaylist.title || "",
125
+ description: fetchedPlaylist.description || "",
126
+ coverUrl: fetchedPlaylist.coverUrl || "",
127
+ tracks: fetchedPlaylist.tracks || [],
128
+ url: fetchedPlaylist.url || "",
129
+ isPublic: fetchedPlaylist.isPublic !== false,
130
+ isCollaborative: fetchedPlaylist.isCollaborative || false,
131
+ _id: fetchedPlaylist._id
132
+ });
133
+ } catch (error) {
134
+ console.error("Error fetching playlist:", error);
135
+ actions$2.setError({
136
+ message: "Failed to load playlist details"
137
+ });
138
+ }
139
+ };
140
+ const validateForm = () => {
141
+ let isValid = true;
142
+ if (!playlist.title.trim()) {
143
+ validation.title = {
144
+ message: "Playlist title is required"
145
+ };
146
+ isValid = false;
147
+ } else {
148
+ validation.title = false;
149
+ }
150
+ if (playlist.description && playlist.description.length > 2e3) {
151
+ validation.description = {
152
+ message: "Description is too long (max 2000 characters)"
153
+ };
154
+ isValid = false;
155
+ } else {
156
+ validation.description = false;
157
+ }
158
+ return isValid;
159
+ };
37
160
  const submitForm = async () => {
38
- validationErrors.title = !form.title ? { message: "Playlist name is required" } : null;
39
- if (Object.values(validationErrors).some((error) => error !== null)) {
161
+ if (!validateForm()) {
40
162
  return;
41
163
  }
42
- const playlistData = {
43
- ...form,
44
- creator: {
45
- type: "User",
46
- target: state.user._id
47
- },
48
- owner: {
49
- type: "User",
50
- target: state.user._id
51
- }
52
- };
53
164
  try {
54
- const playlist = await actions.createPlaylist(playlistData);
55
- emit("created", playlist);
165
+ const formData = {
166
+ ...playlist,
167
+ tracks: playlist.tracks.map((track) => ({
168
+ track: track._id || track,
169
+ addedAt: /* @__PURE__ */ new Date()
170
+ }))
171
+ };
172
+ if (!props.editMode) {
173
+ formData.creator = {
174
+ type: "user",
175
+ target: state$1.user._id
176
+ };
177
+ formData.owner = {
178
+ type: "user",
179
+ target: state$1.user._id
180
+ };
181
+ }
182
+ let result;
183
+ if (props.editMode) {
184
+ result = await actions$1.updatePlaylist(formData);
185
+ } else {
186
+ result = await actions$1.createPlaylist(formData);
187
+ }
188
+ setTimeout(() => {
189
+ router.push({
190
+ name: "playlist",
191
+ params: { url: result.url }
192
+ });
193
+ }, 1e3);
56
194
  } catch (error) {
57
- console.error("Error creating playlist:", error);
195
+ console.error("Error saving playlist:", error);
196
+ actions$2.setError({
197
+ message: "Failed to save playlist"
198
+ });
58
199
  }
59
200
  };
201
+ const handleUploadError = (error) => {
202
+ console.error("Upload error:", error);
203
+ actions$2.setError({
204
+ message: "Error uploading image"
205
+ });
206
+ };
207
+ onMounted(async () => {
208
+ if (props.editMode) {
209
+ await fetchPlaylist();
210
+ urlManuallySet.value = true;
211
+ }
212
+ });
60
213
  return (_ctx, _cache) => {
61
214
  return openBlock(), createElementBlock("div", _hoisted_1, [
215
+ createElementVNode("h2", _hoisted_2, toDisplayString(__props.editMode ? "Edit Playlist" : "Create Playlist"), 1),
62
216
  createElementVNode("form", {
63
- onSubmit: withModifiers(submitForm, ["prevent"])
217
+ onSubmit: withModifiers(submitForm, ["prevent"]),
218
+ class: "cols-1 gap-medium"
64
219
  }, [
65
- createElementVNode("div", _hoisted_2, [
66
- _cache[6] || (_cache[6] = createElementVNode("label", {
67
- for: "title",
68
- class: "t-medium mn-b-thin d-block"
69
- }, "Playlist Name", -1)),
70
- createVNode(Field, {
71
- field: form.title,
72
- "onUpdate:field": _cache[0] || (_cache[0] = ($event) => form.title = $event),
73
- id: "title",
74
- type: "text",
75
- placeholder: "New Playlist",
76
- validation: validationErrors.title,
77
- class: "w-100 pd-small bg-dark-transp-25 radius-small"
78
- }, null, 8, ["field", "validation"])
79
- ]),
80
220
  createElementVNode("div", _hoisted_3, [
81
- _cache[7] || (_cache[7] = createElementVNode("label", {
82
- for: "description",
83
- class: "t-medium mn-b-thin d-block"
84
- }, "Description", -1)),
221
+ _cache[11] || (_cache[11] = createElementVNode("h3", { class: "h3 mn-b-medium" }, "Basic Information", -1)),
222
+ createElementVNode("div", _hoisted_4, [
223
+ _cache[10] || (_cache[10] = createElementVNode("p", { class: "p-semi mn-b-small" }, "Playlist Cover", -1)),
224
+ createVNode(_sfc_main$1, {
225
+ photo: playlist.coverUrl,
226
+ "onUpdate:photo": _cache[0] || (_cache[0] = ($event) => playlist.coverUrl = $event),
227
+ uploadPath: "playlists/covers",
228
+ class: "w-100 h-15r radius-small o-hidden mn-b-small",
229
+ onError: handleUploadError
230
+ }, null, 8, ["photo"])
231
+ ]),
85
232
  createVNode(Field, {
86
- field: form.description,
87
- "onUpdate:field": _cache[1] || (_cache[1] = ($event) => form.description = $event),
88
- id: "description",
233
+ field: playlist.title,
234
+ "onUpdate:field": _cache[1] || (_cache[1] = ($event) => playlist.title = $event),
235
+ label: "Title",
236
+ placeholder: "Enter playlist title",
237
+ class: "bg-white radius-small pd-small mn-b-thin",
238
+ validation: validation.title
239
+ }, null, 8, ["field", "validation"]),
240
+ createVNode(Field, {
241
+ field: playlist.url,
242
+ "onUpdate:field": _cache[2] || (_cache[2] = ($event) => playlist.url = $event),
243
+ label: "URL",
244
+ placeholder: "Leave blank for auto-generation based on the playlist title",
245
+ class: "bg-white radius-small pd-small mn-b-small"
246
+ }, null, 8, ["field"]),
247
+ createVNode(Field, {
248
+ field: playlist.description,
249
+ "onUpdate:field": _cache[3] || (_cache[3] = ($event) => playlist.description = $event),
250
+ label: "Description",
89
251
  type: "textarea",
90
- placeholder: "Add an optional description",
91
- validation: validationErrors.description,
92
- class: "w-100 pd-small bg-dark-transp-25 radius-small"
252
+ placeholder: "Enter playlist description",
253
+ class: "bg-white radius-small pd-small mn-b-thin",
254
+ validation: validation.description
93
255
  }, null, 8, ["field", "validation"])
94
256
  ]),
95
- createElementVNode("div", _hoisted_4, [
96
- _cache[8] || (_cache[8] = createElementVNode("label", { class: "t-medium mn-b-thin d-block" }, "Privacy", -1)),
97
- createElementVNode("div", _hoisted_5, [
98
- createVNode(_sfc_main$1, {
99
- radio: form.isPublic,
100
- "onUpdate:radio": _cache[2] || (_cache[2] = ($event) => form.isPublic = $event),
101
- value: true,
102
- name: "privacy",
103
- label: "Public",
104
- class: ""
105
- }, null, 8, ["radio"]),
106
- createVNode(_sfc_main$1, {
107
- radio: form.isPublic,
108
- "onUpdate:radio": _cache[3] || (_cache[3] = ($event) => form.isPublic = $event),
109
- value: false,
110
- name: "privacy",
111
- label: "Private",
112
- class: ""
113
- }, null, 8, ["radio"])
114
- ])
115
- ]),
116
- createElementVNode("div", _hoisted_6, [
117
- _cache[9] || (_cache[9] = createElementVNode("label", { class: "t-medium mn-b-thin d-block" }, "Cover Image", -1)),
118
- createElementVNode("div", _hoisted_7, [
119
- createElementVNode("div", _hoisted_8, [
120
- form.coverUrl ? (openBlock(), createBlock(Media, {
121
- key: 0,
122
- url: form.coverUrl,
123
- class: "w-10r h-10r object-fit-cover"
124
- }, null, 8, ["url"])) : (openBlock(), createElementBlock("div", _hoisted_9, [
125
- createVNode(_sfc_main$2, {
126
- class: "i-big",
127
- fill: "rgb(var(--grey))"
128
- })
129
- ]))
130
- ]),
131
- createVNode(_sfc_main$3, {
132
- photo: form.coverUrl,
133
- "onUpdate:photo": _cache[4] || (_cache[4] = ($event) => form.coverUrl = $event),
134
- uploadPath: "playlists",
135
- class: "flex-1 h-10r bg-dark-transp-25 radius-small"
136
- }, null, 8, ["photo"])
257
+ createVNode(_sfc_main$2, { title: "Tracks" }, {
258
+ default: withCtx(() => [
259
+ createVNode(BlockMultiselect, {
260
+ modelValue: playlist.tracks,
261
+ "onUpdate:modelValue": _cache[4] || (_cache[4] = ($event) => playlist.tracks = $event),
262
+ placeholder: "Search tracks...",
263
+ multiple: true,
264
+ transform: (item) => ({
265
+ _id: item._id,
266
+ title: item.title,
267
+ artists: item.artists,
268
+ album: item.album,
269
+ duration: item.duration
270
+ }),
271
+ store: {
272
+ read: (options) => actions.fetchTracks(options),
273
+ state
274
+ },
275
+ options: {
276
+ rootOnly: false,
277
+ excludeChildren: false,
278
+ limit: 50
279
+ },
280
+ skeleton: {
281
+ hide: false,
282
+ horizontal: true,
283
+ class: "radius-small",
284
+ structure: [{
285
+ block: "text",
286
+ size: "large"
287
+ }]
288
+ },
289
+ states: {
290
+ empty: {
291
+ title: "No tracks found",
292
+ description: "Try different search terms",
293
+ class: "radius-small"
294
+ }
295
+ },
296
+ key: "_id",
297
+ label: (item) => item.title,
298
+ classSearch: "bg-white radius-small",
299
+ classSelected: "bg-white pd-small radius-small",
300
+ classDropdown: "bg-white pd-small radius-medium bs-small",
301
+ classItem: "pd-small radius-small hover-bg-light cursor-pointer",
302
+ classFeed: "h-max-30r gap-thin flex-column flex o-scroll"
303
+ }, {
304
+ selected: withCtx(({ item, clear, index }) => [
305
+ createElementVNode("div", _hoisted_5, [
306
+ playlist.tracks.length > 1 ? (openBlock(), createElementBlock("button", {
307
+ key: 0,
308
+ onClick: withModifiers(($event) => moveTrack(index, "up"), ["stop"]),
309
+ disabled: index === 0,
310
+ class: "i-small pd-micro bg-grey-nano radius-extra flex-center flex aspect-1x1 hover-scale-1"
311
+ }, [
312
+ createVNode(_sfc_main$3, { class: "i-micro" })
313
+ ], 8, _hoisted_6)) : createCommentVNode("", true),
314
+ playlist.tracks.length > 1 ? (openBlock(), createElementBlock("button", {
315
+ key: 1,
316
+ onClick: withModifiers(($event) => moveTrack(index, "down"), ["stop"]),
317
+ disabled: index === playlist.tracks.length - 1,
318
+ class: "i-small pd-micro bg-grey-nano radius-extra flex-center flex aspect-1x1 hover-scale-1"
319
+ }, [
320
+ createVNode(_sfc_main$3, { class: "i-micro" })
321
+ ], 8, _hoisted_7)) : createCommentVNode("", true),
322
+ createElementVNode("div", _hoisted_8, [
323
+ createElementVNode("p", _hoisted_9, toDisplayString(item.title), 1),
324
+ createElementVNode("p", _hoisted_10, [
325
+ createTextVNode(toDisplayString(item.artists?.map((a) => a.name || a).join(", ")) + " ", 1),
326
+ item.album ? (openBlock(), createElementBlock("span", _hoisted_11, " • " + toDisplayString(item.album.title || item.album), 1)) : createCommentVNode("", true)
327
+ ])
328
+ ]),
329
+ item.duration ? (openBlock(), createElementBlock("span", _hoisted_12, toDisplayString(formatDuration(item.duration)), 1)) : createCommentVNode("", true),
330
+ createElementVNode("button", {
331
+ onClick: withModifiers(clear, ["stop"]),
332
+ class: "i-small pd-micro bg-red radius-extra flex-center flex aspect-1x1 hover-scale-1"
333
+ }, [
334
+ createVNode(_sfc_main$3, { class: "i-micro fill-white" })
335
+ ], 8, _hoisted_13)
336
+ ])
337
+ ]),
338
+ item: withCtx(({ item }) => [
339
+ createElementVNode("div", _hoisted_14, [
340
+ createElementVNode("div", _hoisted_15, [
341
+ createElementVNode("p", _hoisted_16, toDisplayString(item.title), 1),
342
+ createElementVNode("p", _hoisted_17, [
343
+ createTextVNode(toDisplayString(item.artists?.map((a) => a.name || a).join(", ")) + " ", 1),
344
+ item.album ? (openBlock(), createElementBlock("span", _hoisted_18, " • " + toDisplayString(item.album.title || item.album), 1)) : createCommentVNode("", true)
345
+ ])
346
+ ]),
347
+ item.duration ? (openBlock(), createElementBlock("span", _hoisted_19, toDisplayString(formatDuration(item.duration)), 1)) : createCommentVNode("", true)
348
+ ])
349
+ ]),
350
+ _: 1
351
+ }, 8, ["modelValue", "transform", "store", "label"]),
352
+ playlist.tracks.length > 0 ? (openBlock(), createElementBlock("div", _hoisted_20, toDisplayString(playlist.tracks.length) + " tracks • " + toDisplayString(formatDuration(totalDuration.value)), 1)) : createCommentVNode("", true)
353
+ ]),
354
+ _: 1
355
+ }),
356
+ createElementVNode("div", _hoisted_21, [
357
+ _cache[14] || (_cache[14] = createElementVNode("h3", { class: "h3 mn-b-medium" }, "Privacy & Settings", -1)),
358
+ createElementVNode("div", _hoisted_22, [
359
+ _cache[12] || (_cache[12] = createElementVNode("p", { class: "p-semi mn-b-small" }, "Privacy", -1)),
360
+ createElementVNode("div", _hoisted_23, [
361
+ createVNode(_sfc_main$4, {
362
+ radio: playlist.isPublic,
363
+ "onUpdate:radio": _cache[5] || (_cache[5] = ($event) => playlist.isPublic = $event),
364
+ value: true,
365
+ name: "privacy",
366
+ label: "Public",
367
+ class: "bg-white pd-small radius-small"
368
+ }, null, 8, ["radio"]),
369
+ createVNode(_sfc_main$4, {
370
+ radio: playlist.isPublic,
371
+ "onUpdate:radio": _cache[6] || (_cache[6] = ($event) => playlist.isPublic = $event),
372
+ value: false,
373
+ name: "privacy",
374
+ label: "Private",
375
+ class: "bg-white pd-small radius-small"
376
+ }, null, 8, ["radio"])
377
+ ])
378
+ ]),
379
+ createElementVNode("div", _hoisted_24, [
380
+ _cache[13] || (_cache[13] = createElementVNode("p", { class: "p-semi mn-b-small" }, "Collaborative Playlist", -1)),
381
+ createElementVNode("div", _hoisted_25, [
382
+ createVNode(_sfc_main$4, {
383
+ radio: playlist.isCollaborative,
384
+ "onUpdate:radio": _cache[7] || (_cache[7] = ($event) => playlist.isCollaborative = $event),
385
+ value: true,
386
+ name: "collaborative",
387
+ label: "Yes",
388
+ class: "bg-white pd-small radius-small"
389
+ }, null, 8, ["radio"]),
390
+ createVNode(_sfc_main$4, {
391
+ radio: playlist.isCollaborative,
392
+ "onUpdate:radio": _cache[8] || (_cache[8] = ($event) => playlist.isCollaborative = $event),
393
+ value: false,
394
+ name: "collaborative",
395
+ label: "No",
396
+ class: "bg-white pd-small radius-small"
397
+ }, null, 8, ["radio"])
398
+ ])
137
399
  ])
138
400
  ]),
139
- createElementVNode("div", _hoisted_10, [
140
- createVNode(_sfc_main$4, {
141
- onClick: _cache[5] || (_cache[5] = ($event) => _ctx.$emit("cancel")),
142
- type: "button",
143
- class: "bg-dark-transp-25 pd-small radius-small mn-r-small hover-bg-dark",
144
- showLoader: false,
145
- showSucces: false
401
+ createElementVNode("div", _hoisted_26, [
402
+ createVNode(_sfc_main$5, {
403
+ onClick: _cache[9] || (_cache[9] = ($event) => _ctx.$router.go(-1)),
404
+ class: "bg-grey-nano t-black",
405
+ showSucces: false,
406
+ showLoader: false
146
407
  }, {
147
- default: withCtx(() => _cache[10] || (_cache[10] = [
408
+ default: withCtx(() => _cache[15] || (_cache[15] = [
148
409
  createTextVNode(" Cancel ")
149
410
  ])),
150
411
  _: 1
151
412
  }),
152
- createVNode(_sfc_main$4, {
153
- type: "submit",
154
- class: "bg-main pd-small radius-small hover-scale-1",
413
+ createVNode(_sfc_main$5, {
155
414
  submit: submitForm,
156
- showLoader: true,
157
- showSucces: true,
158
- validation: !!Object.keys(validationErrors).length
415
+ class: "bg-main t-black",
416
+ text: {
417
+ success: __props.editMode ? "Updated!" : "Created!"
418
+ }
159
419
  }, {
160
- default: withCtx(() => _cache[11] || (_cache[11] = [
161
- createTextVNode(" Create Playlist ")
162
- ])),
420
+ default: withCtx(() => [
421
+ createTextVNode(toDisplayString(__props.editMode ? "Update Playlist" : "Create Playlist"), 1)
422
+ ]),
163
423
  _: 1
164
- }, 8, ["validation"])
424
+ }, 8, ["text"])
165
425
  ])
166
426
  ], 32)
167
427
  ]);
@@ -1 +1 @@
1
- {"version":3,"file":"PlaylistForm.vue.js","sources":["../../../../../../../src/modules/music/components/forms/PlaylistForm.vue"],"sourcesContent":["<!-- components/forms/PlaylistForm.vue -->\n<template>\n <div class=\"playlist-form\">\n <form @submit.prevent=\"submitForm\">\n <div class=\"form-group mn-b-medium\">\n <label for=\"title\" class=\" t-medium mn-b-thin d-block\">Playlist Name</label>\n <Field \n v-model:field=\"form.title\"\n id=\"title\"\n type=\"text\"\n placeholder=\"New Playlist\"\n :validation=\"validationErrors.title\"\n class=\"w-100 pd-small bg-dark-transp-25 radius-small \"\n />\n </div>\n \n <div class=\"form-group mn-b-medium\">\n <label for=\"description\" class=\" t-medium mn-b-thin d-block\">Description</label>\n <Field \n v-model:field=\"form.description\"\n id=\"description\"\n type=\"textarea\"\n placeholder=\"Add an optional description\"\n :validation=\"validationErrors.description\"\n class=\"w-100 pd-small bg-dark-transp-25 radius-small \"\n />\n </div>\n \n <div class=\"form-group mn-b-medium\">\n <label class=\" t-medium mn-b-thin d-block\">Privacy</label>\n <div class=\"flex gap-small\">\n <Radio \n v-model:radio=\"form.isPublic\"\n :value=\"true\"\n name=\"privacy\"\n label=\"Public\"\n class=\"\"\n />\n <Radio \n v-model:radio=\"form.isPublic\"\n :value=\"false\"\n name=\"privacy\"\n label=\"Private\"\n class=\"\"\n />\n </div>\n </div>\n \n <div class=\"form-group mn-b-medium\">\n <label class=\" t-medium mn-b-thin d-block\">Cover Image</label>\n <div class=\"playlist-cover-upload flex gap-medium\">\n <div class=\"playlist-cover-preview bg-dark-transp-25 radius-small o-hidden\">\n <Media \n v-if=\"form.coverUrl\"\n :url=\"form.coverUrl\"\n class=\"w-10r h-10r object-fit-cover\"\n />\n <div v-else class=\"w-10r h-10r flex-center flex\">\n <IconMusic class=\"i-big\" fill=\"rgb(var(--grey))\"/>\n </div>\n </div>\n \n <UploadImage\n v-model:photo=\"form.coverUrl\"\n uploadPath=\"playlists\"\n class=\"flex-1 h-10r bg-dark-transp-25 radius-small\"\n />\n </div>\n </div>\n \n <div class=\"form-actions t-right\">\n <Button \n @click=\"$emit('cancel')\"\n type=\"button\"\n class=\"bg-dark-transp-25 pd-small radius-small mn-r-small hover-bg-dark\"\n :showLoader=\"false\" \n :showSucces=\"false\"\n >\n Cancel\n </Button>\n \n <Button \n type=\"submit\"\n class=\"bg-main pd-small radius-small hover-scale-1\"\n :submit=\"submitForm\"\n :showLoader=\"true\" \n :showSucces=\"true\"\n :validation=\"!!Object.keys(validationErrors).length\"\n >\n Create Playlist\n </Button>\n </div>\n </form>\n </div>\n</template>\n\n<script setup>\nimport { ref, reactive } from 'vue';\nimport Field from '@martyrs/src/components/Field/Field.vue';\nimport Radio from '@martyrs/src/components/Radio/Radio.vue';\nimport Button from '@martyrs/src/components/Button/Button.vue';\nimport UploadImage from '@martyrs/src/components/UploadImage/UploadImage.vue';\nimport Media from '@martyrs/src/components/Media/Media.vue';\nimport IconMusic from '@martyrs/src/modules/icons/entities/IconMusic.vue';\n\n// Import auth store and playlists store\nimport { state as authState } from '@martyrs/src/modules/auth/views/store/auth.js';\nimport { actions as playlistsActions } from '../../store/playlists.js';\n\nconst emit = defineEmits(['created', 'cancel']);\n\n// Form data\nconst form = reactive({\n title: '',\n description: '',\n isPublic: true,\n coverUrl: '',\n isCollaborative: false,\n tracks: []\n});\n\n// Validation\nconst validationErrors = reactive({});\n\n// Form submission\nconst submitForm = async () => {\n // Validate form\n validationErrors.title = !form.title ? { message: 'Playlist name is required' } : null;\n \n // If there are validation errors, don't submit\n if (Object.values(validationErrors).some(error => error !== null)) {\n return;\n }\n \n // Prepare playlist data\n const playlistData = {\n ...form,\n creator: {\n type: 'User',\n target: authState.user._id\n },\n owner: {\n type: 'User',\n target: authState.user._id\n }\n };\n \n try {\n const playlist = await playlistsActions.createPlaylist(playlistData);\n emit('created', playlist);\n } catch (error) {\n console.error('Error creating playlist:', error);\n // Handle error (could add form-level error message)\n }\n};\n</script>"],"names":["authState","playlistsActions"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AA6GA,UAAM,OAAO;AAGb,UAAM,OAAO,SAAS;AAAA,MACpB,OAAO;AAAA,MACP,aAAa;AAAA,MACb,UAAU;AAAA,MACV,UAAU;AAAA,MACV,iBAAiB;AAAA,MACjB,QAAQ,CAAA;AAAA,IACV,CAAC;AAGD,UAAM,mBAAmB,SAAS,EAAE;AAGpC,UAAM,aAAa,YAAY;AAE7B,uBAAiB,QAAQ,CAAC,KAAK,QAAQ,EAAE,SAAS,4BAA2B,IAAK;AAGlF,UAAI,OAAO,OAAO,gBAAgB,EAAE,KAAK,WAAS,UAAU,IAAI,GAAG;AACjE;AAAA,MACF;AAGA,YAAM,eAAe;AAAA,QACnB,GAAG;AAAA,QACH,SAAS;AAAA,UACP,MAAM;AAAA,UACN,QAAQA,MAAU,KAAK;AAAA,QAC7B;AAAA,QACI,OAAO;AAAA,UACL,MAAM;AAAA,UACN,QAAQA,MAAU,KAAK;AAAA,QAC7B;AAAA,MACA;AAEE,UAAI;AACF,cAAM,WAAW,MAAMC,QAAiB,eAAe,YAAY;AACnE,aAAK,WAAW,QAAQ;AAAA,MAC1B,SAAS,OAAO;AACd,gBAAQ,MAAM,4BAA4B,KAAK;AAAA,MAEjD;AAAA,IACF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"PlaylistForm.vue.js","sources":["../../../../../../../src/modules/music/components/forms/PlaylistForm.vue"],"sourcesContent":["<template>\n <div class=\"pd-medium\">\n <h2 class=\"h2 mn-b-medium\">{{ editMode ? 'Edit Playlist' : 'Create Playlist' }}</h2>\n \n <form @submit.prevent=\"submitForm\" class=\"cols-1 gap-medium\">\n <!-- Basic Info Section -->\n <div class=\"bg-light pd-medium radius-medium\">\n <h3 class=\"h3 mn-b-medium\">Basic Information</h3>\n \n <!-- Playlist Cover -->\n <div class=\"mn-b-medium\">\n <p class=\"p-semi mn-b-small\">Playlist Cover</p>\n <UploadImage\n v-model:photo=\"playlist.coverUrl\"\n uploadPath=\"playlists/covers\"\n class=\"w-100 h-15r radius-small o-hidden mn-b-small\"\n @error=\"handleUploadError\"\n />\n </div>\n \n <!-- Title -->\n <Field\n v-model:field=\"playlist.title\"\n label=\"Title\"\n placeholder=\"Enter playlist title\"\n class=\"bg-white radius-small pd-small mn-b-thin\"\n :validation=\"validation.title\"\n />\n \n <!-- URL -->\n <Field\n v-model:field=\"playlist.url\"\n label=\"URL\"\n placeholder=\"Leave blank for auto-generation based on the playlist title\"\n class=\"bg-white radius-small pd-small mn-b-small\"\n />\n \n <!-- Description -->\n <Field\n v-model:field=\"playlist.description\"\n label=\"Description\"\n type=\"textarea\"\n placeholder=\"Enter playlist description\"\n class=\"bg-white radius-small pd-small mn-b-thin\"\n :validation=\"validation.description\"\n />\n </div>\n \n <!-- Tracks Section -->\n <Block title=\"Tracks\">\n <BlockMultiselect\n v-model=\"playlist.tracks\"\n placeholder=\"Search tracks...\"\n :multiple=\"true\"\n :transform=\"(item) => ({ \n _id: item._id, \n title: item.title,\n artists: item.artists,\n album: item.album,\n duration: item.duration \n })\"\n :store=\"{\n read: (options) => tracksStore.actions.fetchTracks(options),\n state: tracksStore.state\n }\"\n :options=\"{\n rootOnly: false,\n excludeChildren: false,\n limit: 50\n }\"\n :skeleton=\"{\n hide: false,\n horizontal: true,\n class: 'radius-small',\n structure: [{ \n block: 'text', size: 'large'\n }]\n }\"\n :states=\"{\n empty: {\n title: 'No tracks found',\n description: 'Try different search terms',\n class: 'radius-small'\n }\n }\"\n key=\"_id\"\n :label=\"item => item.title\"\n classSearch=\"bg-white radius-small\"\n classSelected=\"bg-white pd-small radius-small\"\n classDropdown=\"bg-white pd-small radius-medium bs-small\"\n classItem=\"pd-small radius-small hover-bg-light cursor-pointer\"\n classFeed=\"h-max-30r gap-thin flex-column flex o-scroll\"\n >\n <!-- Selected tracks with reorder support -->\n <template #selected=\"{ item, clear, index }\">\n <div class=\"flex-nowrap flex-v-center flex gap-thin\">\n <button \n v-if=\"playlist.tracks.length > 1\"\n @click.stop=\"moveTrack(index, 'up')\"\n :disabled=\"index === 0\"\n class=\"i-small pd-micro bg-grey-nano radius-extra flex-center flex aspect-1x1 hover-scale-1\"\n >\n <IconArrowUp class=\"i-micro\" />\n </button>\n \n <button \n v-if=\"playlist.tracks.length > 1\"\n @click.stop=\"moveTrack(index, 'down')\"\n :disabled=\"index === playlist.tracks.length - 1\"\n class=\"i-small pd-micro bg-grey-nano radius-extra flex-center flex aspect-1x1 hover-scale-1\"\n >\n <IconArrowDown class=\"i-micro\" />\n </button>\n \n <div class=\"flex-1\">\n <p class=\"t-medium\">{{ item.title }}</p>\n <p class=\"t-small t-transp\">\n {{ item.artists?.map(a => a.name || a).join(', ') }}\n <span v-if=\"item.album\"> • {{ item.album.title || item.album }}</span>\n </p>\n </div>\n \n <span v-if=\"item.duration\" class=\"t-small t-transp\">\n {{ formatDuration(item.duration) }}\n </span>\n \n <button \n @click.stop=\"clear\"\n class=\"i-small pd-micro bg-red radius-extra flex-center flex aspect-1x1 hover-scale-1\"\n >\n <IconCross class=\"i-micro fill-white\" />\n </button>\n </div>\n </template>\n \n <!-- Track items in dropdown -->\n <template #item=\"{ item }\">\n <div class=\"flex-nowrap flex-v-center flex\">\n <div class=\"w-100\">\n <p class=\"t-medium\">{{ item.title }}</p>\n <p class=\"t-small t-transp\">\n {{ item.artists?.map(a => a.name || a).join(', ') }}\n <span v-if=\"item.album\"> • {{ item.album.title || item.album }}</span>\n </p>\n </div>\n <span v-if=\"item.duration\" class=\"t-small t-transp mn-l-small\">\n {{ formatDuration(item.duration) }}\n </span>\n </div>\n </template>\n </BlockMultiselect>\n \n <!-- Tracks summary -->\n <div v-if=\"playlist.tracks.length > 0\" class=\"t-small t-transp mn-t-small\">\n {{ playlist.tracks.length }} tracks • {{ formatDuration(totalDuration) }}\n </div>\n </Block>\n \n <!-- Privacy & Settings Section -->\n <div class=\"bg-light pd-medium radius-medium\">\n <h3 class=\"h3 mn-b-medium\">Privacy & Settings</h3>\n \n <!-- Privacy -->\n <div class=\"mn-b-medium\">\n <p class=\"p-semi mn-b-small\">Privacy</p>\n <div class=\"flex gap-medium\">\n <Radio\n v-model:radio=\"playlist.isPublic\"\n :value=\"true\"\n name=\"privacy\"\n label=\"Public\"\n class=\"bg-white pd-small radius-small\"\n />\n <Radio\n v-model:radio=\"playlist.isPublic\"\n :value=\"false\"\n name=\"privacy\"\n label=\"Private\"\n class=\"bg-white pd-small radius-small\"\n />\n </div>\n </div>\n \n <!-- Collaborative -->\n <div class=\"mn-b-medium\">\n <p class=\"p-semi mn-b-small\">Collaborative Playlist</p>\n <div class=\"flex gap-medium\">\n <Radio\n v-model:radio=\"playlist.isCollaborative\"\n :value=\"true\"\n name=\"collaborative\"\n label=\"Yes\"\n class=\"bg-white pd-small radius-small\"\n />\n <Radio\n v-model:radio=\"playlist.isCollaborative\"\n :value=\"false\"\n name=\"collaborative\"\n label=\"No\"\n class=\"bg-white pd-small radius-small\"\n />\n </div>\n </div>\n </div>\n \n <!-- Submit Button -->\n <div class=\"flex flex-justify-between\">\n <Button\n @click=\"$router.go(-1)\"\n class=\"bg-grey-nano t-black\"\n :showSucces=\"false\"\n :showLoader=\"false\"\n >\n Cancel\n </Button>\n \n <Button\n :submit=\"submitForm\"\n class=\"bg-main t-black\"\n :text=\"{\n success: editMode ? 'Updated!' : 'Created!'\n }\"\n >\n {{ editMode ? 'Update Playlist' : 'Create Playlist' }}\n </Button>\n </div>\n </form>\n </div>\n</template>\n\n<script setup>\nimport { ref, reactive, onMounted, watch, computed } from 'vue';\nimport { useRouter, useRoute } from 'vue-router';\n\n// Import Martyrs components\nimport Field from '@martyrs/src/components/Field/Field.vue';\nimport Block from '@martyrs/src/components/Block/Block.vue';\nimport Button from '@martyrs/src/components/Button/Button.vue';\nimport Radio from '@martyrs/src/components/Radio/Radio.vue';\nimport UploadImage from '@martyrs/src/components/UploadImage/UploadImage.vue';\nimport IconCross from '@martyrs/src/modules/icons/navigation/IconCross.vue';\nimport IconArrowUp from '@martyrs/src/modules/icons/navigation/IconCross.vue';\nimport IconArrowDown from '@martyrs/src/modules/icons/navigation/IconCross.vue';\n\nimport BlockMultiselect from '@martyrs/src/modules/globals/views/components/blocks/BlockMultiselect.vue';\n\n// Import stores\nimport * as playlistsStore from '../../store/playlists';\nimport * as tracksStore from '../../store/tracks';\nimport * as globals from '@martyrs/src/modules/globals/views/store/globals.js';\nimport * as auth from '@martyrs/src/modules/auth/views/store/auth.js';\n\n// Props\nconst props = defineProps({\n editMode: {\n type: Boolean,\n default: false\n },\n url: {\n type: String,\n default: ''\n }\n});\n\n// Router and route\nconst router = useRouter();\nconst route = useRoute();\n\n// State\nconst playlist = reactive({\n title: '',\n description: '',\n coverUrl: '',\n tracks: [],\n url: '',\n isPublic: true,\n isCollaborative: false\n});\n\nconst validation = reactive({\n title: false,\n description: false\n});\n\n// Track if URL was manually entered\nconst urlManuallySet = ref(false);\n\n// Function to generate URL-friendly slug from text\nconst generateSlug = (text) => {\n if (!text) return '';\n return text\n .toLowerCase()\n .replace(/[^a-z0-9\\s-]/g, '') // Remove special characters\n .replace(/\\s+/g, '-') // Replace spaces with hyphens\n .replace(/-+/g, '-') // Replace multiple hyphens with single\n .trim('-'); // Remove leading/trailing hyphens\n};\n\n// Watch for changes in playlist title to auto-generate URL\nwatch(() => playlist.title, (newTitle) => {\n // Only auto-generate if URL hasn't been manually set and we're not in edit mode\n if (!urlManuallySet.value && !props.editMode) {\n playlist.url = generateSlug(newTitle);\n }\n});\n\n// Watch for manual changes to URL field\nwatch(() => playlist.url, (newUrl, oldUrl) => {\n // If user manually changes URL, mark as manually set\n if (newUrl !== generateSlug(playlist.title)) {\n urlManuallySet.value = true;\n }\n});\n\n// Computed\nconst totalDuration = computed(() => {\n return playlist.tracks.reduce((sum, track) => sum + (track.duration || 0), 0);\n});\n\n// Methods\nconst formatDuration = (seconds) => {\n if (!seconds) return '0:00';\n const hours = Math.floor(seconds / 3600);\n const minutes = Math.floor((seconds % 3600) / 60);\n const secs = seconds % 60;\n \n if (hours > 0) {\n return `${hours}:${minutes.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`;\n }\n return `${minutes}:${secs.toString().padStart(2, '0')}`;\n};\n\nconst moveTrack = (index, direction) => {\n const newIndex = direction === 'up' ? index - 1 : index + 1;\n if (newIndex < 0 || newIndex >= playlist.tracks.length) return;\n \n const tracks = [...playlist.tracks];\n [tracks[index], tracks[newIndex]] = [tracks[newIndex], tracks[index]];\n playlist.tracks = tracks;\n};\n\nconst fetchPlaylist = async () => {\n if (!props.url) return;\n \n try {\n const fetchedPlaylist = await playlistsStore.actions.fetchPlaylistByUrl(props.url);\n \n if (!fetchedPlaylist) {\n globals.actions.setError({\n message: 'Playlist not found'\n });\n return;\n }\n \n // Update local playlist data\n Object.assign(playlist, {\n title: fetchedPlaylist.title || '',\n description: fetchedPlaylist.description || '',\n coverUrl: fetchedPlaylist.coverUrl || '',\n tracks: fetchedPlaylist.tracks || [],\n url: fetchedPlaylist.url || '',\n isPublic: fetchedPlaylist.isPublic !== false,\n isCollaborative: fetchedPlaylist.isCollaborative || false,\n _id: fetchedPlaylist._id\n });\n \n } catch (error) {\n console.error('Error fetching playlist:', error);\n globals.actions.setError({\n message: 'Failed to load playlist details'\n });\n }\n};\n\nconst validateForm = () => {\n let isValid = true;\n \n // Validate title\n if (!playlist.title.trim()) {\n validation.title = {\n message: 'Playlist title is required'\n };\n isValid = false;\n } else {\n validation.title = false;\n }\n \n // Validate description\n if (playlist.description && playlist.description.length > 2000) {\n validation.description = {\n message: 'Description is too long (max 2000 characters)'\n };\n isValid = false;\n } else {\n validation.description = false;\n }\n \n return isValid;\n};\n\nconst submitForm = async () => {\n if (!validateForm()) {\n return;\n }\n \n try {\n // Prepare data for submission\n const formData = {\n ...playlist,\n tracks: playlist.tracks.map(track => ({\n track: track._id || track,\n addedAt: new Date()\n }))\n };\n \n // Add ownership data if creating new playlist\n if (!props.editMode) {\n formData.creator = {\n type: 'user',\n target: auth.state.user._id\n };\n formData.owner = {\n type: 'user',\n target: auth.state.user._id\n };\n }\n \n let result;\n if (props.editMode) {\n result = await playlistsStore.actions.updatePlaylist(formData);\n } else {\n result = await playlistsStore.actions.createPlaylist(formData);\n }\n \n // Navigate to playlist detail page\n setTimeout(() => {\n router.push({\n name: 'playlist',\n params: { url: result.url }\n });\n }, 1000);\n \n } catch (error) {\n console.error('Error saving playlist:', error);\n globals.actions.setError({\n message: 'Failed to save playlist'\n });\n }\n};\n\nconst handleUploadError = (error) => {\n console.error('Upload error:', error);\n globals.actions.setError({\n message: 'Error uploading image'\n });\n};\n\n// Lifecycle hooks\nonMounted(async () => {\n if (props.editMode) {\n await fetchPlaylist();\n // Mark URL as manually set in edit mode to prevent auto-generation\n urlManuallySet.value = true;\n }\n});\n</script>"],"names":["playlistsStore.actions","globals.actions","auth.state"],"mappings":"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"}