@necrolab/dashboard 0.4.221 → 0.5.2

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 (141) hide show
  1. package/.prettierrc +27 -1
  2. package/.vscode/extensions.json +1 -1
  3. package/README.md +64 -2
  4. package/artwork/image.png +0 -0
  5. package/backend/api.js +26 -24
  6. package/backend/auth.js +2 -2
  7. package/backend/batching.js +1 -1
  8. package/backend/endpoints.js +8 -11
  9. package/backend/index.js +2 -2
  10. package/backend/mock-data.js +27 -36
  11. package/backend/mock-src/classes/logger.js +5 -7
  12. package/backend/mock-src/classes/utils.js +3 -2
  13. package/backend/mock-src/ticketmaster.js +4 -4
  14. package/backend/validator.js +2 -2
  15. package/config/configs.json +0 -1
  16. package/dev-server.js +134 -0
  17. package/exit +209 -0
  18. package/index.html +80 -8
  19. package/index.js +1 -1
  20. package/jsconfig.json +16 -0
  21. package/package.json +39 -25
  22. package/postcss.config.js +1 -1
  23. package/postinstall.js +124 -20
  24. package/public/android-chrome-192x192.png +0 -0
  25. package/public/android-chrome-512x512.png +0 -0
  26. package/public/apple-touch-icon.png +0 -0
  27. package/public/favicon-16x16.png +0 -0
  28. package/public/favicon-32x32.png +0 -0
  29. package/public/favicon.ico +0 -0
  30. package/public/img/logo_trans.png +0 -0
  31. package/public/img/necro_logo.png +0 -0
  32. package/public/manifest.json +16 -10
  33. package/public/reconnect-logo.png +0 -0
  34. package/run +176 -9
  35. package/src/App.vue +498 -85
  36. package/src/assets/css/base/reset.scss +43 -0
  37. package/src/assets/css/base/scroll.scss +114 -0
  38. package/src/assets/css/base/typography.scss +37 -0
  39. package/src/assets/css/components/buttons.scss +216 -0
  40. package/src/assets/css/components/forms.scss +221 -0
  41. package/src/assets/css/components/modals.scss +13 -0
  42. package/src/assets/css/components/tables.scss +27 -0
  43. package/src/assets/css/components/toasts.scss +100 -0
  44. package/src/assets/css/main.scss +202 -122
  45. package/src/assets/img/background.svg +2 -2
  46. package/src/assets/img/background.svg.backup +11 -0
  47. package/src/assets/img/logo_trans.png +0 -0
  48. package/src/components/Auth/LoginForm.vue +95 -11
  49. package/src/components/Editors/Account/Account.vue +116 -40
  50. package/src/components/Editors/Account/AccountCreator.vue +88 -39
  51. package/src/components/Editors/Account/AccountView.vue +102 -34
  52. package/src/components/Editors/Account/CreateAccount.vue +80 -32
  53. package/src/components/Editors/Profile/CreateProfile.vue +269 -83
  54. package/src/components/Editors/Profile/Profile.vue +132 -47
  55. package/src/components/Editors/Profile/ProfileCountryChooser.vue +82 -20
  56. package/src/components/Editors/Profile/ProfileView.vue +89 -32
  57. package/src/components/Editors/TagLabel.vue +67 -6
  58. package/src/components/Editors/TagToggle.vue +7 -2
  59. package/src/components/Filter/Filter.vue +288 -71
  60. package/src/components/Filter/FilterPreview.vue +202 -31
  61. package/src/components/Filter/PriceSortToggle.vue +76 -6
  62. package/src/components/Table/Header.vue +1 -1
  63. package/src/components/Table/Row.vue +1 -1
  64. package/src/components/Table/Table.vue +19 -2
  65. package/src/components/Tasks/CheckStock.vue +6 -8
  66. package/src/components/Tasks/Controls/DesktopControls.vue +27 -17
  67. package/src/components/Tasks/Controls/MobileControls.vue +8 -45
  68. package/src/components/Tasks/CreateTaskAXS.vue +80 -72
  69. package/src/components/Tasks/CreateTaskTM.vue +95 -141
  70. package/src/components/Tasks/MassEdit.vue +4 -6
  71. package/src/components/Tasks/QuickSettings.vue +199 -30
  72. package/src/components/Tasks/ScrapeVenue.vue +5 -6
  73. package/src/components/Tasks/Stats.vue +50 -24
  74. package/src/components/Tasks/Task.vue +384 -179
  75. package/src/components/Tasks/TaskLabel.vue +2 -2
  76. package/src/components/Tasks/TaskView.vue +136 -48
  77. package/src/components/Tasks/Utilities.vue +25 -10
  78. package/src/components/Tasks/ViewTask.vue +321 -0
  79. package/src/components/icons/Bag.vue +1 -1
  80. package/src/components/icons/Check.vue +5 -0
  81. package/src/components/icons/Close.vue +21 -0
  82. package/src/components/icons/CloseX.vue +5 -0
  83. package/src/components/icons/Eye.vue +6 -0
  84. package/src/components/icons/Key.vue +21 -0
  85. package/src/components/icons/Loyalty.vue +1 -1
  86. package/src/components/icons/Mail.vue +2 -2
  87. package/src/components/icons/Pencil.vue +21 -0
  88. package/src/components/icons/Play.vue +2 -2
  89. package/src/components/icons/Profile.vue +18 -0
  90. package/src/components/icons/Reload.vue +4 -5
  91. package/src/components/icons/Sandclock.vue +2 -2
  92. package/src/components/icons/Sell.vue +21 -0
  93. package/src/components/icons/Spinner.vue +42 -0
  94. package/src/components/icons/SquareCheck.vue +18 -0
  95. package/src/components/icons/SquareUncheck.vue +18 -0
  96. package/src/components/icons/Stadium.vue +1 -1
  97. package/src/components/icons/Wildcard.vue +18 -0
  98. package/src/components/icons/index.js +26 -1
  99. package/src/components/ui/Modal.vue +107 -13
  100. package/src/components/ui/Navbar.vue +175 -40
  101. package/src/components/ui/ReconnectIndicator.vue +351 -55
  102. package/src/components/ui/Splash.vue +5 -35
  103. package/src/components/ui/controls/CountryChooser.vue +200 -62
  104. package/src/components/ui/controls/atomic/Checkbox.vue +119 -10
  105. package/src/components/ui/controls/atomic/Dropdown.vue +216 -39
  106. package/src/components/ui/controls/atomic/LoadingButton.vue +45 -0
  107. package/src/components/ui/controls/atomic/MultiDropdown.vue +300 -37
  108. package/src/components/ui/controls/atomic/Switch.vue +53 -25
  109. package/src/composables/useClickOutside.js +21 -0
  110. package/src/composables/useDropdownPosition.js +174 -0
  111. package/src/libs/Filter.js +60 -24
  112. package/src/registerServiceWorker.js +1 -1
  113. package/src/stores/connection.js +4 -4
  114. package/src/stores/sampleData.js +172 -199
  115. package/src/stores/ui.js +55 -20
  116. package/src/stores/utils.js +30 -4
  117. package/src/types/index.js +41 -0
  118. package/src/utils/debug.js +1 -0
  119. package/src/views/Accounts.vue +116 -50
  120. package/src/views/Console.vue +394 -77
  121. package/src/views/Editor.vue +1176 -123
  122. package/src/views/FilterBuilder.vue +528 -250
  123. package/src/views/Login.vue +75 -14
  124. package/src/views/Profiles.vue +119 -34
  125. package/src/views/Tasks.vue +266 -98
  126. package/static/offline.html +192 -50
  127. package/switch-branch.sh +41 -0
  128. package/tailwind.config.js +119 -27
  129. package/vite.config.js +73 -16
  130. package/workbox-config.cjs +63 -0
  131. package/ICONS.md +0 -21
  132. package/public/img/background.svg +0 -14
  133. package/public/img/logo.png +0 -0
  134. package/public/img/logo_icon.png +0 -0
  135. package/public/img/logo_icon_2.png +0 -0
  136. package/src/assets/css/_input.scss +0 -143
  137. package/src/assets/img/logo.png +0 -0
  138. package/src/assets/img/logo_icon.png +0 -0
  139. package/src/assets/img/logo_icon_2.png +0 -0
  140. package/vue.config.js +0 -32
  141. package/workbox-config.js +0 -7
