@ozdao/martyrs 0.2.582 → 0.2.583

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 (119) hide show
  1. package/dist/martyrs/src/components/Button/Button.vue.js +1 -1
  2. package/dist/martyrs/src/components/Feed/Carousel.vue.js +1 -1
  3. package/dist/martyrs/src/components/Feed/Feed.vue.js +2 -2
  4. package/dist/martyrs/src/components/Loader/{Loader.vue.js → Loader.vue2.js} +2 -2
  5. package/dist/martyrs/src/components/Loader/Loader.vue2.js.map +1 -0
  6. package/dist/martyrs/src/components/LocationMarker/LocationMarker.vue.js +1 -1
  7. package/dist/martyrs/src/components/Media/Media.vue.js +1 -1
  8. package/dist/martyrs/src/components/Menu/{Menu.vue.js → Menu.vue2.js} +2 -2
  9. package/dist/martyrs/src/components/Menu/Menu.vue2.js.map +1 -0
  10. package/dist/martyrs/src/components/Spoiler/{Spoiler.vue.js → Spoiler.vue2.js} +2 -2
  11. package/dist/martyrs/src/components/Spoiler/Spoiler.vue2.js.map +1 -0
  12. package/dist/martyrs/src/components/Tab/{Tab.vue.js → Tab.vue2.js} +2 -2
  13. package/dist/martyrs/src/components/Tab/Tab.vue2.js.map +1 -0
  14. package/dist/martyrs/src/components/UploadImage/UploadImage.vue.js +1 -1
  15. package/dist/martyrs/src/components/UploadImageMultiple/UploadImageMultiple.vue.js +1 -1
  16. package/dist/martyrs/src/modules/auth/views/components/pages/EnterPassword.vue.js +1 -1
  17. package/dist/martyrs/src/modules/auth/views/components/pages/Invite.vue.js +1 -1
  18. package/dist/martyrs/src/modules/auth/views/components/pages/Profile.vue.js +8 -14
  19. package/dist/martyrs/src/modules/auth/views/components/pages/Profile.vue.js.map +1 -1
  20. package/dist/martyrs/src/modules/auth/views/components/pages/ProfileBlogposts.vue.js +1 -1
  21. package/dist/martyrs/src/modules/auth/views/components/pages/ProfileEdit.vue.js +1 -1
  22. package/dist/martyrs/src/modules/auth/views/components/pages/ResetPassword.vue.js +1 -1
  23. package/dist/martyrs/src/modules/auth/views/components/pages/SignIn.vue.js +1 -1
  24. package/dist/martyrs/src/modules/auth/views/components/pages/SignUp.vue.js +1 -1
  25. package/dist/martyrs/src/modules/auth/views/components/pages/UserDashboard.vue.js +182 -89
  26. package/dist/martyrs/src/modules/auth/views/components/pages/UserDashboard.vue.js.map +1 -1
  27. package/dist/martyrs/src/modules/auth/views/configs/navigation.user.config.js +9 -2
  28. package/dist/martyrs/src/modules/auth/views/configs/navigation.user.config.js.map +1 -1
  29. package/dist/martyrs/src/modules/community/components/pages/BlogPost.vue.js +1 -1
  30. package/dist/martyrs/src/modules/core/views/components/blocks/CardHeader.vue.js +1 -1
  31. package/dist/martyrs/src/modules/core/views/components/blocks/PopupDateSelector.vue.js +1 -1
  32. package/dist/martyrs/src/modules/core/views/components/layouts/Client.vue.js +1 -1
  33. package/dist/martyrs/src/modules/core/views/components/partials/Navigation.vue.js +1 -1
  34. package/dist/martyrs/src/modules/core/views/components/sections/{Filters.vue.js → Filters.vue2.js} +2 -2
  35. package/dist/martyrs/src/modules/core/views/components/sections/Filters.vue2.js.map +1 -0
  36. package/dist/martyrs/src/modules/core/views/components/sections/SectionPageTitle.vue.js +1 -1
  37. package/dist/martyrs/src/modules/events/components/pages/EditEvent.vue.js +1 -1
  38. package/dist/martyrs/src/modules/events/components/pages/Event.vue.js +2 -2
  39. package/dist/martyrs/src/modules/events/components/pages/EventsBackoffice.vue.js +1 -1
  40. package/dist/martyrs/src/modules/events/components/sections/Feed.vue.js +1 -1
  41. package/dist/martyrs/src/modules/events/components/sections/List.vue.js +1 -1
  42. package/dist/martyrs/src/modules/landing/components/sections/SectionGuide.vue.js +1 -1
  43. package/dist/martyrs/src/modules/marketplace/views/components/pages/Marketplace.vue.js +1 -1
  44. package/dist/martyrs/src/modules/marketplace/views/components/sections/SectionMenu.vue.js +1 -1
  45. package/dist/martyrs/src/modules/music/components/forms/ArtistForm.vue.js +1 -1
  46. package/dist/martyrs/src/modules/music/components/pages/Album.vue.js +1 -1
  47. package/dist/martyrs/src/modules/music/components/pages/Artist.vue.js +1 -1
  48. package/dist/martyrs/src/modules/music/components/pages/Playlist.vue.js +1 -1
  49. package/dist/martyrs/src/modules/music/components/pages/SearchResults.vue.js +1 -1
  50. package/dist/martyrs/src/modules/music/components/pages/Track.vue.js +1 -1
  51. package/dist/martyrs/src/modules/music/components/pages/TrackCreate.vue.js +1 -1
  52. package/dist/martyrs/src/modules/notifications/components/elements/NotificationBadge.vue.js +3 -3
  53. package/dist/martyrs/src/modules/notifications/components/elements/NotificationBadge.vue.js.map +1 -1
  54. package/dist/martyrs/src/modules/notifications/components/sections/NotificationPreferences.vue.js +1 -1
  55. package/dist/martyrs/src/modules/orders/components/blocks/CardOrderUser.vue.js +90 -175
  56. package/dist/martyrs/src/modules/orders/components/blocks/CardOrderUser.vue.js.map +1 -1
  57. package/dist/martyrs/src/modules/orders/components/forms/FormSelectCustomer.vue.js +1 -1
  58. package/dist/martyrs/src/modules/orders/components/pages/OrderBackoffice.vue.js +6 -6
  59. package/dist/martyrs/src/modules/orders/components/pages/OrderBackoffice.vue.js.map +1 -1
  60. package/dist/martyrs/src/modules/orders/components/pages/OrderCreateBackoffice.vue.js +1 -1
  61. package/dist/martyrs/src/modules/orders/components/pages/Orders.vue.js +41 -28
  62. package/dist/martyrs/src/modules/orders/components/pages/Orders.vue.js.map +1 -1
  63. package/dist/martyrs/src/modules/orders/components/sections/FormDelivery.vue.js +2 -2
  64. package/dist/martyrs/src/modules/orders/orders.client.js +14 -14
  65. package/dist/martyrs/src/modules/orders/orders.client.js.map +1 -1
  66. package/dist/martyrs/src/modules/organizations/components/blocks/CardDepartment.vue.js +1 -1
  67. package/dist/martyrs/src/modules/organizations/components/forms/DepartmentForm.vue.js +1 -1
  68. package/dist/martyrs/src/modules/organizations/components/pages/Department.vue.js +1 -1
  69. package/dist/martyrs/src/modules/organizations/components/pages/Organization.vue.js +1 -1
  70. package/dist/martyrs/src/modules/organizations/components/pages/OrganizationBackoffice.vue.js +1 -1
  71. package/dist/martyrs/src/modules/organizations/components/pages/OrganizationEdit.vue.js +89 -40
  72. package/dist/martyrs/src/modules/organizations/components/pages/OrganizationEdit.vue.js.map +1 -1
  73. package/dist/martyrs/src/modules/organizations/components/pages/Organizations.vue.js +1 -1
  74. package/dist/martyrs/src/modules/organizations/components/sections/Documents.vue.js +1 -1
  75. package/dist/martyrs/src/modules/organizations/components/sections/Organizations.vue.js +2 -2
  76. package/dist/martyrs/src/modules/pages/views/components/blocks/CardPage.vue.js +1 -1
  77. package/dist/martyrs/src/modules/products/components/elements/Image360.vue.js +1 -1
  78. package/dist/martyrs/src/modules/products/components/pages/Categories.vue.js +1 -1
  79. package/dist/martyrs/src/modules/products/components/pages/CategoryEdit.vue.js +2 -2
  80. package/dist/martyrs/src/modules/products/components/pages/Product.vue.js +2 -2
  81. package/dist/martyrs/src/modules/products/components/pages/ProductEdit.vue.js +1 -1
  82. package/dist/martyrs/src/modules/products/components/pages/Products.vue.js +3 -3
  83. package/dist/martyrs/src/modules/products/components/sections/FilterProducts.vue.js +1 -1
  84. package/dist/martyrs/src/modules/products/components/sections/SectionProduct.vue.js +1 -1
  85. package/dist/martyrs/src/modules/rents/views/components/pages/Gant/GanttToolbar.vue.js +1 -1
  86. package/dist/martyrs/src/modules/rents/views/components/pages/Rents.vue.js +1 -1
  87. package/dist/martyrs/src/modules/spots/components/layouts/Spots.vue.js +1 -1
  88. package/dist/martyrs/src/modules/spots/components/pages/Spot.vue.js +1 -1
  89. package/dist/martyrs/src/modules/spots/components/pages/SpotEdit.vue.js +1 -1
  90. package/dist/style.css +72 -77
  91. package/package.json +1 -1
  92. package/src/modules/TASKS.MD +26 -1
  93. package/src/modules/auth/views/components/pages/Profile.vue +9 -15
  94. package/src/modules/auth/views/components/pages/UserDashboard.vue +214 -125
  95. package/src/modules/auth/views/configs/navigation.user.config.js +8 -2
  96. package/src/modules/notifications/components/elements/NotificationBadge.vue +1 -1
  97. package/src/modules/orders/components/blocks/CardOrderUser.vue +88 -190
  98. package/src/modules/orders/components/pages/OrderBackoffice.vue +5 -5
  99. package/src/modules/orders/components/pages/Orders.vue +56 -50
  100. package/src/modules/organizations/components/pages/OrganizationEdit.vue +42 -11
  101. package/dist/martyrs/src/components/Loader/Loader.vue.js.map +0 -1
  102. package/dist/martyrs/src/components/Menu/Menu.vue.js.map +0 -1
  103. package/dist/martyrs/src/components/SelectMulti/SelectMulti.vue2.js +0 -625
  104. package/dist/martyrs/src/components/SelectMulti/SelectMulti.vue2.js.map +0 -1
  105. package/dist/martyrs/src/components/Spoiler/Spoiler.vue.js.map +0 -1
  106. package/dist/martyrs/src/components/Tab/Tab.vue.js.map +0 -1
  107. package/dist/martyrs/src/modules/core/views/components/sections/Filters.vue.js.map +0 -1
  108. package/dist/martyrs/src/modules/orders/components/icons/IconStatusCanceled.vue.js +0 -32
  109. package/dist/martyrs/src/modules/orders/components/icons/IconStatusCanceled.vue.js.map +0 -1
  110. package/dist/martyrs/src/modules/orders/components/icons/IconStatusConfirmed.vue.js +0 -32
  111. package/dist/martyrs/src/modules/orders/components/icons/IconStatusConfirmed.vue.js.map +0 -1
  112. package/dist/martyrs/src/modules/orders/components/icons/IconStatusCreated.vue.js +0 -32
  113. package/dist/martyrs/src/modules/orders/components/icons/IconStatusCreated.vue.js.map +0 -1
  114. package/dist/martyrs/src/modules/orders/components/icons/IconStatusDelay.vue.js +0 -32
  115. package/dist/martyrs/src/modules/orders/components/icons/IconStatusDelay.vue.js.map +0 -1
  116. package/dist/martyrs/src/modules/orders/components/icons/IconStatusFinished.vue.js +0 -32
  117. package/dist/martyrs/src/modules/orders/components/icons/IconStatusFinished.vue.js.map +0 -1
  118. package/dist/martyrs/src/modules/orders/components/icons/IconStatusInUse.vue.js +0 -32
  119. package/dist/martyrs/src/modules/orders/components/icons/IconStatusInUse.vue.js.map +0 -1
