@necrolab/dashboard 0.4.47 → 0.4.49

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 (39) hide show
  1. package/.claude/settings.local.json +2 -1
  2. package/exit +209 -0
  3. package/index.html +1 -1
  4. package/package.json +1 -1
  5. package/postinstall.js +9 -0
  6. package/public/manifest.json +8 -3
  7. package/src/assets/css/_input.scss +104 -111
  8. package/src/assets/css/_utilities.scss +441 -0
  9. package/src/assets/css/main.scss +228 -154
  10. package/src/components/Auth/LoginForm.vue +8 -8
  11. package/src/components/Editors/Account/Account.vue +156 -146
  12. package/src/components/Editors/Account/AccountCreator.vue +1 -1
  13. package/src/components/Editors/Account/AccountView.vue +13 -13
  14. package/src/components/Editors/Account/CreateAccount.vue +25 -16
  15. package/src/components/Editors/Profile/CreateProfile.vue +1 -1
  16. package/src/components/Editors/Profile/Profile.vue +1 -1
  17. package/src/components/Editors/Profile/ProfileCountryChooser.vue +83 -19
  18. package/src/components/Editors/Profile/ProfileView.vue +11 -11
  19. package/src/components/Tasks/CreateTaskAXS.vue +3 -3
  20. package/src/components/Tasks/CreateTaskTM.vue +7 -35
  21. package/src/components/Tasks/QuickSettings.vue +112 -9
  22. package/src/components/Tasks/Stats.vue +29 -25
  23. package/src/components/Tasks/Task.vue +489 -365
  24. package/src/components/Tasks/TaskView.vue +21 -23
  25. package/src/components/icons/Sandclock.vue +2 -2
  26. package/src/components/icons/Stadium.vue +1 -1
  27. package/src/components/ui/Modal.vue +37 -35
  28. package/src/components/ui/controls/CountryChooser.vue +200 -62
  29. package/src/components/ui/controls/atomic/Dropdown.vue +177 -91
  30. package/src/components/ui/controls/atomic/MultiDropdown.vue +247 -168
  31. package/src/composables/useClickOutside.js +21 -0
  32. package/src/composables/useDropdownPosition.js +174 -0
  33. package/src/stores/ui.js +5 -4
  34. package/src/views/Accounts.vue +2 -2
  35. package/src/views/Console.vue +25 -45
  36. package/src/views/Editor.vue +1194 -730
  37. package/src/views/Profiles.vue +2 -2
  38. package/src/views/Tasks.vue +170 -137
  39. package/tailwind.config.js +47 -21
@@ -68,13 +68,13 @@
68
68
  @change="(f) => (ui.search.profiles.tag = f)"
69
69
  /> -->
70
70
  <Dropdown
71
- class="rounded-r-lg w-32 bg-dark-500 relative z-50 border-2 border-dark-600 search-dropdown"
72
- style="margin-left: 0 !important; border-width: 2px !important"
71
+ class="dropdown-base rounded-r-lg w-32 relative z-50 search-dropdown"
73
72
  rightAmount="right-1"
74
73
  default="Any"
75
74
  :value="ui.search.profiles.tag"
76
75
  :onClick="(f) => (ui.search.profiles.tag = f)"
77
76
  :options="allTags"
77
+ :includeAdjacentButtons="true"
78
78
  :capitalize="true"
79
79
  />
80
80
  </div>
@@ -1,157 +1,185 @@
1
1
  <template>