@@ -1,37 +1,44 @@
1
1
  <template>
2
- <div @click="toggleOpened" class="relative dropdown w-full p-2 h-10 text-white ml-auto rounded ring-0">
3
- <span class="gap-3 justify-between items-center z-inf">
4
- <span style="width: full" :class="`overflow-hidden block ${capitalize ? 'capitalize' : ''}`">{{
5
- currentValue ? currentValue : props.default
6
- }}</span>
7
- <DownIcon :class="`absolute ${props.rightAmount || 'right-4'} top-3.5`" />
2
+ <div @click="toggleOpened" class="dropdown" :class="props.variant" ref="dropdownRef">
3
+ <span class="dropdown-display">
4
+ <span class="dropdown-value" :class="capitalize ? 'capitalize' : ''">
5
+ {{ currentValue ? currentValue : props.default }}
6
+ </span>
7
+ <DownIcon class="dropdown-arrow" :class="opened ? 'rotate-180' : ''" />
8
8
  </span>
9
- <div
10
- class="dropdown-content z-inf custom-dropdown-content max-h-40 overflow-y-auto hidden-scrollbars"
11
- v-if="opened"
12
- >
13
- <div class="grid grid-rows-1">
14
- <button
15
- v-bind:key="f"
16
- :class="` cursor-pointer text-left w-full ${
17
- i !== 0 ? `border-t ${props.topPadding || 'pt-3 mt-3'}` : ''
18
- } border-light-300`"
19
- v-for="(f, i) in !allowDefault ? props.options : ['', ...props.options]"
20
- @click="chose(f)"
21
- >
22
- <span :class="`overflow-hidden smooth-hover ${capitalize ? 'capitalize' : ''}`">{{
23
- f ? f : props.default
24
- }}</span>
25
- </button>
26
- </div>
27
- </div>
9
+ <Teleport to="body">
10
+ <transition name="dropdown-fade">
11
+ <div
12
+ v-if="opened"
13
+ class="dropdown-menu-portal scrollable"
14
+ :style="menuStyle"
15
+ @click.stop
16
+ @wheel.stop
17
+ @touchmove.stop>
18
+ <button
19
+ v-bind:key="f"
20
+ class="dropdown-item"
21
+ :class="i !== 0 ? 'border-t border-dark-650' : ''"
22
+ v-for="(f, i) in !allowDefault ? props.options : ['', ...props.options]"
23
+ @click.stop="chose(f)">
24
+ <span class="dropdown-item-text" :class="capitalize ? 'capitalize' : ''">
25
+ {{ f ? f : props.default }}
26
+ </span>
27
+ <CheckmarkIcon v-if="(f || props.default) === currentValue" class="ml-2" />
28
+ </button>
29
+ </div>
30
+ </transition>
31
+ </Teleport>
28
32
  </div>
29
33
  </template>
30
34
 
31
35
  <script setup>
32
- import { ref, computed } from "vue";
33
- import { DownIcon } from "@/components/icons";
36
+ import { ref, computed, watch } from "vue";
37
+ import { DownIcon, CheckmarkIcon } from "@/components/icons";
34
38
  import { useUIStore } from "@/stores/ui";
39
+ import { useDropdownPosition } from "@/composables/useDropdownPosition";
40
+ import { useClickOutside } from "@/composables/useClickOutside";
41
+
35
42
  const ui = useUIStore();
36
43
 
37
44
  const props = defineProps({
@@ -42,35 +49,205 @@ const props = defineProps({
42
49
  allowDefault: { type: Boolean },
43
50
  rightAmount: { type: String },
44
51
  topPadding: { type: String },
45
- capitalize: { type: Boolean }
52
+ capitalize: { type: Boolean },
53
+ includeAdjacentButtons: { type: Boolean, default: false },
54
+ variant: { type: String, default: "default" }
46
55
  });
47
56
 
48
57
  const currentValue = ref(props.value);
58
+ const dropdownRef = ref(null);
59
+
60
+ // Watch for changes to the value prop and update currentValue
61
+ watch(
62
+ () => props.value,
63
+ (newValue) => {
64
+ currentValue.value = newValue;
65
+ }
66
+ );
67
+
49
68
  const id = Math.random();
50
69
  const opened = computed(() => ui.currentDropdown === id);
51
70
 
71
+ // Use composables for positioning and click outside
72
+ const { menuStyle, updatePosition } = useDropdownPosition(dropdownRef, {
73
+ maxHeight: 200,
74
+ includeAdjacentButtons: props.includeAdjacentButtons,
75
+ estimateHeight: () => {
76
+ const optionsCount = !props.allowDefault ? props.options?.length || 0 : (props.options?.length || 0) + 1;
77
+ return Math.min(optionsCount * 44, 200);
78
+ }
79
+ });
80
+
81
+ useClickOutside(dropdownRef, () => {
82
+ if (opened.value) {
83
+ ui.setCurrentDropdown("");
84
+ }
85
+ });
86
+
52
87
  const toggleOpened = () => {
53
- if (opened.value) ui.setCurrentDropdown("");
54
- else ui.setCurrentDropdown(id);
88
+ if (opened.value) {
89
+ ui.setCurrentDropdown("");
90
+ } else {
91
+ ui.setCurrentDropdown(id);
92
+ updatePosition();
93
+ }
55
94
  };
56
95
 
57
96
  const chose = (f) => {
58
97
  ui.logger.Info("Dropdown: chosen", f, "hiding...");
59
98
  currentValue.value = f;
60
- opened.value = false;
99
+ ui.setCurrentDropdown("");
100
+ if (props.onClick) props.onClick(f);
101
+ // Ensure dropdown closes
61
102
  setTimeout(() => {
62
- opened.value = false;
63
- ui.logger.Info("Showing dropdown again");
103
+ ui.setCurrentDropdown("");
64
104
  }, 50);
65
- props.onClick(f);
66
105
  };
67
106
  </script>
68
107
 
69
108
  <style scoped>
70
- .custom-dropdown-content {
71
- top: 2.5rem !important;
72
- @apply border border-light-300;
73
- left: -1px !important;
74
- width: calc(100% + 2px);
109
+ .dropdown {
110
+ @apply relative w-full text-white ml-auto rounded-lg ring-0 h-10;
111
+ background: linear-gradient(135deg, oklch(0.18 0 0) 0%, oklch(0.20 0 0) 100%);
112
+ border: 1px solid oklch(0.26 0 0);
113
+ padding: 0.75rem;
114
+ }
115
+
116
+ .dropdown.transparent {
117
+ background: transparent !important;
118
+ border: none !important;
119
+ box-shadow: none !important;
120
+ padding: 0 !important;
121
+ height: 40px !important;
122
+ }
123
+
124
+ .dropdown.transparent:hover,
125
+ .dropdown.transparent:focus-within {
126
+ border: none !important;
127
+ background: transparent !important;
128
+ box-shadow: none !important;
129
+ }
130
+
131
+ .dropdown:not(.transparent):hover {
132
+ border-color: oklch(0.30 0 0);
133
+ }
134
+
135
+ .dropdown:not(.transparent):focus-within,
136
+ .dropdown:not(.transparent).opened {
137
+ border-color: oklch(0.72 0.15 145) !important;
138
+ outline: 1px solid oklch(0.72 0.15 145) !important;
139
+ outline-offset: 0;
140
+ }
141
+
142
+ @media (min-width: 768px) {
143
+ .dropdown {
144
+ height: 40px;
145
+ padding: 0.625rem;
146
+ }
147
+ }
148
+
149
+ .dropdown-display {
150
+ @apply flex items-center justify-between z-10 w-full h-full;
151
+ }
152
+
153
+ .dropdown-value {
154
+ @apply overflow-hidden truncate min-w-0 flex-1 mr-2 text-sm;
155
+ }
156
+
157
+ @media (min-width: 768px) {
158
+ .dropdown-value {
159
+ font-size: 12px;
160
+ }
161
+ }
162
+
163
+ .dropdown-arrow {
164
+ @apply w-4 h-4 transition-all duration-300 flex-shrink-0;
165
+ }
166
+
167
+ .dropdown-menu-portal {
168
+ @apply rounded-xl shadow-2xl overflow-hidden;
169
+ background: linear-gradient(135deg, oklch(0.18 0 0) 0%, oklch(0.20 0 0) 100%);
170
+ border: 1px solid oklch(0.26 0 0);
171
+ backdrop-filter: blur(12px);
172
+ box-shadow: 0 20px 25px -5px oklch(0 0 0 / 0.4), 0 10px 10px -5px oklch(0 0 0 / 0.2),
173
+ 0 0 0 1px oklch(1 0 0 / 0.05);
174
+ overflow-y: auto !important;
175
+ overscroll-behavior: contain !important;
176
+ touch-action: pan-y !important;
177
+ -webkit-overflow-scrolling: touch !important;
178
+ scrollbar-width: none;
179
+ -ms-overflow-style: none;
180
+ }
181
+
182
+ .dropdown-menu-portal::-webkit-scrollbar {
183
+ display: none;
184
+ }
185
+
186
+ .dropdown-item {
187
+ @apply cursor-pointer text-left w-full text-white transition-all duration-200 flex items-center justify-between;
188
+ padding: 0.75rem 1rem;
189
+ font-size: 0.875rem;
190
+ font-weight: 500;
191
+ border-bottom: 1px solid rgba(61, 62, 68, 0.3);
192
+ }
193
+
194
+ .dropdown-item:last-child {
195
+ border-bottom: none;
196
+ }
197
+
198
+ .dropdown-item:hover {
199
+ @apply bg-dark-600;
200
+ color: oklch(1 0 0);
201
+ }
202
+
203
+ .dropdown-item:active {
204
+ @apply bg-dark-650;
205
+ box-shadow: inset 0 2px 4px oklch(0 0 0 / 0.4);
206
+ }
207
+
208
+ .dropdown-item.selected {
209
+ background: oklch(0.72 0.15 145 / 0.15);
210
+ color: oklch(0.72 0.15 145);
211
+ }
212
+
213
+ .dropdown-item:first-child {
214
+ @apply rounded-t-xl;
215
+ }
216
+
217
+ .dropdown-item:last-child {
218
+ @apply rounded-b-xl;
219
+ }
220
+
221
+ .dropdown-item-text {
222
+ @apply overflow-hidden truncate pr-2;
223
+ }
224
+
225
+ .dropdown-item svg {
226
+ @apply w-4 h-4;
227
+ color: oklch(0.72 0.15 145);
228
+ }
229
+
230
+ .dropdown-fade-enter-active {
231
+ @apply transition-all duration-300;
232
+ }
233
+
234
+ .dropdown-fade-leave-active {
235
+ @apply transition-all duration-200;
236
+ }
237
+
238
+ .dropdown-fade-enter-from {
239
+ @apply opacity-0;
240
+ transform: translateY(-8px) scale(0.95);
241
+ }
242
+
243
+ .dropdown-fade-leave-to {
244
+ @apply opacity-0;
245
+ transform: translateY(-4px) scale(0.98);
246
+ }
247
+
248
+ .dropdown-fade-enter-to,
249
+ .dropdown-fade-leave-from {
250
+ @apply opacity-100;
251
+ transform: translateY(0) scale(1);
75
252
  }
76
253
  </style>
@@ -0,0 +1,45 @@
1
+ <template>
2
+ <button
3
+ :class="[
4
+ 'btn-primary',
5
+ {
6
+ 'opacity-50 cursor-not-allowed': loading || disabled,
7
+ 'btn-secondary': variant === 'secondary',
8
+ 'btn-danger': variant === 'danger'
9
+ }
10
+ ]"
11
+ :disabled="loading || disabled"
12
+ @click="$emit('click')"
13
+ v-bind="$attrs"
14
+ >
15
+ <div v-if="loading" class="flex items-center justify-center gap-2">
16
+ <div class="loading-spinner"></div>
17
+ <span v-if="loadingText">{{ loadingText }}</span>
18
+ </div>
19
+ <slot v-else />
20
+ </button>
21
+ </template>
22
+
23
+ <script setup>
24
+ defineProps({
25
+ loading: {
26
+ type: Boolean,
27
+ default: false
28
+ },
29
+ disabled: {
30
+ type: Boolean,
31
+ default: false
32
+ },
33
+ loadingText: {
34
+ type: String,
35
+ default: ''
36
+ },
37
+ variant: {
38
+ type: String,
39
+ default: 'primary',
40
+ validator: (value) => ['primary', 'secondary', 'danger'].includes(value)
41
+ }
42
+ });
43
+
44
+ defineEmits(['click']);
45
+ </script>