package/dist/style.css CHANGED
@@ -1439,21 +1439,21 @@ to {
1439
1439
  margin-left: 0.5rem;
1440
1440
  }
1441
1441
 
1442
- .notification-badge-container[data-v-ce5c73ba] {
1442
+ .notification-badge-container[data-v-bea4263c] {
1443
1443
  position: relative;
1444
1444
  display: inline-block;
1445
1445
  }
1446
- .notification-button[data-v-ce5c73ba] {
1446
+ .notification-button[data-v-bea4263c] {
1447
1447
  background: none;
1448
1448
  border: none;
1449
1449
  cursor: pointer;
1450
1450
  position: relative;
1451
1451
  font-size: 1.2rem;
1452
1452
  }
1453
- .notification-icon[data-v-ce5c73ba] {
1453
+ .notification-icon[data-v-bea4263c] {
1454
1454
  font-size: 1.4rem;
1455
1455
  }
1456
- .button-counter[data-v-ce5c73ba] {
1456
+ .button-counter[data-v-bea4263c] {
1457
1457
  position: absolute;
1458
1458
  right: -8px;
1459
1459
  bottom: -8px;
@@ -1467,8 +1467,8 @@ to {
1467
1467
  line-height: 16px;
1468
1468
  font-size: 10px;
1469
1469
  }
1470
- .notifications-loading[data-v-ce5c73ba],
1471
- .notifications-empty[data-v-ce5c73ba] {
1470
+ .notifications-loading[data-v-bea4263c],
1471
+ .notifications-empty[data-v-bea4263c] {
1472
1472
  padding: 24px;
1473
1473
  text-align: center;
1474
1474
  color: rgb(var(--texfw-light));
@@ -1743,6 +1743,66 @@ to {
1743
1743
  white-space: pre-line;
1744
1744
  word-wrap: break-word;
1745
1745
  }
1746
+ .icon-search-popup[data-v-3479d8be] {
1747
+ min-height: 500px;
1748
+ }
1749
+ .icon-grid[data-v-3479d8be] {
1750
+ min-height: 400px;
1751
+ }
1752
+ .icon-item[data-v-3479d8be] {
1753
+ transition: all 0.2s ease;
1754
+ }
1755
+ .icon-item[data-v-3479d8be]:hover {
1756
+ background-color: rgb(var(--light-hover));
1757
+ transform: scale(1.05);
1758
+ }
1759
+ .icon-preview[data-v-3479d8be] {
1760
+ background: rgb(var(--light));
1761
+ border-radius: 8px;
1762
+ }
1763
+ .icon-svg[data-v-3479d8be] {
1764
+ filter: none;
1765
+ }
1766
+ .w-max-800[data-v-3479d8be] {
1767
+ max-width: 800px;
1768
+ width: 90vw;
1769
+ }
1770
+ [data-v-3479d8be] .feed-enter-active,[data-v-3479d8be] .feed-leave-active {
1771
+ transition: all 0.3s ease;
1772
+ }
1773
+ [data-v-3479d8be] .feed-enter-from,[data-v-3479d8be] .feed-leave-to {
1774
+ opacity: 0;
1775
+ transform: scale(0.9);
1776
+ }
1777
+
1778
+ .h-60[data-v-ac4d495b] {
1779
+ height: 60%;
1780
+ }
1781
+ .notification[data-v-ac4d495b] {
1782
+ z-index: 100;
1783
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
1784
+ transition: all 0.3s ease;
1785
+ animation: fadeIn-ac4d495b 0.3s;
1786
+ }
1787
+ @keyframes fadeIn-ac4d495b {
1788
+ from { opacity: 0; transform: translateY(20px);
1789
+ }
1790
+ to { opacity: 1; transform: translateY(0);
1791
+ }
1792
+ }
1793
+ .icon-card .replace-btn[data-v-ac4d495b] {
1794
+ opacity: 0;
1795
+ transition: opacity 0.2s ease;
1796
+ }
1797
+ .icon-card:hover .replace-btn[data-v-ac4d495b] {
1798
+ opacity: 1;
1799
+ }
1800
+ .flex-justify-between[data-v-ac4d495b] {
1801
+ display: flex;
1802
+ justify-content: space-between;
1803
+ align-items: center;
1804
+ }
1805
+
1746
1806
  fieldset[disabled] .multiselect {
1747
1807
  pointer-events: none;
1748
1808
  }
@@ -2158,66 +2218,6 @@ to {
2158
2218
  }.bg-white-overlay[data-v-0f5877fc] {
2159
2219
  background: linear-gradient(0deg, rgba(var(--white), 1) 0%, rgba(var(--white), 0) 100%);
2160
2220
  }
2161
- .icon-search-popup[data-v-3479d8be] {
2162
- min-height: 500px;
2163
- }
2164
- .icon-grid[data-v-3479d8be] {
2165
- min-height: 400px;
2166
- }
2167
- .icon-item[data-v-3479d8be] {
2168
- transition: all 0.2s ease;
2169
- }
2170
- .icon-item[data-v-3479d8be]:hover {
2171
- background-color: rgb(var(--light-hover));
2172
- transform: scale(1.05);
2173
- }
2174
- .icon-preview[data-v-3479d8be] {
2175
- background: rgb(var(--light));
2176
- border-radius: 8px;
2177
- }
2178
- .icon-svg[data-v-3479d8be] {
2179
- filter: none;
2180
- }
2181
- .w-max-800[data-v-3479d8be] {
2182
- max-width: 800px;
2183
- width: 90vw;
2184
- }
2185
- [data-v-3479d8be] .feed-enter-active,[data-v-3479d8be] .feed-leave-active {
2186
- transition: all 0.3s ease;
2187
- }
2188
- [data-v-3479d8be] .feed-enter-from,[data-v-3479d8be] .feed-leave-to {
2189
- opacity: 0;
2190
- transform: scale(0.9);
2191
- }
2192
-
2193
- .h-60[data-v-ac4d495b] {
2194
- height: 60%;
2195
- }
2196
- .notification[data-v-ac4d495b] {
2197
- z-index: 100;
2198
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
2199
- transition: all 0.3s ease;
2200
- animation: fadeIn-ac4d495b 0.3s;
2201
- }
2202
- @keyframes fadeIn-ac4d495b {
2203
- from { opacity: 0; transform: translateY(20px);
2204
- }
2205
- to { opacity: 1; transform: translateY(0);
2206
- }
2207
- }
2208
- .icon-card .replace-btn[data-v-ac4d495b] {
2209
- opacity: 0;
2210
- transition: opacity 0.2s ease;
2211
- }
2212
- .icon-card:hover .replace-btn[data-v-ac4d495b] {
2213
- opacity: 1;
2214
- }
2215
- .flex-justify-between[data-v-ac4d495b] {
2216
- display: flex;
2217
- justify-content: space-between;
2218
- align-items: center;
2219
- }
2220
-
2221
2221
  /* Existing styles can stay unchanged */
2222
2222
 
2223
2223
  #eventPage {
@@ -2691,14 +2691,7 @@ to { opacity: 1; transform: translateY(0);
2691
2691
  }
2692
2692
  .vue-select-header {
2693
2693
  height: 3rem;
2694
- }.shop-cart-item[data-v-1e6239c6]:first-of-type {
2695
- padding-top: 0;
2696
2694
  }
2697
- /* Добавляем стиль для текста "просрочено" */
2698
- .t-red[data-v-06132302] {
2699
- color: red;
2700
- }
2701
-
2702
2695
  .bg-light[data-v-1239e806] {
2703
2696
  background-color: var(--color-bg-light, #f8f9fa);
2704
2697
  }
@@ -2712,7 +2705,9 @@ to { opacity: 1; transform: translateY(0);
2712
2705
  .bg-danger[data-v-7562ca0a] {
2713
2706
  background-color: #ef4444;
2714
2707
  }
2715
- #map[data-v-e9370e2c]:focus {
2708
+ .shop-cart-item[data-v-1e6239c6]:first-of-type {
2709
+ padding-top: 0;
2710
+ }#map[data-v-e9370e2c]:focus {
2716
2711
  outline: none;
2717
2712
  }
2718
2713
  /* Add styles for the user card component here */
@@ -3409,10 +3404,10 @@ html.barcode-scanner-active-html {
3409
3404
  aspect-ratio: 1/1;
3410
3405
  height: 100%;
3411
3406
  background: #ccc;
3412
- }.blink[data-v-134b043e] {
3413
- animation: blink-animation-134b043e 1s ease infinite;
3407
+ }.blink[data-v-f82cb957] {
3408
+ animation: blink-animation-f82cb957 1s ease infinite;
3414
3409
  }
3415
- @keyframes blink-animation-134b043e {
3410
+ @keyframes blink-animation-f82cb957 {
3416
3411
  0%, 100% {
3417
3412
  opacity: 1;
3418
3413
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ozdao/martyrs",
3
- "version": "0.2.582",
3
+ "version": "0.2.583",
4
4
  "description": "Fullstack framework focused on user experience and ease of development.",
5
5
  "author": "OZ DAO <hello@ozdao.dev>",
6
6
  "license": "GPL-3.0-or-later",
@@ -14,4 +14,29 @@
14
14
  - `/Users/magicofoz/Development/OZDAO/ozdao.dev/app/martyrs/src/modules/core/models/schemas/common.schema.js`
15
15
  - `/Users/magicofoz/Development/OZDAO/ozdao.dev/app/martyrs/src/modules/products/models/category.model.js`
16
16
  - `/Users/magicofoz/Development/OZDAO/ozdao.dev/app/martyrs/src/modules/products/controllers/categories.controller.js`
17
- - Все компоненты фронтенда, использующие статус 'featured'
17
+ - Все компоненты фронтенда, использующие статус 'featured'
18
+
19
+ ---
20
+
21
+ ### Перенос конфигурации модулей в базу данных
22
+
23
+ **Проблема**: Конфигурация модулей (статусы заказов, ставки VAT, fees и т.д.) хранится в `global.config.js`. Это означает:
24
+ - Изменения требуют редеплоя
25
+ - Нет возможности управлять настройками через UI
26
+ - Разные инстансы не могут иметь разные настройки
27
+
28
+ **Решение**: Перенести конфигурацию в базу данных и управлять через бекофис.
29
+
30
+ **Что нужно сделать**:
31
+ 1. Создать модель `ModuleSettings` для хранения настроек модулей в БД
32
+ 2. Создать страницу в бекофисе `/backoffice/settings` для управления параметрами
33
+ 3. Перенести настройки из `global.config.js`:
34
+ - `orders.statuses` - статусы заказов
35
+ - `orders.showFees`, `orders.feesRate` - настройки комиссий
36
+ - `orders.showVat`, `orders.vatRate` - настройки НДС
37
+ - `orders.showDeliveryFee`, `orders.deliveryRate` - настройки доставки
38
+ - Другие параметры модулей
39
+ 4. Загружать настройки при старте приложения и кэшировать
40
+ 5. Обновить компоненты для получения настроек из store вместо config
41
+
42
+ **Приоритет**: Высокий - статусы заказов особенно критичны для разных проектов
@@ -161,13 +161,7 @@
161
161
  <template v-for="(module, moduleName) in modules" :key="moduleName">
162
162
  <MenuItem
163
163
  v-if="isModuleInstalled(moduleName) && (!module.visible || module.visible(auth))"
164
- @click="router.push({
165
- name: `${module.route}`,
166
- params: {
167
- _id: route.params._id,
168
- user: route.params._id
169
- }
170
- })"
164
+ @click="router.push(module.path(route.params._id))"
171
165
  class="profile-menu-item cursor-pointer"
172
166
  >
173
167
  <component
@@ -285,30 +279,30 @@ const { isModuleInstalled } = useGlobalMixins()
285
279
  const modules = {
286
280
  events: {
287
281
  displayName: 'Events',
288
- route: 'User Events',
282
+ path: (_id) => `/users/${_id}/events`,
289
283
  icon: IconEvents,
290
284
  visible: () => true
291
285
  },
292
286
  organizations: {
293
287
  displayName: 'Groups',
294
- route: 'User Organizations',
288
+ path: (_id) => `/users/${_id}/organizations`,
295
289
  icon: IconGroups,
296
290
  visible: () => true
297
291
  },
298
- blogposts: {
292
+ community: {
299
293
  displayName: 'Posts',
300
- route: 'User Posts',
294
+ path: (_id) => `/users/${_id}/blogposts`,
301
295
  icon: IconCommunity,
302
296
  visible: () => true
303
297
  },
304
298
  orders: {
305
299
  displayName: 'Orders',
306
- route: 'UserOrdersList',
300
+ path: (_id) => `/users/${_id}/orders`,
307
301
  icon: IconOrders,
308
302
  visible: (auth) => auth.state.user && (
309
- auth.state.user._id === route.params._id ||
310
- (auth.state.access && auth.state.access.roles &&
311
- (auth.state.access.roles.includes('ROLE_MODERATOR') ||
303
+ auth.state.user._id === route.params._id ||
304
+ (auth.state.access && auth.state.access.roles &&
305
+ (auth.state.access.roles.includes('ROLE_MODERATOR') ||
312
306
  auth.state.access.roles.includes('ROLE_ADMIN'))
313
307
  )
314
308
  )
@@ -1,160 +1,249 @@
1
1
  <template>
2
- <div class="pd-medium bg-white">
3
- <h2 class="mn-b-small">Overview</h2>
4
- <div class="mn-b-medium cols-3 mobile:cols-1 gap-thin">
5
- <Block class="pos-relative">
6
- <span class="t-green fw-semi pos-absolute pos-t-small pos-r-small">+12.5%</span>
7
- <div class="mn-b-medium radius-small w-max bg-main"><IconGroups class="i-medium mn-small"/></div>
8
- <p class="h3 mn-b-thin">{{ stats.organizations || 0 }}</p>
9
- <p>My Groups</p>
10
- </Block>
11
-
12
- <Block class="pos-relative">
13
- <span class="t-green fw-semi pos-absolute pos-t-small pos-r-small">+14.8%</span>
14
- <div class="mn-b-medium radius-small w-max bg-main"><IconOrders class="i-medium mn-small"/></div>
15
- <p class="h3 mn-b-thin">{{ stats.orders || 0 }}</p>
16
- <p>My Orders</p>
17
- </Block>
18
-
19
- <Block class="pos-relative">
20
- <span class="t-green fw-semi pos-absolute pos-t-small pos-r-small">+25.1%</span>
21
- <div class="mn-b-medium radius-small w-max bg-main"><IconEvents class="i-medium mn-small"/></div>
22
- <p class="h3 mn-b-thin">{{ stats.events || 0 }}</p>
23
- <p>My Events</p>
24
- </Block>
2
+ <div class="pd-medium">
3
+ <h2 class="mn-b-medium">Overview</h2>
4
+
5
+ <!-- Stats Cards -->
6
+ <div class="mn-b-medium cols-3 mobile:cols-1 gap-small">
7
+ <router-link
8
+ :to="`/users/${auth.state.user._id}/organizations`"
9
+ class="d-block bg-light pd-medium radius-medium hover-scale-1 transition-default"
10
+ >
11
+ <div class="flex flex-v-center gap-small mn-b-small">
12
+ <div class="radius-small bg-main flex flex-center">
13
+ <IconGroups class="i-medium mn-small" :fill="'rgb(var(--white))'"/>
14
+ </div>
15
+ <span class="t-grey t-small">My Groups</span>
16
+ </div>
17
+ <p class="h2 fw-semi">{{ stats.organizations || 0 }}</p>
18
+ </router-link>
19
+
20
+ <router-link
21
+ :to="`/users/${auth.state.user._id}/orders`"
22
+ class="d-block bg-light pd-medium radius-medium hover-scale-1 transition-default"
23
+ >
24
+ <div class="flex flex-v-center gap-small mn-b-small">
25
+ <div class="radius-small bg-main flex flex-center">
26
+ <IconOrders class="i-medium mn-small" :fill="'rgb(var(--white))'"/>
27
+ </div>
28
+ <span class="t-grey t-small">My Orders</span>
29
+ </div>
30
+ <p class="h2 fw-semi">{{ stats.orders || 0 }}</p>
31
+ </router-link>
32
+
33
+ <router-link
34
+ :to="`/users/${auth.state.user._id}/events`"
35
+ class="d-block bg-light pd-medium radius-medium hover-scale-1 transition-default"
36
+ >
37
+ <div class="flex flex-v-center gap-small mn-b-small">
38
+ <div class="radius-small bg-main flex flex-center">
39
+ <IconEvents class="i-medium mn-small" :fill="'rgb(var(--white))'"/>
40
+ </div>
41
+ <span class="t-grey t-small">My Events</span>
42
+ </div>
43
+ <p class="h2 fw-semi">{{ stats.events || 0 }}</p>
44
+ </router-link>
25
45
  </div>
26
46
 
27
- <div class="cols-2 mobile:cols-1 gap-thin">
28
- <Block
29
- title="Recent Orders"
30
- class="pos-relative"
31
- >
47
+ <!-- Content Grid -->
48
+ <div class="cols-2 mobile:cols-1 gap-small">
49
+ <!-- Recent Orders -->
50
+ <Block title="Recent Orders">
32
51
  <Feed
33
- :showLoadMore="false"
34
- :LoadMore="false"
35
- :states="{
36
- empty: {
37
- title: 'No Orders',
38
- description: 'You have no orders yet.'
39
- }
40
- }"
41
- :store="{
42
- read: (options) => orders.actions.read(options),
43
- state: orders.state
44
- }"
45
- :options="{
46
- customer: auth.state.user._id,
47
- limit: 5,
48
- page: 1
49
- }"
50
- v-slot="{
51
- items
52
- }"
53
- class="cols-1 gap-thin"
54
- >
52
+ :showLoadMore="false"
53
+ :states="{
54
+ empty: {
55
+ title: 'No Orders',
56
+ description: 'You have no orders yet.'
57
+ }
58
+ }"
59
+ :store="{
60
+ read: (options) => orders.actions.read(options),
61
+ state: orders.state
62
+ }"
63
+ :options="{
64
+ customer: auth.state.user._id,
65
+ limit: 5,
66
+ page: 1
67
+ }"
68
+ v-slot="{ items }"
69
+ >
55
70
  <Table
56
- class="radius-semi bg-white"
71
+ class="radius-small bg-white"
57
72
  :items="items"
58
- :columns="[{
59
- key: '_id',
60
- label: 'ID',
61
- formatter: (value) => `#${value.slice(0, 4)}...${value.slice(-4)}`
62
- },
63
- {
64
- key: 'positions',
65
- label: 'Items',
66
- formatter: (value) => value?.length || 0
67
- },
68
- {
69
- key: 'status',
70
- label: 'Status',
71
- component: StatusBadge
72
- },
73
- {
74
- key: 'createdAt',
75
- label: 'Date',
76
- formatter: (value) => new Date(value).toLocaleDateString()
77
- }]"
78
- />
79
- </Feed>
80
-
73
+ :columns="columns.orders"
74
+ >
75
+ <template #cell-_id="{ value }">
76
+ <span class="t-dark fw-medium">#{{ formatId(value) }}</span>
77
+ </template>
78
+ <template #cell-positions="{ value }">
79
+ <span class="t-dark">{{ value?.length || 0 }} items</span>
80
+ </template>
81
+ <template #cell-status="{ value }">
82
+ <span
83
+ class="pd-thin pd-l-small pd-r-small radius-small t-small fw-medium"
84
+ :class="getStatusClass(value)"
85
+ >
86
+ {{ value }}
87
+ </span>
88
+ </template>
89
+ <template #cell-createdAt="{ value }">
90
+ <span class="t-grey t-small">{{ formatDate(value) }}</span>
91
+ </template>
92
+ </Table>
93
+ </Feed>
81
94
  </Block>
82
95
 
83
- <Block
84
- title="Upcoming Events"
85
- class="pos-relative"
86
- >
96
+ <!-- Upcoming Events -->
97
+ <Block title="Upcoming Events">
87
98
  <Feed
88
- :showLoadMore="false"
89
- :LoadMore="false"
90
- :states="{
91
- empty: {
92
- title: 'No Events',
93
- description: 'You have no upcoming events.'
94
- }
95
- }"
96
- :store="{
97
- read: (options) => events.read(options),
98
- }"
99
- :options="{
100
- creator: auth.state.user._id,
101
- sortParam: 'date.start',
102
- sortOrder: 'asc',
103
- limit: 5,
104
- page: 1
105
- }"
106
- v-slot="{
107
- items
108
- }"
109
- class="cols-1 gap-thin"
110
- >
111
- <CardEvent
112
- v-for="event in items"
113
- :key="event._id"
114
- :event="event"
115
- :user="auth.state.user._id"
116
- :type="'compact'"
117
- class="bg-light radius-medium"
118
- />
119
- </Feed>
99
+ :showLoadMore="false"
100
+ :states="{
101
+ empty: {
102
+ title: 'No Events',
103
+ description: 'You have no upcoming events.'
104
+ }
105
+ }"
106
+ :store="{
107
+ read: (options) => events.read(options)
108
+ }"
109
+ :options="{
110
+ creator: auth.state.user._id,
111
+ sortParam: 'date.start',
112
+ sortOrder: 'asc',
113
+ limit: 5,
114
+ page: 1
115
+ }"
116
+ v-slot="{ items }"
117
+ class="flex flex-column gap-thin"
118
+ >
119
+ <router-link
120
+ v-for="event in items"
121
+ :key="event._id"
122
+ :to="`/events/${event._id}`"
123
+ class="d-block bg-white pd-small radius-small hover-scale-1 transition-default"
124
+ >
125
+ <div class="flex flex-v-center gap-small">
126
+ <div
127
+ class="flex-none w-3r h-3r radius-small bg-main-transp flex flex-center o-hidden"
128
+ >
129
+ <img
130
+ v-if="event.cover"
131
+ :src="(FILE_SERVER_URL || '') + event.cover"
132
+ class="w-100 h-100 object-fit-cover"
133
+ alt=""
134
+ />
135
+ <IconEvents v-else class="i-regular" :fill="'rgb(var(--main))'"/>
136
+ </div>
137
+ <div class="flex-child o-hidden">
138
+ <p class="fw-medium t-truncate mn-b-nano">{{ event.name }}</p>
139
+ <p class="t-grey t-small">{{ formatEventDate(event.date) }}</p>
140
+ </div>
141
+ <div class="flex-none">
142
+ <span
143
+ class="pd-thin pd-l-small pd-r-small radius-small t-small fw-medium"
144
+ :class="getEventStatusClass(event.date)"
145
+ >
146
+ {{ getEventStatus(event.date) }}
147
+ </span>
148
+ </div>
149
+ </div>
150
+ </router-link>
151
+ </Feed>
120
152
  </Block>
