@necrolab/dashboard 0.5.14 → 0.5.16

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 (120) hide show
  1. package/backend/api.js +2 -3
  2. package/eslint.config.js +46 -0
  3. package/index.html +2 -1
  4. package/package.json +5 -2
  5. package/src/App.vue +140 -170
  6. package/src/assets/css/base/mixins.scss +72 -0
  7. package/src/assets/css/base/reset.scss +0 -2
  8. package/src/assets/css/base/scroll.scss +43 -36
  9. package/src/assets/css/base/typography.scss +9 -10
  10. package/src/assets/css/base/variables.scss +43 -0
  11. package/src/assets/css/components/accessibility.scss +37 -0
  12. package/src/assets/css/components/buttons.scss +58 -15
  13. package/src/assets/css/components/forms.scss +31 -32
  14. package/src/assets/css/components/headers.scss +119 -0
  15. package/src/assets/css/components/modals.scss +2 -2
  16. package/src/assets/css/components/search-groups.scss +28 -19
  17. package/src/assets/css/components/tables.scss +5 -7
  18. package/src/assets/css/components/toasts.scss +7 -7
  19. package/src/assets/css/components/utilities.scss +220 -0
  20. package/src/assets/css/main.scss +72 -75
  21. package/src/components/Auth/LoginForm.vue +5 -84
  22. package/src/components/Editors/Account/Account.vue +8 -10
  23. package/src/components/Editors/Account/AccountCreator.vue +28 -59
  24. package/src/components/Editors/Account/AccountView.vue +38 -86
  25. package/src/components/Editors/Account/CreateAccount.vue +8 -50
  26. package/src/components/Editors/Profile/CreateProfile.vue +74 -131
  27. package/src/components/Editors/Profile/Profile.vue +15 -17
  28. package/src/components/Editors/Profile/ProfileCountryChooser.vue +16 -60
  29. package/src/components/Editors/Profile/ProfileView.vue +46 -96
  30. package/src/components/Editors/TagLabel.vue +16 -55
  31. package/src/components/Editors/TagToggle.vue +20 -8
  32. package/src/components/Filter/Filter.vue +62 -75
  33. package/src/components/Filter/FilterPreview.vue +161 -135
  34. package/src/components/Filter/PriceSortToggle.vue +36 -43
  35. package/src/components/Table/Header.vue +1 -1
  36. package/src/components/Table/Table.vue +61 -12
  37. package/src/components/Tasks/CheckStock.vue +7 -16
  38. package/src/components/Tasks/Controls/DesktopControls.vue +15 -60
  39. package/src/components/Tasks/Controls/MobileControls.vue +5 -20
  40. package/src/components/Tasks/CreateTaskAXS.vue +20 -118
  41. package/src/components/Tasks/CreateTaskTM.vue +33 -189
  42. package/src/components/Tasks/EventDetailRow.vue +21 -0
  43. package/src/components/Tasks/MassEdit.vue +6 -16
  44. package/src/components/Tasks/QuickSettings.vue +140 -216
  45. package/src/components/Tasks/ScrapeVenue.vue +4 -13
  46. package/src/components/Tasks/Stats.vue +19 -38
  47. package/src/components/Tasks/Task.vue +65 -268
  48. package/src/components/Tasks/TaskLabel.vue +9 -3
  49. package/src/components/Tasks/TaskView.vue +43 -63
  50. package/src/components/Tasks/Utilities.vue +10 -42
  51. package/src/components/Tasks/ViewTask.vue +23 -107
  52. package/src/components/icons/Close.vue +2 -8
  53. package/src/components/icons/Gear.vue +8 -8
  54. package/src/components/icons/Hash.vue +5 -0
  55. package/src/components/icons/Key.vue +2 -8
  56. package/src/components/icons/Pencil.vue +2 -8
  57. package/src/components/icons/Profile.vue +2 -8
  58. package/src/components/icons/Sell.vue +2 -8
  59. package/src/components/icons/Spinner.vue +4 -7
  60. package/src/components/icons/SquareCheck.vue +2 -8
  61. package/src/components/icons/SquareUncheck.vue +2 -8
  62. package/src/components/icons/Wildcard.vue +2 -8
  63. package/src/components/icons/index.js +3 -1
  64. package/src/components/ui/ActionButtonGroup.vue +113 -52
  65. package/src/components/ui/BalanceIndicator.vue +60 -0
  66. package/src/components/ui/EmptyState.vue +24 -0
  67. package/src/components/ui/EnableDisableToggle.vue +23 -0
  68. package/src/components/ui/FormField.vue +48 -48
  69. package/src/components/ui/IconLabel.vue +23 -0
  70. package/src/components/ui/InfoRow.vue +21 -54
  71. package/src/components/ui/Modal.vue +78 -37
  72. package/src/components/ui/Navbar.vue +60 -41
  73. package/src/components/ui/ReadonlyFieldsSection.vue +31 -0
  74. package/src/components/ui/ReconnectIndicator.vue +111 -124
  75. package/src/components/ui/SectionCard.vue +6 -14
  76. package/src/components/ui/Splash.vue +2 -10
  77. package/src/components/ui/StatusBadge.vue +26 -28
  78. package/src/components/ui/TaskToggle.vue +54 -0
  79. package/src/components/ui/controls/CountryChooser.vue +27 -64
  80. package/src/components/ui/controls/EyeToggle.vue +1 -1
  81. package/src/components/ui/controls/atomic/Checkbox.vue +40 -121
  82. package/src/components/ui/controls/atomic/Dropdown.vue +102 -95
  83. package/src/components/ui/controls/atomic/MultiDropdown.vue +72 -94
  84. package/src/components/ui/controls/atomic/Switch.vue +21 -84
  85. package/src/composables/useColorMapping.js +15 -0
  86. package/src/composables/useCopyToClipboard.js +1 -1
  87. package/src/composables/useDateFormatting.js +21 -0
  88. package/src/composables/useDeviceDetection.js +14 -0
  89. package/src/composables/useDropdownPosition.js +5 -6
  90. package/src/composables/useDynamicTableHeight.js +31 -0
  91. package/src/composables/useRowSelection.js +0 -3
  92. package/src/composables/useTicketPricing.js +16 -0
  93. package/src/composables/useWindowDimensions.js +21 -0
  94. package/src/libs/Filter.js +14 -20
  95. package/src/libs/panzoom.js +1 -5
  96. package/src/libs/utils/array.js +60 -0
  97. package/src/{stores/utils.js → libs/utils/dataGeneration.js} +2 -250
  98. package/src/libs/utils/eventUrl.js +40 -0
  99. package/src/libs/utils/string.js +28 -0
  100. package/src/libs/utils/time.js +20 -0
  101. package/src/libs/utils/validation.js +88 -0
  102. package/src/main.js +0 -2
  103. package/src/stores/connection.js +1 -4
  104. package/src/stores/logger.js +6 -12
  105. package/src/stores/sampleData.js +1 -2
  106. package/src/stores/ui.js +59 -36
  107. package/src/views/Accounts.vue +17 -31
  108. package/src/views/Console.vue +76 -176
  109. package/src/views/Editor.vue +217 -383
  110. package/src/views/FilterBuilder.vue +190 -373
  111. package/src/views/Login.vue +3 -28
  112. package/src/views/Profiles.vue +12 -22
  113. package/src/views/Tasks.vue +51 -38
  114. package/tailwind.config.js +82 -71
  115. package/workbox-config.cjs +47 -5
  116. package/docs/plans/2026-02-08-tailwind-consolidation.md +0 -2416
  117. package/exit +0 -209
  118. package/run +0 -177
  119. package/switch-branch.sh +0 -41
  120. /package/public/{reconnect-logo.png → img/reconnect-logo.png} +0 -0
