@necrolab/dashboard 0.4.37 → 0.4.39

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 (62) hide show
  1. package/.claude/settings.local.json +3 -1
  2. package/backend/api.js +20 -16
  3. package/backend/auth.js +2 -2
  4. package/backend/batching.js +1 -1
  5. package/backend/endpoints.js +5 -5
  6. package/backend/index.js +2 -2
  7. package/backend/mock-data.js +19 -20
  8. package/backend/mock-src/classes/logger.js +5 -7
  9. package/backend/mock-src/classes/utils.js +3 -2
  10. package/backend/mock-src/ticketmaster.js +2 -2
  11. package/backend/validator.js +2 -2
  12. package/dev-server.js +49 -0
  13. package/index.html +1 -1
  14. package/index.js +1 -1
  15. package/package.json +6 -5
  16. package/postcss.config.js +1 -1
  17. package/postinstall.js +5 -3
  18. package/public/android-chrome-192x192.png +0 -0
  19. package/public/android-chrome-512x512.png +0 -0
  20. package/public/apple-touch-icon.png +0 -0
  21. package/public/favicon-16x16.png +0 -0
  22. package/public/favicon-32x32.png +0 -0
  23. package/public/favicon.ico +0 -0
  24. package/public/manifest.json +4 -4
  25. package/src/App.vue +471 -49
  26. package/src/assets/css/_input.scss +25 -25
  27. package/src/assets/css/main.scss +116 -22
  28. package/src/assets/img/android-chrome-192x192.png +0 -0
  29. package/src/assets/img/logo_icon-old.png +0 -0
  30. package/src/assets/img/logo_icon.png +0 -0
  31. package/src/components/Editors/Account/Account.vue +19 -19
  32. package/src/components/Editors/Account/AccountCreator.vue +3 -3
  33. package/src/components/Editors/Account/AccountView.vue +18 -7
  34. package/src/components/Editors/Profile/Profile.vue +24 -24
  35. package/src/components/Editors/Profile/ProfileView.vue +23 -10
  36. package/src/components/Editors/TagLabel.vue +6 -7
  37. package/src/components/Table/Header.vue +1 -1
  38. package/src/components/Table/Row.vue +1 -1
  39. package/src/components/Table/Table.vue +15 -0
  40. package/src/components/Tasks/Controls/DesktopControls.vue +1 -1
  41. package/src/components/Tasks/CreateTaskAXS.vue +15 -15
  42. package/src/components/Tasks/CreateTaskTM.vue +5 -4
  43. package/src/components/Tasks/Task.vue +23 -35
  44. package/src/components/Tasks/TaskView.vue +20 -27
  45. package/src/components/Tasks/Utilities.vue +1 -1
  46. package/src/components/icons/Mail.vue +2 -2
  47. package/src/components/ui/Modal.vue +84 -15
  48. package/src/components/ui/Navbar.vue +118 -39
  49. package/src/components/ui/controls/atomic/Dropdown.vue +23 -3
  50. package/src/components/ui/controls/atomic/MultiDropdown.vue +43 -23
  51. package/src/stores/sampleData.js +5 -4
  52. package/src/stores/ui.js +5 -4
  53. package/src/views/Accounts.vue +2 -2
  54. package/src/views/Console.vue +78 -30
  55. package/src/views/Editor.vue +175 -24
  56. package/src/views/FilterBuilder.vue +21 -7
  57. package/src/views/Profiles.vue +8 -8
  58. package/src/views/Tasks.vue +51 -2
  59. package/tailwind.config.js +1 -1
  60. package/vite.config.js +8 -1
  61. package/vue.config.js +1 -1
  62. package/{workbox-config.js → workbox-config.cjs} +1 -4
@@ -1,7 +1,6 @@
1
1
  <template>
2
2
  <div>
3
3
  <!-- Heading -->
4
- <GearIcon class="w-5 cursor-pointer" @click="ui.toggleModal('quick-settings')" />
5
4
  <h4 class="text-white text-xl font-bold mb-5 pt-5 flex gap-2 items-center">
