@necrolab/dashboard 0.5.34 → 0.5.35
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/package.json +1 -1
- package/src/assets/css/components/headers.scss +10 -4
- package/src/assets/css/components/toasts.scss +17 -1
- package/src/assets/css/main.scss +1 -0
- package/src/components/Tasks/Stats.vue +5 -1
- package/src/components/Tasks/Task.vue +10 -4
- package/src/components/Tasks/TaskView.vue +32 -28
- package/src/libs/Filter.js +0 -4
- package/src/main.js +5 -0
- package/src/stores/ui.js +27 -5
- package/src/views/Tasks.vue +23 -23
package/package.json
CHANGED
|
@@ -7,19 +7,25 @@
|
|
|
7
7
|
@apply flex items-center justify-between;
|
|
8
8
|
padding-top: 0.75rem;
|
|
9
9
|
padding-bottom: 0.5rem;
|
|
10
|
-
flex-wrap: nowrap;
|
|
10
|
+
flex-wrap: nowrap !important;
|
|
11
11
|
gap: 0.5rem;
|
|
12
|
+
min-height: 0;
|
|
12
13
|
|
|
13
14
|
.page-header-card {
|
|
14
15
|
@apply flex items-center gap-2.5 rounded-lg;
|
|
15
16
|
padding: 0.375rem 0.75rem;
|
|
16
17
|
background: linear-gradient(135deg, var(--color-gradient-start) 0%, var(--color-gradient-end) 100%);
|
|
17
18
|
border: 1px solid var(--color-border-light);
|
|
18
|
-
flex: 0
|
|
19
|
+
flex: 0 0 auto;
|
|
19
20
|
min-width: 0;
|
|
20
|
-
max-width: 60%;
|
|
21
21
|
white-space: nowrap;
|
|
22
|
-
|
|
22
|
+
|
|
23
|
+
/* Mobile - allow shrinking if needed */
|
|
24
|
+
@media (max-width: 767px) {
|
|
25
|
+
flex: 0 1 auto;
|
|
26
|
+
max-width: calc(100% - 180px);
|
|
27
|
+
gap: 0.5rem;
|
|
28
|
+
}
|
|
23
29
|
|
|
24
30
|
svg, img {
|
|
25
31
|
width: 17px;
|
|
@@ -38,17 +38,33 @@
|
|
|
38
38
|
.Toastify__toast-container {
|
|
39
39
|
pointer-events: none;
|
|
40
40
|
--toastify-toast-bd-radius: 6px;
|
|
41
|
+
|
|
42
|
+
/* Mobile responsive - prevent overflow and edge-to-edge toasts */
|
|
43
|
+
@media (max-width: 767px) {
|
|
44
|
+
width: calc(100vw - 2rem) !important;
|
|
45
|
+
max-width: 360px;
|
|
46
|
+
right: 1rem !important;
|
|
47
|
+
left: auto !important;
|
|
48
|
+
padding: 0 !important;
|
|
49
|
+
top: calc(env(safe-area-inset-top) + 1rem) !important;
|
|
50
|
+
}
|
|
41
51
|
}
|
|
42
52
|
|
|
43
53
|
.Toastify__toast {
|
|
44
54
|
min-height: 50px !important;
|
|
45
|
-
height:
|
|
55
|
+
height: auto !important;
|
|
46
56
|
pointer-events: auto !important;
|
|
47
57
|
margin-bottom: 6px !important;
|
|
48
58
|
|
|
49
59
|
transition: transform 0.18s cubic-bezier(0.25, 0.1, 0.25, 1), opacity 0.12s cubic-bezier(0.25, 0.1, 0.25, 1) !important;
|
|
50
60
|
transform: translate3d(0, 0, 0);
|
|
51
61
|
|
|
62
|
+
/* Mobile responsive - ensure proper sizing */
|
|
63
|
+
@media (max-width: 767px) {
|
|
64
|
+
margin-bottom: 8px !important;
|
|
65
|
+
border-radius: 6px !important;
|
|
66
|
+
}
|
|
67
|
+
|
|
52
68
|
&.Toastify__slide-enter-active {
|
|
53
69
|
animation: slideInRight 0.22s cubic-bezier(0.25, 0.1, 0.25, 1);
|
|
54
70
|
}
|
package/src/assets/css/main.scss
CHANGED
|
@@ -114,6 +114,7 @@ svg:not([stroke]):not([fill="none"]) polygon:not([fill]) {
|
|
|
114
114
|
|
|
115
115
|
.mobile-icons {
|
|
116
116
|
@apply ml-auto flex items-center gap-x-2 lg:hidden;
|
|
117
|
+
flex-shrink: 0;
|
|
117
118
|
|
|
118
119
|
button {
|
|
119
120
|
@apply flex h-8 w-8 items-center justify-center rounded transition-all duration-150 bg-dark-400;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div
|
|
3
3
|
class="queue-stats"
|
|
4
|
-
:class="{ 'queue-stats--full': visibleCards === 4 }"
|
|
4
|
+
:class="[{ 'queue-stats--full': visibleCards === 4 }, $attrs.class]"
|
|
5
5
|
:style="statsGridStyle"
|
|
6
6
|
v-if="ui.queueStats.show"
|
|
7
7
|
:key="key">
|
|
@@ -91,6 +91,10 @@ import { SkiIcon, TimerIcon, SandclockIcon } from "@/components/icons";
|
|
|
91
91
|
import { useUIStore } from "@/stores/ui";
|
|
92
92
|
import { ref, onUnmounted, computed, onMounted } from "vue";
|
|
93
93
|
|
|
94
|
+
defineOptions({
|
|
95
|
+
inheritAttrs: false
|
|
96
|
+
});
|
|
97
|
+
|
|
94
98
|
const ui = useUIStore();
|
|
95
99
|
|
|
96
100
|
const getQueuePassAmount = (width) => {
|
|
@@ -85,8 +85,8 @@
|
|
|
85
85
|
</div>
|
|
86
86
|
</div>
|
|
87
87
|
<div class="col-span-2 overflow-hidden lg:col-span-3 xl:col-span-2">
|
|
88
|
-
<h4 class="lg:text-2xs text-center text-xs leading-tight
|
|
89
|
-
<span v-if="!props.task.reservedTicketsList">-</span>
|
|
88
|
+
<h4 class="lg:text-2xs text-center text-xs leading-tight">
|
|
89
|
+
<span v-if="!props.task.reservedTicketsList" class="text-light-300">-</span>
|
|
90
90
|
<div v-else class="overflow-hidden">
|
|
91
91
|
<div
|
|
92
92
|
v-for="(l, index) in props.task.reservedTicketsList.split('\n')"
|
|
@@ -99,7 +99,12 @@
|
|
|
99
99
|
'font-bold text-green-400': isTotalPrice(
|
|
100
100
|
l,
|
|
101
101
|
index,
|
|
102
|
-
props.task.reservedTicketsList.split('
|
|
102
|
+
props.task.reservedTicketsList.split('\n')
|
|
103
|
+
),
|
|
104
|
+
'text-light-300': !isTotalPrice(
|
|
105
|
+
l,
|
|
106
|
+
index,
|
|
107
|
+
props.task.reservedTicketsList.split('\n')
|
|
103
108
|
)
|
|
104
109
|
}">
|
|
105
110
|
{{ l.trim() }}
|
|
@@ -109,7 +114,8 @@
|
|
|
109
114
|
<span
|
|
110
115
|
class="mt-1 block text-xs font-bold"
|
|
111
116
|
:class="{
|
|
112
|
-
'text-red-400': taskTimeLeft === '00:00' || taskTimeLeft === 'No Cartholds'
|
|
117
|
+
'text-red-400': taskTimeLeft === '00:00' || taskTimeLeft === 'No Cartholds',
|
|
118
|
+
'text-light-300': taskTimeLeft !== '00:00' && taskTimeLeft !== 'No Cartholds'
|
|
113
119
|
}">
|
|
114
120
|
{{ taskTimeLeft !== "00:00" ? taskTimeLeft : "Expired" }}
|
|
115
121
|
</span>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div
|
|
2
|
+
<div
|
|
3
|
+
class="table-component relative box-border flex flex-col overflow-x-hidden rounded-lg bg-dark-500 bg-clip-padding shadow-sm">
|
|
3
4
|
<Header class="grid-cols-10 gap-2 text-center lg:grid-cols-12">
|
|
4
5
|
<div class="col-span-1 flex items-center justify-start lg:col-span-2">
|
|
5
6
|
<Checkbox
|
|
@@ -9,26 +10,26 @@
|
|
|
9
10
|
:isHeader="true" />
|
|
10
11
|
<div class="mx-auto hidden items-center lg:flex" @click="ui.toggleSort('eventId')">
|
|
11
12
|
<EventIcon class="lg:mr-3" />
|
|
12
|
-
<h4 class="hidden lg:flex
|
|
13
|
+
<h4 class="hidden text-white lg:flex">Event</h4>
|
|
13
14
|
<DownIcon v-if="ui.sortData.sortBy === 'eventId' && !ui.sortData.reversed" class="ml-1" />
|
|
14
15
|
<UpIcon v-if="ui.sortData.sortBy === 'eventId' && ui.sortData.reversed" class="ml-1" />
|
|
15
16
|
</div>
|
|
16
17
|
</div>
|
|
17
18
|
<div class="col-span-2 flex items-center justify-center lg:col-span-3 xl:col-span-2" v-once>
|
|
18
19
|
<TicketIcon class="mr-0 lg:mr-3" />
|
|
19
|
-
<h4 class="hidden lg:flex
|
|
20
|
+
<h4 class="hidden text-white lg:flex">Tickets</h4>
|
|
20
21
|
</div>
|
|
21
22
|
<div
|
|
22
23
|
class="col-span-6 flex items-center justify-center md:col-span-5 lg:col-span-4 xl:col-span-5"
|
|
23
24
|
@click="ui.toggleSort('status')">
|
|
24
25
|
<StatusIcon class="mr-0 lg:mr-3" />
|
|
25
|
-
<h4 class="hidden lg:flex
|
|
26
|
+
<h4 class="hidden text-white lg:flex">Status</h4>
|
|
26
27
|
<DownIcon v-if="ui.sortData.sortBy === 'status' && !ui.sortData.reversed" class="ml-1" />
|
|
27
28
|
<UpIcon v-if="ui.sortData.sortBy === 'status' && ui.sortData.reversed" class="ml-1" />
|
|
28
29
|
</div>
|
|
29
30
|
<div class="col-span-1 flex items-center justify-end md:col-span-2 md:justify-center lg:col-span-3" v-once>
|
|
30
31
|
<ClickIcon class="mr-0 lg:mr-3" />
|
|
31
|
-
<h4 class="hidden lg:flex
|
|
32
|
+
<h4 class="hidden text-white lg:flex">Actions</h4>
|
|
32
33
|
</div>
|
|
33
34
|
<div class="absolute right-5 top-3.5 hidden items-center xl:flex">
|
|
34
35
|
<h4 class="text-center text-xs text-white">ID</h4>
|
|
@@ -36,7 +37,7 @@
|
|
|
36
37
|
</Header>
|
|
37
38
|
<DynamicScroller
|
|
38
39
|
v-if="virtualTaskItems.length && useVirtualScroller"
|
|
39
|
-
class="hidden-scrollbars
|
|
40
|
+
class="hidden-scrollbars scrollable min-h-0 touch-pan-y overflow-y-auto overflow-x-hidden"
|
|
40
41
|
:style="{ height: maxTableHeight, maxHeight: maxTableHeight }"
|
|
41
42
|
:items="virtualTaskItems"
|
|
42
43
|
:min-item-size="virtualMinItemSize"
|
|
@@ -56,7 +57,7 @@
|
|
|
56
57
|
]"
|
|
57
58
|
:data-index="index">
|
|
58
59
|
<div
|
|
59
|
-
class="shrink-0 border-b border-dark-650
|
|
60
|
+
class="mobile-portrait:min-h-12.5 min-h-14.5 shrink-0 border-b border-dark-650 transition-colors duration-150 ease-in-out hover:!bg-dark-550 has-[.event-details]:min-h-18.75 md:min-h-17.25">
|
|
60
61
|
<Task
|
|
61
62
|
v-if="props.tasks[item.taskId]"
|
|
62
63
|
:task="props.tasks[item.taskId]"
|
|
@@ -68,12 +69,12 @@
|
|
|
68
69
|
</DynamicScroller>
|
|
69
70
|
<div
|
|
70
71
|
v-else-if="virtualTaskItems.length"
|
|
71
|
-
class="hidden-scrollbars
|
|
72
|
+
class="hidden-scrollbars scrollable min-h-0 touch-pan-y overflow-y-auto overflow-x-hidden"
|
|
72
73
|
:style="{ maxHeight: maxTableHeight }">
|
|
73
74
|
<div
|
|
74
75
|
v-for="(item, index) in virtualTaskItems"
|
|
75
76
|
:key="item.taskId"
|
|
76
|
-
class="shrink-0 border-b border-dark-650
|
|
77
|
+
class="mobile-portrait:min-h-12.5 min-h-14.5 shrink-0 border-b border-dark-650 transition-colors duration-150 ease-in-out hover:!bg-dark-550 has-[.event-details]:min-h-18.75 md:min-h-17.25">
|
|
77
78
|
<Task
|
|
78
79
|
v-if="props.tasks[item.taskId]"
|
|
79
80
|
:task="props.tasks[item.taskId]"
|
|
@@ -83,18 +84,15 @@
|
|
|
83
84
|
</div>
|
|
84
85
|
<div
|
|
85
86
|
v-else
|
|
86
|
-
class="empty-state flex flex-col items-center justify-center py-8 text-center
|
|
87
|
+
class="empty-state flex flex-col items-center justify-center bg-dark-400 py-8 text-center text-sm font-medium text-light-500"
|
|
87
88
|
:style="{ minHeight: emptyStateHeight }">
|
|
88
|
-
<div
|
|
89
|
-
|
|
90
|
-
!ui.queueStats.queued && !ui.queueStats.sleeping && ui.queueStats.nextQueuePasses.length === 0
|
|
91
|
-
">
|
|
92
|
-
<TasksIcon class="mx-auto empty-state-icon" />
|
|
89
|
+
<div v-if="!ui.queueStats.queued && !ui.queueStats.sleeping && ui.queueStats.nextQueuePasses.length === 0">
|
|
90
|
+
<TasksIcon class="empty-state-icon mx-auto" />
|
|
93
91
|
<p class="text-sm text-light-400">No tasks yet</p>
|
|
94
92
|
<p class="mt-1 text-xs text-light-500">Create tasks to get started</p>
|
|
95
93
|
</div>
|
|
96
94
|
<div v-else>
|
|
97
|
-
<TasksIcon class="
|
|
95
|
+
<TasksIcon class="empty-state-icon mx-auto" />
|
|
98
96
|
<p class="text-sm text-light-400">No tasks match current filters</p>
|
|
99
97
|
<p class="mt-1 text-xs text-light-500">Adjust filters to see tasks</p>
|
|
100
98
|
</div>
|
|
@@ -118,7 +116,7 @@ const props = defineProps({
|
|
|
118
116
|
},
|
|
119
117
|
searchQuery: {
|
|
120
118
|
type: String,
|
|
121
|
-
default:
|
|
119
|
+
default: ""
|
|
122
120
|
},
|
|
123
121
|
preferEventName: {
|
|
124
122
|
type: Boolean,
|
|
@@ -203,7 +201,11 @@ const filteredTaskIds = computed(() => {
|
|
|
203
201
|
continue;
|
|
204
202
|
}
|
|
205
203
|
|
|
206
|
-
if (
|
|
204
|
+
if (
|
|
205
|
+
task.siteId !== ui.currentCountry.siteId &&
|
|
206
|
+
!siteIdEdgeCases[task.siteId]?.includes(ui.currentCountry.siteId)
|
|
207
|
+
)
|
|
208
|
+
continue;
|
|
207
209
|
if (ui.currentEvent && task.eventId !== ui.currentEvent) continue;
|
|
208
210
|
if (!shouldTaskShow(task)) continue;
|
|
209
211
|
if (!shouldTaskMatchSearch(task, searchLower)) continue;
|
|
@@ -264,7 +266,7 @@ const handleVirtualWheel = (event) => {
|
|
|
264
266
|
|
|
265
267
|
const maxTableHeight = computed(() => {
|
|
266
268
|
// Detect PWA mode (standalone display)
|
|
267
|
-
const isPWA = window.matchMedia(
|
|
269
|
+
const isPWA = window.matchMedia("(display-mode: standalone)").matches;
|
|
268
270
|
|
|
269
271
|
// Calculate available space for table
|
|
270
272
|
const headerHeight = windowWidth.value >= 1024 ? 80 : 64; // Navbar padding (lg:pt-20 vs pt-16)
|
|
@@ -292,15 +294,17 @@ const maxTableHeight = computed(() => {
|
|
|
292
294
|
})();
|
|
293
295
|
|
|
294
296
|
// Reserve more space for UTILS on iPhone PWA to prevent overflow
|
|
295
|
-
const utilitiesHeight =
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
297
|
+
const utilitiesHeight =
|
|
298
|
+
isPWA && windowWidth.value <= 768
|
|
299
|
+
? 150 // iPhone PWA: extra space for UTILS
|
|
300
|
+
: windowWidth.value > 1024
|
|
301
|
+
? 200 // Desktop
|
|
302
|
+
: windowWidth.value <= 768
|
|
303
|
+
? 150 // Mobile browser
|
|
304
|
+
: 210; // Tablet
|
|
305
|
+
|
|
306
|
+
const margins =
|
|
307
|
+
windowWidth.value >= 1024 ? 30 : windowWidth.value <= 480 && windowHeight.value > windowWidth.value ? 8 : 12;
|
|
304
308
|
|
|
305
309
|
const totalUsedSpace =
|
|
306
310
|
headerHeight + titleHeight + controlsHeight + filtersAndStatsHeight + utilitiesHeight + margins;
|
package/src/libs/Filter.js
CHANGED
|
@@ -164,7 +164,6 @@ const getSectionNameMapping = () => {
|
|
|
164
164
|
}
|
|
165
165
|
});
|
|
166
166
|
|
|
167
|
-
log("getSectionNameMapping:", sectionRealName);
|
|
168
167
|
return sectionRealName;
|
|
169
168
|
};
|
|
170
169
|
|
|
@@ -583,14 +582,11 @@ export default class FilterBuilder {
|
|
|
583
582
|
// Use BOTH stroke and fill to cover entire section area, not just row lines
|
|
584
583
|
this.cssClasses += `.svg-wrapper path.hover-highlight-stroke {stroke: ${colors.HIGHLIGHT} !important; fill: ${colors.HIGHLIGHT} !important; fill-opacity: 0.3 !important;}\n`;
|
|
585
584
|
this.cssClasses += `.svg-wrapper path.hover-highlight-fill {fill: ${colors.HIGHLIGHT} !important;}\n`;
|
|
586
|
-
|
|
587
|
-
log("Generated CSS:", this.cssClasses);
|
|
588
585
|
}
|
|
589
586
|
|
|
590
587
|
addLabelHandlers() {
|
|
591
588
|
const labels = document.querySelectorAll("tspan");
|
|
592
589
|
const gaSectionNameMapping = this.getSectionNameMapping();
|
|
593
|
-
log("addLabelHandlers: gaSectionNameMapping", gaSectionNameMapping);
|
|
594
590
|
|
|
595
591
|
for (let i = 0; i < labels.length; i++) {
|
|
596
592
|
const label = labels[i];
|
package/src/main.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createApp } from "vue";
|
|
2
2
|
import { createPinia } from "pinia";
|
|
3
3
|
import VueVirtualScroller from "vue-virtual-scroller";
|
|
4
|
+
import Vue3Toastify from "vue3-toastify";
|
|
4
5
|
|
|
5
6
|
import App from "./App.vue";
|
|
6
7
|
import router from "./router";
|
|
@@ -18,4 +19,8 @@ app.config.performance = true;
|
|
|
18
19
|
app.use(createPinia());
|
|
19
20
|
app.use(router);
|
|
20
21
|
app.use(VueVirtualScroller);
|
|
22
|
+
app.use(Vue3Toastify, {
|
|
23
|
+
newestOnTop: true,
|
|
24
|
+
position: "top-right"
|
|
25
|
+
});
|
|
21
26
|
app.mount("#app");
|
package/src/stores/ui.js
CHANGED
|
@@ -5,6 +5,10 @@ import { toast } from "vue3-toastify";
|
|
|
5
5
|
import { createLogger } from "@/stores/logger";
|
|
6
6
|
import { betterSort, sortTaskIds } from "@/libs/utils/array";
|
|
7
7
|
|
|
8
|
+
// Track active toast IDs for manual limit enforcement
|
|
9
|
+
const activeToasts = [];
|
|
10
|
+
const MAX_TOASTS = 2;
|
|
11
|
+
|
|
8
12
|
const TOAST_CONFIG = {
|
|
9
13
|
autoClose: 1400,
|
|
10
14
|
pauseOnHover: false,
|
|
@@ -17,6 +21,27 @@ const TOAST_CONFIG = {
|
|
|
17
21
|
newestOnTop: true
|
|
18
22
|
};
|
|
19
23
|
|
|
24
|
+
// Helper to enforce toast limit
|
|
25
|
+
const showToastWithLimit = (type, message) => {
|
|
26
|
+
// If we're at the limit, remove the oldest toast
|
|
27
|
+
if (activeToasts.length >= MAX_TOASTS) {
|
|
28
|
+
const oldestId = activeToasts.shift();
|
|
29
|
+
toast.remove(oldestId);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Show new toast and track its ID
|
|
33
|
+
const toastId = toast[type](message, TOAST_CONFIG);
|
|
34
|
+
activeToasts.push(toastId);
|
|
35
|
+
|
|
36
|
+
// Remove from tracking when it auto-closes
|
|
37
|
+
setTimeout(() => {
|
|
38
|
+
const index = activeToasts.indexOf(toastId);
|
|
39
|
+
if (index > -1) activeToasts.splice(index, 1);
|
|
40
|
+
}, TOAST_CONFIG.autoClose + 100);
|
|
41
|
+
|
|
42
|
+
return toastId;
|
|
43
|
+
};
|
|
44
|
+
|
|
20
45
|
import mockTaskData from "@/stores/sampleData.js";
|
|
21
46
|
import { useRouter } from "vue-router";
|
|
22
47
|
import { DEBUG } from "@/utils/debug";
|
|
@@ -264,7 +289,6 @@ export const useUIStore = defineStore("ui", () => {
|
|
|
264
289
|
input.style.userSelect = "auto";
|
|
265
290
|
input.style.touchAction = "pan-x pan-y";
|
|
266
291
|
});
|
|
267
|
-
|
|
268
292
|
};
|
|
269
293
|
|
|
270
294
|
const enableScroll = () => {
|
|
@@ -301,7 +325,6 @@ export const useUIStore = defineStore("ui", () => {
|
|
|
301
325
|
|
|
302
326
|
// Restore scroll position
|
|
303
327
|
window.scrollTo(0, parseInt(scrollY || "0") * -1);
|
|
304
|
-
|
|
305
328
|
};
|
|
306
329
|
|
|
307
330
|
const refreshQueueStats = () => {
|
|
@@ -538,7 +561,6 @@ export const useUIStore = defineStore("ui", () => {
|
|
|
538
561
|
mainCheckbox,
|
|
539
562
|
toggleMainCheckbox,
|
|
540
563
|
|
|
541
|
-
|
|
542
564
|
// single
|
|
543
565
|
deleteTask: (taskId) => {
|
|
544
566
|
delete tasks.value[taskId];
|
|
@@ -607,8 +629,8 @@ export const useUIStore = defineStore("ui", () => {
|
|
|
607
629
|
massEditPresaleCode: (eventId, presaleCode) => connection.sendMassEditPresaleCode(eventId, presaleCode),
|
|
608
630
|
|
|
609
631
|
// alerts
|
|
610
|
-
showError: (err) =>
|
|
611
|
-
showSuccess: (msg) =>
|
|
632
|
+
showError: (err) => showToastWithLimit("error", err),
|
|
633
|
+
showSuccess: (msg) => showToastWithLimit("success", msg),
|
|
612
634
|
// Country
|
|
613
635
|
currentCountry,
|
|
614
636
|
setCurrentCountry: (country, closeModal, newModule) => {
|
package/src/views/Tasks.vue
CHANGED
|
@@ -37,21 +37,8 @@
|
|
|
37
37
|
@deleteAll="ui.deleteTasks()" />
|
|
38
38
|
</div>
|
|
39
39
|
|
|
40
|
-
<div class="mb-2
|
|
40
|
+
<div class="mb-2 md:hidden">
|
|
41
41
|
<Stats class="stats-component w-full" />
|
|
42
|
-
<div class="flex-gap-2 items-center justify-end">
|
|
43
|
-
<div
|
|
44
|
-
class="flex h-8 items-center justify-between rounded-md border border-dark-650 bg-dark-400 px-2 text-xs font-medium text-white">
|
|
45
|
-
<p class="text-2xs">Name</p>
|
|
46
|
-
<Switch class="scale-75" v-model="preferEventName" />
|
|
47
|
-
</div>
|
|
48
|
-
<PriceSortToggle
|
|
49
|
-
class="h-8 min-w-20 max-w-28 flex-shrink-0"
|
|
50
|
-
:options="['All', 'Checkout']"
|
|
51
|
-
:darker="true"
|
|
52
|
-
:current="ui.taskFilter"
|
|
53
|
-
@change="(e) => ui.setTaskFilter(e)" />
|
|
54
|
-
</div>
|
|
55
42
|
</div>
|
|
56
43
|
|
|
57
44
|
<div class="mb-1 hidden flex-wrap items-center gap-2 md:flex xl:flex-nowrap lg:mb-2">
|
|
@@ -103,16 +90,29 @@
|
|
|
103
90
|
class="input-default event-dropdown w-full hover:bg-dark-400"
|
|
104
91
|
rightAmount="right-2" />
|
|
105
92
|
</div>
|
|
106
|
-
<div class="w-full">
|
|
107
|
-
<div class="
|
|
108
|
-
<input
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
93
|
+
<div class="flex w-full items-center gap-2">
|
|
94
|
+
<div class="flex-1">
|
|
95
|
+
<div class="input-default flex items-center">
|
|
96
|
+
<input
|
|
97
|
+
v-model="taskSearchQuery"
|
|
98
|
+
type="text"
|
|
99
|
+
placeholder="Search tasks..."
|
|
100
|
+
aria-label="Search tasks"
|
|
101
|
+
class="transparent-input" />
|
|
102
|
+
<span v-if="taskSearchQuery" class="ml-2 text-xs text-light-500">{{ filteredTaskCount }}</span>
|
|
103
|
+
</div>
|
|
104
|
+
</div>
|
|
105
|
+
<div
|
|
106
|
+
class="flex h-8 items-center justify-between rounded-md border border-dark-650 bg-dark-400 px-2 text-xs font-medium text-white flex-shrink-0">
|
|
107
|
+
<p class="text-2xs">Name</p>
|
|
108
|
+
<Switch class="scale-75" v-model="preferEventName" />
|
|
115
109
|
</div>
|
|
110
|
+
<PriceSortToggle
|
|
111
|
+
class="h-8 min-w-20 max-w-28 flex-shrink-0"
|
|
112
|
+
:options="['All', 'Checkout']"
|
|
113
|
+
:darker="true"
|
|
114
|
+
:current="ui.taskFilter"
|
|
115
|
+
@change="(e) => ui.setTaskFilter(e)" />
|
|
116
116
|
</div>
|
|
117
117
|
</div>
|
|
118
118
|
|