@@ -6,9 +6,9 @@
6
6
  </template>
7
7
 
8
8
  <div class="my-3">
9
- <div class="editor-container">
10
- <div class="editor-wrapper">
11
- <pre ref="codeDisplay" class="language-json code-highlight"></pre>
9
+ <div class="relative min-h-75 max-h-125 rounded-lg overflow-hidden shadow-card bg-dark-350">
10
+ <div class="relative w-full h-full min-h-75 max-h-125">
11
+ <pre ref="codeDisplay" class="code-highlight language-json"></pre>
12
12
  <textarea
13
13
  ref="codeEditor"
14
14
  v-model="text"
@@ -19,173 +19,99 @@
19
19
  @keydown.tab.prevent="handleTab"></textarea>
20
20
  </div>
21
21
  </div>
22
- <p class="text-red-400 text-bold mt-2">{{ errorMessage }}</p>
22
+ <p class="text-red-400 font-bold mt-2">{{ errorMessage }}</p>
23
23
  </div>
24
24
 
25
25
  <div class="ml-auto flex gap-3 mt-3">
26
- <button class="modal-btn save-btn" @click="save()">Apply</button>
27
- <button class="modal-btn" @click="done()">Close</button>
26
+ <button
27
+ class="smooth-hover flex h-10 items-center justify-center rounded-md border border-dark-650 bg-dark-400 px-6 text-xs font-medium text-white transition-all duration-150 hover:border-dark-700 btn-focus-ring"
28
+ @click="save()">
29
+ Apply
30
+ </button>
31
+ <button
32
+ class="smooth-hover flex h-10 items-center justify-center rounded-md border border-dark-650 bg-dark-400 px-6 text-xs font-medium text-white transition-all duration-150 hover:border-dark-700 btn-focus-ring"
33
+ @click="done()">
34
+ Close
35
+ </button>
28
36
  </div>