6
5
  Editor <img src="@/assets/img/pencil.svg" />
7
6
  </h4>
@@ -9,8 +8,8 @@
9
8
  <div class="card-dark p-2">
10
9
  <div v-if="ui.profile.admin">
11
10
  <h5 class="text-white text-xl font-bold flex gap-x-3 mb-3">Admin Editor</h5>
12
- <div class="flex justify-between items-center">
13
- <div class="w-64 flex">
11
+ <div class="flex justify-between items-center gap-4 editor-controls-row">
12
+ <div class="w-64 flex flex-shrink-0 dropdown-container">
14
13
  <div class="relative flex-grow">
15
14
  <Dropdown
16
15
  class="bg-dark-500 border-2 border-r-0 border-dark-550 admin-file-dropdown w-full"
@@ -30,7 +29,7 @@
30
29
  </button>
31
30
  </div>
32
31
  <!-- Admin editor buttons moved here -->
33
- <div v-if="textEditorVisible" class="flex gap-x-2" style="margin-right: 1px;">
32
+ <div v-if="textEditorVisible" class="flex gap-x-2 flex-shrink-0">
34
33
  <button class="btn-action" @click="format()" v-if="isJsonFile()">
35
34
  <svg
36
35
  xmlns="http://www.w3.org/2000/svg"
@@ -68,6 +67,23 @@
68
67
  </svg>
69
68
  <span>Save File</span>
70
69
  </button>
70
+ <button class="btn-action" @click="closeFile">
71
+ <svg
72
+ xmlns="http://www.w3.org/2000/svg"
73
+ width="16"
74
+ height="16"
75
+ viewBox="0 0 24 24"
76
+ fill="none"
77
+ stroke="currentColor"
78
+ stroke-width="2"
79
+ stroke-linecap="round"
80
+ stroke-linejoin="round"
81
+ >
82
+ <line x1="18" y1="6" x2="6" y2="18"></line>
83
+ <line x1="6" y1="6" x2="18" y2="18"></line>
84
+ </svg>
85
+ <span>Close File</span>
86
+ </button>
71
87
  </div>
72
88
  </div>
73
89
  </div>
@@ -76,7 +92,7 @@
76
92
  <div v-if="textEditorVisible" class="my-3 relative">
77
93
  <div class="pb-4">
78
94
  <!-- Syntax Highlighting Editor -->
79
- <div class="editor-container">
95
+ <div class="editor-container table-component">
80
96
  <div class="editor-wrapper">
81
97
  <pre ref="codeDisplay" class="language-json code-highlight"></pre>
82
98
  <textarea
@@ -94,10 +110,17 @@
94
110
 
95
111
  <div v-if="errorMessage" class="error-container">
96
112
  <div class="error-icon">
97
- <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
98
- <circle cx="12" cy="12" r="10"/>
99
- <line x1="15" y1="9" x2="9" y2="15"/>
100
- <line x1="9" y1="9" x2="15" y2="15"/>
113
+ <svg
114
+ width="16"
115
+ height="16"
116
+ viewBox="0 0 24 24"
117
+ fill="none"
118
+ stroke="currentColor"
119
+ stroke-width="2"
120
+ >
121
+ <circle cx="12" cy="12" r="10" />
122
+ <line x1="15" y1="9" x2="9" y2="15" />
123
+ <line x1="9" y1="9" x2="15" y2="15" />
101
124
  </svg>
102
125
  </div>
103
126
  <div class="error-content">
@@ -110,9 +133,9 @@
110
133
  <div class="border border-dark-650 my-8" />
111
134
 
112
135
  <h5 class="text-white text-xl font-bold flex gap-x-3 mb-3">Proxy Editor</h5>
