@ozdao/martyrs 0.2.494 → 0.2.495

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 (79) 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 +42 -43
  6. package/dist/builder.js +44 -45
  7. package/dist/martyrs/src/components/FieldTags/FieldTags.vue.cjs +1 -1
  8. package/dist/martyrs/src/components/FieldTags/FieldTags.vue.js +1 -1
  9. package/dist/martyrs/src/modules/community/components/pages/CreateBlogPost.vue.cjs +1 -1
  10. package/dist/martyrs/src/modules/community/components/pages/CreateBlogPost.vue.js +1 -1
  11. package/dist/martyrs/src/modules/globals/globals.client.cjs +1 -1
  12. package/dist/martyrs/src/modules/globals/globals.client.cjs.map +1 -1
  13. package/dist/martyrs/src/modules/globals/globals.client.js +1 -1
  14. package/dist/martyrs/src/modules/globals/globals.client.js.map +1 -1
  15. package/dist/martyrs/src/modules/globals/views/classes/globals.i18n.cjs +1 -1
  16. package/dist/martyrs/src/modules/globals/views/classes/globals.i18n.js +1 -1
  17. package/dist/martyrs/src/modules/globals/views/components/layouts/Client.vue.cjs +28 -13
  18. package/dist/martyrs/src/modules/globals/views/components/layouts/Client.vue.cjs.map +1 -1
  19. package/dist/martyrs/src/modules/globals/views/components/layouts/Client.vue.js +28 -13
  20. package/dist/martyrs/src/modules/globals/views/components/layouts/Client.vue.js.map +1 -1
  21. package/dist/martyrs/src/modules/globals/views/router/scrollBehavior.cjs +1 -1
  22. package/dist/martyrs/src/modules/globals/views/router/scrollBehavior.cjs.map +1 -1
  23. package/dist/martyrs/src/modules/globals/views/router/scrollBehavior.js +1 -1
  24. package/dist/martyrs/src/modules/globals/views/router/scrollBehavior.js.map +1 -1
  25. package/dist/martyrs/src/modules/music/components/cards/TrackListCard.vue.cjs +1 -1
  26. package/dist/martyrs/src/modules/music/components/cards/TrackListCard.vue.cjs.map +1 -1
  27. package/dist/martyrs/src/modules/music/components/cards/TrackListCard.vue.js +1 -1
  28. package/dist/martyrs/src/modules/music/components/cards/TrackListCard.vue.js.map +1 -1
  29. package/dist/martyrs/src/modules/music/components/forms/SearchForm.vue.cjs +2 -2
  30. package/dist/martyrs/src/modules/music/components/forms/SearchForm.vue.cjs.map +1 -1
  31. package/dist/martyrs/src/modules/music/components/forms/SearchForm.vue.js +2 -2
  32. package/dist/martyrs/src/modules/music/components/forms/SearchForm.vue.js.map +1 -1
  33. package/dist/martyrs/src/modules/music/components/pages/Album.vue.cjs +86 -81
  34. package/dist/martyrs/src/modules/music/components/pages/Album.vue.cjs.map +1 -1
  35. package/dist/martyrs/src/modules/music/components/pages/Album.vue.js +88 -83
  36. package/dist/martyrs/src/modules/music/components/pages/Album.vue.js.map +1 -1
  37. package/dist/martyrs/src/modules/music/components/pages/Artist.vue.cjs +4 -4
  38. package/dist/martyrs/src/modules/music/components/pages/Artist.vue.cjs.map +1 -1
  39. package/dist/martyrs/src/modules/music/components/pages/Artist.vue.js +4 -4
  40. package/dist/martyrs/src/modules/music/components/pages/Artist.vue.js.map +1 -1
  41. package/dist/martyrs/src/modules/music/components/pages/MusicLibrary.vue.cjs +5 -5
  42. package/dist/martyrs/src/modules/music/components/pages/MusicLibrary.vue.cjs.map +1 -1
  43. package/dist/martyrs/src/modules/music/components/pages/MusicLibrary.vue.js +5 -5
  44. package/dist/martyrs/src/modules/music/components/pages/MusicLibrary.vue.js.map +1 -1
  45. package/dist/martyrs/src/modules/music/components/pages/Playlist.vue.cjs +12 -9
  46. package/dist/martyrs/src/modules/music/components/pages/Playlist.vue.cjs.map +1 -1
  47. package/dist/martyrs/src/modules/music/components/pages/Playlist.vue.js +12 -9
  48. package/dist/martyrs/src/modules/music/components/pages/Playlist.vue.js.map +1 -1
  49. package/dist/martyrs/src/modules/music/components/pages/SearchResults.vue.cjs +7 -7
  50. package/dist/martyrs/src/modules/music/components/pages/SearchResults.vue.cjs.map +1 -1
  51. package/dist/martyrs/src/modules/music/components/pages/SearchResults.vue.js +7 -7
  52. package/dist/martyrs/src/modules/music/components/pages/SearchResults.vue.js.map +1 -1
  53. package/dist/martyrs/src/modules/music/components/pages/Track.vue.cjs +43 -37
  54. package/dist/martyrs/src/modules/music/components/pages/Track.vue.cjs.map +1 -1
  55. package/dist/martyrs/src/modules/music/components/pages/Track.vue.js +45 -39
  56. package/dist/martyrs/src/modules/music/components/pages/Track.vue.js.map +1 -1
  57. package/dist/martyrs/src/modules/music/music.client.cjs.map +1 -1
  58. package/dist/martyrs/src/modules/music/music.client.js.map +1 -1
  59. package/dist/martyrs/src/modules/notifications/notifications.client.cjs +1 -1
  60. package/dist/martyrs/src/modules/notifications/notifications.client.cjs.map +1 -1
  61. package/dist/martyrs/src/modules/notifications/notifications.client.js +1 -1
  62. package/dist/martyrs/src/modules/notifications/notifications.client.js.map +1 -1
  63. package/dist/style.css +5 -5
  64. package/package.json +1 -1
  65. package/src/builder/rspack/rspack.config.ssr.client.js +41 -41
  66. package/src/modules/globals/globals.client.js +1 -2
  67. package/src/modules/globals/views/components/layouts/Client.vue +13 -11
  68. package/src/modules/globals/views/router/scrollBehavior.js +1 -1
  69. package/src/modules/music/components/SidebarMusic.vue +7 -7
  70. package/src/modules/music/components/cards/TrackListCard.vue +1 -1
  71. package/src/modules/music/components/forms/SearchForm.vue +1 -1
  72. package/src/modules/music/components/pages/Album.vue +26 -29
  73. package/src/modules/music/components/pages/Artist.vue +4 -4
  74. package/src/modules/music/components/pages/MusicLibrary.vue +5 -5
  75. package/src/modules/music/components/pages/Playlist.vue +9 -9
  76. package/src/modules/music/components/pages/SearchResults.vue +6 -6
  77. package/src/modules/music/components/pages/Track.vue +22 -20
  78. package/src/modules/music/music.client.js +1 -1
  79. package/src/modules/notifications/notifications.client.js +1 -1
@@ -229,40 +229,46 @@ const _sfc_main = {
229
229
  onClick: playTrack,
230
230
  color: "primary",
231
231
  size: "medium",
232
- class: "flex-1 flex-center gap-thin"
232
+ class: "flex-1 t-white bg-black radius-thin flex-center gap-thin"
233
233
  }, {
234
234
  default: vue.withCtx(() => [
235
- vue.createVNode(IconPlay.default, { class: "w-1r h-1r" }),
235
+ vue.createVNode(IconPlay.default, {
236
+ fill: "rgb(var(--white))",
237
+ class: "i-medium"
238
+ }),
236
239
  _cache[7] || (_cache[7] = vue.createTextVNode(" Play "))
237
240
  ]),
238
241
  _: 1
239
242
  }),
240
243
  vue.createVNode(Button.default, {
241
- onClick: toggleFavorite,
242
- color: isFavorite.value ? "danger" : "transp",
244
+ onClick: addToQueue,
245
+ color: "primary",
243
246
  size: "medium",
244
- class: "w-3r h-3r radius-full"
247
+ class: "flex-1 bg-light radius-thin flex-center gap-thin"
245
248
  }, {
246
249
  default: vue.withCtx(() => [
247
- vue.createVNode(IconLike.default, {
248
- class: "w-1-25r h-1-25r",
249
- fill: isFavorite.value
250
- }, null, 8, ["fill"])
250
+ vue.createVNode(IconAdd.default, { class: "i-medium" }),
251
+ _cache[8] || (_cache[8] = vue.createTextVNode(" Add to Queue "))
251
252
  ]),
252
253
  _: 1
253
- }, 8, ["color"]),
254
+ }),
254
255
  vue.createVNode(Button.default, {
255
- onClick: addToQueue,
256
- color: "transp",
256
+ onClick: toggleFavorite,
257
+ color: "primary",
257
258
  size: "medium",
258
- class: "w-3r h-3r radius-full"
259
+ class: "flex-1 bg-light radius-thin flex-center gap-thin"
259
260
  }, {
260
261
  default: vue.withCtx(() => [
261
- vue.createVNode(IconAdd.default, { class: "w-1-25r h-1-25r" })
262
+ vue.createVNode(IconLike.default, {
263
+ class: "i-medium",
264
+ fill: isFavorite.value
265
+ }, null, 8, ["fill"]),
266
+ vue.createTextVNode(" " + vue.toDisplayString(isFavorite.value ? "Liked" : "Like"), 1)
262
267
  ]),
263
268
  _: 1
264
269
  }),
