@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
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <div class="table-component">
2
+ <div class="table-component relative box-border flex flex-col rounded-lg bg-dark-500 bg-clip-padding overflow-hidden shadow-sm">
3
3
  <Header class="grid-cols-10 gap-2 text-center lg:grid-cols-12">
4
4
  <div class="col-span-1 flex items-center justify-start lg:col-span-2">
5
5
  <Checkbox
@@ -9,50 +9,50 @@
9
9
  :isHeader="true" />
10
10
  <div class="mx-auto hidden items-center lg:flex" @click="ui.toggleSort('eventId')">
11
11
  <EventIcon class="lg:mr-3" />
12
- <h4 class="hidden lg:flex">Event</h4>
12
+ <h4 class="hidden lg:flex text-white">Event</h4>
13
13
  <DownIcon v-if="ui.sortData.sortBy === 'eventId' && !ui.sortData.reversed" class="ml-1" />
14
14
  <UpIcon v-if="ui.sortData.sortBy === 'eventId' && ui.sortData.reversed" class="ml-1" />
15
15
  </div>
16
16
  </div>
17
- <div class="col-span-2 flex items-center justify-center" v-once>
17
+ <div class="col-span-2 flex items-center justify-center lg:col-span-3 xl:col-span-2" v-once>
18
18
  <TicketIcon class="mr-0 lg:mr-3" />
19
- <h4 class="hidden lg:flex">Tickets</h4>
19
+ <h4 class="hidden lg:flex text-white">Tickets</h4>
20
20
  </div>
21
21
  <div
22
- class="col-span-5 flex items-center justify-center md:col-span-4 lg:col-span-5"
22
+ class="col-span-6 flex items-center justify-center md:col-span-5 lg:col-span-4 xl:col-span-5"
23
23
  @click="ui.toggleSort('status')">
24
24
  <StatusIcon class="mr-0 lg:mr-3" />
25
- <h4 class="hidden lg:flex">Status</h4>
25
+ <h4 class="hidden lg:flex text-white">Status</h4>
26
26
  <DownIcon v-if="ui.sortData.sortBy === 'status' && !ui.sortData.reversed" class="ml-1" />
27
27
  <UpIcon v-if="ui.sortData.sortBy === 'status' && ui.sortData.reversed" class="ml-1" />
28
28
  </div>
29
- <div class="col-span-2 flex items-center justify-center lg:col-span-3" v-once>
29
+ <div class="col-span-1 flex items-center justify-end md:col-span-2 md:justify-center lg:col-span-3" v-once>
30
30
  <ClickIcon class="mr-0 lg:mr-3" />
31
- <h4 class="hidden lg:flex">Actions</h4>
31
+ <h4 class="hidden lg:flex text-white">Actions</h4>
32
32
  </div>
33
- <div class="absolute right-5 top-3.5 hidden items-center lg:flex">
34
- <h4 class="text-center text-xs">ID</h4>
33
+ <div class="absolute right-5 top-3.5 hidden items-center xl:flex">
34
+ <h4 class="text-center text-xs text-white">ID</h4>
35
35
  </div>
36
36
  </Header>
37
37
  <div
38
- class="hidden-scrollbars stop-pan flex flex-col divide-y divide-dark-650 overflow-y-auto overflow-x-hidden"
38
+ class="hidden-scrollbars touch-pan-y flex flex-col divide-y divide-dark-650 overflow-y-auto overflow-x-hidden"
39
39
  :style="{ maxHeight: dynamicTableHeight }">
40
- <div v-for="(task, i) in getTasksInOrder()" :key="task.taskId" class="task-row-container">
40
+ <div v-for="(task, i) in getTasksInOrder()" :key="task.taskId" class="shrink-0 min-h-14.5 md:min-h-17.25 has-[.event-details]:min-h-18.75 mobile-portrait:min-h-12.5 transition-colors duration-150 ease-in-out hover:!bg-dark-550">
41
41
  <Task :task="task" :preferEventName="props.preferEventName" :class="i % 2 == 1 ? 'table-row-even' : 'table-row-odd'" />
42
42
  </div>
43
43
  <div
44
44
  v-if="getTasksInOrder().length === 0"
45
- class="empty-state flex flex-col items-center justify-center py-8 text-center">
45
+ class="empty-state flex flex-col items-center justify-center py-8 text-center bg-dark-400 text-light-500 text-sm font-medium">
46
46
  <div
47
47
  v-if="
48
48
  !ui.queueStats.queued && !ui.queueStats.sleeping && ui.queueStats.nextQueuePasses.length === 0
49
49
  ">
50
- <TasksIcon class="mx-auto mb-3 h-12 w-12 text-dark-400 opacity-50" />
50
+ <TasksIcon class="mx-auto empty-state-icon" />
51
51
  <p class="text-sm text-light-400">No tasks yet</p>
52
52
  <p class="mt-1 text-xs text-light-500">Create tasks to get started</p>
53
53
  </div>