113
- <div class="flex justify-between items-center mb-4 relative z-60">
114
- <div class="w-64">
115
- <div class="relative">
136
+ <div class="flex justify-between items-center gap-4 proxy-controls-row mb-4">
137
+ <div class="w-64 flex flex-shrink-0 dropdown-container">
138
+ <div class="relative flex-grow">
116
139
  <Dropdown
117
140
  class="bg-dark-500 border-2 border-dark-550 rounded-lg w-full h-10"
118
141
  :default="ui.profile.proxyList?.checkout || proxyLists[0]"
@@ -124,7 +147,7 @@
124
147
  </div>
125
148
  </div>
126
149
  <!-- Proxy save button moved here -->
127
- <div v-if="currentProxyList" style="margin-right: 1px;">
150
+ <div v-if="currentProxyList" class="flex gap-x-2 flex-shrink-0">
128
151
  <button class="btn-action h-12" @click="saveProxies">
129
152
  <svg
130
153
  xmlns="http://www.w3.org/2000/svg"
@@ -143,28 +166,40 @@
143
166
  </svg>
144
167
  <span>Save Proxies</span>
145
168
  </button>
169
+ <button class="btn-action h-12" @click="closeProxyFile">
170
+ <svg
171
+ xmlns="http://www.w3.org/2000/svg"
172
+ width="16"
173
+ height="16"
174
+ viewBox="0 0 24 24"
175
+ fill="none"
176
+ stroke="currentColor"
177
+ stroke-width="2"
178
+ stroke-linecap="round"
179
+ stroke-linejoin="round"
180
+ >
181
+ <line x1="18" y1="6" x2="6" y2="18"></line>
182
+ <line x1="6" y1="6" x2="18" y2="18"></line>
183
+ </svg>
184
+ <span>Close File</span>
185
+ </button>
146
186
  </div>
147
187
  </div>
148
188
  <!-- Textarea -->
149
189
  <transition name="fade">
150
190
  <div v-if="currentProxyList" class="relative my-3">
151
191
  <div class="pb-4">
152
- <div class="proxy-editor-container">
153
- <textarea
154
- v-model="proxyContent"
155
- class="proxy-editor"
156
- spellcheck="false"
157
- ></textarea>
192
+ <div class="proxy-editor-container table-component">
193
+ <textarea v-model="proxyContent" class="proxy-editor" spellcheck="false"></textarea>
158
194
  </div>
159
195
  </div>
160
196
  </div>
161
197
  </transition>
162
198
  </div>
163
- <QuickSettings v-if="activeModal === 'quick-settings'" />
164
199
  </div>
165
200
  </template>
166
201
  <script setup>
167
- import { ref, computed, watch, onMounted, nextTick } from "vue";
202
+ import { ref, computed, watch, onMounted, onUnmounted, nextTick } from "vue";
168
203
  import { DownIcon, ReloadIcon, EditIcon } from "@/components/icons";
169
204
  import { useUIStore } from "@/stores/ui";
170
205
  import Dropdown from "@/components/ui/controls/atomic/Dropdown.vue";
@@ -402,6 +437,19 @@ const saveAll = async () => {
402
437
  await saveQuickConfig();
403
438
  };
404
439
 