29
37
  </Modal>
30
38
  </template>
31
- <style lang="scss" scoped>
32
- .modal-btn {
33
- @apply rounded transition-all duration-150 flex items-center justify-center;
34
- background: oklch(0.2046 0 0);
35
- border: 2px solid oklch(0.2809 0 0);
36
- color: oklch(0.90 0 0);
37
- height: 2.5rem;
38
- width: 6.5rem;
39
- font-size: 0.75rem;
40
- font-weight: 500;
41
-
42
- &:hover {
43
- border-color: oklch(0.72 0.15 145);
44
- }
45
-
46
- &:active, &:focus {
47
- border-color: oklch(0.72 0.15 145);
48
- outline: 1px solid oklch(0.72 0.15 145);
49
- outline-offset: 0;
50
- }
51
-
52
- &.save-btn {
53
- background-color: oklch(0.72 0.15 145 / 0.15);
54
- border-color: oklch(0.72 0.15 145 / 0.5);
55
-
56
- &:hover {
57
- background-color: oklch(0.72 0.15 145 / 0.25);
58
- border-color: oklch(0.72 0.15 145);
59
- }
60
- }
61
- }
62
-
63
- /* Prism.js syntax highlighting styles */
64
- .editor-container {
65
- position: relative;
66
- min-height: 300px;
67
- max-height: 500px;
68
- border-radius: 8px;
69
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
70
- overflow: hidden;
71
- background-color: oklch(0.19 0 0);
72
- }
73
-
74
- .editor-wrapper {
75
- position: relative;
76
- width: 100%;
77
- height: 100%;
78
- min-height: 300px;
79
- max-height: 500px;
80
- }
81
-
82
- .code-editor {
83
- width: 100%;
84
- height: 100%;
85
- min-height: 300px;
86
- max-height: 500px;
87
- background-color: transparent;
88
- /* Make text completely transparent */
89
- color: rgba(0, 0, 0, 0);
90
- caret-color: #e2e8f0;
91
- font-family: "JetBrains Mono", "Fira Code", "Menlo", "Monaco", "Courier New", monospace;
92
- padding: 12px;
93
- border: none;
94
- resize: none;
95
- font-size: 14px;
96
- line-height: 1.6;
97
- tab-size: 4;
98
- outline: none;
99
- border: 1px solid oklch(0.26 0 0);
100
- border-radius: 8px;
101
- z-index: 10;
102
- position: absolute;
103
- top: 0;
104
- left: 0;
105
- right: 0;
106
- bottom: 0;
107
- white-space: pre;
108
- overflow: auto;
109
- }
110
-
111
- .code-highlight {
112
- width: 100%;
113
- height: 100%;
114
- min-height: 300px;
115
- max-height: 500px;
116
- overflow: auto;
117
- white-space: pre;
118
- font-family: "JetBrains Mono", "Fira Code", "Menlo", "Monaco", "Courier New", monospace;
119
- font-size: 14px;
120
- line-height: 1.6;
121
- background-color: transparent !important;
122
- pointer-events: none;
123
- z-index: 5;
124
- position: absolute;
125
- top: 0;
126
- left: 0;
127
- right: 0;
128
- bottom: 0;
129
- padding: 12px;
130
- margin: 0;
131
- }
132
- </style>
133
39
  <script setup>