265
270
  vue.createVNode(Dropdown.default, {
271
+ label: { component: IconEllipsis.default, class: "bg-light radius-thin pd-thin i-big" },
266
272
  modelValue: showDropdown.value,
267
273
  "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => showDropdown.value = $event),
268
274
  class: "relative"
@@ -287,7 +293,7 @@ const _sfc_main = {
287
293
  size: "small",
288
294
  class: "w-100 justify-start"
289
295
  }, {
290
- default: vue.withCtx(() => _cache[8] || (_cache[8] = [
296
+ default: vue.withCtx(() => _cache[9] || (_cache[9] = [
291
297
  vue.createTextVNode(" Add to Playlist ")
292
298
  ])),
293
299
  _: 1
@@ -298,20 +304,20 @@ const _sfc_main = {
298
304
  size: "small",
299
305
  class: "w-100 justify-start"
300
306
  }, {
301
- default: vue.withCtx(() => _cache[9] || (_cache[9] = [
307
+ default: vue.withCtx(() => _cache[10] || (_cache[10] = [
302
308
  vue.createTextVNode(" Copy Link ")
303
309
  ])),
304
310
  _: 1
305
311
  }),
306
312
  isOwner.value ? (vue.openBlock(), vue.createElementBlock(vue.Fragment, { key: 0 }, [
307
- _cache[12] || (_cache[12] = vue.createElementVNode("hr", { class: "mn-v-thin border-dark-transp-10" }, null, -1)),
313
+ _cache[13] || (_cache[13] = vue.createElementVNode("hr", { class: "mn-v-thin border-dark-transp-10" }, null, -1)),
308
314
  vue.createVNode(Button.default, {
309
315
  onClick: editTrack,
310
316
  color: "transp",
311
317
  size: "small",
312
318
  class: "w-100 justify-start"
313
319
  }, {
314
- default: vue.withCtx(() => _cache[10] || (_cache[10] = [
320
+ default: vue.withCtx(() => _cache[11] || (_cache[11] = [
315
321
  vue.createTextVNode(" Edit Track ")
316
322
  ])),
317
323
  _: 1
@@ -322,7 +328,7 @@ const _sfc_main = {
322
328
  size: "small",
323
329
  class: "w-100 justify-start"
324
330
  }, {
325
- default: vue.withCtx(() => _cache[11] || (_cache[11] = [
331
+ default: vue.withCtx(() => _cache[12] || (_cache[12] = [
326
332
  vue.createTextVNode(" Delete Track ")
327
333
  ])),
328
334
  _: 1
@@ -331,11 +337,11 @@ const _sfc_main = {
331
337
  ])
332
338
  ]),
333
339
  _: 1
334
- }, 8, ["modelValue"])
340
+ }, 8, ["label", "modelValue"])
335
341
  ]),
336
342
  vue.createElementVNode("div", _hoisted_18, [
337
343
  vue.createVNode(_component_router_link, {
338
- to: `/artist/${track.value.artist.url}`,
344
+ to: { name: "artist", params: { url: track.value.artist.url } },
339
345
  class: "flex items-center gap-medium flex-1 hover-opacity"
340
346
  }, {
341
347
  default: vue.withCtx(() => [
@@ -355,7 +361,7 @@ const _sfc_main = {
355
361
  class: "w-1r h-1r t-primary"
356
362
  })) : vue.createCommentVNode("", true)
357
363
  ]),
358
- _cache[13] || (_cache[13] = vue.createElementVNode("span", { class: "t-small t-transp" }, "Artist", -1))
364
+ _cache[14] || (_cache[14] = vue.createElementVNode("span", { class: "t-small t-transp" }, "Artist", -1))
359
365
  ])
360
366
  ]),
361
367
  _: 1
@@ -375,43 +381,43 @@ const _sfc_main = {
375
381
  vue.createElementVNode("div", _hoisted_23, [
376
382
  vue.createElementVNode("div", _hoisted_24, [
377
383
  vue.createElementVNode("div", _hoisted_25, [
378
- vue.createVNode(IconTime.default, { class: "w-1-5r h-1-5r t-primary" })
384
+ vue.createVNode(IconTime.default, { class: "i-regular t-primary" })
379
385
  ]),
380
386
  vue.createElementVNode("div", null, [
381
- _cache[14] || (_cache[14] = vue.createElementVNode("div", { class: "t-small t-transp t-uppercase" }, "Duration", -1)),
387
+ _cache[15] || (_cache[15] = vue.createElementVNode("div", { class: "t-small t-transp t-uppercase" }, "Duration", -1)),
382
388
  vue.createElementVNode("div", _hoisted_26, vue.toDisplayString(formatDuration(track.value.duration)), 1)
383
389
  ])
384
390
  ]),
385
391
  vue.createElementVNode("div", _hoisted_27, [
386
392
  vue.createElementVNode("div", _hoisted_28, [
387
- vue.createVNode(IconCalendar.default, { class: "w-1-5r h-1-5r t-primary" })
393
+ vue.createVNode(IconCalendar.default, { class: "i-regular t-primary" })
388
394
  ]),
389
395
  vue.createElementVNode("div", null, [
390
- _cache[15] || (_cache[15] = vue.createElementVNode("div", { class: "t-small t-transp t-uppercase" }, "Released", -1)),
396
+ _cache[16] || (_cache[16] = vue.createElementVNode("div", { class: "t-small t-transp t-uppercase" }, "Released", -1)),
391
397
  vue.createElementVNode("div", _hoisted_29, vue.toDisplayString(formatDate(track.value.releaseDate)), 1)
392
398
  ])
393
399
  ]),
394
400
  vue.createElementVNode("div", _hoisted_30, [
395
401
  vue.createElementVNode("div", _hoisted_31, [
396
- vue.createVNode(IconCheckmark.default, { class: "w-1-5r h-1-5r t-success" })
402
+ vue.createVNode(IconCheckmark.default, { class: "i-regular t-success" })
397
403
  ]),
398
404
  vue.createElementVNode("div", null, [
399
- _cache[16] || (_cache[16] = vue.createElementVNode("div", { class: "t-small t-transp t-uppercase" }, "Status", -1)),
405
+ _cache[17] || (_cache[17] = vue.createElementVNode("div", { class: "t-small t-transp t-uppercase" }, "Status", -1)),
400
406
  vue.createElementVNode("div", _hoisted_32, vue.toDisplayString(track.value.status), 1)
401
407
  ])
402
408
  ]),
403
409
  vue.createElementVNode("div", _hoisted_33, [
404
410
  vue.createElementVNode("div", _hoisted_34, [
405
- vue.createVNode(IconShow.default, { class: "w-1-5r h-1-5r t-primary" })
411
+ vue.createVNode(IconShow.default, { class: "i-regular t-primary" })
406
412
  ]),
407
413
  vue.createElementVNode("div", null, [
408
- _cache[17] || (_cache[17] = vue.createElementVNode("div", { class: "t-small t-transp t-uppercase" }, "Visibility", -1)),
414
+ _cache[18] || (_cache[18] = vue.createElementVNode("div", { class: "t-small t-transp t-uppercase" }, "Visibility", -1)),
409
415
  vue.createElementVNode("div", _hoisted_35, vue.toDisplayString(track.value.isPublic ? "Public" : "Private"), 1)
410
416
  ])
411
417
  ])
412
418
  ]),
413
419
  track.value.album ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_36, [
414
- _cache[18] || (_cache[18] = vue.createElementVNode("div", { class: "t-small t-transp t-uppercase mn-b-thin" }, "From Album", -1)),
420
+ _cache[19] || (_cache[19] = vue.createElementVNode("div", { class: "t-small t-transp t-uppercase mn-b-thin" }, "From Album", -1)),
415
421
  vue.createVNode(_component_router_link, {
416
422
  to: `/album/${track.value.album.url}`,
417
423
  class: "flex items-center gap-medium hover-opacity"
@@ -429,7 +435,7 @@ const _sfc_main = {
429
435
  }, 8, ["to"])
430
436
  ])) : vue.createCommentVNode("", true),
431
437
  track.value.genre && track.value.genre.length || track.value.tags && track.value.tags.length ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_38, [
432
- _cache[19] || (_cache[19] = vue.createElementVNode("h3", { class: "t-medium mn-b-small" }, "Genres & Tags", -1)),
438
+ _cache[20] || (_cache[20] = vue.createElementVNode("h3", { class: "t-medium mn-b-small" }, "Genres & Tags", -1)),
433
439
  vue.createElementVNode("div", _hoisted_39, [
434
440
  (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(track.value.genre, (genre) => {
435
441
  return vue.openBlock(), vue.createElementBlock("span", {
@@ -446,17 +452,17 @@ const _sfc_main = {
446
452
  ])
447
453
  ])) : vue.createCommentVNode("", true),
448
454
  track.value.description ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_40, [
449
- _cache[20] || (_cache[20] = vue.createElementVNode("h3", { class: "t-medium mn-b-small" }, "About", -1)),
455
+ _cache[21] || (_cache[21] = vue.createElementVNode("h3", { class: "t-medium mn-b-small" }, "About", -1)),
450
456
  vue.createElementVNode("p", _hoisted_41, vue.toDisplayString(track.value.description), 1)
451
457
  ])) : vue.createCommentVNode("", true),
452
458
  track.value.lyrics ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_42, [
453
- _cache[21] || (_cache[21] = vue.createElementVNode("h3", { class: "t-medium mn-b-small" }, "Lyrics", -1)),
459
+ _cache[22] || (_cache[22] = vue.createElementVNode("h3", { class: "t-medium mn-b-small" }, "Lyrics", -1)),
454
460
  vue.createElementVNode("pre", _hoisted_43, vue.toDisplayString(track.value.lyrics), 1)
455
461
  ])) : vue.createCommentVNode("", true)
456
462
  ])
457
463
  ])) : vue.createCommentVNode("", true),
458
464
  track.value && relatedTracks.value && relatedTracks.value.length ? (vue.openBlock(), vue.createElementBlock("section", _hoisted_44, [
459
- _cache[22] || (_cache[22] = vue.createElementVNode("h2", { class: "h2 mn-b-medium" }, "Related Tracks", -1)),
465
+ _cache[23] || (_cache[23] = vue.createElementVNode("h2", { class: "h2 mn-b-medium" }, "Related Tracks", -1)),
460
466
  vue.createVNode(Feed.default, {
461
467
  store: {
462
468
  read: () => new _ctx.Promise((resolve) => resolve(relatedTracks.value || [])),
@@ -492,9 +498,9 @@ const _sfc_main = {
492
498
  showAddToPlaylistModal.value ? (vue.openBlock(), vue.createBlock(Popup.default, {
493
499
  key: 4,
494
500
  onClosePopup: _cache[2] || (_cache[2] = ($event) => showAddToPlaylistModal.value = false),
495
- class: "bg-dark pd-medium w-m-25r radius-medium"
501
+ class: "bg-white pd-medium w-m-25r radius-medium"
496
502
  }, {
497
- default: vue.withCtx(() => _cache[23] || (_cache[23] = [
503
+ default: vue.withCtx(() => _cache[24] || (_cache[24] = [
498
504
  vue.createElementVNode("h3", { class: "h3 mn-b-medium" }, "Add to Playlist", -1),
499
505
  vue.createElementVNode("p", { class: "t-transp" }, "Playlist selector coming soon...", -1)
500
506
  ])),
@@ -1 +1 @@
1
- {"version":3,"file":"Track.vue.cjs","sources":["../../../../../../../src/modules/music/components/pages/Track.vue"],"sourcesContent":["<!-- components/pages/Track.vue -->\n<template>\n <div class=\"track-page pd-small\">\n <!-- Loading -->\n <div v-if=\"isLoading\" class=\"w-100 h-25r flex-center flex\">\n <Loader />\n </div>\n\n <!-- Not Found -->\n <div v-if=\"hasLoaded && !track\" class=\"t-center pd-big\">\n <h2 class=\"\">Track not found</h2>\n <p class=\"t-transp t-medium\">The track you're looking for doesn't exist or has been removed.</p>\n </div>\n\n <!-- Track Content -->\n <div v-if=\"track\" class=\"track-content cols-2-fit-content mobile:cols-1 gap-big\">\n <!-- Left Column - Cover & Stats -->\n <div class=\"pos-sticky pos-t-0 mobile:pos-relative track-cover-section\">\n <!-- Cover with Play Overlay -->\n <div class=\"cover-container relative mn-b-medium radius-big overflow-hidden shadow-big\">\n <Media \n :url=\"track.coverUrl || (track.album && track.album.coverUrl) || '/logo/logo-placeholder.jpg'\" \n :alt=\"track.title\"\n class=\"aspect-1x1 w-100 radius-medium o-hidden\"\n />\n <!-- <div class=\"cover-overlay absolute inset-0 bg-black-transp-40 flex-center opacity-0 hover-opacity-100 transition\">\n <Button\n @click=\"playTrack\"\n color=\"white\"\n size=\"big\"\n class=\"w-5r h-5r radius-full shadow-big hover-scale-110\"\n >\n <IconPlay class=\"w-2r h-2r\" />\n </Button>\n </div> -->\n </div>\n\n \n\n <!-- Quick Stats -->\n <div class=\"stats-grid grid cols-2 gap-small\">\n <div class=\"stat-card bg-light pd-medium radius-medium t-center\">\n <div class=\" mn-b-thin\">{{ formatNumber(track.playCount) }}</div>\n <div class=\"t-small t-transp t-uppercase\">Plays</div>\n </div>\n <div class=\"stat-card bg-light pd-medium radius-medium t-center\">\n <div class=\" mn-b-thin\">{{ formatNumber(track.views) }}</div>\n <div class=\"t-small t-transp t-uppercase\">Views</div>\n </div>\n </div>\n </div>\n\n <!-- Right Column - Track Details -->\n <div class=\"track-details-section\">\n <!-- Track Type Badge -->\n <div class=\"flex items-center gap-small mn-b-small\">\n <span class=\"badge bg-primary-transp-20 t-primary pd-thin-big radius-small t-small t-uppercase\">Single</span>\n <span v-if=\"track.isExplicit\" class=\"badge bg-danger-transp-20 t-danger pd-thin-big radius-small t-small\">Explicit</span>\n </div>\n\n <!-- Track Title -->\n <h1 class=\"h1 mn-b-medium\">{{ track.title }}</h1>\n <!-- Action Buttons -->\n <div class=\"flex gap-small mn-b-medium\">\n <Button\n @click=\"playTrack\"\n color=\"primary\"\n size=\"medium\"\n class=\"flex-1 flex-center gap-thin\"\n >\n <IconPlay class=\"w-1r h-1r\" />\n Play\n </Button>\n \n <Button\n @click=\"toggleFavorite\"\n :color=\"isFavorite ? 'danger' : 'transp'\"\n size=\"medium\"\n class=\"w-3r h-3r radius-full\"\n >\n <IconLike class=\"w-1-25r h-1-25r\" :fill=\"isFavorite\" />\n </Button>\n \n <Button\n @click=\"addToQueue\"\n color=\"transp\"\n size=\"medium\"\n class=\"w-3r h-3r radius-full\"\n >\n <IconAdd class=\"w-1-25r h-1-25r\" />\n </Button>\n \n <Dropdown v-model=\"showDropdown\" class=\"relative\">\n <template #trigger>\n <Button color=\"transp\" size=\"medium\" class=\"w-3r h-3r radius-full\">\n <IconEllipsis class=\"w-1-25r h-1-25r\" />\n </Button>\n </template>\n <template #default>\n <div class=\"dropdown-menu bg-dark pd-small radius-medium shadow-big mn-t-thin\">\n <Button @click=\"showAddToPlaylistModal = true\" color=\"transp\" size=\"small\" class=\"w-100 justify-start\">\n Add to Playlist\n </Button>\n <Button @click=\"copyLink\" color=\"transp\" size=\"small\" class=\"w-100 justify-start\">\n Copy Link\n </Button>\n <template v-if=\"isOwner\">\n <hr class=\"mn-v-thin border-dark-transp-10\" />\n <Button @click=\"editTrack\" color=\"transp\" size=\"small\" class=\"w-100 justify-start\">\n Edit Track\n </Button>\n <Button @click=\"deleteTrack\" color=\"danger\" size=\"small\" class=\"w-100 justify-start\">\n Delete Track\n </Button>\n </template>\n </div>\n </template>\n </Dropdown>\n </div>\n\n <!-- Artist Card -->\n <div class=\"artist-card bg-light pd-medium radius-medium flex items-center gap-medium mn-b-big\">\n <router-link \n :to=\"`/artist/${track.artist.url}`\"\n class=\"flex items-center gap-medium flex-1 hover-opacity\"\n >\n <div class=\"artist-avatar\">\n <Media \n v-if=\"track.artist.photoUrl\"\n :src=\"track.artist.photoUrl\"\n :alt=\"track.artist.name\"\n class=\"w-4r h-4r radius-full object-cover\"\n />\n <div v-else class=\"w-4r h-4r radius-full bg-primary flex-center \">\n {{ track.artist.name.charAt(0) }}\n </div>\n </div>\n <div>\n <div class=\"flex items-center gap-thin\">\n <span class=\"t-large \">{{ track.artist.name }}</span>\n <IconVerified v-if=\"track.artist.isVerified\" class=\"w-1r h-1r t-primary\" />\n </div>\n <span class=\"t-small t-transp\">Artist</span>\n </div>\n </router-link>\n <Button \n v-if=\"!isOwner\"\n @click=\"toggleFollowArtist\"\n :color=\"isFollowingArtist ? 'primary' : 'transp'\"\n size=\"small\"\n >\n {{ isFollowingArtist ? 'Following' : 'Follow' }}\n </Button>\n </div>\n\n\n\n <!-- Metadata Cards -->\n <div class=\"metadata-grid grid cols-2 gap-small mn-b-big\">\n <!-- Duration -->\n <div class=\"metadata-card bg-light pd-medium radius-medium flex items-center gap-medium\">\n <div class=\"icon-wrapper bg-primary-transp-20 w-3r h-3r radius-small flex-center\">\n <IconClock class=\"w-1-5r h-1-5r t-primary\" />\n </div>\n <div>\n <div class=\"t-small t-transp t-uppercase\">Duration</div>\n <div class=\"t-medium \">{{ formatDuration(track.duration) }}</div>\n </div>\n </div>\n\n <!-- Release Date -->\n <div class=\"metadata-card bg-light pd-medium radius-medium flex items-center gap-medium\">\n <div class=\"icon-wrapper bg-primary-transp-20 w-3r h-3r radius-small flex-center\">\n <IconCalendar class=\"w-1-5r h-1-5r t-primary\" />\n </div>\n <div>\n <div class=\"t-small t-transp t-uppercase\">Released</div>\n <div class=\"t-medium \">{{ formatDate(track.releaseDate) }}</div>\n </div>\n </div>\n\n <!-- Status -->\n <div class=\"metadata-card bg-light pd-medium radius-medium flex items-center gap-medium\">\n <div class=\"icon-wrapper bg-success-transp-20 w-3r h-3r radius-small flex-center\">\n <IconCheck class=\"w-1-5r h-1-5r t-success\" />\n </div>\n <div>\n <div class=\"t-small t-transp t-uppercase\">Status</div>\n <div class=\"t-medium t-success\">{{ track.status }}</div>\n </div>\n </div>\n\n <!-- Visibility -->\n <div class=\"metadata-card bg-light pd-medium radius-medium flex items-center gap-medium\">\n <div class=\"icon-wrapper bg-primary-transp-20 w-3r h-3r radius-small flex-center\">\n <IconEye class=\"w-1-5r h-1-5r t-primary\" />\n </div>\n <div>\n <div class=\"t-small t-transp t-uppercase\">Visibility</div>\n <div class=\"t-medium \">{{ track.isPublic ? 'Public' : 'Private' }}</div>\n </div>\n </div>\n </div>\n\n <!-- Album Info -->\n <div v-if=\"track.album\" class=\"album-card bg-light pd-medium radius-medium mn-b-medium\">\n <div class=\"t-small t-transp t-uppercase mn-b-thin\">From Album</div>\n <router-link \n :to=\"`/album/${track.album.url}`\"\n class=\"flex items-center gap-medium hover-opacity\"\n >\n <Media \n v-if=\"track.album.coverUrl\"\n :src=\"track.album.coverUrl\"\n :alt=\"track.album.title\"\n class=\"w-3r h-3r radius-small object-cover\"\n />\n <span class=\"t-medium \">{{ track.album.title }}</span>\n </router-link>\n </div>\n\n <!-- Genres & Tags -->\n <div v-if=\"(track.genre && track.genre.length) || (track.tags && track.tags.length)\" class=\"tags-section mn-b-medium\">\n <h3 class=\"t-medium mn-b-small\">Genres & Tags</h3>\n <div class=\"flex gap-thin flex-wrap\">\n <span \n v-for=\"genre in track.genre\" \n :key=\"genre\"\n class=\"tag bg-primary-transp-20 t-primary pd-thin-big radius-small t-small hover-bg-primary-transp-30 cursor-pointer\"\n >\n {{ genre }}\n </span>\n <span \n v-for=\"tag in track.tags\" \n :key=\"tag\"\n class=\"tag bg-light t-transp pd-thin-big radius-small t-small hover-bg-light cursor-pointer\"\n >\n #{{ tag }}\n </span>\n </div>\n </div>\n\n <!-- Description -->\n <div v-if=\"track.description\" class=\"description-section bg-light pd-medium radius-medium mn-b-medium\">\n <h3 class=\"t-medium mn-b-small\">About</h3>\n <p class=\"t-transp\">{{ track.description }}</p>\n </div>\n\n <!-- Lyrics -->\n <div v-if=\"track.lyrics\" class=\"lyrics-section bg-light pd-medium radius-medium\">\n <h3 class=\"t-medium mn-b-small\">Lyrics</h3>\n <pre class=\"t-transp t-small\">{{ track.lyrics }}</pre>\n </div>\n </div>\n </div>\n\n <!-- Related Tracks -->\n <section v-if=\"track && relatedTracks && relatedTracks.length\" class=\"related-section mn-t-big\">\n <h2 class=\"h2 mn-b-medium\">Related Tracks</h2>\n <Feed\n :store=\"{\n read: () => new Promise(resolve => resolve(relatedTracks || [])),\n state: { isLoading: false }\n }\"\n :external=\"true\"\n :items=\"relatedTracks\"\n :states=\"{\n empty: {\n title: 'No related tracks',\n description: 'Check back later for recommendations',\n class: 'pd-medium bg-light radius-medium'\n }\n }\"\n class=\"grid cols-2 cols-m-3 cols-l-4 gap-medium\"\n >\n <template #default=\"{ items }\">\n <div class=\"bg-light radius-medium o-hidden\">\n <TrackListCard\n v-for=\"(relatedTrack, index) in items\"\n :key=\"relatedTrack._id\"\n :track=\"relatedTrack\"\n :index=\"index\"\n :showAlbum=\"true\"\n :showCover=\"true\"\n />\n </div>\n </template>\n </Feed>\n </section>\n\n <!-- Add to Playlist Modal -->\n <Popup \n v-if=\"showAddToPlaylistModal\" \n @close-popup=\"showAddToPlaylistModal = false\" \n class=\"bg-dark pd-medium w-m-25r radius-medium\"\n >\n <h3 class=\"h3 mn-b-medium\">Add to Playlist</h3>\n <!-- <PlaylistSelector \n :trackId=\"track._id\" \n @added=\"showAddToPlaylistModal = false\"\n /> -->\n <p class=\"t-transp\">Playlist selector coming soon...</p>\n </Popup>\n </div>\n</template>\n\n<script setup>\nimport { ref, computed, onMounted, watch } from 'vue';\nimport { useRoute, useRouter } from 'vue-router';\nimport Button from '@martyrs/src/components/Button/Button.vue';\nimport Loader from '@martyrs/src/components/Loader/Loader.vue';\nimport Media from '@martyrs/src/components/Media/Media.vue';\nimport Dropdown from '@martyrs/src/components/Dropdown/Dropdown.vue';\nimport Popup from '@martyrs/src/components/Popup/Popup.vue';\nimport Feed from '@martyrs/src/components/Feed/Feed.vue';\n\n// Icons\nimport IconPlay from '@martyrs/src/modules/icons/navigation/IconPlay.vue';\nimport IconLike from '@martyrs/src/modules/icons/navigation/IconLike.vue';\nimport IconEllipsis from '@martyrs/src/modules/icons/navigation/IconEllipsis.vue';\nimport IconAdd from '@martyrs/src/modules/icons/navigation/IconAdd.vue';\nimport IconClock from '@martyrs/src/modules/icons/entities/IconTime.vue';\nimport IconCalendar from '@martyrs/src/modules/icons/entities/IconCalendar.vue';\nimport IconCheck from '@martyrs/src/modules/icons/navigation/IconCheckmark.vue';\nimport IconEye from '@martyrs/src/modules/icons/actions/IconShow.vue';\nimport IconVerified from '@martyrs/src/modules/icons/navigation/IconCheckmark.vue';\n\n// Components\nimport TrackListCard from '../cards/TrackListCard.vue';\n// import PlaylistSelector from '../forms/PlaylistSelector.vue';\n\n// Store\nimport { state as tracksState, actions as tracksActions } from '../../store/tracks.js';\nimport { actions as playerActions } from '../../store/player.js';\nimport { state as authState } from '@martyrs/src/modules/auth/views/store/auth.js';\n\nconst route = useRoute();\nconst router = useRouter();\n\n// Emits\nconst emits = defineEmits(['page-loading', 'page-loaded']);\n\n// State\nconst hasLoaded = ref(false);\nconst showDropdown = ref(false);\nconst showAddToPlaylistModal = ref(false);\nconst isFavorite = ref(false);\nconst isFollowingArtist = ref(false);\n\n// Clear state\ntracksState.currentTrack = null;\ntracksState.relatedTracks = [];\n\n// Computed\nconst track = computed(() => tracksState.currentTrack);\nconst relatedTracks = computed(() => tracksState.relatedTracks || []);\n\nconst isOwner = computed(() => {\n return track.value?.owner?.target === authState.user?._id;\n});\n\n// Format helpers\nconst formatDuration = (seconds) => {\n if (!seconds) return '0:00';\n const h = Math.floor(seconds / 3600);\n const m = Math.floor((seconds % 3600) / 60);\n const s = Math.floor(seconds % 60);\n \n if (h > 0) {\n return `${h}:${m.toString().padStart(2, '0')}:${s.toString().padStart(2, '0')}`;\n }\n return `${m}:${s.toString().padStart(2, '0')}`;\n};\n\nconst formatDate = (dateString) => {\n if (!dateString) return 'Unknown';\n return new Date(dateString).toLocaleDateString('en-US', {\n year: 'numeric',\n month: 'long',\n day: 'numeric'\n });\n};\n\nconst formatNumber = (num) => {\n if (!num) return '0';\n if (num >= 1000000) {\n return (num / 1000000).toFixed(1) + 'M';\n } else if (num >= 1000) {\n return (num / 1000).toFixed(1) + 'K';\n }\n return num.toString();\n};\n\n// Actions\nconst playTrack = () => {\n if (track.value) {\n playerActions.setQueue([track.value]);\n }\n};\n\nconst toggleFavorite = () => {\n isFavorite.value = !isFavorite.value;\n // TODO: Implement actual saving\n};\n\nconst toggleFollowArtist = () => {\n isFollowingArtist.value = !isFollowingArtist.value;\n // TODO: Implement actual following\n};\n\nconst addToQueue = () => {\n if (track.value) {\n playerActions.addToQueue(track.value);\n }\n};\n\nconst editTrack = () => {\n router.push({ name: 'track-edit', params: { url: track.value.url } });\n};\n\nconst deleteTrack = async () => {\n if (confirm('Are you sure you want to delete this track?')) {\n try {\n await tracksActions.deleteTrack(track.value._id);\n router.push({ name: 'music-library' });\n } catch (error) {\n console.error('Failed to delete track:', error);\n }\n }\n};\n\nconst copyLink = () => {\n navigator.clipboard.writeText(window.location.href);\n showDropdown.value = false;\n};\n\n// Data fetching\nconst fetchTrackData = async () => {\n try {\n await tracksActions.fetchTrackByUrl(route.params.url);\n await tracksActions.fetchRelatedTracks(route.params.url);\n } catch (error) {\n console.error('Error loading track:', error);\n }\n};\n\n// Lifecycle\nonMounted(async () => {\n emits('page-loading');\n \n await fetchTrackData();\n \n hasLoaded.value = true;\n emits('page-loaded');\n});\n</script>\n\n<style scoped>\n</style>"],"names":["useRoute","useRouter","ref","tracksState","computed","authState","playerActions","tracksActions","onMounted"],"mappings":"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"}
1
+ {"version":3,"file":"Track.vue.cjs","sources":["../../../../../../../src/modules/music/components/pages/Track.vue"],"sourcesContent":["<!-- components/pages/Track.vue -->\n<template>\n <div class=\"track-page pd-small\">\n <!-- Loading -->\n <div v-if=\"isLoading\" class=\"w-100 h-25r flex-center flex\">\n <Loader />\n </div>\n\n <!-- Not Found -->\n <div v-if=\"hasLoaded && !track\" class=\"t-center pd-big\">\n <h2 class=\"\">Track not found</h2>\n <p class=\"t-transp t-medium\">The track you're looking for doesn't exist or has been removed.</p>\n </div>\n\n <!-- Track Content -->\n <div v-if=\"track\" class=\"track-content cols-2-fit-content mobile:cols-1 gap-big\">\n <!-- Left Column - Cover & Stats -->\n <div class=\"pos-sticky pos-t-0 mobile:pos-relative track-cover-section\">\n <!-- Cover with Play Overlay -->\n <div class=\"cover-container relative mn-b-medium radius-big overflow-hidden shadow-big\">\n <Media \n :url=\"track.coverUrl || (track.album && track.album.coverUrl) || '/logo/logo-placeholder.jpg'\" \n :alt=\"track.title\"\n class=\"aspect-1x1 w-100 radius-medium o-hidden\"\n />\n <!-- <div class=\"cover-overlay absolute inset-0 bg-black-transp-40 flex-center opacity-0 hover-opacity-100 transition\">\n <Button\n @click=\"playTrack\"\n color=\"white\"\n size=\"big\"\n class=\"w-5r h-5r radius-full shadow-big hover-scale-110\"\n >\n <IconPlay class=\"w-2r h-2r\" />\n </Button>\n </div> -->\n </div>\n\n \n\n <!-- Quick Stats -->\n <div class=\"stats-grid grid cols-2 gap-small\">\n <div class=\"stat-card bg-light pd-medium radius-medium t-center\">\n <div class=\" mn-b-thin\">{{ formatNumber(track.playCount) }}</div>\n <div class=\"t-small t-transp t-uppercase\">Plays</div>\n </div>\n <div class=\"stat-card bg-light pd-medium radius-medium t-center\">\n <div class=\" mn-b-thin\">{{ formatNumber(track.views) }}</div>\n <div class=\"t-small t-transp t-uppercase\">Views</div>\n </div>\n </div>\n </div>\n\n <!-- Right Column - Track Details -->\n <div class=\"track-details-section\">\n <!-- Track Type Badge -->\n <div class=\"flex items-center gap-small mn-b-small\">\n <span class=\"badge bg-primary-transp-20 t-primary pd-thin-big radius-small t-small t-uppercase\">Single</span>\n <span v-if=\"track.isExplicit\" class=\"badge bg-danger-transp-20 t-danger pd-thin-big radius-small t-small\">Explicit</span>\n </div>\n\n <!-- Track Title -->\n <h1 class=\"h1 mn-b-medium\">{{ track.title }}</h1>\n <!-- Action Buttons -->\n <div class=\"flex gap-small mn-b-medium\">\n <Button\n @click=\"playTrack\"\n color=\"primary\"\n size=\"medium\"\n class=\"flex-1 t-white bg-black radius-thin flex-center gap-thin\"\n >\n <IconPlay fill=\"rgb(var(--white))\" class=\"i-medium\" />\n Play\n </Button>\n\n <Button\n @click=\"addToQueue\"\n color=\"primary\"\n size=\"medium\"\n class=\"flex-1 bg-light radius-thin flex-center gap-thin\"\n >\n <IconAdd class=\"i-medium\" />\n Add to Queue\n </Button>\n\n <Button\n @click=\"toggleFavorite\"\n color=\"primary\"\n size=\"medium\"\n class=\"flex-1 bg-light radius-thin flex-center gap-thin\"\n >\n <IconLike class=\"i-medium\" :fill=\"isFavorite\" />\n {{isFavorite ? 'Liked' : 'Like'}}\n </Button>\n\n <Dropdown :label=\"{component: IconEllipsis, class: 'bg-light radius-thin pd-thin i-big' }\" v-model=\"showDropdown\" class=\"relative\">\n <template #trigger>\n <Button color=\"transp\" size=\"medium\" class=\"w-3r h-3r radius-full\">\n <IconEllipsis class=\"w-1-25r h-1-25r\" />\n </Button>\n </template>\n <template #default>\n <div class=\"dropdown-menu bg-dark pd-small radius-medium shadow-big mn-t-thin\">\n <Button @click=\"showAddToPlaylistModal = true\" color=\"transp\" size=\"small\" class=\"w-100 justify-start\">\n Add to Playlist\n </Button>\n <Button @click=\"copyLink\" color=\"transp\" size=\"small\" class=\"w-100 justify-start\">\n Copy Link\n </Button>\n <template v-if=\"isOwner\">\n <hr class=\"mn-v-thin border-dark-transp-10\" />\n <Button @click=\"editTrack\" color=\"transp\" size=\"small\" class=\"w-100 justify-start\">\n Edit Track\n </Button>\n <Button @click=\"deleteTrack\" color=\"danger\" size=\"small\" class=\"w-100 justify-start\">\n Delete Track\n </Button>\n </template>\n </div>\n </template>\n </Dropdown>\n </div>\n\n <!-- Artist Card -->\n <div class=\"artist-card bg-light pd-medium radius-medium flex items-center gap-medium mn-b-big\">\n <router-link \n :to=\"{ name: 'artist', params: { url: track.artist.url } }\"\n class=\"flex items-center gap-medium flex-1 hover-opacity\"\n >\n <div class=\"artist-avatar\">\n <Media \n v-if=\"track.artist.photoUrl\"\n :src=\"track.artist.photoUrl\"\n :alt=\"track.artist.name\"\n class=\"w-4r h-4r radius-full object-cover\"\n />\n <div v-else class=\"w-4r h-4r radius-full bg-primary flex-center \">\n {{ track.artist.name.charAt(0) }}\n </div>\n </div>\n <div>\n <div class=\"flex items-center gap-thin\">\n <span class=\"t-large \">{{ track.artist.name }}</span>\n <IconVerified v-if=\"track.artist.isVerified\" class=\"w-1r h-1r t-primary\" />\n </div>\n <span class=\"t-small t-transp\">Artist</span>\n </div>\n </router-link>\n <Button \n v-if=\"!isOwner\"\n @click=\"toggleFollowArtist\"\n :color=\"isFollowingArtist ? 'primary' : 'transp'\"\n size=\"small\"\n >\n {{ isFollowingArtist ? 'Following' : 'Follow' }}\n </Button>\n </div>\n\n\n\n <!-- Metadata Cards -->\n <div class=\"metadata-grid grid cols-2 gap-small mn-b-big\">\n <!-- Duration -->\n <div class=\"metadata-card bg-light pd-medium radius-medium flex items-center gap-medium\">\n <div class=\"icon-wrapper bg-primary-transp-20 w-3r h-3r radius-small flex-center\">\n <IconClock class=\"i-regular t-primary\" />\n </div>\n <div>\n <div class=\"t-small t-transp t-uppercase\">Duration</div>\n <div class=\"t-medium \">{{ formatDuration(track.duration) }}</div>\n </div>\n </div>\n\n <!-- Release Date -->\n <div class=\"metadata-card bg-light pd-medium radius-medium flex items-center gap-medium\">\n <div class=\"icon-wrapper bg-primary-transp-20 w-3r h-3r radius-small flex-center\">\n <IconCalendar class=\"i-regular t-primary\" />\n </div>\n <div>\n <div class=\"t-small t-transp t-uppercase\">Released</div>\n <div class=\"t-medium \">{{ formatDate(track.releaseDate) }}</div>\n </div>\n </div>\n\n <!-- Status -->\n <div class=\"metadata-card bg-light pd-medium radius-medium flex items-center gap-medium\">\n <div class=\"icon-wrapper bg-success-transp-20 w-3r h-3r radius-small flex-center\">\n <IconCheck class=\"i-regular t-success\" />\n </div>\n <div>\n <div class=\"t-small t-transp t-uppercase\">Status</div>\n <div class=\"t-medium t-success\">{{ track.status }}</div>\n </div>\n </div>\n\n <!-- Visibility -->\n <div class=\"metadata-card bg-light pd-medium radius-medium flex items-center gap-medium\">\n <div class=\"icon-wrapper bg-primary-transp-20 w-3r h-3r radius-small flex-center\">\n <IconEye class=\"i-regular t-primary\" />\n </div>\n <div>\n <div class=\"t-small t-transp t-uppercase\">Visibility</div>\n <div class=\"t-medium \">{{ track.isPublic ? 'Public' : 'Private' }}</div>\n </div>\n </div>\n </div>\n\n <!-- Album Info -->\n <div v-if=\"track.album\" class=\"album-card bg-light pd-medium radius-medium mn-b-medium\">\n <div class=\"t-small t-transp t-uppercase mn-b-thin\">From Album</div>\n <router-link \n :to=\"`/album/${track.album.url}`\"\n class=\"flex items-center gap-medium hover-opacity\"\n >\n <Media \n v-if=\"track.album.coverUrl\"\n :src=\"track.album.coverUrl\"\n :alt=\"track.album.title\"\n class=\"w-3r h-3r radius-small object-cover\"\n />\n <span class=\"t-medium \">{{ track.album.title }}</span>\n </router-link>\n </div>\n\n <!-- Genres & Tags -->\n <div v-if=\"(track.genre && track.genre.length) || (track.tags && track.tags.length)\" class=\"tags-section mn-b-medium\">\n <h3 class=\"t-medium mn-b-small\">Genres & Tags</h3>\n <div class=\"flex gap-thin flex-wrap\">\n <span \n v-for=\"genre in track.genre\" \n :key=\"genre\"\n class=\"tag bg-primary-transp-20 t-primary pd-thin-big radius-small t-small hover-bg-primary-transp-30 cursor-pointer\"\n >\n {{ genre }}\n </span>\n <span \n v-for=\"tag in track.tags\" \n :key=\"tag\"\n class=\"tag bg-light t-transp pd-thin-big radius-small t-small hover-bg-light cursor-pointer\"\n >\n #{{ tag }}\n </span>\n </div>\n </div>\n\n <!-- Description -->\n <div v-if=\"track.description\" class=\"description-section bg-light pd-medium radius-medium mn-b-medium\">\n <h3 class=\"t-medium mn-b-small\">About</h3>\n <p class=\"t-transp\">{{ track.description }}</p>\n </div>\n\n <!-- Lyrics -->\n <div v-if=\"track.lyrics\" class=\"lyrics-section bg-light pd-medium radius-medium\">\n <h3 class=\"t-medium mn-b-small\">Lyrics</h3>\n <pre class=\"t-transp t-small\">{{ track.lyrics }}</pre>\n </div>\n </div>\n </div>\n\n <!-- Related Tracks -->\n <section v-if=\"track && relatedTracks && relatedTracks.length\" class=\"related-section mn-t-big\">\n <h2 class=\"h2 mn-b-medium\">Related Tracks</h2>\n <Feed\n :store=\"{\n read: () => new Promise(resolve => resolve(relatedTracks || [])),\n state: { isLoading: false }\n }\"\n :external=\"true\"\n :items=\"relatedTracks\"\n :states=\"{\n empty: {\n title: 'No related tracks',\n description: 'Check back later for recommendations',\n class: 'pd-medium bg-light radius-medium'\n }\n }\"\n class=\"grid cols-2 cols-m-3 cols-l-4 gap-medium\"\n >\n <template #default=\"{ items }\">\n <div class=\"bg-light radius-medium o-hidden\">\n <TrackListCard\n v-for=\"(relatedTrack, index) in items\"\n :key=\"relatedTrack._id\"\n :track=\"relatedTrack\"\n :index=\"index\"\n :showAlbum=\"true\"\n :showCover=\"true\"\n />\n </div>\n </template>\n </Feed>\n </section>\n\n <!-- Add to Playlist Modal -->\n <Popup \n v-if=\"showAddToPlaylistModal\" \n @close-popup=\"showAddToPlaylistModal = false\" \n class=\"bg-white pd-medium w-m-25r radius-medium\"\n >\n <h3 class=\"h3 mn-b-medium\">Add to Playlist</h3>\n <!-- <PlaylistSelector \n :trackId=\"track._id\" \n @added=\"showAddToPlaylistModal = false\"\n /> -->\n <p class=\"t-transp\">Playlist selector coming soon...</p>\n </Popup>\n </div>\n</template>\n\n<script setup>\nimport { ref, computed, onMounted, watch } from 'vue';\nimport { useRoute, useRouter } from 'vue-router';\nimport Button from '@martyrs/src/components/Button/Button.vue';\nimport Loader from '@martyrs/src/components/Loader/Loader.vue';\nimport Media from '@martyrs/src/components/Media/Media.vue';\nimport Dropdown from '@martyrs/src/components/Dropdown/Dropdown.vue';\nimport Popup from '@martyrs/src/components/Popup/Popup.vue';\nimport Feed from '@martyrs/src/components/Feed/Feed.vue';\n\n// Icons\nimport IconPlay from '@martyrs/src/modules/icons/navigation/IconPlay.vue';\nimport IconLike from '@martyrs/src/modules/icons/navigation/IconLike.vue';\nimport IconEllipsis from '@martyrs/src/modules/icons/navigation/IconEllipsis.vue';\nimport IconAdd from '@martyrs/src/modules/icons/navigation/IconAdd.vue';\nimport IconClock from '@martyrs/src/modules/icons/entities/IconTime.vue';\nimport IconCalendar from '@martyrs/src/modules/icons/entities/IconCalendar.vue';\nimport IconCheck from '@martyrs/src/modules/icons/navigation/IconCheckmark.vue';\nimport IconEye from '@martyrs/src/modules/icons/actions/IconShow.vue';\nimport IconVerified from '@martyrs/src/modules/icons/navigation/IconCheckmark.vue';\n\n// Components\nimport TrackListCard from '../cards/TrackListCard.vue';\n// import PlaylistSelector from '../forms/PlaylistSelector.vue';\n\n// Store\nimport { state as tracksState, actions as tracksActions } from '../../store/tracks.js';\nimport { actions as playerActions } from '../../store/player.js';\nimport { state as authState } from '@martyrs/src/modules/auth/views/store/auth.js';\n\nconst route = useRoute();\nconst router = useRouter();\n\n// Emits\nconst emits = defineEmits(['page-loading', 'page-loaded']);\n\n// State\nconst hasLoaded = ref(false);\nconst showDropdown = ref(false);\nconst showAddToPlaylistModal = ref(false);\nconst isFavorite = ref(false);\nconst isFollowingArtist = ref(false);\n\n// Clear state\ntracksState.currentTrack = null;\ntracksState.relatedTracks = [];\n\n// Computed\nconst track = computed(() => tracksState.currentTrack);\nconst relatedTracks = computed(() => tracksState.relatedTracks || []);\n\nconst isOwner = computed(() => {\n return track.value?.owner?.target === authState.user?._id;\n});\n\n// Format helpers\nconst formatDuration = (seconds) => {\n if (!seconds) return '0:00';\n const h = Math.floor(seconds / 3600);\n const m = Math.floor((seconds % 3600) / 60);\n const s = Math.floor(seconds % 60);\n \n if (h > 0) {\n return `${h}:${m.toString().padStart(2, '0')}:${s.toString().padStart(2, '0')}`;\n }\n return `${m}:${s.toString().padStart(2, '0')}`;\n};\n\nconst formatDate = (dateString) => {\n if (!dateString) return 'Unknown';\n return new Date(dateString).toLocaleDateString('en-US', {\n year: 'numeric',\n month: 'long',\n day: 'numeric'\n });\n};\n\nconst formatNumber = (num) => {\n if (!num) return '0';\n if (num >= 1000000) {\n return (num / 1000000).toFixed(1) + 'M';\n } else if (num >= 1000) {\n return (num / 1000).toFixed(1) + 'K';\n }\n return num.toString();\n};\n\n// Actions\nconst playTrack = () => {\n if (track.value) {\n playerActions.setQueue([track.value]);\n }\n};\n\nconst toggleFavorite = () => {\n isFavorite.value = !isFavorite.value;\n // TODO: Implement actual saving\n};\n\nconst toggleFollowArtist = () => {\n isFollowingArtist.value = !isFollowingArtist.value;\n // TODO: Implement actual following\n};\n\nconst addToQueue = () => {\n if (track.value) {\n playerActions.addToQueue(track.value);\n }\n};\n\nconst editTrack = () => {\n router.push({ name: 'track-edit', params: { url: track.value.url } });\n};\n\nconst deleteTrack = async () => {\n if (confirm('Are you sure you want to delete this track?')) {\n try {\n await tracksActions.deleteTrack(track.value._id);\n router.push({ name: 'music-library' });\n } catch (error) {\n console.error('Failed to delete track:', error);\n }\n }\n};\n\nconst copyLink = () => {\n navigator.clipboard.writeText(window.location.href);\n showDropdown.value = false;\n};\n\n// Data fetching\nconst fetchTrackData = async () => {\n try {\n await tracksActions.fetchTrackByUrl(route.params.url);\n await tracksActions.fetchRelatedTracks(route.params.url);\n } catch (error) {\n console.error('Error loading track:', error);\n }\n};\n\n// Lifecycle\nonMounted(async () => {\n emits('page-loading');\n \n await fetchTrackData();\n \n hasLoaded.value = true;\n emits('page-loaded');\n});\n</script>\n\n<style scoped>\n</style>"],"names":["useRoute","useRouter","ref","tracksState","computed","authState","playerActions","tracksActions","onMounted"],"mappings":"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"}
@@ -7,9 +7,9 @@ import _sfc_main$5 from "../../../../components/Dropdown/Dropdown.vue.js";
7
7
  import _sfc_main$c from "../../../../components/Popup/Popup.vue.js";
8
8
  import _sfc_main$a from "../../../../components/Feed/Feed.vue.js";
9
9
  import _sfc_main$2 from "../../../icons/navigation/IconPlay.vue.js";
10
- import _sfc_main$3 from "../../../icons/navigation/IconLike.vue.js";
10
+ import _sfc_main$4 from "../../../icons/navigation/IconLike.vue.js";
11
11
  import _sfc_main$6 from "../../../icons/navigation/IconEllipsis.vue.js";
12
- import _sfc_main$4 from "../../../icons/navigation/IconAdd.vue.js";
12
+ import _sfc_main$3 from "../../../icons/navigation/IconAdd.vue.js";
13
13
  import IconClock from "../../../icons/entities/IconTime.vue.js";
14
14
  import _sfc_main$8 from "../../../icons/entities/IconCalendar.vue.js";
15
15
  import _sfc_main$7 from "../../../icons/navigation/IconCheckmark.vue.js";
@@ -227,40 +227,46 @@ const _sfc_main = {
227
227
  onClick: playTrack,
228
228
  color: "primary",
229
229
  size: "medium",
230
- class: "flex-1 flex-center gap-thin"
230
+ class: "flex-1 t-white bg-black radius-thin flex-center gap-thin"
231
231
  }, {
232
232
  default: withCtx(() => [
233
- createVNode(_sfc_main$2, { class: "w-1r h-1r" }),
233
+ createVNode(_sfc_main$2, {
234
+ fill: "rgb(var(--white))",
235
+ class: "i-medium"
236
+ }),
234
237
  _cache[7] || (_cache[7] = createTextVNode(" Play "))
235
238
  ]),
236
239
  _: 1
237
240
  }),
238
241
  createVNode(_sfc_main$1, {
239
- onClick: toggleFavorite,
240
- color: isFavorite.value ? "danger" : "transp",
242
+ onClick: addToQueue,
243
+ color: "primary",
241
244
  size: "medium",
242
- class: "w-3r h-3r radius-full"
245
+ class: "flex-1 bg-light radius-thin flex-center gap-thin"
243
246
  }, {
244
247
  default: withCtx(() => [
245
- createVNode(_sfc_main$3, {
246
- class: "w-1-25r h-1-25r",
247
- fill: isFavorite.value
248
- }, null, 8, ["fill"])
248
+ createVNode(_sfc_main$3, { class: "i-medium" }),
249
+ _cache[8] || (_cache[8] = createTextVNode(" Add to Queue "))
249
250
  ]),
250
251
  _: 1
251
- }, 8, ["color"]),
252
+ }),
252
253
  createVNode(_sfc_main$1, {
253
- onClick: addToQueue,
254
- color: "transp",
254
+ onClick: toggleFavorite,
255
+ color: "primary",
255
256
  size: "medium",
256
- class: "w-3r h-3r radius-full"
257
+ class: "flex-1 bg-light radius-thin flex-center gap-thin"
257
258
  }, {
258
259
  default: withCtx(() => [
259
- createVNode(_sfc_main$4, { class: "w-1-25r h-1-25r" })
260
+ createVNode(_sfc_main$4, {
261
+ class: "i-medium",
262
+ fill: isFavorite.value
263
+ }, null, 8, ["fill"]),
264
+ createTextVNode(" " + toDisplayString(isFavorite.value ? "Liked" : "Like"), 1)
260
265
  ]),
261
266
  _: 1
262
267
  }),
263
268
  createVNode(_sfc_main$5, {
269
+ label: { component: _sfc_main$6, class: "bg-light radius-thin pd-thin i-big" },
264
270
  modelValue: showDropdown.value,
265
271
  "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => showDropdown.value = $event),
266
272
  class: "relative"
@@ -285,7 +291,7 @@ const _sfc_main = {
285
291
  size: "small",
286
292
  class: "w-100 justify-start"
287
293
  }, {
288
- default: withCtx(() => _cache[8] || (_cache[8] = [
294
+ default: withCtx(() => _cache[9] || (_cache[9] = [
289
295
  createTextVNode(" Add to Playlist ")
290
296
  ])),
291
297
  _: 1
@@ -296,20 +302,20 @@ const _sfc_main = {
296
302
  size: "small",
297
303
  class: "w-100 justify-start"
298
304
  }, {
299
- default: withCtx(() => _cache[9] || (_cache[9] = [
305
+ default: withCtx(() => _cache[10] || (_cache[10] = [
300
306
  createTextVNode(" Copy Link ")
301
307
  ])),
302
308
  _: 1
303
309
  }),
304
310
  isOwner.value ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
305
- _cache[12] || (_cache[12] = createElementVNode("hr", { class: "mn-v-thin border-dark-transp-10" }, null, -1)),
311
+ _cache[13] || (_cache[13] = createElementVNode("hr", { class: "mn-v-thin border-dark-transp-10" }, null, -1)),
306
312
  createVNode(_sfc_main$1, {
307
313
  onClick: editTrack,
308
314
  color: "transp",
309
315
  size: "small",
310
316
  class: "w-100 justify-start"
311
317
  }, {
312
- default: withCtx(() => _cache[10] || (_cache[10] = [
318
+ default: withCtx(() => _cache[11] || (_cache[11] = [
313
319
  createTextVNode(" Edit Track ")
314
320
  ])),
315
321
  _: 1
@@ -320,7 +326,7 @@ const _sfc_main = {
320
326
  size: "small",
321
327
  class: "w-100 justify-start"
322
328
  }, {
323
- default: withCtx(() => _cache[11] || (_cache[11] = [
329
+ default: withCtx(() => _cache[12] || (_cache[12] = [
324
330
  createTextVNode(" Delete Track ")
325
331
  ])),
326
332
  _: 1
@@ -329,11 +335,11 @@ const _sfc_main = {
329
335
  ])
330
336
  ]),
331
337
  _: 1
332
- }, 8, ["modelValue"])
338
+ }, 8, ["label", "modelValue"])
333
339
  ]),
334
340
  createElementVNode("div", _hoisted_18, [
335
341
  createVNode(_component_router_link, {
336
- to: `/artist/${track.value.artist.url}`,
342
+ to: { name: "artist", params: { url: track.value.artist.url } },
337
343
  class: "flex items-center gap-medium flex-1 hover-opacity"
338
344
  }, {
339
345
  default: withCtx(() => [
@@ -353,7 +359,7 @@ const _sfc_main = {
353
359
  class: "w-1r h-1r t-primary"
354
360
  })) : createCommentVNode("", true)
355
361
  ]),
356
- _cache[13] || (_cache[13] = createElementVNode("span", { class: "t-small t-transp" }, "Artist", -1))
362
+ _cache[14] || (_cache[14] = createElementVNode("span", { class: "t-small t-transp" }, "Artist", -1))
357
363
  ])
358
364
  ]),
359
365
  _: 1
@@ -373,43 +379,43 @@ const _sfc_main = {
373
379
  createElementVNode("div", _hoisted_23, [
374
380
  createElementVNode("div", _hoisted_24, [
375
381
  createElementVNode("div", _hoisted_25, [
376
- createVNode(IconClock, { class: "w-1-5r h-1-5r t-primary" })
382
+ createVNode(IconClock, { class: "i-regular t-primary" })
377
383
  ]),
378
384
  createElementVNode("div", null, [
379
- _cache[14] || (_cache[14] = createElementVNode("div", { class: "t-small t-transp t-uppercase" }, "Duration", -1)),
385
+ _cache[15] || (_cache[15] = createElementVNode("div", { class: "t-small t-transp t-uppercase" }, "Duration", -1)),
380
386
  createElementVNode("div", _hoisted_26, toDisplayString(formatDuration(track.value.duration)), 1)
381
387
  ])
382
388
  ]),
383
389
  createElementVNode("div", _hoisted_27, [
384
390
  createElementVNode("div", _hoisted_28, [
385
- createVNode(_sfc_main$8, { class: "w-1-5r h-1-5r t-primary" })
391
+ createVNode(_sfc_main$8, { class: "i-regular t-primary" })
386
392
  ]),
387
393
  createElementVNode("div", null, [
388
- _cache[15] || (_cache[15] = createElementVNode("div", { class: "t-small t-transp t-uppercase" }, "Released", -1)),
394
+ _cache[16] || (_cache[16] = createElementVNode("div", { class: "t-small t-transp t-uppercase" }, "Released", -1)),
389
395
  createElementVNode("div", _hoisted_29, toDisplayString(formatDate(track.value.releaseDate)), 1)
390
396
  ])
391
397
  ]),
392
398
  createElementVNode("div", _hoisted_30, [
393
399
  createElementVNode("div", _hoisted_31, [
394
- createVNode(_sfc_main$7, { class: "w-1-5r h-1-5r t-success" })
400
+ createVNode(_sfc_main$7, { class: "i-regular t-success" })
395
401
  ]),
396
402
  createElementVNode("div", null, [
397
- _cache[16] || (_cache[16] = createElementVNode("div", { class: "t-small t-transp t-uppercase" }, "Status", -1)),
403
+ _cache[17] || (_cache[17] = createElementVNode("div", { class: "t-small t-transp t-uppercase" }, "Status", -1)),
398
404
  createElementVNode("div", _hoisted_32, toDisplayString(track.value.status), 1)
399
405
  ])
400
406
  ]),
401
407
  createElementVNode("div", _hoisted_33, [
402
408
  createElementVNode("div", _hoisted_34, [
403
- createVNode(_sfc_main$9, { class: "w-1-5r h-1-5r t-primary" })
409
+ createVNode(_sfc_main$9, { class: "i-regular t-primary" })
404
410
  ]),
405
411
  createElementVNode("div", null, [
406
- _cache[17] || (_cache[17] = createElementVNode("div", { class: "t-small t-transp t-uppercase" }, "Visibility", -1)),
412
+ _cache[18] || (_cache[18] = createElementVNode("div", { class: "t-small t-transp t-uppercase" }, "Visibility", -1)),
407
413
  createElementVNode("div", _hoisted_35, toDisplayString(track.value.isPublic ? "Public" : "Private"), 1)
408
414
  ])
409
415
  ])
410
416
  ]),
411
417
  track.value.album ? (openBlock(), createElementBlock("div", _hoisted_36, [
412
- _cache[18] || (_cache[18] = createElementVNode("div", { class: "t-small t-transp t-uppercase mn-b-thin" }, "From Album", -1)),
418
+ _cache[19] || (_cache[19] = createElementVNode("div", { class: "t-small t-transp t-uppercase mn-b-thin" }, "From Album", -1)),
413
419
  createVNode(_component_router_link, {
414
420
  to: `/album/${track.value.album.url}`,
415
421
  class: "flex items-center gap-medium hover-opacity"
@@ -427,7 +433,7 @@ const _sfc_main = {
427
433
  }, 8, ["to"])
428
434
  ])) : createCommentVNode("", true),
429
435
  track.value.genre && track.value.genre.length || track.value.tags && track.value.tags.length ? (openBlock(), createElementBlock("div", _hoisted_38, [
430
- _cache[19] || (_cache[19] = createElementVNode("h3", { class: "t-medium mn-b-small" }, "Genres & Tags", -1)),
436
+ _cache[20] || (_cache[20] = createElementVNode("h3", { class: "t-medium mn-b-small" }, "Genres & Tags", -1)),
431
437
  createElementVNode("div", _hoisted_39, [
432
438
  (openBlock(true), createElementBlock(Fragment, null, renderList(track.value.genre, (genre) => {
433
439
  return openBlock(), createElementBlock("span", {
@@ -444,17 +450,17 @@ const _sfc_main = {
444
450
  ])
445
451
  ])) : createCommentVNode("", true),
446
452
  track.value.description ? (openBlock(), createElementBlock("div", _hoisted_40, [
447
- _cache[20] || (_cache[20] = createElementVNode("h3", { class: "t-medium mn-b-small" }, "About", -1)),
453
+ _cache[21] || (_cache[21] = createElementVNode("h3", { class: "t-medium mn-b-small" }, "About", -1)),
448
454
  createElementVNode("p", _hoisted_41, toDisplayString(track.value.description), 1)
449
455
  ])) : createCommentVNode("", true),
450
456
  track.value.lyrics ? (openBlock(), createElementBlock("div", _hoisted_42, [
451
- _cache[21] || (_cache[21] = createElementVNode("h3", { class: "t-medium mn-b-small" }, "Lyrics", -1)),
457
+ _cache[22] || (_cache[22] = createElementVNode("h3", { class: "t-medium mn-b-small" }, "Lyrics", -1)),
452
458
  createElementVNode("pre", _hoisted_43, toDisplayString(track.value.lyrics), 1)
453
459
  ])) : createCommentVNode("", true)
454
460
  ])
455
461
  ])) : createCommentVNode("", true),
456
462
  track.value && relatedTracks.value && relatedTracks.value.length ? (openBlock(), createElementBlock("section", _hoisted_44, [
457
- _cache[22] || (_cache[22] = createElementVNode("h2", { class: "h2 mn-b-medium" }, "Related Tracks", -1)),
463
+ _cache[23] || (_cache[23] = createElementVNode("h2", { class: "h2 mn-b-medium" }, "Related Tracks", -1)),
458
464
  createVNode(_sfc_main$a, {
459
465
  store: {
460
466
  read: () => new _ctx.Promise((resolve) => resolve(relatedTracks.value || [])),
@@ -490,9 +496,9 @@ const _sfc_main = {
490
496
  showAddToPlaylistModal.value ? (openBlock(), createBlock(_sfc_main$c, {
491
497
  key: 4,
492
498
  onClosePopup: _cache[2] || (_cache[2] = ($event) => showAddToPlaylistModal.value = false),
493
- class: "bg-dark pd-medium w-m-25r radius-medium"
499
+ class: "bg-white pd-medium w-m-25r radius-medium"
494
500
  }, {
495
- default: withCtx(() => _cache[23] || (_cache[23] = [
501
+ default: withCtx(() => _cache[24] || (_cache[24] = [
496
502
  createElementVNode("h3", { class: "h3 mn-b-medium" }, "Add to Playlist", -1),
497
503
  createElementVNode("p", { class: "t-transp" }, "Playlist selector coming soon...", -1)
498
504
  ])),