@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.
- package/backend/api.js +2 -3
- package/eslint.config.js +46 -0
- package/index.html +2 -1
- package/package.json +5 -2
- package/src/App.vue +140 -170
- package/src/assets/css/base/mixins.scss +72 -0
- package/src/assets/css/base/reset.scss +0 -2
- package/src/assets/css/base/scroll.scss +43 -36
- package/src/assets/css/base/typography.scss +9 -10
- package/src/assets/css/base/variables.scss +43 -0
- package/src/assets/css/components/accessibility.scss +37 -0
- package/src/assets/css/components/buttons.scss +58 -15
- package/src/assets/css/components/forms.scss +31 -32
- package/src/assets/css/components/headers.scss +119 -0
- package/src/assets/css/components/modals.scss +2 -2
- package/src/assets/css/components/search-groups.scss +28 -19
- package/src/assets/css/components/tables.scss +5 -7
- package/src/assets/css/components/toasts.scss +7 -7
- package/src/assets/css/components/utilities.scss +220 -0
- package/src/assets/css/main.scss +72 -75
- package/src/components/Auth/LoginForm.vue +5 -84
- package/src/components/Editors/Account/Account.vue +8 -10
- package/src/components/Editors/Account/AccountCreator.vue +28 -59
- package/src/components/Editors/Account/AccountView.vue +38 -86
- package/src/components/Editors/Account/CreateAccount.vue +8 -50
- package/src/components/Editors/Profile/CreateProfile.vue +74 -131
- package/src/components/Editors/Profile/Profile.vue +15 -17
- package/src/components/Editors/Profile/ProfileCountryChooser.vue +16 -60
- package/src/components/Editors/Profile/ProfileView.vue +46 -96
- package/src/components/Editors/TagLabel.vue +16 -55
- package/src/components/Editors/TagToggle.vue +20 -8
- package/src/components/Filter/Filter.vue +62 -75
- package/src/components/Filter/FilterPreview.vue +161 -135
- package/src/components/Filter/PriceSortToggle.vue +36 -43
- package/src/components/Table/Header.vue +1 -1
- package/src/components/Table/Table.vue +61 -12
- package/src/components/Tasks/CheckStock.vue +7 -16
- package/src/components/Tasks/Controls/DesktopControls.vue +15 -60
- package/src/components/Tasks/Controls/MobileControls.vue +5 -20
- package/src/components/Tasks/CreateTaskAXS.vue +20 -118
- package/src/components/Tasks/CreateTaskTM.vue +33 -189
- package/src/components/Tasks/EventDetailRow.vue +21 -0
- package/src/components/Tasks/MassEdit.vue +6 -16
- package/src/components/Tasks/QuickSettings.vue +140 -216
- package/src/components/Tasks/ScrapeVenue.vue +4 -13
- package/src/components/Tasks/Stats.vue +19 -38
- package/src/components/Tasks/Task.vue +65 -268
- package/src/components/Tasks/TaskLabel.vue +9 -3
- package/src/components/Tasks/TaskView.vue +43 -63
- package/src/components/Tasks/Utilities.vue +10 -42
- package/src/components/Tasks/ViewTask.vue +23 -107
- package/src/components/icons/Close.vue +2 -8
- package/src/components/icons/Gear.vue +8 -8
- package/src/components/icons/Hash.vue +5 -0
- package/src/components/icons/Key.vue +2 -8
- package/src/components/icons/Pencil.vue +2 -8
- package/src/components/icons/Profile.vue +2 -8
- package/src/components/icons/Sell.vue +2 -8
- package/src/components/icons/Spinner.vue +4 -7
- package/src/components/icons/SquareCheck.vue +2 -8
- package/src/components/icons/SquareUncheck.vue +2 -8
- package/src/components/icons/Wildcard.vue +2 -8
- package/src/components/icons/index.js +3 -1
- package/src/components/ui/ActionButtonGroup.vue +113 -52
- package/src/components/ui/BalanceIndicator.vue +60 -0
- package/src/components/ui/EmptyState.vue +24 -0
- package/src/components/ui/EnableDisableToggle.vue +23 -0
- package/src/components/ui/FormField.vue +48 -48
- package/src/components/ui/IconLabel.vue +23 -0
- package/src/components/ui/InfoRow.vue +21 -54
- package/src/components/ui/Modal.vue +78 -37
- package/src/components/ui/Navbar.vue +60 -41
- package/src/components/ui/ReadonlyFieldsSection.vue +31 -0
- package/src/components/ui/ReconnectIndicator.vue +111 -124
- package/src/components/ui/SectionCard.vue +6 -14
- package/src/components/ui/Splash.vue +2 -10
- package/src/components/ui/StatusBadge.vue +26 -28
- package/src/components/ui/TaskToggle.vue +54 -0
- package/src/components/ui/controls/CountryChooser.vue +27 -64
- package/src/components/ui/controls/EyeToggle.vue +1 -1
- package/src/components/ui/controls/atomic/Checkbox.vue +40 -121
- package/src/components/ui/controls/atomic/Dropdown.vue +102 -95
- package/src/components/ui/controls/atomic/MultiDropdown.vue +72 -94
- package/src/components/ui/controls/atomic/Switch.vue +21 -84
- package/src/composables/useColorMapping.js +15 -0
- package/src/composables/useCopyToClipboard.js +1 -1
- package/src/composables/useDateFormatting.js +21 -0
- package/src/composables/useDeviceDetection.js +14 -0
- package/src/composables/useDropdownPosition.js +5 -6
- package/src/composables/useDynamicTableHeight.js +31 -0
- package/src/composables/useRowSelection.js +0 -3
- package/src/composables/useTicketPricing.js +16 -0
- package/src/composables/useWindowDimensions.js +21 -0
- package/src/libs/Filter.js +14 -20
- package/src/libs/panzoom.js +1 -5
- package/src/libs/utils/array.js +60 -0
- package/src/{stores/utils.js → libs/utils/dataGeneration.js} +2 -250
- package/src/libs/utils/eventUrl.js +40 -0
- package/src/libs/utils/string.js +28 -0
- package/src/libs/utils/time.js +20 -0
- package/src/libs/utils/validation.js +88 -0
- package/src/main.js +0 -2
- package/src/stores/connection.js +1 -4
- package/src/stores/logger.js +6 -12
- package/src/stores/sampleData.js +1 -2
- package/src/stores/ui.js +59 -36
- package/src/views/Accounts.vue +17 -31
- package/src/views/Console.vue +76 -176
- package/src/views/Editor.vue +217 -383
- package/src/views/FilterBuilder.vue +190 -373
- package/src/views/Login.vue +3 -28
- package/src/views/Profiles.vue +12 -22
- package/src/views/Tasks.vue +51 -38
- package/tailwind.config.js +82 -71
- package/workbox-config.cjs +47 -5
- package/docs/plans/2026-02-08-tailwind-consolidation.md +0 -2416
- package/exit +0 -209
- package/run +0 -177
- package/switch-branch.sh +0 -41
- /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="
|
|
10
|
-
<div class="
|
|
11
|
-
<pre ref="codeDisplay" class="language-json
|
|
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
|
|
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
|
|
27
|
-
|
|
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:
|
|
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
|
-
//
|
|
153
|
-
if (
|
|
154
|
-
console.error("Prism is not loaded");
|
|
155
|
-
return;
|
|
156
|
-
}
|
|
63
|
+
// Debounce to avoid excessive highlighting
|
|
64
|
+
if (highlightTimer) clearTimeout(highlightTimer);
|
|
157
65
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
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
|
-
|
|
172
|
-
|
|
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
|
-
//
|
|
181
|
-
|
|
182
|
-
|
|
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 = (
|
|
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
|
-
'
|
|
6
|
-
|
|
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="
|
|
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:
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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-
|
|
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
|
-
|
|
6
|
+
|
|
7
|
+
<style scoped lang="scss">
|
|
7
8
|
.table-component {
|
|
8
|
-
@apply
|
|
9
|
-
@apply
|
|
10
|
-
|
|
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
|
-
|
|
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 "@/
|
|
46
|
+
import { isEU } from "@/libs/utils/eventUrl";
|
|
56
47
|
|
|
57
48
|
const ui = useUIStore();
|
|
58
49
|
const eventId = ref("");
|