54
54
  <div v-else>
55
- <TasksIcon class="mx-auto mb-3 h-12 w-12 text-dark-400 opacity-50" />
55
+ <TasksIcon class="mx-auto empty-state-icon" />
56
56
  <p class="text-sm text-light-400">No tasks match current filters</p>
57
57
  <p class="mt-1 text-xs text-light-500">Adjust filters to see tasks</p>
58
58
  </div>
@@ -60,58 +60,27 @@
60
60
  </div>
61
61
  </div>
62
62
  </template>
63
- <style lang="scss" scoped>
64
- h4 {
65
- @apply text-white;
66
- }
67
-
68
- .stop-pan {
69
- touch-action: pan-y pan-up pan-down;
70
- }
71
-
72
- .task-row-container {
73
- min-height: 69px;
74
- flex-shrink: 0;
75
- transition: background-color 0.15s ease;
76
-
77
- &:hover {
78
- @apply bg-dark-550 !important;
79
- }
80
-
81
- // Increase height when showing eventName to accommodate multi-line display (desktop only)
82
- @media (min-width: 1024px) {
83
- &:has(.event-details) {
84
- min-height: 75px;
85
- }
86
- }
87
-
88
- @media (max-width: 768px) {
89
- min-height: 58px;
90
- }
91
-
92
- @media (max-width: 480px) and (orientation: portrait) {
93
- min-height: 50px;
94
- }
95
- }
96
-
97
- .empty-state {
98
- @apply bg-dark-400;
99
- font-size: 14px;
100
- font-weight: 500;
101
- }
102
- </style>
103
63
  <script setup>
104
64
  import { computed, ref, onMounted, onUnmounted } from "vue";
105
- import { Table, Header } from "@/components/Table";
65
+ import { Header } from "@/components/Table";
106
66
  import { EventIcon, TicketIcon, StatusIcon, ClickIcon, DownIcon, UpIcon, TasksIcon } from "@/components/icons";
107
67
  import Task from "./Task.vue";
108
68
  import Checkbox from "@/components/ui/controls/atomic/Checkbox.vue";
109
69
  import { useUIStore } from "@/stores/ui";
110
70
 
111
71
  const props = defineProps({
112
- tasks: { type: Object },
113
- searchQuery: { type: String, default: "" },
114
- preferEventName: { type: Boolean, default: false }
72
+ tasks: {
73
+ type: Object,
74
+ required: true
75
+ },
76
+ searchQuery: {
77
+ type: String,
78
+ default: ''
79
+ },
80
+ preferEventName: {
81
+ type: Boolean,
82
+ default: false
83
+ }
115
84
  });
116
85
 