121
153
  </div>
122
-
123
154
  </div>
124
-
125
-
126
155
  </template>
127
156
 
128
157
  <script setup>
129
- import { ref, onMounted } from 'vue';
130
- import { useRoute, useRouter } from 'vue-router'
158
+ import { ref, onMounted, inject } from 'vue'
159
+ import { useRouter } from 'vue-router'
131
160
 
132
161
  import Block from '@martyrs/src/components/Block/Block.vue'
133
162
  import Feed from '@martyrs/src/components/Feed/Feed.vue'
134
163
  import Table from '@martyrs/src/components/Table/Table.vue'
135
- import StatusBadge from '@martyrs/src/components/Table/StatusBadge.vue'
136
-
137
- import CardEvent from '@martyrs/src/modules/events/components/blocks/CardEvent.vue';
138
164
 
139
165
  import IconGroups from '@martyrs/src/modules/icons/entities/IconGroups.vue'
140
166
  import IconEvents from '@martyrs/src/modules/icons/entities/IconEvents.vue'
141
167
  import IconOrders from '@martyrs/src/modules/icons/entities/IconOrders.vue'
142
168
 
143
- import * as auth from '@martyrs/src/modules/auth/views/store/auth.js'
144
- import * as orders from '@martyrs/src/modules/orders/store/orders.js'
169
+ import * as auth from '@martyrs/src/modules/auth/views/store/auth.js'
170
+ import * as orders from '@martyrs/src/modules/orders/store/orders.js'
145
171
  import * as events from '@martyrs/src/modules/events/store/events.js'