2
- <div class="tasks-page">
3
- <div class="flex-between pt-5 pb-2">
4
- <div class="flex-center gap-4">
5
- <GearIcon class="w-5 cursor-pointer smooth-hover" @click="ui.toggleModal('quick-settings')" />
6
- <h4 class="text-heading">
7
- Tasks
8
- <span class="text-subheading pl-1">{{ taskCount }}</span>
9
- </h4>
10
- </div>
11
- <ul class="mobile-icons mobile-header-controls">
12
- <li>
13
- <button @click="ui.startTasks()"><PlayIcon class="w-4 h-4" /></button>
14
- </li>
15
- <li>
16
- <button @click="ui.stopTasks()"><PauseIcon class="w-4 h-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
- >
24
- <PlusIcon class="w-4 h-4" />
25
- </button>
26
- </li>
27
- <li>
28
- <button @click="ui.deleteTasks()"><TrashIcon class="h-3.5 w-3.5" /></button>
29
- </li>
30
- </ul>
31
- </div>
2
+ <div class="tasks-page">
3
+ <div class="flex-between pt-5 pb-2">
4
+ <div class="flex-center gap-4">
5
+ <GearIcon
6
+ class="w-5 cursor-pointer smooth-hover"
7
+ @click="ui.toggleModal('quick-settings')"
8
+ />
9
+ <h4 class="text-heading">
10
+ Tasks
11
+ <span class="text-subheading 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>
32
35
 
33
- <Stats class="stats-component" />
36
+ <div class="controls-wrapper">
37
+ <Stats class="stats-component" />
34
38
 
35
- <div class="controls-wrapper lg:mb-6 mb-3">
36
- <DesktopControls
37
- class="desktop-controls-hide"
38
- @stopAll="ui.stopTasks()"
39
- @startAll="ui.startTasks()"
40
- @deleteAll="ui.deleteTasks()"
41
- />
42
- </div>
39
+ <div class="controls-wrapper lg:mb-3">
40
+ <DesktopControls
41
+ class="desktop-controls-hide"
42
+ @stopAll="ui.stopTasks()"
43
+ @startAll="ui.startTasks()"
44
+ @deleteAll="ui.deleteTasks()"
45
+ />
46
+ </div>
43
47
 
44
- <div class="flex items-center justify-between gap-2 lg:mb-2 mb-1">
45
- <div v-if="uniqEventIds.length > 1" class="flex-1 md:min-w-96 md:max-w-96 md:flex-none">
46
- <Dropdown
47
- :onClick="(f) => ui.setCurrentEvent(f)"
48
- default="All events"
49
- :chosen="ui.currentEvent"
50
- :options="uniqEventIds"
51
- :allowDefault="true"
52
- class="input-default w-full hover:bg-dark-400 h-10"
53
- rightAmount="right-2"
54
- />
55
- </div>
56
- <PriceSortToggle
57
- class="min-w-24 max-w-28 flex-shrink-0"
58
- :options="['All', 'Checkout']"
59
- :darker="true"
60
- :current="ui.taskFilter"
61
- @change="(e) => ui.setTaskFilter(e)"
62
- />
48
+ <div class="flex items-center justify-between gap-2 lg:mb-2 mb-1 filter-controls">
49
+ <div
50
+ v-if="uniqEventIds.length > 1"
51
+ class="flex-1 md:min-w-96 md:max-w-96 md:flex-none min-w-0"
52
+ >
53
+ <Dropdown
54
+ :onClick="(f) => ui.setCurrentEvent(f)"
55
+ default="All events"
56
+ :chosen="ui.currentEvent"
57
+ :options="uniqEventIds"
58
+ :allowDefault="true"
59
+ class="input-default w-full hover:bg-dark-400 event-dropdown"
60
+ rightAmount="right-2"
61
+ />
63
62
  </div>
63
+ <PriceSortToggle
64
+ class="min-w-24 max-w-28 flex-shrink-0"
65
+ :options="['All', 'Checkout']"
66
+ :darker="true"
67
+ :current="ui.taskFilter"
68
+ @change="(e) => ui.setTaskFilter(e)"
69
+ />
70
+ </div>
64
71
 
65
- <TaskView class="lg:mb-6 mb-3" :tasks="ui.tasks" />
72
+ <TaskView class="lg:mb-6 mb-3" :tasks="ui.tasks" />
66
73
 