134
40
  import Modal from "@/components/ui/Modal.vue";
135
41
  import { FilterIcon } from "@/components/icons";
136
42
  import { useUIStore } from "@/stores/ui";
137
43
  import { ref, computed, onMounted, nextTick } from "vue";
44
+ import { DEBUG } from "@/utils/debug";
138
45
 
139
46
  const props = defineProps({
140
- filter: Object
47
+ filter: {
48
+ type: Object,
49
+ required: true
50
+ }
141
51
  });
142
52
 
143
53
  const ui = useUIStore();
144
54
  const text = ref(JSON.stringify(props.filter.out(), null, 4));
145
55
  const codeEditor = ref(null);
146
56
  const codeDisplay = ref(null);
57
+ let highlightTimer = null;
147
58
 
148
59
  // Function to highlight code using Prism
149
60
  const highlightCode = () => {
150
61
  if (!codeDisplay.value || !codeEditor.value) return;
151
62
 
152
- // Ensure Prism is available
153
- if (typeof Prism === "undefined") {
154
- console.error("Prism is not loaded");
155
- return;
156
- }
63
+ // Debounce to avoid excessive highlighting
64
+ if (highlightTimer) clearTimeout(highlightTimer);
157
65
 
158
- // Use requestAnimationFrame for smoother updates
159
- requestAnimationFrame(() => {
160
- try {
161
- // Update the pre element with highlighted HTML
162
- const highlighted = Prism.highlight(text.value || "", Prism.languages.json, "json");
163
- codeDisplay.value.innerHTML = highlighted;
164
- codeDisplay.value.className = "language-json code-highlight";
165
- } catch (e) {
166
- console.error("Highlight error:", e);
167
- // Fallback to plain text if highlighting fails
168
- codeDisplay.value.textContent = text.value || "";
169
- }
66
+ highlightTimer = setTimeout(() => {
67
+ requestAnimationFrame(() => {
68
+ try {
69
+ // Check if Prism is available
70
+ if (typeof window.Prism === "undefined" || !window.Prism.languages?.json) {
71
+ // Fallback to plain text
72
+ if (codeDisplay.value) {
73
+ codeDisplay.value.textContent = text.value || "";
74
+ codeDisplay.value.className = "language-json";
75
+ }
76
+ return;
77
+ }
170
78
 
171
- // Ensure scroll positions are synced after highlighting
172
- syncScroll();
173
- });
79
+ // Highlight the code (Prism.highlight returns sanitized HTML)
80
+ const highlighted = window.Prism.highlight(
81
+ text.value || "",
82
+ window.Prism.languages.json,
83
+ "json"
84
+ );
85
+
86
+ if (codeDisplay.value) {
87
+ codeDisplay.value.innerHTML = highlighted;
88
+ codeDisplay.value.className = "language-json code-highlight";
89
+ }
90
+ } catch (e) {
91
+ if (DEBUG) ui.logger.Error("Highlight error:", e);
92
+ // Fallback to plain text
93
+ if (codeDisplay.value) {
94
+ codeDisplay.value.textContent = text.value || "";
95
+ }
96
+ } finally {
97
+ // Always sync scroll
98
+ syncScroll();
99
+ }
100
+ });
101
+ }, 50);
174
102
  };