146
172
 
147
- const route = useRoute()
173
+ const FILE_SERVER_URL = inject('FILE_SERVER_URL', '')
148
174
  const router = useRouter()
149
175
 
150
176
  const stats = ref({
151
- organizations: 0,
152
- orders: 0,
153
- events: 0
177
+ organizations: 0,
178
+ orders: 0,
179
+ events: 0
154
180
  })
155
181
 
182
+ const columns = {
183
+ orders: [
184
+ { key: '_id', label: 'Order' },
185
+ { key: 'positions', label: 'Items' },
186
+ { key: 'status', label: 'Status' },
187
+ { key: 'createdAt', label: 'Date' }
188
+ ]
189
+ }
190
+
191
+ // Formatters
192
+ const formatId = (id) => id ? `${id.slice(0, 4)}...${id.slice(-4)}` : ''
193
+
194
+ const formatDate = (date) => {
195
+ if (!date) return ''
196
+ return new Date(date).toLocaleDateString()
197
+ }
198
+
199
+ const formatEventDate = (date) => {
200
+ if (!date?.start) return ''
201
+ const start = new Date(date.start)
202
+ return start.toLocaleDateString(undefined, { day: '2-digit', month: 'short', year: 'numeric' })
203
+ }
204
+
205
+ const getStatusClass = (status) => {
206
+ const classes = {
207
+ pending: 'bg-second-transp t-second',
208
+ processing: 'bg-main-transp t-main',
209
+ completed: 'bg-green-transp t-green',
210
+ cancelled: 'bg-red-transp t-red'
211
+ }
212
+ return classes[status] || 'bg-light t-grey'
213
+ }
214
+
215
+ const getEventStatus = (date) => {
216
+ if (!date?.start) return 'No date'
217
+ const now = new Date()
218
+ const start = new Date(date.start)
219
+ const end = date.end ? new Date(date.end) : start
220
+
221
+ if (now > end) return 'Finished'
222
+ if (now >= start && now <= end) return 'Live'
223
+
224
+ const diffDays = Math.ceil((start - now) / (1000 * 60 * 60 * 24))
225
+ if (diffDays <= 1) return 'Tomorrow'
226
+ if (diffDays <= 7) return `In ${diffDays} days`
227
+ return 'Upcoming'
228
+ }
229
+
230
+ const getEventStatusClass = (date) => {
231
+ const status = getEventStatus(date)
232
+ if (status === 'Finished') return 'bg-light t-grey'
233
+ if (status === 'Live') return 'bg-green-transp t-green'
234
+ if (status === 'Tomorrow') return 'bg-second-transp t-second'
235
+ return 'bg-main-transp t-main'
236
+ }
237
+
156
238
  onMounted(async () => {
157
- // Load user stats if needed
239
+ // Load stats
240
+ try {
241
+ const [orgsData, ordersData, eventsData] = await Promise.all([
242
+ // Load counts if needed
243
+ ])
244
+ } catch (e) {
245
+ console.error('Failed to load dashboard stats:', e)
246
+ }
158
247
  })
159
248
  </script>
160
249