67
- <Utilities class="utilities-section" />
68
-
69
- <transition-group name="fade">
70
- <CreateTaskTM v-if="ui.currentModule == 'TM' && activeModal === 'create-task'" @new="ui.addNewTask" />
71
- <CreateTaskAXS v-if="ui.currentModule == 'AXS' && activeModal === 'create-task'" @new="ui.addNewTask" />
72
- <CheckStock v-if="activeModal === 'check-stock'" />
73
- <ScrapeVenue v-if="activeModal === 'scrape-venue'" />
74
- <MassEditPresaleCode v-if="activeModal === 'mass-edit-presale-code'" />
75
- <QuickSettings v-if="activeModal === 'quick-settings'" />
76
- </transition-group>
74
+ <Utilities class="utilities-section" />
77
75
  </div>
76
+
77
+ <transition-group name="fade">
78
+ <CreateTaskTM
79
+ v-if="ui.currentModule == 'TM' && activeModal === 'create-task'"
80
+ @new="ui.addNewTask"
81
+ />
82
+ <CreateTaskAXS
83
+ v-if="ui.currentModule == 'AXS' && activeModal === 'create-task'"
84
+ @new="ui.addNewTask"
85
+ />
86
+ <CheckStock v-if="activeModal === 'check-stock'" />
87
+ <ScrapeVenue v-if="activeModal === 'scrape-venue'" />
88
+ <MassEditPresaleCode v-if="activeModal === 'mass-edit-presale-code'" />
89
+ <QuickSettings v-if="activeModal === 'quick-settings'" />
90
+ </transition-group>
91
+ </div>
78
92
  </template>
79
93
  <style lang="scss" scoped>
80
94
  .custom-dropdown-content {
81
- top: 2.6rem !important;
82
- left: -13px;
83
- @apply border border-dark-650;
95
+ top: 2.6rem !important;
96
+ left: -13px;
97
+ @apply border border-dark-650;
84
98
  }
85
99
 
100
+ /* ==========================================================================
101
+ TASKS PAGE RESPONSIVE LAYOUT - MOBILE FIRST
102
+ ========================================================================== */
103
+
104
+ /* Default mobile layout */
86
105
  .desktop-controls-hide {
87
- display: none !important;
106
+ display: none;
88
107
  }
89
108
 
90
109
  .mobile-header-controls {
91
- display: flex !important;
110
+ display: flex;
92
111
  }
93
112
 