440
+ const closeFile = () => {
441
+ currentFile.value = "";
442
+ currentContent.value = "";
443
+ textEditorVisible.value = false;
444
+ ui.logger.Info("File closed");
445
+ };
446
+
447
+ const closeProxyFile = () => {
448
+ currentProxyList.value = "";
449
+ proxyContent.value = "";
450
+ ui.logger.Info("Proxy file closed");
451
+ };
452
+
405
453
  const loadProxies = async (list) => {
406
454
  try {
407
455
  if (DEBUG) {
@@ -455,6 +503,47 @@ onMounted(() => {
455
503
  }
456
504
  });
457
505
 
506
+ // iOS-specific editor fixes with cursor tracking
507
+ if (
508
+ /iPad|iPhone|iPod/.test(navigator.platform) ||
509
+ (navigator.maxTouchPoints && navigator.maxTouchPoints > 2 && /MacIntel/.test(navigator.platform))
510
+ ) {
511
+ const trackCursor = (editor) => {
512
+ const scrollToCursor = () => {
513
+ setTimeout(() => {
514
+ const container = editor.closest(".editor-container") || editor.closest(".proxy-editor-container");
515
+ if (container) {
516
+ // Get cursor position and scroll to it
517
+ const lines = editor.value.substring(0, editor.selectionStart).split("\n");
518
+ const lineHeight = 24; // Approximate line height
519
+ const cursorY = lines.length * lineHeight;
520
+ const containerHeight = container.clientHeight;
521
+
522
+ // Scroll to keep cursor in view
523
+ if (cursorY > container.scrollTop + containerHeight - 60) {
524
+ container.scrollTop = cursorY - containerHeight + 60;
525
+ }
526
+ }
527
+ }, 100);
528
+ };
529
+
530
+ editor.addEventListener("focus", scrollToCursor);
531
+ editor.addEventListener("input", scrollToCursor);
532
+ editor.addEventListener("click", scrollToCursor);
533
+ editor.addEventListener("keyup", scrollToCursor);
534
+ };
535
+
536
+ nextTick(() => {
537
+ if (codeEditor.value) {
538
+ trackCursor(codeEditor.value);
539
+ }
540
+ const proxyEditor = document.querySelector(".proxy-editor");
541
+ if (proxyEditor) {
542
+ trackCursor(proxyEditor);
543
+ }
544
+ });
545
+ }
546
+
458
547
  // Watch for editor visibility changes
459
548
  watch(textEditorVisible, (newValue) => {
460
549
  if (newValue) {
@@ -470,6 +559,8 @@ onMounted(() => {
470
559
  });
471
560
  });
472
561
 
562
+ // No cleanup needed - global iOS handling takes care of everything
563
+
473
564
  if (ui.profile.admin && !DEBUG) loadAvailableFiles();
474
565
  loadProxyLists();
475
566
  </script>
@@ -552,8 +643,9 @@ loadProxyLists();
552
643
  max-height: 600px;
553
644
  border-radius: 8px;
554
645
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
555
- overflow: hidden;
646
+ overflow: visible !important;
556
647
  background-color: #2e2f34;
648
+ touch-action: auto !important;
557
649
  }
558
650
 
559
651
  .editor-wrapper {
@@ -562,6 +654,7 @@ loadProxyLists();
562
654
  height: 100%;
563
655
  min-height: 300px;
564
656
  max-height: 600px;
657
+ overflow: visible !important; /* ALLOW SCROLLING */
565
658
  }
566
659
 
567
660
  .code-editor {
@@ -598,6 +691,33 @@ loadProxyLists();
598
691
  background: rgba(98, 114, 164, 0.4);
599
692
  }
600
693
 
694
+ /* iOS keyboard focus fix and scrolling */
695
+ .code-editor:focus,
696
+ .proxy-editor:focus {
697
+ transform: translateZ(0);
698
+ -webkit-transform: translateZ(0);
699
+ }
700
+
701
+ /* Force textarea scrolling to work */
702
+ .code-editor,
703
+ .proxy-editor {
704
+ overflow: auto !important;
705
+ -webkit-overflow-scrolling: touch !important;
706
+ user-select: text !important;
707
+ -webkit-user-select: text !important;
708
+ touch-action: auto !important;
709
+ overscroll-behavior: auto !important;
710
+ }
711
+
712
+ /* Additional override for any global styles */
713
+ textarea.code-editor,
714
+ textarea.proxy-editor {
715
+ overflow: auto !important;
716
+ -webkit-overflow-scrolling: touch !important;
717
+ touch-action: auto !important;
718
+ overscroll-behavior: auto !important;
719
+ }
720
+
601
721
  .code-highlight {
602
722
  width: 100%;
603
723
  height: 100%;
@@ -629,7 +749,8 @@ loadProxyLists();
629
749
 
630
750
  /* Proxy editor container */
631
751
  .proxy-editor-container {
632
- @apply w-full overflow-hidden rounded-lg border border-dark-600;
752
+ @apply w-full rounded-lg border border-dark-600;
753
+ overflow: visible !important; /* ALLOW SCROLLING */
633
754
  height: 400px;
634
755
  max-height: 60vh;
635
756
  background-color: #2e2f34;
@@ -668,7 +789,7 @@ loadProxyLists();
668
789
 
669
790
  .proxy-editor-container:focus-within {
670
791
  border-color: #5d7cc0;
671
- box-shadow: 0 0 0 2px rgba(93, 124, 192, 0.25);
792
+ box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.4);
672
793
  }
673
794
 
674
795
  /* Prism.js dark theme */
@@ -842,4 +963,34 @@ pre[class*="language-"] {
842
963
  word-break: break-word;
843
964
  opacity: 0.9;
844
965
  }
966
+
967
+ /* iPhone portrait mode spacing fixes */
968
+ @media (max-width: 480px) and (orientation: portrait) {
969
+ .editor-controls-row {
970
+ gap: 0.75rem !important;
971
+ flex-wrap: wrap;
972
+ }
973
+
974
+ .dropdown-container {
975
+ width: 100% !important;
976
+ max-width: 16rem;
977
+ margin-bottom: 0.5rem;
978
+ }
979
+
980
+ .editor-controls-row > div:last-child {
981
+ margin-right: auto;
982
+ margin-top: 0.5rem;
983
+ }
984
+
985
+ /* Proxy editor responsive layout */
986
+ .proxy-controls-row {
987
+ gap: 0.75rem !important;
988
+ flex-wrap: wrap;
989
+ }
990
+
991
+ .proxy-controls-row > div:last-child {
992
+ margin-right: auto;
993
+ margin-top: 0.5rem;
994
+ }
995
+ }
845
996
  </style>
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <div class="filter-builder-container w-full min-h-0 flex flex-col overflow-hidden">
3
3
  <!-- Heading -->
4
- <div class="flex-between pt-4 pb-1 px-4 mt-1">
4
+ <div class="flex-between pt-4 pb-1 mt-1">
5
5
  <div class="flex-center gap-4">
6
6
  <FilterIcon class="cursor-pointer smooth-hover text-white" />
7
7
  <h4 class="text-heading">Filter creator</h4>
@@ -47,9 +47,22 @@
47
47
  v-else
48
48
  class="h-full flex items-center justify-center p-2 rounded shadow border-2 border-dark-550 svg-container"
49
49
  >
50
- <div class="text-center text-dark-400">
51
- <StadiumIcon class="mx-auto mb-2 w-8 h-8 opacity-50" />
52
- <p class="text-sm">Enter an event ID and click "Load" to display the venue map</p>
50
+ <div class="text-center">
51
+ <svg
52
+ class="w-12 h-12 mb-3 mx-auto opacity-50"
53
+ viewBox="0 0 19 19"
54
+ fill="none"
55
+ xmlns="http://www.w3.org/2000/svg"
56
+ >
57
+ <path
58
+ d="M2.37499 5.54165V2.37498L5.54166 3.95831L2.37499 5.54165ZM14.25 5.54165V2.37498L17.4167 3.95831L14.25 5.54165ZM8.70833 4.74998V1.58331L11.875 3.16665L8.70833 4.74998ZM8.70833 17.4166C7.70555 17.3903 6.77218 17.3079 5.9082 17.1696C5.0437 17.0308 4.29162 16.8559 3.65195 16.6448C3.01176 16.4337 2.50694 16.1896 2.13749 15.9125C1.76805 15.6354 1.58333 15.3451 1.58333 15.0416V7.91665C1.58333 7.58678 1.79127 7.27988 2.20716 6.99594C2.62252 6.71252 3.18645 6.46183 3.89895 6.24385C4.61145 6.02641 5.4493 5.85488 6.4125 5.72927C7.37569 5.60419 8.40486 5.54165 9.49999 5.54165C10.5951 5.54165 11.6243 5.60419 12.5875 5.72927C13.5507 5.85488 14.3885 6.02641 15.101 6.24385C15.8135 6.46183 16.3775 6.71252 16.7928 6.99594C17.2087 7.27988 17.4167 7.58678 17.4167 7.91665V15.0416C17.4167 15.3451 17.2319 15.6354 16.8625 15.9125C16.493 16.1896 15.9885 16.4337 15.3488 16.6448C14.7086 16.8559 13.9565 17.0308 13.0926 17.1696C12.2281 17.3079 11.2944 17.3903 10.2917 17.4166V14.25H8.70833V17.4166ZM9.49999 8.70831C10.7799 8.70831 11.885 8.63231 12.8155 8.48031C13.7454 8.32884 14.4875 8.15415 15.0417 7.95623C15.0417 7.89026 14.5403 7.73509 13.5375 7.49073C12.5347 7.2469 11.1889 7.12498 9.49999 7.12498C7.81111 7.12498 6.46527 7.2469 5.46249 7.49073C4.45972 7.73509 3.95833 7.89026 3.95833 7.95623C4.51249 8.15415 5.25481 8.32884 6.18529 8.48031C7.11523 8.63231 8.22013 8.70831 9.49999 8.70831ZM7.12499 15.7146V12.6666H11.875V15.7146C12.9305 15.609 13.7948 15.4538 14.4677 15.2491C15.1406 15.0448 15.5958 14.8635 15.8333 14.7052V9.34165C15.1076 9.63192 14.1972 9.86283 13.1021 10.0344C12.0069 10.2059 10.8062 10.2916 9.49999 10.2916C8.19374 10.2916 6.99305 10.2059 5.89791 10.0344C4.80277 9.86283 3.89236 9.63192 3.16666 9.34165V14.7052C3.40416 14.8635 3.85937 15.0448 4.53229 15.2491C5.2052 15.4538 6.06944 15.609 7.12499 15.7146Z"
59
+ fill="#F5F5F5"
60
+ />
61
+ </svg>
62
+ <p class="text-light-400 text-sm">No Map</p>
63
+ <p class="text-light-500 text-xs">
64
+ Enter an event ID and click "Load" to display the venue map
65
+ </p>
53
66
  </div>
54
67
  </div>
55
68
  </div>
@@ -83,13 +96,13 @@
83
96
  <div class="flex items-center gap-2">
84
97
  <span class="text-base">Filters</span>
85
98
  <span class="text-base text-light-300">{{ filterBuilder.filters.length }}</span>
99
+ </div>
100
+ <div class="flex gap-2 items-center">
86
101
  <PriceSortToggle
87
102
  class="w-14 smooth-hover"
88
103
  :options="['All', 'WL', 'BL']"
89
104
  @change="(e) => (shownFilters = e)"
90
105
  />
91
- </div>
92
- <div class="flex gap-2 items-center">
93
106
  <button class="header-btn save-btn" @click="saveFilter">
94
107
  <EditIcon class="w-4 h-4" />
95
108
  <span class="lg:block hidden">Save</span>
@@ -167,7 +180,7 @@
167
180
  </div>
168
181
  </div>
169
182
 
170
- <transition-group name="fade" mode="out-in">
183
+ <transition-group name="fade">
171
184
  <FilterPreview v-if="activeModal === 'preview-filter'" :filter="filterBuilder" />
172
185
  </transition-group>
173
186
  </div>
@@ -562,6 +575,7 @@ const updateShownVenue = async () => {
562
575
 
563
576
  const loadFilter = async () => {
564
577
  try {
578
+ if (!eventId.value) return;
565
579
  const res = await fetch(`/api/filter/load?eventId=${eventId.value}`);
566
580
  const data = await res.json();
567
581
  if (eventId.value) ui.showSuccess("Loaded filter data");
@@ -23,18 +23,18 @@
23
23
  </button>
24
24
  </li>
25
25
  <li>
26
- <button
27
- :disabled="ui.disabledButtons['add-profiles']"
28
- @click="disable"
26
+ <button
27
+ :disabled="ui.disabledButtons['add-profiles']"
28
+ @click="disable"
29
29
  class="smooth-hover text-red-400"
30
30
  >
31
31
  <CloseXIcon />
32
32
  </button>
33
33
  </li>
34
34
  <li>
35
- <button
36
- :disabled="ui.disabledButtons['add-profiles']"
37
- @click="enable"
35
+ <button
36
+ :disabled="ui.disabledButtons['add-profiles']"
37
+ @click="enable"
38
38
  class="smooth-hover text-green-400"
39
39
  >
40
40
  <CheckIcon />
@@ -112,10 +112,10 @@
112
112
  </div>
113
113
 
114
114
  <!-- Tasks (Table) -->
115
- <ProfileView :tasks="processedTasks" />
115
+ <ProfileView :profiles="processedTasks" />
116
116
 
117
117
  <!-- Modal -->
118
- <transition-group name="fade" mode="out-in">
118
+ <transition-group name="fade">
119
119
  <CreateProfile v-if="activeModal === 'create-profile'" />
120
120
  </transition-group>
121
121
  </div>
@@ -30,7 +30,7 @@
30
30
  </ul>
31
31
  </div>
32
32
 
33
- <Stats />
33
+ <Stats class="stats-component" />
34
34
 
35
35
  <div class="controls-wrapper lg:mb-6 mb-3">
36
36
  <DesktopControls
@@ -66,7 +66,7 @@
66
66
 
67
67
  <Utilities class="utilities-section" />
68
68
 
69
- <transition-group name="fade" mode="out-in">
69
+ <transition-group name="fade">
70
70
  <CreateTaskTM v-if="ui.currentModule == 'TM' && activeModal === 'create-task'" @new="ui.addNewTask" />
71
71
  <CreateTaskAXS v-if="ui.currentModule == 'AXS' && activeModal === 'create-task'" @new="ui.addNewTask" />
72
72
  <CheckStock v-if="activeModal === 'check-stock'" />
@@ -100,6 +100,55 @@
100
100
  display: none !important;
101
101
  }
102
102
  }
103
+
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
+ }
151
+ }
103
152
  </style>
104
153
  <script setup>
105
154
  import { computed } from "vue";
@@ -1,5 +1,5 @@
1
1
  /** @type {import('tailwindcss').Config} */
2
- module.exports = {
2
+ export default {
3
3
  content: ["./index.html", "./src/**/*.{vue,js,ts,jsx,tsx}"],
4
4
  theme: {
5
5
  colors: {
package/vite.config.js CHANGED
@@ -59,6 +59,13 @@ export default defineConfig({
59
59
  strictPort: true,
60
60
  host: true,
61
61
  cors: true,
62
- hmr: false
62
+ hmr: {
63
+ overlay: false
64
+ },
65
+ // Handle iOS connection resets gracefully
66
+ watch: {
67
+ usePolling: false,
68
+ interval: 1000
69
+ }
63
70
  }
64
71
  });
package/vue.config.js CHANGED
@@ -1,4 +1,4 @@
1
- module.exports = {
1
+ export default {
2
2
  chainWebpack: (config) => {
3
3
  config.plugin('preload').tap((options) => {
4
4
  options[0].as = (entry) => {
@@ -1,9 +1,6 @@
1
1
  module.exports = {
2
2
  globDirectory: "public/",
3
- globPatterns: [
4
- "**/*.{png,ico,svg,jpg,jpeg,webp}",
5
- "manifest.json"
6
- ],
3
+ globPatterns: ["**/*.{png,ico,svg,jpg,jpeg,webp}", "manifest.json"],
7
4
  swDest: "public/sw.js",
8
5
  sourcemap: false,
9
6
  skipWaiting: true,