@necrolab/dashboard 0.5.10 → 0.5.12

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@necrolab/dashboard",
3
- "version": "0.5.10",
3
+ "version": "0.5.12",
4
4
  "type": "module",
5
5
  "scripts": {
6
6
  "build": "rm -rf dist && npx workbox-cli generateSW workbox-config.cjs && vite build",
package/src/App.vue CHANGED
@@ -737,17 +737,31 @@ body {
737
737
 
738
738
  // iPhone landscape lock overlay
739
739
  .iphone-landscape-lock {
740
- display: none;
741
740
  position: fixed;
742
741
  inset: 0;
743
742
  background: oklch(0.1822 0 0);
744
743
  z-index: 99999;
745
744
  align-items: center;
746
745
  justify-content: center;
746
+ display: flex;
747
+ opacity: 1;
748
+ transition: opacity 0.1s ease-out;
749
+
750
+ // Hide in portrait mode
751
+ @media (max-device-width: 430px) and (orientation: portrait) {
752
+ opacity: 0;
753
+ pointer-events: none;
754
+ }
747
755
 
748
- // Only show on iPhone (not iPad) in landscape
756
+ // Show immediately in landscape
749
757
  @media (max-device-width: 430px) and (orientation: landscape) {
750
- display: flex;
758
+ opacity: 1;
759
+ pointer-events: all;
760
+ }
761
+
762
+ // Hide completely on iPad and desktop
763
+ @media (min-device-width: 431px) {
764
+ display: none;
751
765
  }
752
766
 
753
767
  .rotate-message {
@@ -20,6 +20,8 @@
20
20
  body {
21
21
  background-color: oklch(0.1822 0 0);
22
22
  position: relative;
23
+ min-height: 100vh;
24
+ min-height: 100dvh;
23
25
 
24
26
  &::before {
25
27
  content: "";
@@ -38,6 +40,14 @@ body {
38
40
  will-change: transform;
39
41
  -webkit-transform: translateZ(0);
40
42
  transform: translateZ(0);
43
+
44
+ // Extend into safe areas only in PWA mode
45
+ @media (display-mode: standalone) {
46
+ top: -50px;
47
+ left: -50px;
48
+ right: -50px;
49
+ bottom: -50px;
50
+ }
41
51
  }
42
52
  }
43
53
 
@@ -98,6 +108,23 @@ svg:not([stroke]):not([fill="none"]) polygon:not([fill]) {
98
108
  stroke: oklch(0.60 0.20 25) !important;
99
109
  }
100
110
 
111
+ /* ==========================================================================
112
+ PWA MODE FIXES
113
+ ========================================================================== */
114
+
115
+ // Add padding to all page headers in PWA mode to prevent hiding under navbar
116
+ @media (display-mode: standalone) {
117
+ // Accounts page header
118
+ .flex.items-center.justify-between.pt-5.pb-2 {
119
+ padding-top: 3.5rem !important;
120
+ }
121
+
122
+ // Console page header
123
+ h4.mb-2.flex.items-center.gap-2.pt-5 {
124
+ padding-top: 3.5rem !important;
125
+ }
126
+ }
127
+
101
128
  /* ==========================================================================
102
129
  COMPONENT UTILITIES
103
130
  ========================================================================== */
@@ -38,7 +38,7 @@
38
38
  />
39
39
  </div>
40
40
 
41
- <div class="input-container relative-positioned z-dropdown">
41
+ <div class="input-container relative-positioned z-dropdown">
42
42
  <span class="w-1/3 text-light-300 font-medium text-xs">Queue Proxies</span>
43
43
  <Dropdown
44
44
  class="!w-2/3"
@@ -228,6 +228,12 @@
228
228
  -webkit-overflow-scrolling: touch !important;
229
229
  border: 1px solid oklch(0.26 0 0) !important;
230
230
  background: linear-gradient(135deg, oklch(0.18 0 0) 0%, oklch(0.20 0 0) 100%) !important;
231
+ width: calc(100vw - 4rem) !important;
232
+ max-width: 600px !important;
233
+
234
+ @media (min-width: 700px) {
235
+ width: 600px !important;
236
+ }
231
237
  }
232
238
 
233
239
  :deep(.dropdown-item) {
@@ -56,7 +56,7 @@ onClickOutside(target, (event) => {
56
56
  </script>
57
57
  <style lang="scss" scoped>
58
58
  .modal-mask {
59
- @apply fixed left-0 top-0 flex h-screen w-screen duration-300 ease-in-out;
59
+ @apply fixed left-0 top-0 flex w-screen duration-300 ease-in-out;
60
60
  z-index: 25000;
61
61
  align-items: flex-start;
62
62
  justify-content: center;
@@ -64,19 +64,25 @@ onClickOutside(target, (event) => {
64
64
  padding-top: 3.5rem;
65
65
  background-color: rgba(17, 17, 17, 0.85);
66
66
  backdrop-filter: blur(4px);
67
+ height: 100dvh;
67
68
  overflow-y: auto;
68
69
  -webkit-overflow-scrolling: touch;
69
- // Prevent zoom in modals
70
70
  touch-action: pan-y !important;
71
+
72
+ @supports not (height: 100dvh) {
73
+ height: 100vh;
74
+ }
71
75
  }
72
76
 
73
77
  .component-modal {
74
78
  width: 640px;
75
- margin-bottom: 10rem;
79
+ margin-bottom: 20rem;
76
80
  overflow-y: visible;
77
81
  @apply flex flex-col rounded-lg bg-dark-300 px-5 py-5;
78
- // Prevent zoom in modal content
79
- touch-action: pan-y !important;
82
+
83
+ @media (max-width: 480px) {
84
+ margin-bottom: 25rem;
85
+ }
80
86
 
81
87
  .modal-header {
82
88
  @apply flex font-bold text-white;
@@ -94,16 +100,16 @@ onClickOutside(target, (event) => {
94
100
 
95
101
  @media (max-width: 810px) {
96
102
  .modal-mask {
97
- align-items: flex-start; // Start from top on mobile
103
+ align-items: flex-start;
98
104
  justify-content: center;
99
105
  padding: 1rem;
100
106
  padding-top: 3rem;
101
- padding-bottom: 2rem; // Ensure bottom space
107
+ padding-bottom: 15rem !important;
102
108
  }
103
109
 
104
110
  .component-modal {
105
111
  width: calc(100vw - 2rem);
106
- margin-bottom: 6rem; // Increased bottom margin for better button access
112
+ margin-bottom: 10rem;
107
113
  }
108
114
 
109
115
  .modal-body {
@@ -157,8 +157,9 @@ export default {
157
157
  active: true,
158
158
  email: "suphathrphrnb@gmail.com",
159
159
  password: "PrthYTpNPk1hfm3",
160
- status: "Waiting for Stock",
161
- statusColor: "white",
160
+ status: "Checked out! #123467",
161
+ statusColor: "green",
162
+ orderNumber: "#123456",
162
163
  manual: false,
163
164
  quickQueue: false,
164
165
  loginAfterCart: false,
@@ -7,7 +7,7 @@
7
7
 
8
8
  <div>
9
9
  <div class="mb-3 flex flex-col gap-3 lg:flex-row lg:items-center lg:justify-between">
10
- <div class="flex flex-col gap-3 md:flex-row md:items-center md:flex-1">
10
+ <div class="flex flex-col gap-3 md:flex-1 md:flex-row md:items-center">
11
11
  <div class="w-full md:w-64">
12
12
  <Dropdown
13
13
  class="console-dropdown input-default w-full border-2 border-dark-550 bg-dark-500"
@@ -22,8 +22,8 @@
22
22
  .sort((a, b) => a.localeCompare(b))
23
23
  " />
24
24
  </div>
25
- <div class="flex items-center gap-2 flex-1">
26
- <div class="input-default flex items-center flex-1 md:max-w-64">
25
+ <div class="flex flex-1 items-center gap-2">
26
+ <div class="input-default flex flex-1 items-center md:max-w-64">
27
27
  <input
28
28
  v-model="searchQuery"
29
29
  type="text"
@@ -52,7 +52,7 @@
52
52
  </button>
53
53
  </div>
54
54
  </div>
55
- <div class="flex items-center gap-3 hidden md:flex">
55
+ <div class="flex hidden items-center gap-3 md:flex">
56
56
  <!-- Hide Monitors and Auto buttons only on desktop -->
57
57
  <div class="hidden items-center gap-3 md:flex">
58
58
  <button
@@ -72,7 +72,7 @@
72
72
  </div>
73
73
  <!-- Scroll buttons - desktop only (mobile has them inline with search) -->
74
74
  <button
75
- class="hidden md:flex h-10 w-10 items-center justify-center rounded border border-dark-650 bg-dark-400 shadow-sm transition-colors duration-150 hover:bg-dark-300 active:bg-dark-200"
75
+ class="hidden h-10 w-10 items-center justify-center rounded border border-dark-650 bg-dark-400 shadow-sm transition-colors duration-150 hover:bg-dark-300 active:bg-dark-200 md:flex"
76
76
  @mousedown="startScrolling('up')"
77
77
  @mouseup="stopScrolling"
78
78
  @mouseleave="stopScrolling"
@@ -81,7 +81,7 @@
81
81
  <UpIcon class="pointer-events-none h-5 w-5" />
82
82
  </button>
83
83
  <button
84
- class="hidden md:flex h-10 w-10 items-center justify-center rounded border border-dark-650 bg-dark-400 shadow-sm transition-colors duration-150 hover:bg-dark-300 active:bg-dark-200"
84
+ class="hidden h-10 w-10 items-center justify-center rounded border border-dark-650 bg-dark-400 shadow-sm transition-colors duration-150 hover:bg-dark-300 active:bg-dark-200 md:flex"
85
85
  @mousedown="startScrolling('down')"
86
86
  @mouseup="stopScrolling"
87
87
  @mouseleave="stopScrolling"
@@ -94,7 +94,7 @@
94
94
 
95
95
  <Smoothie
96
96
  :weight="0.2"
97
- class="console scrollable smooth-scroll overflow-y-auto overflow-x-auto font-mono text-white"
97
+ class="console scrollable smooth-scroll overflow-x-auto overflow-y-auto font-mono text-white"
98
98
  style="min-height: 12rem !important"
99
99
  ref="$autoscroll"
100
100
  @wheel.stop
@@ -118,7 +118,7 @@
118
118
  v-bind:key="`log-${index}`"
119
119
  :style="{ '--index': index }"><code class="md:text-sm lg:text-base" v-html="line"></code></pre>
120
120
  </Smoothie>
121
- <div class="console-switches mt-4 mb-6 flex justify-between md:hidden">
121
+ <div class="console-switches mb-6 mt-4 flex justify-between md:hidden">
122
122
  <button
123
123
  class="flex h-10 items-center justify-center gap-3 rounded border border-dark-650 bg-dark-400 px-2 shadow-sm">
124
124
  <h3 class="text-sm text-white">Hide Monitors</h3>
@@ -261,7 +261,8 @@
261
261
  border-color: oklch(0.2809 0 0);
262
262
  transition: all 0.15s ease;
263
263
 
264
- &:hover, &:active {
264
+ &:hover,
265
+ &:active {
265
266
  border-color: oklch(0.72 0.15 145) !important;
266
267
  outline: 1px solid oklch(0.72 0.15 145);
267
268
  outline-offset: 0;
@@ -525,7 +526,7 @@ window.startDebugConsoleMessages = () => {
525
526
  setInterval(() => {
526
527
  var taskId = Math.round(Math.random() * 10);
527
528
  const log = {
528
- log: `\u001b[96m[12:16:02.273]\u001b[00m \u001b[96m[TASK-${taskId}]\u001b[00m TEST TEST TEST TEST TEST TEST TEST`,
529
+ log: `\u001b[96m[12:16:02.273]\u001b[00m \u001b[96m[TASK-${taskId}]\u001b[00m TEST TEST TEST TEST TEST TEST TEST TEST TEST TEST`,
529
530
  metadata: {
530
531
  taskId: taskId,
531
532
  siteId: "TM_US",
@@ -1,161 +1,153 @@
1
1
  <template>
2
- <div class="tasks-page">
3
- <div class="flex items-center justify-between pb-2" style="padding-top: 1.5rem">
4
- <div class="flex items-center justify-center gap-4">
5
- <GearIcon
6
- class="w-5 cursor-pointer smooth-hover"
7
- @click="ui.toggleModal('quick-settings')"
8
- />
9
- <h4 class="text-base font-semibold text-light-300">
10
- Tasks
11
- <span class="text-sm font-medium text-light-400 pl-1">{{ taskCount }}</span>
12
- </h4>
13
- </div>
14
- <ul class="mobile-icons mobile-header-controls">
15
- <li>
16
- <button @click="ui.startTasks()"><PlayIcon class="w-4 h-4" /></button>
17
- </li>
18
- <li>
19
- <button @click="ui.stopTasks()"><PauseIcon class="w-4 h-4" /></button>
20
- </li>
21
- <li>
22
- <button
23
- class="text-sm"
24
- :disabled="ui.disabledButtons['add-tasks']"
25
- @click="ui.toggleModal('create-task')"
26
- >
27
- <PlusIcon class="w-4 h-4" />
28
- </button>
29
- </li>
30
- <li>
31
- <button @click="ui.deleteTasks()"><TrashIcon class="h-3.5 w-3.5" /></button>
32
- </li>
33
- </ul>
34
- </div>
35
-
36
- <div class="controls-wrapper">
37
- <div class="controls-wrapper lg:mb-3">
38
- <DesktopControls
39
- class="desktop-controls-hide"
40
- @stopAll="ui.stopTasks()"
41
- @startAll="ui.startTasks()"
42
- @deleteAll="ui.deleteTasks()"
43
- />
44
- </div>
45
-
46
- <div class="flex md:hidden items-center justify-between gap-2 mb-1">
47
- <Stats class="stats-component flex-1" />
48
- <div class="flex gap-2 items-center">
49
- <div class="bg-dark-400 border border-dark-650 justify-between px-2 flex text-white text-xs font-medium items-center rounded-md h-8">
50
- <p class="text-[10px]">Name</p>
51
- <Switch class="scale-75" v-model="preferEventName" />
52
- </div>
53
- <PriceSortToggle
54
- class="min-w-20 max-w-28 flex-shrink-0 h-8"
55
- :options="['All', 'Checkout']"
56
- :darker="true"
57
- :current="ui.taskFilter"
58
- @change="(e) => ui.setTaskFilter(e)"
59
- />
60
- </div>
61
- </div>
62
-
63
- <div class="hidden md:flex items-center gap-2 lg:mb-2 mb-1">
64
- <div
65
- v-if="uniqEventIds.length > 1"
66
- class="w-52 flex-shrink-0"
67
- >
68
- <Dropdown
69
- :onClick="(f) => ui.setCurrentEvent(f)"
70
- default="All events"
71
- :chosen="ui.currentEvent"
72
- :options="uniqEventIds"
73
- :allowDefault="true"
74
- class="input-default w-full hover:bg-dark-400 event-dropdown"
75
- rightAmount="right-2"
76
- />
77
- </div>
78
- <div class="w-52 flex-shrink-0">
79
- <div class="input-default flex items-center">
80
- <input
81
- v-model="taskSearchQuery"
82
- type="text"
83
- placeholder="Search tasks..."
84
- class="h-full w-full bg-transparent text-sm text-white outline-none"
85
- />
86
- <span v-if="taskSearchQuery" class="ml-2 text-xs text-light-500">{{ filteredTaskCount }}</span>
87
- </div>
88
- </div>
89
- <div class="bg-dark-400 border border-dark-650 justify-between px-3 w-32 flex text-white text-xs font-medium items-center rounded-md h-10">
90
- <p>Name</p>
91
- <Switch class="scale-75" v-model="preferEventName" />
2
+ <div class="tasks-page">
3
+ <div class="tasks-header flex items-center justify-between pb-2" style="padding-top: 1.5rem">
4
+ <div class="flex items-center justify-center gap-4">
5
+ <GearIcon class="smooth-hover w-5 cursor-pointer" @click="ui.toggleModal('quick-settings')" />
6
+ <h4 class="text-base font-semibold text-light-300">
7
+ Tasks
8
+ <span class="pl-1 text-sm font-medium text-light-400">{{ taskCount }}</span>
9
+ </h4>
10
+ </div>
11
+ <ul class="mobile-icons mobile-header-controls">
12
+ <li>
13
+ <button @click="ui.startTasks()"><PlayIcon class="h-4 w-4" /></button>
14
+ </li>
15
+ <li>
16
+ <button @click="ui.stopTasks()"><PauseIcon class="h-4 w-4" /></button>
17
+ </li>
18
+ <li>
19
+ <button
20
+ class="text-sm"
21
+ :disabled="ui.disabledButtons['add-tasks']"
22
+ @click="ui.toggleModal('create-task')">
23
+ <PlusIcon class="h-4 w-4" />
24
+ </button>
25
+ </li>
26
+ <li>
27
+ <button @click="ui.deleteTasks()"><TrashIcon class="h-3.5 w-3.5" /></button>
28
+ </li>
29
+ </ul>
92
30
  </div>
93
- <PriceSortToggle
94
- class="min-w-24 max-w-28 flex-shrink-0"
95
- :options="['All', 'Checkout']"
96
- :darker="true"
97
- :current="ui.taskFilter"
98
- @change="(e) => ui.setTaskFilter(e)"
99
- />
100
- <Stats class="stats-component ml-auto" />
101
- </div>
102
-
103
- <div class="flex md:hidden flex-col gap-2 mb-1">
104
- <div
105
- v-if="uniqEventIds.length > 1"
106
- class="w-full"
107
- >
108
- <Dropdown
109
- :onClick="(f) => ui.setCurrentEvent(f)"
110
- default="All events"
111
- :chosen="ui.currentEvent"
112
- :options="uniqEventIds"
113
- :allowDefault="true"
114
- class="input-default w-full hover:bg-dark-400 event-dropdown"
115
- rightAmount="right-2"
116
- />
117
- </div>
118
- <div class="w-full">
119
- <div class="input-default flex items-center">
120
- <input
121
- v-model="taskSearchQuery"
122
- type="text"
123
- placeholder="Search tasks..."
124
- class="h-full w-full bg-transparent text-sm text-white outline-none"
125
- />
126
- <span v-if="taskSearchQuery" class="ml-2 text-xs text-light-500">{{ filteredTaskCount }}</span>
127
- </div>
31
+
32
+ <div class="controls-wrapper">
33
+ <div class="controls-wrapper lg:mb-3">
34
+ <DesktopControls
35
+ class="desktop-controls-hide"
36
+ @stopAll="ui.stopTasks()"
37
+ @startAll="ui.startTasks()"
38
+ @deleteAll="ui.deleteTasks()" />
39
+ </div>
40
+
41
+ <div class="mb-1 flex items-center justify-between gap-2 md:hidden">
42
+ <Stats class="stats-component flex-1" />
43
+ <div class="flex items-center gap-2">
44
+ <div
45
+ 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">
46
+ <p class="text-[10px]">Name</p>
47
+ <Switch class="scale-75" v-model="preferEventName" />
48
+ </div>
49
+ <PriceSortToggle
50
+ class="h-8 min-w-20 max-w-28 flex-shrink-0"
51
+ :options="['All', 'Checkout']"
52
+ :darker="true"
53
+ :current="ui.taskFilter"
54
+ @change="(e) => ui.setTaskFilter(e)" />
55
+ </div>
56
+ </div>
57
+
58
+ <div class="mb-1 hidden items-center gap-2 md:flex lg:mb-2">
59
+ <div v-if="uniqEventIds.length > 1" class="w-52 flex-shrink-0">
60
+ <Dropdown
61
+ :onClick="(f) => ui.setCurrentEvent(f)"
62
+ default="All events"
63
+ :chosen="ui.currentEvent"
64
+ :options="uniqEventIds"
65
+ :allowDefault="true"
66
+ class="input-default event-dropdown w-full hover:bg-dark-400"
67
+ rightAmount="right-2" />
68
+ </div>
69
+ <div class="w-52 flex-shrink-0">
70
+ <div class="input-default flex items-center">
71
+ <input
72
+ v-model="taskSearchQuery"
73
+ type="text"
74
+ placeholder="Search tasks..."
75
+ class="h-full w-full bg-transparent text-sm text-white outline-none" />
76
+ <span v-if="taskSearchQuery" class="ml-2 text-xs text-light-500">{{ filteredTaskCount }}</span>
77
+ </div>
78
+ </div>
79
+ <div
80
+ class="flex h-10 w-32 items-center justify-between rounded-md border border-dark-650 bg-dark-400 px-3 text-xs font-medium text-white">
81
+ <p>Name</p>
82
+ <Switch class="scale-75" v-model="preferEventName" />
83
+ </div>
84
+ <PriceSortToggle
85
+ class="min-w-24 max-w-28 flex-shrink-0"
86
+ :options="['All', 'Checkout']"
87
+ :darker="true"
88
+ :current="ui.taskFilter"
89
+ @change="(e) => ui.setTaskFilter(e)" />
90
+ <Stats class="stats-component ml-auto" />
91
+ </div>
92
+
93
+ <div class="mb-1 flex flex-col gap-2 md:hidden">
94
+ <div v-if="uniqEventIds.length > 1" class="w-full">
95
+ <Dropdown
96
+ :onClick="(f) => ui.setCurrentEvent(f)"
97
+ default="All events"
98
+ :chosen="ui.currentEvent"
99
+ :options="uniqEventIds"
100
+ :allowDefault="true"
101
+ class="input-default event-dropdown w-full hover:bg-dark-400"
102
+ rightAmount="right-2" />
103
+ </div>
104
+ <div class="w-full">
105
+ <div class="input-default flex items-center">
106
+ <input
107
+ v-model="taskSearchQuery"
108
+ type="text"
109
+ placeholder="Search tasks..."
110
+ class="h-full w-full bg-transparent text-sm text-white outline-none" />
111
+ <span v-if="taskSearchQuery" class="ml-2 text-xs text-light-500">{{ filteredTaskCount }}</span>
112
+ </div>
113
+ </div>
114
+ </div>
115
+
116
+ <TaskView
117
+ class="mb-2 lg:mb-3"
118
+ :tasks="ui.tasks"
119
+ :searchQuery="taskSearchQuery"
120
+ :preferEventName="preferEventName" />
121
+
122
+ <Utilities class="utilities-section" />
128
123
  </div>
129
- </div>
130
124
 
131
- <TaskView class="lg:mb-3 mb-2" :tasks="ui.tasks" :searchQuery="taskSearchQuery" :preferEventName="preferEventName" />
125
+ <ViewTask v-if="ui.activeModal === 'view-task' && ui.selectedTaskForView" :task="ui.selectedTaskForView" />
132
126
 
133
- <Utilities class="utilities-section" />
127
+ <transition-group name="fade">
128
+ <CreateTaskTM v-if="ui.currentModule == 'TM' && activeModal === 'create-task'" @new="ui.addNewTask" />
129
+ <CreateTaskAXS v-if="ui.currentModule == 'AXS' && activeModal === 'create-task'" @new="ui.addNewTask" />
130
+ <CheckStock v-if="activeModal === 'check-stock'" />
131
+ <ScrapeVenue v-if="activeModal === 'scrape-venue'" />
132
+ <MassEditPresaleCode v-if="activeModal === 'mass-edit-presale-code'" />
133
+ <QuickSettings v-if="activeModal === 'quick-settings'" />
134
+ </transition-group>
134
135
  </div>
135
-
136
- <ViewTask v-if="ui.activeModal === 'view-task' && ui.selectedTaskForView" :task="ui.selectedTaskForView" />
137
-
138
- <transition-group name="fade">
139
- <CreateTaskTM
140
- v-if="ui.currentModule == 'TM' && activeModal === 'create-task'"
141
- @new="ui.addNewTask"
142
- />
143
- <CreateTaskAXS
144
- v-if="ui.currentModule == 'AXS' && activeModal === 'create-task'"
145
- @new="ui.addNewTask"
146
- />
147
- <CheckStock v-if="activeModal === 'check-stock'" />
148
- <ScrapeVenue v-if="activeModal === 'scrape-venue'" />
149
- <MassEditPresaleCode v-if="activeModal === 'mass-edit-presale-code'" />
150
- <QuickSettings v-if="activeModal === 'quick-settings'" />
151
- </transition-group>
152
- </div>
153
136
  </template>
154
137
  <style lang="scss" scoped>
138
+ // Add padding in PWA mode to prevent content hiding under navbar
139
+ .tasks-header {
140
+ @media (display-mode: standalone) {
141
+ padding-top: 3.5rem !important;
142
+ }
143
+ }
144
+
145
+ // Bottom padding now handled globally in App.vue component-container
146
+
155
147
  .custom-dropdown-content {
156
- top: 2.6rem !important;
157
- left: -13px;
158
- @apply border border-dark-650;
148
+ top: 2.6rem !important;
149
+ left: -13px;
150
+ @apply border border-dark-650;
159
151
  }
160
152
 
161
153
  /* ==========================================================================
@@ -164,79 +156,79 @@
164
156
 
165
157
  /* Default mobile layout */
166
158
  .desktop-controls-hide {
167
- display: none;
159
+ display: none;
168
160
  }
169
161
 
170
162
  .mobile-header-controls {
171
- display: flex;
163
+ display: flex;
172
164
  }
173
165
 
174
166
  /* Event dropdown base styling */
175
167
  .event-dropdown {
176
- min-width: 0;
177
- /* Match PriceSortToggle height instead of input-default */
178
- height: 40px !important;
168
+ min-width: 0;
169
+ /* Match PriceSortToggle height instead of input-default */
170
+ height: 40px !important;
179
171
  }
180
172
 
181
173
  .event-dropdown .dropdown-value {
182
- max-width: 100%;
183
- overflow: hidden;
184
- text-overflow: ellipsis;
185
- white-space: nowrap;
174
+ max-width: 100%;
175
+ overflow: hidden;
176
+ text-overflow: ellipsis;
177
+ white-space: nowrap;
186
178
  }
187
179
 
188
180
  /* Small mobile screens (portrait) */
189
181
  @media (max-width: 480px) and (orientation: portrait) {
190
- .event-dropdown {
191
- height: 40px !important; /* Match PriceSortToggle height exactly */
192
- }
193
-
194
- .event-dropdown .dropdown-value {
195
- max-width: calc(100vw - 140px);
196
- font-size: 0.875rem;
197
- }
198
-
199
- .event-dropdown .dropdown-display {
200
- padding-right: 2rem;
201
- }
182
+ .event-dropdown {
183
+ height: 40px !important; /* Match PriceSortToggle height exactly */
184
+ }
185
+
186
+ .event-dropdown .dropdown-value {
187
+ max-width: calc(100vw - 140px);
188
+ font-size: 0.875rem;
189
+ }
190
+
191
+ .event-dropdown .dropdown-display {
192
+ padding-right: 2rem;
193
+ }
202
194
  }
203
195
 
204
196
  /* Extra small screens */
205
197
  @media (max-width: 375px) and (orientation: portrait) {
206
- .event-dropdown {
207
- height: 40px !important; /* Maintain 40px height to match PriceSortToggle */
208
- }
209
-
210
- .event-dropdown .dropdown-value {
211
- max-width: calc(100vw - 120px);
212
- font-size: 0.8rem;
213
- }
198
+ .event-dropdown {
199
+ height: 40px !important; /* Maintain 40px height to match PriceSortToggle */
200
+ }
201
+
202
+ .event-dropdown .dropdown-value {
203
+ max-width: calc(100vw - 120px);
204
+ font-size: 0.8rem;
205
+ }
214
206
  }
215
207
 
216
208
  /* Mobile landscape - hide non-essential elements */
217
209
  @media (max-height: 500px) and (orientation: landscape) {
218
- .stats-component,
219
- .utilities-section,
220
- .filter-controls {
221
- display: none;
222
- }
223
-
224
- .pb-2 {
225
- padding-top: 1rem !important;
226
- padding-bottom: 0.25rem;
227
- margin-bottom: 0.25rem;
228
- }
210
+ .stats-component,
211
+ .utilities-section,
212
+ .filter-controls {
213
+ display: none;
214
+ }
215
+
216
+ .pb-2 {
217
+ padding-top: 1rem !important;
218
+ padding-bottom: 0.25rem;
219
+ margin-bottom: 0.25rem;
220
+ }
229
221
  }
230
222
 
231
223
  /* Tablet and small desktop - show desktop controls */
232
224
  @media (min-width: 650px) {
233
- .desktop-controls-hide {
234
- display: flex;
235
- }
225
+ .desktop-controls-hide {
226
+ display: flex;
227
+ }
236
228
 
237
- .mobile-header-controls {
238
- display: none;
239
- }
229
+ .mobile-header-controls {
230
+ display: none;
231
+ }
240
232
  }
241
233
  </style>
242
234
  <script setup>
@@ -263,55 +255,58 @@ const activeModal = computed(() => ui.activeModal);
263
255
  const taskCount = computed(() => Object.keys(ui.getSelectedTasks()).length);
264
256
  ui.refreshQueueStats();
265
257
 
266
- const taskSearchQuery = ref('');
258
+ const taskSearchQuery = ref("");
267
259
  // Load preference from localStorage, default to true
268
- const preferEventName = ref(localStorage.getItem('preferEventName') !== 'false');
260
+ const preferEventName = ref(localStorage.getItem("preferEventName") !== "false");
269
261
 
270
262
  // Persist preference to localStorage when changed
271
263
  watch(preferEventName, (newValue) => {
272
- localStorage.setItem('preferEventName', String(newValue));
264
+ localStorage.setItem("preferEventName", String(newValue));
273
265
  });
274
266
 
275
267
  const filteredTaskCount = computed(() => {
276
- if (!taskSearchQuery.value.trim()) return '';
277
-
278
- const searchLower = taskSearchQuery.value.toLowerCase().trim();
279
- let count = 0;
280
-
281
- Object.values(ui.tasks).forEach(task => {
282
- if (task.hidden) return;
283
-
284
- const searchableText = [
285
- task.eventId,
286
- task.eventName,
287
- task.eventVenue,
288
- task.email,
289
- task.taskId,
290
- task.status,
291
- task.profileName,
292
- task.presaleCode,
293
- task.reservedTicketsList
294
- ].filter(Boolean).join(' ').toLowerCase();
295
-
296
- if (searchableText.includes(searchLower)) count++;
297
- });
298
-
299
- return count;
268
+ if (!taskSearchQuery.value.trim()) return "";
269
+
270
+ const searchLower = taskSearchQuery.value.toLowerCase().trim();
271
+ let count = 0;
272
+
273
+ Object.values(ui.tasks).forEach((task) => {
274
+ if (task.hidden) return;
275
+
276
+ const searchableText = [
277
+ task.eventId,
278
+ task.eventName,
279
+ task.eventVenue,
280
+ task.email,
281
+ task.taskId,
282
+ task.status,
283
+ task.profileName,
284
+ task.presaleCode,
285
+ task.reservedTicketsList
286
+ ]
287
+ .filter(Boolean)
288
+ .join(" ")
289
+ .toLowerCase();
290
+
291
+ if (searchableText.includes(searchLower)) count++;
292
+ });
293
+
294
+ return count;
300
295
  });
301
296
 
302
297
  // Ensure "All events" is always selected on page load
303
298
  onMounted(() => {
304
- ui.setCurrentEvent("");
299
+ ui.setCurrentEvent("");
305
300
  });
306
301
 
307
302
  const uniqEventIds = computed(() => {
308
- const ids = [
309
- ...new Set(
310
- Object.values(ui.tasks)
311
- .filter((t) => t.siteId === ui.currentCountry.siteId && !t.eventId?.includes("@"))
312
- .map((v) => `${v.eventName} (${v.eventId})`)
313
- ),
314
- ];
315
- return ids;
303
+ const ids = [
304
+ ...new Set(
305
+ Object.values(ui.tasks)
306
+ .filter((t) => t.siteId === ui.currentCountry.siteId && !t.eventId?.includes("@"))
307
+ .map((v) => `${v.eventName} (${v.eventId})`)
308
+ )
309
+ ];
310
+ return ids;
316
311
  });
317
312
  </script>