94
- @media (min-width: 650px) {
95
- .desktop-controls-hide {
96
- display: flex !important;
97
- }
113
+ /* Event dropdown base styling */
114
+ .event-dropdown {
115
+ min-width: 0;
116
+ /* Match PriceSortToggle height instead of input-default */
117
+ height: 40px !important;
118
+ }
119
+
120
+ .event-dropdown .dropdown-value {
121
+ max-width: 100%;
122
+ overflow: hidden;
123
+ text-overflow: ellipsis;
124
+ white-space: nowrap;
125
+ }
98
126
 
99
- .mobile-header-controls {
100
- display: none !important;
101
- }
127
+ /* Small mobile screens (portrait) */
128
+ @media (max-width: 480px) and (orientation: portrait) {
129
+ .event-dropdown {
130
+ height: 40px !important; /* Match PriceSortToggle height exactly */
131
+ }
132
+
133
+ .event-dropdown .dropdown-value {
134
+ max-width: calc(100vw - 140px);
135
+ font-size: 0.875rem;
136
+ }
137
+
138
+ .event-dropdown .dropdown-display {
139
+ padding-right: 2rem;
140
+ }
141
+ }
142
+
143
+ /* Extra small screens */
144
+ @media (max-width: 375px) and (orientation: portrait) {
145
+ .event-dropdown {
146
+ height: 40px !important; /* Maintain 40px height to match PriceSortToggle */
147
+ }
148
+
149
+ .event-dropdown .dropdown-value {
150
+ max-width: calc(100vw - 120px);
151
+ font-size: 0.8rem;
152
+ }
153
+ }
154
+
155
+ /* Mobile landscape - hide non-essential elements */
156
+ @media (max-height: 500px) and (orientation: landscape) {
157
+ .stats-component,
158
+ .utilities-section,
159
+ .filter-controls {
160
+ display: none;
161
+ }
162
+
163
+ .flex-between.pt-5.pb-2 {
164
+ padding-top: 0.5rem;
165
+ padding-bottom: 0.25rem;
166
+ margin-bottom: 0.25rem;
167
+ }
102
168
  }
103
169
 
104
- /* iPhone landscape mode optimizations */
105
- @media screen and (max-height: 500px) and (orientation: landscape) {
106
- /* Hide Stats component */
107
- .stats-component {
108
- display: none !important;
109
- }
110
-
111
- /* Hide Utilities section (Scrape Venue, Check Stock) */
112
- .utilities-section {
113
- display: none !important;
114
- }
115
-
116
- /* Hide event filter and price sort toggle row */
117
- .flex.items-center.justify-between.gap-2 {
118
- display: none !important;
119
- }
120
-
121
- /* Hide desktop controls and show mobile controls */
122
- .desktop-controls-hide {
123
- display: none !important;
124
- }
125
-
126
- .mobile-header-controls {
127
- display: flex !important;
128
- }
129
-
130
- /* Hide the controls-wrapper completely */
131
- .controls-wrapper {
132
- display: none !important;
133
- }
134
-
135
- /* Reduce all margins to save space but keep proper navbar spacing */
136
- .lg\\:mb-6, .mb-3 {
137
- margin-bottom: 0.25rem !important;
138
- }
139
-
140
- /* Make header more compact but keep safe distance from navbar */
141
- .flex-between.pt-5.pb-2 {
142
- padding-top: 1rem !important; // Keep distance from navbar
143
- padding-bottom: 0.5rem !important;
144
- margin-bottom: 0.5rem !important;
145
- }
146
-
147
- /* Ensure task view has proper spacing */
148
- .lg\\:mb-6.mb-3 {
149
- margin-bottom: 0.25rem !important;
150
- }
170
+ /* Tablet and small desktop - show desktop controls */
171
+ @media (min-width: 650px) {
172
+ .desktop-controls-hide {
173
+ display: flex;
174
+ }
175
+
176
+ .mobile-header-controls {
177
+ display: none;
178
+ }
151
179
  }
152
180
  </style>
153
181
  <script setup>
154
- import { computed } from "vue";
182
+ import { computed, onMounted } from "vue";
155
183
  import { DesktopControls } from "@/components/Tasks/Controls";
156
184
  import TaskView from "@/components/Tasks/TaskView.vue";
157
185
  import Utilities from "@/components/Tasks/Utilities.vue";
@@ -172,14 +200,19 @@ const activeModal = computed(() => ui.activeModal);
172
200
  const taskCount = computed(() => Object.keys(ui.getSelectedTasks()).length);
173
201
  ui.refreshQueueStats();
174
202
 
203
+ // Ensure "All events" is always selected on page load
204
+ onMounted(() => {
205
+ ui.setCurrentEvent("");
206
+ });
207
+
175
208
  const uniqEventIds = computed(() => {
176
- const ids = [
177
- ...new Set(
178
- Object.values(ui.tasks)
179
- .filter((t) => t.siteId === ui.currentCountry.siteId && !t.eventId.includes("@"))
180
- .map((v) => `${v.eventName} (${v.eventId})`)
181
- )
182
- ];
183
- return ids;
209
+ const ids = [
210
+ ...new Set(
211
+ Object.values(ui.tasks)
212
+ .filter((t) => t.siteId === ui.currentCountry.siteId && !t.eventId.includes("@"))
213
+ .map((v) => `${v.eventName} (${v.eventId})`)
214
+ ),
215
+ ];
216
+ return ids;
184
217
  });
185
218
  </script>
@@ -5,7 +5,7 @@ export default {
5
5
  colors: {
6
6
  transparent: "transparent",
7
7
  white: "#ffffff",
8
- pure: "#ffffff",
8
+ pure: "#ffffff",
9
9
  lightgray: "#e5e7eb",
10
10
  green: {
11
11
  300: "#4ade80",
@@ -29,10 +29,10 @@ export default {
29
29
  },
30
30
  dark: {
31
31
  50: "#f8fafc",
32
- 100: "#f1f5f9",
32
+ 100: "#f1f5f9",
33
33
  200: "#e2e8f0",
34
34
  300: "#1a1b1e", // Deep charcoal base
35
- 400: "#242529", // Card backgrounds
35
+ 400: "#242529", // Card backgrounds
36
36
  500: "#2e2f34", // Input backgrounds
37
37
  550: "#35363c", // Subtle elevation
38
38
  600: "#3d3e44", // Borders
@@ -41,18 +41,18 @@ export default {
41
41
  750: "#52535a", // Selected states
42
42
  800: "#13141a", // Deep background
43
43
  850: "#0d0e14", // Deepest background
44
- 900: "#06070d" // Ultra deep
44
+ 900: "#06070d" // Ultra deep
45
45
  },
46
46
  light: {
47
47
  100: "#f6f8fa",
48
- 200: "#e1e4e8",
48
+ 200: "#e1e4e8",
49
49
  300: "#e2e2e5", // Primary text
50
50
  400: "#d0d0d3", // Secondary text
51
51
  500: "#a0a0a6", // Muted text
52
52
  600: "#71717a", // Disabled text
53
53
  700: "#57575f", // Very muted
54
54
  800: "#3e3e46", // Dark muted
55
- 900: "#27272d" // Darkest muted
55
+ 900: "#27272d" // Darkest muted
56
56
  },
57
57
  gray: {
58
58
  50: "#f9fafb",
@@ -68,7 +68,7 @@ export default {
68
68
  },
69
69
  accent: {
70
70
  blue: "#6b7a9a",
71
- purple: "#b794c0",
71
+ purple: "#b794c0",
72
72
  pink: "#d16d9e",
73
73
  orange: "#d4976e",
74
74
  yellow: "#e6d192",
@@ -77,24 +77,50 @@ export default {
77
77
  border: "#3d3e44"
78
78
  },
79
79
  screens: {
80
- xs: "500px",
81
- sm: "640px",
82
- // => @media (min-width: 640px) { ... }
80
+ // Mobile first approach
81
+ xs: "480px", // Small mobile landscape / large mobile portrait
82
+ sm: "640px", // Tablet portrait
83
+ md: "768px", // Tablet landscape / small desktop
84
+ lg: "1024px", // Desktop
85
+ xl: "1280px", // Large desktop
83
86
 
84
- md: "768px",
85
- // => @media (min-width: 768px) { ... }
87
+ // Device-specific breakpoints
88
+ tablet: "768px", // Tablet-specific styling
89
+ desktop: "1024px", // Desktop-specific styling
86
90
 
87
- ipadlg: "1000px",
88
- lg: "1030px",
89
- // => @media (min-width: 1024px) { ... }
90
-
91
- xl: "1280px",
92
- // => @media (min-width: 1280px) { ... }
93
-
94
- "2xl": "1536px",
95
- // => @media (min-width: 1536px) { ... }
91
+ // Orientation-based breakpoints
96
92
  landscape: {
97
93
  raw: "(orientation: landscape)"
94
+ },
95
+ portrait: {
96
+ raw: "(orientation: portrait)"
97
+ },
98
+
99
+ // Height-based breakpoints for better mobile experience
100
+ "h-sm": {
101
+ raw: "(max-height: 500px)"
102
+ },
103
+ "h-md": {
104
+ raw: "(min-height: 600px)"
105
+ },
106
+ "h-lg": {
107
+ raw: "(min-height: 900px)"
108
+ },
109
+
110
+ // Combined orientation and size breakpoints
111
+ "mobile-landscape": {
112
+ raw: "(max-width: 896px) and (orientation: landscape) and (max-height: 500px)"
113
+ },
114
+ "mobile-portrait": {
115
+ raw: "(max-width: 480px) and (orientation: portrait)"
116
+ },
117
+
118
+ // Touch device detection
119
+ touch: {
120
+ raw: "(hover: none) and (pointer: coarse)"
121
+ },
122
+ "no-touch": {
123
+ raw: "(hover: hover) and (pointer: fine)"
98
124
  }
99
125
  }
100
126
  },