175
103
 
176
104
  // Function to sync scrolling between textarea and highlighted code
177
105
  const syncScroll = () => {
178
106
  if (!codeDisplay.value || !codeEditor.value) return;
179
107
 
180
- // Synchronize scrolling between the textarea and the highlighted code
181
- requestAnimationFrame(() => {
182
- codeDisplay.value.scrollTop = codeEditor.value.scrollTop;
183
- codeDisplay.value.scrollLeft = codeEditor.value.scrollLeft;
184
- });
108
+ // Direct synchronization without RAF for immediate response
109
+ codeDisplay.value.scrollTop = codeEditor.value.scrollTop;
110
+ codeDisplay.value.scrollLeft = codeEditor.value.scrollLeft;
185
111
  };
186
112
 
187
113
  // Function to handle tab key press in the editor
188
- const handleTab = (e) => {
114
+ const handleTab = () => {
189
115
  const textarea = codeEditor.value;
190
116
  const start = textarea.selectionStart;
191
117
  const end = textarea.selectionEnd;
@@ -225,10 +151,12 @@ function done() {
225
151
 
226
152
  function save() {
227
153
  const out = JSON.parse(text.value);
154
+ /* eslint-disable vue/no-mutating-props -- intentional sync from JSON to filter */
228
155
  props.filter.reset();
229
156
  props.filter.globalFilter = out.globalFilter;
230
157
  props.filter.filters = out.filters;
231
158
  props.filter.updateCss();
159
+ /* eslint-enable vue/no-mutating-props */
232
160
  done();
233
161
  }
234
162
 
@@ -241,3 +169,101 @@ const errorMessage = computed(() => {
241
169
  }
242
170
  });
243
171
  </script>
172
+
173
+ <style scoped>
174
+ /* Shared base styles for perfect alignment */
175
+ .code-editor,
176
+ .code-highlight {
177
+ position: absolute;
178
+ inset: 0;
179
+ width: 100%;
180
+ height: 100%;
181
+ min-height: 300px;
182
+ max-height: 500px;
183
+ padding: 12px;
184
+ margin: 0;
185
+ overflow: auto;
186
+ white-space: pre;
187
+ font-family: "JetBrains Mono", "Fira Code", "Menlo", "Monaco", "Courier New", monospace;
188
+ font-size: 14px;
189
+ line-height: 1.6;
190
+ tab-size: 4;
191
+ -moz-tab-size: 4;
192
+ word-wrap: normal;
193
+ word-break: normal;
194
+ border: 0;
195
+ outline: none;
196
+ background: transparent;
197
+ box-sizing: border-box;
198
+ }
199
+
200
+ /* Code editor layer - interactive */
201
+ .code-editor {
202
+ z-index: 2;
203
+ color: transparent !important;
204
+ caret-color: #ffffff;
205
+ resize: none;
206
+ }
207
+
208
+ .code-editor::selection {
209
+ background-color: rgba(38, 79, 120, 0.6);
210
+ color: transparent;
211
+ }
212
+
213
+ .code-editor::-moz-selection {
214
+ background-color: rgba(38, 79, 120, 0.6);
215
+ color: transparent;
216
+ }
217
+
218
+ /* Highlight layer - visual only */
219
+ .code-highlight {
220
+ z-index: 1;
221
+ pointer-events: none;
222
+ user-select: none;
223
+ -webkit-user-select: none;
224
+ -moz-user-select: none;
225
+ }
226
+
227
+ :deep(.token.property),
228
+ :deep(.token.tag),
229
+ :deep(.token.boolean),
230
+ :deep(.token.number),
231
+ :deep(.token.constant),
232
+ :deep(.token.symbol) {
233
+ color: #b5cea8;
234
+ }
235
+
236
+ :deep(.token.selector),
237
+ :deep(.token.attr-name),
238
+ :deep(.token.string),
239
+ :deep(.token.char),
240
+ :deep(.token.builtin) {
241
+ color: #ce9178;
242
+ }
243
+
244
+ :deep(.token.punctuation) {
245
+ color: #d4d4d4;
246
+ }
247
+
248
+ :deep(.token.operator),
249
+ :deep(.token.entity),
250
+ :deep(.token.url) {
251
+ color: #d4d4d4;
252
+ }
253
+
254
+ :deep(.token.atrule),
255
+ :deep(.token.attr-value),
256
+ :deep(.token.keyword) {
257
+ color: #c586c0;
258
+ }
259
+
260
+ :deep(.token.function),
261
+ :deep(.token.class-name) {
262
+ color: #dcdcaa;
263
+ }
264
+
265
+ :deep(.token.comment) {
266
+ color: #6a9955;
267
+ font-style: italic;
268
+ }
269
+ </style>
@@ -2,12 +2,12 @@
2
2
  <button
3
3
  @click="increase"
4
4
  :class="[
5
- 'sort-toggle',
6
- { 'darker': props.darker }
5
+ 'flex items-center gap-2 px-3 py-2 rounded text-sm font-medium focus:outline-none text-light-300 border-2 border-dark-550 h-10',
6
+ props.darker ? 'bg-dark-400 min-w-25' : 'bg-dark-350 min-w-20'
7
7
  ]"
8
8
  >
9
- <component :is="getCurrentIcon()" class="icon" />
10
- <span class="text">{{ getCurrentText() }}</span>
9
+ <component :is="getCurrentIcon()" class="w-4 h-4 flex-shrink-0" />
10
+ <span class="text-center flex-1">{{ getCurrentText() }}</span>
11
11
  </button>
12
12
  </template>
13
13
 
@@ -19,13 +19,34 @@ let sortOptions = ref(["none", "asc", "desc", "none"]);
19
19
  const currentOpt = ref(0);
20
20
 
21
21
  const props = defineProps({
22
- filter: Object,
23
- index: Number,
24
- expandedFilter: Number,
25
- filterBuilder: Object,
26
- options: Object,
27
- current: String,
28
- darker: Boolean
22
+ filter: {
23
+ type: Object,
24
+ default: () => ({})
25
+ },
26
+ index: {
27
+ type: Number,
28
+ default: 0
29
+ },
30
+ expandedFilter: {
31
+ type: Number,
32
+ default: null
33
+ },
34
+ filterBuilder: {
35
+ type: Object,
36
+ default: () => ({})
37
+ },
38
+ options: {
39
+ type: Array,
40
+ default: () => ['none', 'asc', 'desc', 'none']
41
+ },
42
+ current: {
43
+ type: String,
44
+ default: 'none'
45
+ },
46
+ darker: {
47
+ type: Boolean,
48
+ default: false
49
+ }
29
50
  });
30
51
 
31
52
  if (props.options) sortOptions.value = props.options;
@@ -40,7 +61,7 @@ const increase = () => {
40
61
 
41
62
  const getCurrentIcon = () => {
42
63
  const current = sortOptions.value[currentOpt.value];
43
-
64
+
44
65
  // Handle filter options (All, WL, BL)
45
66
  if (props.options && props.options.includes('All')) {
46
67
  switch (current) {
@@ -50,7 +71,7 @@ const getCurrentIcon = () => {
50
71
  default: return FilterIcon;
51
72
  }
52
73
  }
53
-
74
+
54
75
  // Handle sort options (none, asc, desc)
55
76
  switch (current) {
56
77
  case 'asc': return UpIcon;
@@ -62,12 +83,12 @@ const getCurrentIcon = () => {
62
83
 
63
84
  const getCurrentText = () => {
64
85
  const current = sortOptions.value[currentOpt.value];
65
-
86
+
66
87
  // Handle filter options (All, WL, BL)
67
88
  if (props.options && props.options.includes('All')) {
68
89
  return current;
69
90
  }
70
-
91
+
71
92
  // Handle sort options
72
93
  switch (current) {
73
94
  case 'asc': return 'Low';
@@ -77,31 +98,3 @@ const getCurrentText = () => {
77
98
  }
78
99
  };
79
100
  </script>
80
-
81
- <style scoped>
82
- .sort-toggle {
83
- @apply flex items-center gap-2 px-3 py-2 rounded text-sm font-medium focus:outline-none;
84
- background: oklch(0.2603 0 0);
85
- border: 2px solid oklch(0.2809 0 0);
86
- color: oklch(0.90 0 0);
87
- min-width: 80px;
88
- height: 40px;
89
- }
90
-
91
- .sort-toggle.darker {
92
- background: oklch(0.2046 0 0);
93
- border: 2px solid oklch(0.2809 0 0);
94
- color: oklch(0.90 0 0);
95
- min-width: 100px;
96
- height: 40px;
97
- padding: 0 0.75rem;
98
- }
99
-
100
- .icon {
101
- @apply w-4 h-4 flex-shrink-0;
102
- }
103
-
104
- .text {
105
- @apply text-center flex-1;
106
- }
107
- </style>
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <div class="border-b border-dark-600 w-full px-2 md:px-4 text-white text-xs py-4 grid items-center bg-dark-300">
2
+ <div class="relative border-b border-dark-550 w-full px-2 md:px-4 text-white text-xs py-4 grid items-center bg-dark-300">
3
3
  <slot />
4
4
  </div>
5
5
  </template>
@@ -1,24 +1,73 @@
1
1
  <template>
2
- <div class="table-component">
2
+ <div class="table-component" style="border-color: var(--color-border);">
3
3
  <slot />
4
4
  </div>
5
5
  </template>
6
- <style lang="scss">
6
+
7
+ <style scoped lang="scss">
7
8
  .table-component {
8
- @apply flex-col bg-clip-padding rounded relative box-border border border-dark-600 bg-dark-500;
9
- @apply overflow-x-auto overflow-y-auto touch-pan-x touch-pan-y;
10
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
11
- overscroll-behavior: auto;
9
+ @apply relative box-border flex flex-col rounded-lg;
10
+ @apply bg-dark-500 bg-clip-padding overflow-auto shadow-sm;
11
+
12
12
  max-height: calc(100vh - 200px);
13
+ overscroll-behavior: auto;
13
14
  -webkit-overflow-scrolling: touch;
14
- }
15
+ touch-action: pan-x pan-y;
15
16
 
16
- .table-component > .grid {
17
- @apply bg-dark-400;
18
- border-bottom: 1px solid oklch(0.26 0 0);
19
- // Only enforce min-width on desktop, allow mobile to fit screen
20
17
  @media (min-width: 768px) {
21
- min-width: 640px;
18
+ max-height: calc(100vh - 280px);
19
+ }
20
+
21
+ @media (min-width: 1024px) {
22
+ max-height: calc(100vh - 240px);
23
+ }
24
+
25
+ @media (min-width: 1280px) {
26
+ max-height: calc(100vh - 220px);
27
+ }
28
+
29
+ @media (display-mode: standalone) {
30
+ max-height: calc(100vh - 240px);
31
+
32
+ @media (min-width: 768px) {
33
+ max-height: calc(100vh - 320px);
34
+ }
35
+
36
+ @media (min-width: 1024px) {
37
+ max-height: calc(100vh - 280px);
38
+ }
39
+
40
+ @media (min-width: 1280px) {
41
+ max-height: calc(100vh - 260px);
42
+ }
43
+ }
44
+
45
+ & > :not(:first-child) {
46
+ @apply border-b border-dark-500;
47
+
48
+ @media (min-width: 768px) {
49
+ min-width: 640px;
50
+ }
51
+ }
52
+
53
+ & > :last-child {
54
+ @apply border-b-0 rounded-b-lg overflow-hidden;
55
+ }
56
+
57
+ & > :nth-child(odd) {
58
+ @apply bg-dark-300;
59
+ }
60
+
61
+ & > :nth-child(even) {
62
+ @apply bg-dark-400;
63
+ }
64
+
65
+ & > :first-child {
66
+ @apply border-b border-dark-500 rounded-t-lg overflow-hidden;
67
+
68
+ @media (min-width: 768px) {
69
+ min-width: 640px;
70
+ }
22
71
  }
23
72
  }
24
73
  </style>
@@ -3,7 +3,7 @@
3
3
  <template #header> Check Stock <BoxIcon class="ml-4" /> </template>
4
4
  <!-- Event ID -->
5
5
  <div class="input-wrapper mt-7 mb-4">
6
- <label class="label-override mb-2">Event ID or URL <StadiumIcon /></label>
6
+ <label class="label-override mb-2 flex">Event ID or URL <StadiumIcon /></label>
7
7
  <div class="input-default required">
8
8
  <input
9
9
  :placeholder="!isEU(ui.currentCountry.siteId) ? '102PDA9125510GYU' : '529171'"
@@ -13,46 +13,37 @@
13
13
  </div>
14
14
  <!-- Presale Code -->
15
15
  <div class="input-wrapper mb-4">
16
- <label class="label-override mb-2">Presale code <AwardIcon /></label>
16
+ <label class="label-override mb-2 flex">Presale code <AwardIcon /></label>
17
17
  <div class="input-default">
18
18
  <input placeholder="Presale code" v-model="presaleCode" />
19
19
  </div>
20
20
  </div>
21
21
  <!-- DID -->
22
22
  <div class="input-wrapper mb-4" v-if="!isEU(ui.currentCountry.siteId)">
23
- <label class="label-override mb-2">DID <AwardIcon /></label>
23
+ <label class="label-override mb-2 flex">DID <AwardIcon /></label>
24
24
  <div class="input-default">
25
25
  <input placeholder="psl" v-model="eventDid" />
26
26
  </div>
27
27
  </div>
28
28
  <!-- CL ORIGIN -->
29
29
  <div class="input-wrapper mb-8" v-if="isEU(ui.currentCountry.siteId)">
30
- <label class="label-override mb-2">CL Origin / SubChannel ID <AwardIcon /></label>
30
+ <label class="label-override mb-2 flex">CL Origin / SubChannel ID <AwardIcon /></label>
31
31
  <div class="input-default">
32
32
  <input placeholder="ORIGIN2" v-model="clOrigin" />
33
33
  </div>
34
34
  </div>
35
- <button
36
- class="button-default ml-auto mt-4 flex w-48 items-center justify-center gap-x-2 bg-dark-400 text-xs"
37
- @click="done()">
35
+ <button class="btn-modal ml-auto mt-4 w-48" @click="done()">
38
36
  Check Stock
39
- <BoxIcon />
37
+ <BoxIcon class="ml-2" />
40
38
  </button>
41
39
  </Modal>
42
40
  </template>
43
- <style lang="scss" scoped>
44
- .input-wrapper {
45
- label {
46
- @apply flex;
47
- }
48
- }
49
- </style>
50
41
  <script setup>
51
42
  import Modal from "@/components/ui/Modal.vue";
52
43
  import { StadiumIcon, BoxIcon, AwardIcon } from "@/components/icons";
53
44
  import { useUIStore } from "@/stores/ui";
54
45
  import { ref } from "vue";
55
- import { isEU } from "@/stores/utils";
46
+ import { isEU } from "@/libs/utils/eventUrl";
56
47
 
57
48
  const ui = useUIStore();
58
49
  const eventId = ref("");