117
86
  const shouldTaskShow = (task) => {
@@ -189,8 +158,11 @@ onUnmounted(() => {
189
158
  });
190
159
 
191
160
  const dynamicTableHeight = computed(() => {
161
+ // Detect PWA mode (standalone display)
162
+ const isPWA = window.matchMedia('(display-mode: standalone)').matches;
163
+
192
164
  // Calculate available space for table
193
- const headerHeight = 55; // Header + navbar
165
+ const headerHeight = windowWidth.value >= 1024 ? 80 : 64; // Navbar padding (lg:pt-20 vs pt-16)
194
166
  const titleHeight = 45; // Tasks title and mobile controls
195
167
  const controlsHeight = windowWidth.value >= 650 ? 55 : 0; // Desktop controls
196
168
  // On desktop: stats + filters all in one row (45px)
@@ -203,9 +175,17 @@ const dynamicTableHeight = computed(() => {
203
175
  : ui.queueStats.show
204
176
  ? 130
205
177
  : 90; // Mobile: stats row + stacked filters
206
- const utilitiesHeight = windowWidth.value <= 768 ? 180 : 160; // Increase mobile utilities space to prevent cutoff
207
- const margins =
208
- windowWidth.value >= 1024 ? 20 : windowWidth.value <= 480 && windowHeight.value > windowWidth.value ? 8 : 12;
178
+
179
+ // Reserve more space for UTILS on iPhone PWA to prevent overflow
180
+ const utilitiesHeight = isPWA && windowWidth.value <= 768
181
+ ? 260 // iPhone PWA: extra space for UTILS
182
+ : windowWidth.value > 1024
183
+ ? 200 // Desktop
184
+ : windowWidth.value <= 768
185
+ ? 220 // Mobile browser
186
+ : 180; // Tablet
187
+
188
+ const margins = windowWidth.value >= 1024 ? 30 : windowWidth.value <= 480 && windowHeight.value > windowWidth.value ? 8 : 12;
209
189
 
210
190
  const totalUsedSpace =
211
191
  headerHeight + titleHeight + controlsHeight + filtersAndStatsHeight + utilitiesHeight + margins;
@@ -1,56 +1,24 @@
1
1
  <template>
2
- <div class="utilities-wrapper grid grid-cols-1 gap-3 lg:grid-cols-1" v-if="ui.currentModule == 'TM'">
3
- <div class="lg:justify-self-end">
4
- <h4 class="hidden lg:block text-white opacity-40 uppercase font-medium mb-1">Utils</h4>
5
- <div class="flex gap-3 justify-between lg:justify-start">
6
- <button class="button-default w-44 bg-dark-400 flex items-center justify-center gap-x-2 utility-btn" @click="ui.toggleModal('scrape-venue')">
2
+ <div class="grid grid-cols-1 gap-3 mt-4 mb-6 md:mb-10" v-if="ui.currentModule == 'TM'">
3
+ <div>
4
+ <h4 class="hidden lg:block text-white opacity-40 uppercase font-medium mb-1 text-xs">Utils</h4>
5
+ <div class="flex gap-3 flex-wrap justify-between lg:justify-start">
6
+ <button class="btn-modal w-40 sm:w-44" @click="ui.toggleModal('scrape-venue')">
7
7
  Scrape Venue
8
- <ScrapeIcon />
8
+ <ScrapeIcon class="w-3.5 h-3.5 flex-shrink-0 ml-2" />
9
9
  </button>
10
- <button class="button-default w-44 bg-dark-400 flex items-center justify-center gap-x-2 utility-btn" @click="ui.toggleModal('check-stock')">
10
+ <button class="btn-modal w-40 sm:w-44" @click="ui.toggleModal('check-stock')">
11
11
  Check Stock
12
- <BoxIcon />
12
+ <BoxIcon class="w-3.5 h-3.5 flex-shrink-0 ml-2" />
13
13
  </button>
14
14
  </div>
15
- <h4 class="text-white opacity-40 uppercase font-medium block lg:hidden">Utils</h4>
15
+ <h4 class="text-white opacity-40 uppercase font-medium block lg:hidden text-xs text-center mt-2 px-4">Utils</h4>
16
16
  </div>
17
17
  </div>
18
18
  </template>
19
19
  <script setup>
20
- import { BoxIcon, ScrapeIcon, CameraIcon, GroupIcon } from "@/components/icons";
20
+ import { BoxIcon, ScrapeIcon } from "@/components/icons";
21
21
  import { useUIStore } from "@/stores/ui";
22
22
 
23
23
  const ui = useUIStore();
24
24
  </script>
25
- <style lang="scss" scoped>
26
- .utilities-wrapper {
27
- // Add extra margin on mobile to prevent buttons from being cut off
28
- @media (max-width: 768px) {
29
- margin-top: 1rem;
30
- margin-bottom: 1.5rem;
31
- }
32
- }
33
-
34
- .utility-btn {
35
- height: 50px;
36
-
37
- @media (max-width: 768px) {
38
- height: 40px;
39
- font-size: 0.75rem;
40
- }
41
- }
42
-
43
- button {
44
- font-size: 0.75rem;
45
-
46
- svg {
47
- width: 14px;
48
- height: 14px;
49
- flex-shrink: 0;
50
- }
51
- }
52
-
53
- h4 {
54
- font-size: 12px;
55
- }
56
- </style>
@@ -96,10 +96,10 @@
96
96
  label="Password">
97
97
  {{ showPassword ? taskSnapshot.password : "••••••••" }}
98
98
  <template #action>
99
- <button @click.stop="showPassword = !showPassword" class="flex items-center justify-center w-8 h-8 rounded transition-all hover:bg-dark-600">
99
+ <button @click.stop="showPassword = !showPassword" class="flex items-center justify-center w-8 h-8 rounded transition-all hover:bg-dark-550">
100
100
  <EyeToggle :visible="showPassword" />
101
101
  </button>
102
- <button @click.stop="copy(taskSnapshot.password, 'Copied password')" class="copy-button flex items-center justify-center w-8 h-8 rounded transition-all hover:bg-dark-600 text-light-500 hover:text-light-300">
102
+ <button @click.stop="copy(taskSnapshot.password, 'Copied password')" class="copy-button flex items-center justify-center w-8 h-8 rounded transition-all hover:bg-dark-550 text-light-500 hover:text-light-300">
103
103
  <CopyIcon class="w-4 h-4" />
104
104
  </button>
105
105
  </template>
@@ -146,53 +146,32 @@
146
146
  <!-- Task Settings Toggles -->
147
147
  <SectionCard title="Task Settings" class="mb-4">
148
148
  <div class="grid grid-cols-2 gap-4 md:grid-cols-3">
149
- <div class="toggle-item">
150
- <div class="toggle-label">
151
- <TimerIcon class="h-4 w-4" />
152
- <span>Smart Timer</span>
153
- </div>
149
+ <div class="flex flex-col items-center gap-2">
150
+ <IconLabel :icon="TimerIcon" label="Smart Timer" />
154
151
  <Switch v-model="toggles.smartTimer" disabled />
155
152
  </div>
156
- <div class="toggle-item">
157
- <div class="toggle-label">
158
- <GroupIcon class="h-4 w-4" />
159
- <span>Login Later</span>
160
- </div>
153
+ <div class="flex flex-col items-center gap-2">
154
+ <IconLabel :icon="GroupIcon" label="Login Later" />
161
155
  <Switch v-model="toggles.loginAfterCart" disabled />
162
156
  </div>
163
- <div class="toggle-item">
164
- <div class="toggle-label">
165
- <HandIcon class="h-4 w-4" />
166
- <span>Manual</span>
167
- </div>
157
+ <div class="flex flex-col items-center gap-2">
158
+ <IconLabel :icon="HandIcon" label="Manual" />
168
159
  <Switch v-model="toggles.manual" disabled />
169
160
  </div>
170
- <div class="toggle-item">
171
- <div class="toggle-label">
172
- <SavingsIcon class="h-4 w-4" />
173
- <span>Do Not Pay</span>
174
- </div>
161
+ <div class="flex flex-col items-center gap-2">
162
+ <IconLabel :icon="SavingsIcon" label="Do Not Pay" />
175
163
  <Switch v-model="toggles.doNotPay" disabled />
176
164
  </div>
177
- <div class="toggle-item">
178
- <div class="toggle-label">
179
- <LoyaltyIcon class="h-4 w-4" />
180
- <span>Presale Mode</span>
181
- </div>
165
+ <div class="flex flex-col items-center gap-2">
166
+ <IconLabel :icon="LoyaltyIcon" label="Presale Mode" />
182
167
  <Switch v-model="toggles.presaleMode" disabled />
183
168
  </div>
184
- <div class="toggle-item">
185
- <div class="toggle-label">
186
- <SkiIcon class="h-4 w-4" />
187
- <span>Quick Queue</span>
188
- </div>
169
+ <div class="flex flex-col items-center gap-2">
170
+ <IconLabel :icon="SkiIcon" label="Quick Queue" />
189
171
  <Switch v-model="toggles.quickQueue" disabled />
190
172
  </div>
191
- <div class="toggle-item">
192
- <div class="toggle-label">
193
- <SandclockIcon class="h-4 w-4" />
194
- <span>Aged Account</span>
195
- </div>
173
+ <div class="flex flex-col items-center gap-2">
174
+ <IconLabel :icon="SandclockIcon" label="Aged Account" />
196
175
  <Switch v-model="toggles.agedAccount" disabled />
197
176
  </div>
198
177
  </div>
@@ -207,8 +186,12 @@ import Switch from "@/components/ui/controls/atomic/Switch.vue";
207
186
  import EyeToggle from "@/components/ui/controls/EyeToggle.vue";
208
187
  import InfoRow from "@/components/ui/InfoRow.vue";
209
188
  import SectionCard from "@/components/ui/SectionCard.vue";
189
+ import IconLabel from "@/components/ui/IconLabel.vue";
210
190
  import { useUIStore } from "@/stores/ui";
211
191
  import { useCopyToClipboard } from "@/composables/useCopyToClipboard";
192
+ import { useColorMapping } from "@/composables/useColorMapping";
193
+ import { useDateFormatting } from "@/composables/useDateFormatting";
194
+ import { useTicketPricing } from "@/composables/useTicketPricing";
212
195
  import {
213
196
  EyeIcon,
214
197
  StadiumIcon,
@@ -235,6 +218,9 @@ import {
235
218
 
236
219
  const ui = useUIStore();
237
220
  const { copy } = useCopyToClipboard();
221
+ const { colorToClass } = useColorMapping();
222
+ const { formatEventDate: formatDate } = useDateFormatting();
223
+ const { isTotalPrice } = useTicketPricing();
238
224
  const showPassword = ref(false);
239
225
 
240
226
  const props = defineProps({
@@ -274,74 +260,4 @@ const toggles = computed(() => ({
274
260
  quickQueue: taskSnapshot.value.quickQueue,
275
261
  agedAccount: taskSnapshot.value.agedAccount
276
262
  }));
277
-
278
- const formatDate = (dateString) => {
279
- if (!dateString) return "";
280
- try {
281
- const date = new Date(dateString);
282
- const options = {
283
- month: "short",
284
- day: "numeric",
285
- year: "numeric",
286
- hour: "numeric",
287
- minute: "2-digit",
288
- hour12: true
289
- };
290
- return date.toLocaleString("en-US", options).replace(",", "");
291
- } catch {
292
- return dateString;
293
- }
294
- };
295
-
296
- const isTotalPrice = (line, index, lines) => {
297
- const trimmed = line.trim();
298
- const nonEmptyLines = lines.filter((l) => l.trim());
299
- const isLastLine = index === lines.lastIndexOf(nonEmptyLines[nonEmptyLines.length - 1]);
300
- if (!isLastLine) return false;
301
- // Match currency symbols ($, €, £, etc.) OR currency codes (USD, EUR, AUD, etc.)
302
- const totalPricePattern = /^([$€£¥₹₽¢]|[A-Z]{3})\s*[\d,]+\.?\d*$/;
303
- return totalPricePattern.test(trimmed) && !trimmed.includes("(");
304
- };
305
-
306
- const colorToClass = (color) => {
307
- const colorMap = {
308
- red: "bg-red-400",
309
- green: "bg-green-400",
310
- yellow: "bg-yellow-400",
311
- blue: "bg-blue-400"
312
- };
313
- return colorMap[color?.toLowerCase()] || "bg-gray-400";
314
- };
315
263
  </script>
316
-
317
- <style lang="scss" scoped>
318
- .toggle-item {
319
- @apply flex flex-col items-center gap-2;
320
- }
321
-
322
- .toggle-label {
323
- @apply flex items-center gap-2 text-xs;
324
- color: oklch(0.9 0 0);
325
-
326
- svg {
327
- color: oklch(0.9 0 0) !important;
328
- width: 16px !important;
329
- height: 16px !important;
330
- }
331
- }
332
-
333
- .status-indicator {
334
- @apply h-2 w-2 flex-shrink-0 rounded-full;
335
- }
336
-
337
- .info-icon {
338
- @apply h-4 w-4 flex-shrink-0;
339
- color: oklch(0.9 0 0) !important;
340
-
341
- svg {
342
- color: oklch(0.9 0 0) !important;
343
- width: 16px !important;
344
- height: 16px !important;
345
- }
346
- }
347
- </style>
@@ -5,17 +5,11 @@
5
5
  viewBox="0 0 17 17"
6
6
  fill="none"
7
7
  xmlns="http://www.w3.org/2000/svg"
8
- class="close-icon"
8
+ class="w-4 h-4"
9
9
  >
10
10
  <path
11
11
  d="M2.20006 16.375L0.625061 14.8L6.92506 8.5L0.625061 2.2L2.20006 0.625L8.50006 6.925L14.8001 0.625L16.3751 2.2L10.0751 8.5L16.3751 14.8L14.8001 16.375L8.50006 10.075L2.20006 16.375Z"
12
12
  fill="currentColor"
13
13
  />
14
14
  </svg>
15
- </template>
16
-
17
- <style scoped>
18
- .close-icon {
19
- @apply w-4 h-4;
20
- }
21
- </style>
15
+ </template>
@@ -1,8 +1,8 @@
1
- <template>
2
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
3
- <path
4
- fill="#fff"
5
- d="M495.9 166.6c3.2 8.7 .5 18.4-6.4 24.6l-43.3 39.4c1.1 8.3 1.7 16.8 1.7 25.4s-.6 17.1-1.7 25.4l43.3 39.4c6.9 6.2 9.6 15.9 6.4 24.6c-4.4 11.9-9.7 23.3-15.8 34.3l-4.7 8.1c-6.6 11-14 21.4-22.1 31.2c-5.9 7.2-15.7 9.6-24.5 6.8l-55.7-17.7c-13.4 10.3-28.2 18.9-44 25.4l-12.5 57.1c-2 9.1-9 16.3-18.2 17.8c-13.8 2.3-28 3.5-42.5 3.5s-28.7-1.2-42.5-3.5c-9.2-1.5-16.2-8.7-18.2-17.8l-12.5-57.1c-15.8-6.5-30.6-15.1-44-25.4L83.1 425.9c-8.8 2.8-18.6 .3-24.5-6.8c-8.1-9.8-15.5-20.2-22.1-31.2l-4.7-8.1c-6.1-11-11.4-22.4-15.8-34.3c-3.2-8.7-.5-18.4 6.4-24.6l43.3-39.4C64.6 273.1 64 264.6 64 256s.6-17.1 1.7-25.4L22.4 191.2c-6.9-6.2-9.6-15.9-6.4-24.6c4.4-11.9 9.7-23.3 15.8-34.3l4.7-8.1c6.6-11 14-21.4 22.1-31.2c5.9-7.2 15.7-9.6 24.5-6.8l55.7 17.7c13.4-10.3 28.2-18.9 44-25.4l12.5-57.1c2-9.1 9-16.3 18.2-17.8C227.3 1.2 241.5 0 256 0s28.7 1.2 42.5 3.5c9.2 1.5 16.2 8.7 18.2 17.8l12.5 57.1c15.8 6.5 30.6 15.1 44 25.4l55.7-17.7c8.8-2.8 18.6-.3 24.5 6.8c8.1 9.8 15.5 20.2 22.1 31.2l4.7 8.1c6.1 11 11.4 22.4 15.8 34.3zM256 336a80 80 0 1 0 0-160 80 80 0 1 0 0 160z"
6
- />
7
- </svg>
8
- </template>
1
+ <template>
2
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
3
+ <path
4
+ fill="#fff"
5
+ d="M495.9 166.6c3.2 8.7 .5 18.4-6.4 24.6l-43.3 39.4c1.1 8.3 1.7 16.8 1.7 25.4s-.6 17.1-1.7 25.4l43.3 39.4c6.9 6.2 9.6 15.9 6.4 24.6c-4.4 11.9-9.7 23.3-15.8 34.3l-4.7 8.1c-6.6 11-14 21.4-22.1 31.2c-5.9 7.2-15.7 9.6-24.5 6.8l-55.7-17.7c-13.4 10.3-28.2 18.9-44 25.4l-12.5 57.1c-2 9.1-9 16.3-18.2 17.8c-13.8 2.3-28 3.5-42.5 3.5s-28.7-1.2-42.5-3.5c-9.2-1.5-16.2-8.7-18.2-17.8l-12.5-57.1c-15.8-6.5-30.6-15.1-44-25.4L83.1 425.9c-8.8 2.8-18.6 .3-24.5-6.8c-8.1-9.8-15.5-20.2-22.1-31.2l-4.7-8.1c-6.1-11-11.4-22.4-15.8-34.3c-3.2-8.7-.5-18.4 6.4-24.6l43.3-39.4C64.6 273.1 64 264.6 64 256s.6-17.1 1.7-25.4L22.4 191.2c-6.9-6.2-9.6-15.9-6.4-24.6c4.4-11.9 9.7-23.3 15.8-34.3l4.7-8.1c6.6-11 14-21.4 22.1-31.2c5.9-7.2 15.7-9.6 24.5-6.8l55.7 17.7c13.4-10.3 28.2-18.9 44-25.4l12.5-57.1c2-9.1 9-16.3 18.2-17.8C227.3 1.2 241.5 0 256 0s28.7 1.2 42.5 3.5c9.2 1.5 16.2 8.7 18.2 17.8l12.5 57.1c15.8 6.5 30.6 15.1 44 25.4l55.7-17.7c8.8-2.8 18.6-.3 24.5 6.8c8.1 9.8 15.5 20.2 22.1 31.2l4.7 8.1c6.1 11 11.4 22.4 15.8 34.3zM256 336a80 80 0 1 0 0-160 80 80 0 1 0 0 160z"
6
+ />
7
+ </svg>
8
+ </template>
@@ -0,0 +1,5 @@
1
+ <template>
2
+ <svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
3
+ <path d="M10 3L8 21M16 3L14 21M4 8H20M3 16H19" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
4
+ </svg>
5
+ </template>
@@ -5,17 +5,11 @@
5
5
  viewBox="0 0 16 9"
6
6
  fill="none"
7
7
  xmlns="http://www.w3.org/2000/svg"
8
- class="key-icon"
8
+ class="w-4 h-4"
9
9
  >
10
10
  <path
11
11
  d="M4.44791 5.89583C4.09843 5.89583 3.79936 5.77129 3.5507 5.52221C3.30161 5.27355 3.17707 4.97448 3.17707 4.625C3.17707 4.27552 3.30161 3.97624 3.5507 3.72716C3.79936 3.4785 4.09843 3.35417 4.44791 3.35417C4.79739 3.35417 5.09645 3.4785 5.34511 3.72716C5.5942 3.97624 5.71874 4.27552 5.71874 4.625C5.71874 4.97448 5.5942 5.27355 5.34511 5.52221C5.09645 5.77129 4.79739 5.89583 4.44791 5.89583ZM4.44791 8.4375C3.38888 8.4375 2.4887 8.06684 1.74739 7.32552C1.00607 6.5842 0.635406 5.68403 0.635406 4.625C0.635406 3.56597 1.00607 2.6658 1.74739 1.92448C2.4887 1.18316 3.38888 0.8125 4.44791 0.8125C5.15745 0.8125 5.80092 0.987239 6.3783 1.33672C6.95526 1.6862 7.41318 2.14688 7.75207 2.71875H13.3437L15.25 4.625L12.3906 7.48438L11.1198 6.53125L9.84895 7.48438L8.49869 6.53125H7.75207C7.41318 7.10313 6.95526 7.5638 6.3783 7.91328C5.80092 8.26276 5.15745 8.4375 4.44791 8.4375ZM4.44791 7.16667C5.04096 7.16667 5.56264 6.98663 6.01294 6.62656C6.46281 6.26649 6.76188 5.81111 6.91015 5.26042H8.89582L9.81718 5.91172L11.1198 4.94271L12.2476 5.81641L13.4391 4.625L12.8036 3.98958H6.91015C6.76188 3.43889 6.46281 2.98351 6.01294 2.62344C5.56264 2.26337 5.04096 2.08333 4.44791 2.08333C3.74895 2.08333 3.1506 2.33221 2.65285 2.82995C2.15511 3.32769 1.90624 3.92604 1.90624 4.625C1.90624 5.32396 2.15511 5.92231 2.65285 6.42005C3.1506 6.9178 3.74895 7.16667 4.44791 7.16667Z"
12
12
  fill="currentColor"
13
13
  />
14
14
  </svg>
15
- </template>
16
-
17
- <style scoped>
18
- .key-icon {
19
- @apply w-4 h-4;
20
- }
21
- </style>
15
+ </template>
@@ -5,17 +5,11 @@
5
5
  viewBox="0 0 19 20"
6
6
  fill="none"
7
7
  xmlns="http://www.w3.org/2000/svg"
8
- class="pencil-icon"
8
+ class="w-4 h-4"
9
9
  >
10
10
  <path
11
11
  d="M0.75 20V16.5H18.25V20H0.75ZM2.5 14.75V11.4688L10.4187 3.55004L13.7 6.83129L5.78125 14.75H2.5ZM4.25 13H5.0375L11.25 6.83129L10.4187 6.00004L4.25 12.2125V13ZM14.6844 5.86879L11.4031 2.58754L12.9781 1.01254C13.1385 0.837536 13.3427 0.753536 13.5906 0.760536C13.8385 0.768119 14.0427 0.852119 14.2031 1.01254L16.2594 3.06879C16.4198 3.2292 16.5 3.42987 16.5 3.67079C16.5 3.91112 16.4198 4.11879 16.2594 4.29379L14.6844 5.86879Z"
12
12
  fill="currentColor"
13
13
  />
14
14
  </svg>
15
- </template>
16
-
17
- <style scoped>
18
- .pencil-icon {
19
- @apply w-4 h-4;
20
- }
21
- </style>
15
+ </template>
@@ -2,17 +2,11 @@
2
2
  <svg
3
3
  xmlns="http://www.w3.org/2000/svg"
4
4
  viewBox="0 0 1024 1024"
5
- class="profile-icon"
5
+ class="w-4 h-4"
6
6
  >
7
7
  <path
8
8
  fill="currentColor"
9
9
  d="M0 1024v-72.874521c0-149.917478 93.497315-353.841814 241.330575-402.948929l9.031614-2.998349 4.497524 8.117483a316.618401 316.618401 0 0 0 33.201237 48.485506l10.567354 12.688138-16.088705 4.387828c-118.178851 32.579628-201.986378 215.917734-206.88612 332.341454h872.519723c-4.899742-116.387154-99.457449-299.834957-217.6363-332.341454l-16.088705-4.387828 10.457658-12.578442a316.874358 316.874358 0 0 0 33.201237-48.485507l4.497524-8.117483 8.921918 2.888654c147.979521 49.107115 252.300146 252.994886 252.300147 402.948929V1024H0z m511.91334-365.652386a246.888491 246.888491 0 0 1-255.95667-255.95667V256.129989a246.888491 246.888491 0 0 1 255.95667-255.95667 246.888491 246.888491 0 0 1 255.956671 255.95667v146.260955a246.888491 246.888491 0 0 1-255.956671 255.95667z m182.826193-402.217625A182.826193 182.826193 0 1 0 329.087147 256.129989v146.260955a182.826193 182.826193 0 1 0 365.652386 0V256.129989z"
10
10
  />
11
11
  </svg>
12
- </template>
13
-
14
- <style scoped>
15
- .profile-icon {
16
- @apply w-4 h-4;
17
- }
18
- </style>
12
+ </template>
@@ -5,17 +5,11 @@
5
5
  viewBox="0 0 16 16"
6
6
  fill="none"
7
7
  xmlns="http://www.w3.org/2000/svg"
8
- class="sell-icon"
8
+ class="w-4 h-4"
9
9
  >
10
10
  <path
11
11
  d="M9.68747 15.05C9.39997 15.3375 9.04372 15.4812 8.61872 15.4812C8.19372 15.4812 7.83747 15.3375 7.54997 15.05L0.949969 8.44995C0.812469 8.31245 0.70322 8.14995 0.62222 7.96245C0.54072 7.77495 0.499969 7.57495 0.499969 7.36245V1.99995C0.499969 1.58745 0.64697 1.2342 0.94097 0.940204C1.23447 0.646704 1.58747 0.499954 1.99997 0.499954H7.36247C7.57497 0.499954 7.77497 0.540454 7.96247 0.621454C8.14997 0.702954 8.31247 0.812454 8.44997 0.949954L15.05 7.5687C15.3375 7.8562 15.4812 8.2092 15.4812 8.6277C15.4812 9.0467 15.3375 9.39995 15.05 9.68745L9.68747 15.05ZM8.61872 14L13.9812 8.63745L7.36247 1.99995H1.99997V7.36245L8.61872 14ZM3.87497 4.99995C4.18747 4.99995 4.45297 4.89045 4.67147 4.67145C4.89047 4.45295 4.99997 4.18745 4.99997 3.87495C4.99997 3.56245 4.89047 3.29695 4.67147 3.07845C4.45297 2.85945 4.18747 2.74995 3.87497 2.74995C3.56247 2.74995 3.29697 2.85945 3.07847 3.07845C2.85947 3.29695 2.74997 3.56245 2.74997 3.87495C2.74997 4.18745 2.85947 4.45295 3.07847 4.67145C3.29697 4.89045 3.56247 4.99995 3.87497 4.99995Z"
12
12
  fill="currentColor"
13
13
  />
14
14
  </svg>
15
- </template>
16
-
17
- <style scoped>
18
- .sell-icon {
19
- @apply w-4 h-4;
20
- }
21
- </style>
15
+ </template>
@@ -1,19 +1,16 @@
1
1
  <template>
2
- <svg class="spinner" viewBox="0 0 50 50">
2
+ <svg class="spinner mx-auto h-7.5 w-7.5" viewBox="0 0 50 50">
3
3
  <circle class="path" cx="25" cy="25" r="20" fill="none" stroke-width="5"></circle>
4
4
  </svg>
5
5
  </template>
6
6
 
7
7
  <style lang="scss" scoped>
8
8
  .spinner {
9
- @apply mx-auto;
10
- animation: rotate 2s linear infinite;
11
9
  z-index: 2;
12
- width: 30px;
13
- height: 30px;
14
-
10
+ animation: rotate 2s linear infinite;
11
+
15
12
  & .path {
16
- stroke: rgba(70, 198, 210, 100%);
13
+ stroke: oklch(0.75 0.1 195);
17
14
  stroke-linecap: round;
18
15
  animation: dash 1.5s ease-in-out infinite;
19
16
  }
@@ -2,17 +2,11 @@
2
2
  <svg
3
3
  xmlns="http://www.w3.org/2000/svg"
4
4
  viewBox="0 0 448 512"
5
- class="square-check-icon"
5
+ class="w-4 h-4"
6
6
  >
7
7
  <path
8
8
  fill="currentColor"
9
9
  d="M64 80c-8.8 0-16 7.2-16 16V416c0 8.8 7.2 16 16 16H384c8.8 0 16-7.2 16-16V96c0-8.8-7.2-16-16-16H64zM0 96C0 60.7 28.7 32 64 32H384c35.3 0 64 28.7 64 64V416c0 35.3-28.7 64-64 64H64c-35.3 0-64-28.7-64-64V96zM337 209L209 337c-9.4 9.4-24.6 9.4-33.9 0l-64-64c-9.4-9.4-9.4-24.6 0-33.9s24.6-9.4 33.9 0l47 47L303 175c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9z"
10
10
  />
11
11
  </svg>
12
- </template>
13
-
14
- <style scoped>
15
- .square-check-icon {
16
- @apply w-4 h-4;
17
- }
18
- </style>
12
+ </template>
@@ -2,17 +2,11 @@
2
2
  <svg
3
3
  xmlns="http://www.w3.org/2000/svg"
4
4
  viewBox="0 0 448 512"
5
- class="square-uncheck-icon"
5
+ class="w-4 h-4"
6
6
  >
7
7
  <path
8
8
  fill="currentColor"
9
9
  d="M64 80c-8.8 0-16 7.2-16 16V416c0 8.8 7.2 16 16 16H384c8.8 0 16-7.2 16-16V96c0-8.8-7.2-16-16-16H64zM0 96C0 60.7 28.7 32 64 32H384c35.3 0 64 28.7 64 64V416c0 35.3-28.7 64-64 64H64c-35.3 0-64-28.7-64-64V96zM152 232H296c13.3 0 24 10.7 24 24s-10.7 24-24 24H152c-13.3 0-24-10.7-24-24s10.7-24 24-24z"
10
10
  />
11
11
  </svg>
12
- </template>
13
-
14
- <style scoped>
15
- .square-uncheck-icon {
16
- @apply w-4 h-4;
17
- }
18
- </style>
12
+ </template>
@@ -2,17 +2,11 @@
2
2
  <svg
3
3
  xmlns="http://www.w3.org/2000/svg"
4
4
  viewBox="0 0 512 512"
5
- class="wildcard-icon"
5
+ class="w-4 h-4"
6
6
  >
7
7
  <path
8
8
  fill="currentColor"
9
9
  d="M208 32c0-17.7 14.3-32 32-32h32c17.7 0 32 14.3 32 32V172.9l122-70.4c15.3-8.8 34.9-3.6 43.7 11.7l16 27.7c8.8 15.3 3.6 34.9-11.7 43.7L352 256l122 70.4c15.3 8.8 20.5 28.4 11.7 43.7l-16 27.7c-8.8 15.3-28.4 20.6-43.7 11.7L304 339.1V480c0 17.7-14.3 32-32 32H240c-17.7 0-32-14.3-32-32V339.1L86 409.6c-15.3 8.8-34.9 3.6-43.7-11.7l-16-27.7c-8.8-15.3-3.6-34.9 11.7-43.7L160 256 38 185.6c-15.3-8.8-20.5-28.4-11.7-43.7l16-27.7C51.1 98.8 70.7 93.6 86 102.4l122 70.4V32z"
10
10
  />
11
11
  </svg>
12
- </template>
13
-
14
- <style scoped>
15
- .wildcard-icon {
16
- @apply w-4 h-4;
17
- }
18
- </style>
12
+ </template>