@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
@@ -7,21 +7,21 @@
7
7
  <div class="col-span-3 lg:col-span-2 flex">
8
8
  <Checkbox
9
9
  class="ml-0 mr-4"
10
- :toggled="props.task.selected"
11
- @valueUpdate="ui.toggleProfileSelected(props.task._id)"
10
+ :toggled="props.profile.selected"
11
+ @valueUpdate="ui.toggleProfileSelected(props.profile._id)"
12
12
  />
13
13
  <h4 class="mx-auto text-white">
14
- {{ props.task.profileName }}
14
+ {{ props.profile.profileName }}
15
15
  </h4>
16
16
  </div>
17
17
  <div class="col-span-1 lg:col-span-2">
18
18
  <h4 class="text-white flex justify-center items-center gap-2">
19
19
  <span class="hidden ipadlg:block">{{
20
- props.task.privacy
21
- ? props.task.cardNumber[0] +
22
- "•".repeat(props.task.cardNumber.length - 5) +
23
- props.task.cardNumber.slice(-4)
24
- : validateCard(props.task.cardNumber).formatted
20
+ props.profile.privacy
21
+ ? props.profile.cardNumber[0] +
22
+ "•".repeat(props.profile.cardNumber.length - 5) +
23
+ props.profile.cardNumber.slice(-4)
24
+ : validateCard(props.profile.cardNumber).formatted
25
25
  }}</span>
26
26
  <img class="w-6 h-6" :src="getAccountType()" />
27
27
  </h4>
@@ -30,7 +30,7 @@
30
30
  <h4 class="text-white">{{ expDate() }}</h4>
31
31
  </div>
32
32
  <div class="col-span-1">
33
- <h4 v-if="props.task.enabled" class="text-green-400 flex justify-center">
33
+ <h4 v-if="props.profile.enabled" class="text-green-400 flex justify-center">
34
34
  <img class="w-3 h-3 green" src="/img/controls/enable.svg" />
35
35
  </h4>
36
36
  <h4 v-else class="text-red-400 flex justify-center">
@@ -40,18 +40,18 @@
40
40
 
41
41
  <div class="col-span-1 hidden lg:block">
42
42
  <h4 class="text-white flex justify-center gap-1">
43
- <TagLabel v-for="tag in props.task.tags" :key="tag" :text="tag" />
43
+ <TagLabel v-for="tag in props.profile.tags" :key="tag" :text="tag" />
44
44
  </h4>
45
45
  </div>
46
46
 
47
47
  <div class="col-span-1 flex">
48
- <ul class="task-buttons">
48
+ <ul class="profile-buttons">
49
49
  <li>
50
50
  <button @click="edit">
51
51
  <EditIcon />
52
52
  </button>
53
53
  </li>
54
- <li v-if="props.task.enabled">
54
+ <li v-if="props.profile.enabled">
55
55
  <button @click="disable">
56
56
  <img class="w-4 h-4" src="/img/controls/disable.svg" />
57
57
  </button>
@@ -76,7 +76,7 @@
76
76
  h4 {
77
77
  @apply text-center;
78
78
  }
79
- .task-buttons {
79
+ .profile-buttons {
80
80
  @apply flex items-center justify-center mx-auto bg-dark-500 border border-dark-650 rounded;
81
81
  padding: 3px;
82
82
  gap: 2px;
@@ -119,7 +119,7 @@ h4 {
119
119
  font-size: 10px !important;
120
120
  }
121
121
 
122
- .task-buttons {
122
+ .profile-buttons {
123
123
  padding: 3px;
124
124
  gap: 2px;
125
125
 
@@ -135,7 +135,7 @@ h4 {
135
135
  }
136
136
  }
137
137
 
138
- .task-id {
138
+ .profile-id {
139
139
  font-size: 6px !important;
140
140
  margin-right: -12px;
141
141
  margin-top: 20px;
@@ -144,7 +144,7 @@ h4 {
144
144
 
145
145
  // Mobile optimization
146
146
  @media (max-width: 768px) {
147
- .task-buttons {
147
+ .profile-buttons {
148
148
  padding: 2px;
149
149
  gap: 1px;
150
150
 
@@ -163,7 +163,7 @@ h4 {
163
163
 
164
164
  // iPhone vertical (portrait) specific
165
165
  @media (max-width: 480px) and (orientation: portrait) {
166
- .task-buttons {
166
+ .profile-buttons {
167
167
  padding: 2px;
168
168
  gap: 1px;
169
169
 
@@ -195,23 +195,23 @@ import TagLabel from "@/components/Editors/TagLabel.vue";
195
195
  const ui = useUIStore();
196
196
 
197
197
  const props = defineProps({
198
- task: { type: Object }
198
+ profile: { type: Object }
199
199
  });
200
200
 
201
201
  const getAccountType = () => {
202
- var cn = props.task.cardNumber;
202
+ var cn = props.profile.cardNumber;
203
203
  if (cn.startsWith("4")) return `/img/banks/visa.svg`; // visa
204
204
  else if (cn.startsWith("3")) return `/img/banks/amex.svg`; // amex
205
205
  else if (cn.startsWith("5")) return `/img/banks/mastercard.svg`; // master
206
206
  };
207
207
 
208
208
  const expDate = () =>
209
- props.task.privacy ? "••/••" : `${props.task.expMonth}/${props.task.expYear?.replace("20", "")}`;
210
- const enable = async () => await ui.addProfile({ ...props.task, enabled: true });
211
- const disable = async () => await ui.addProfile({ ...props.task, enabled: false });
209
+ props.profile.privacy ? "••/••" : `${props.profile.expMonth}/${props.profile.expYear?.replace("20", "")}`;
210
+ const enable = async () => await ui.addProfile({ ...props.profile, enabled: true });
211
+ const disable = async () => await ui.addProfile({ ...props.profile, enabled: false });
212
212
  const edit = () => {
213
- ui.currentlyEditing = props.task;
213
+ ui.currentlyEditing = props.profile;
214
214
  ui.toggleModal("create-profile");
215
215
  };
216
- const deleteProfile = async () => await ui.deleteProfile(props.task._id);
216
+ const deleteProfile = async () => await ui.deleteProfile(props.profile._id);
217
217
  </script>
@@ -42,23 +42,25 @@
42
42
  class="scroller max-h-big vue-recycle-scroller ready direction-vertical flex flex-col divide-y divide-dark-650 overflow-y-auto hidden-scrollbars overflow-x-hidden stop-pan"
43
43
  >
44
44
  <template #default="props">
45
- <div class="task" :key="i[props.item.index]">
45
+ <div class="profile" :key="`profile-${props.item._id || props.item.index}`">
46
46
  <Profile
47
47
  @click="i[props.item.index]++"
48
- :class="[props.item.index % 2 == 1 ? 'bg-dark-500' : 'bg-dark-550']"
49
- :task="props.item"
48
+ :style="{ backgroundColor: props.item.index % 2 == 1 ? '#1a1b1e' : '#242529' }"
49
+ :profile="props.item"
50
50
  />
51
51
  </div>
52
52
  </template>
53
53
  </RecycleScroller>
54
54
  </div>
55
- <div v-else class="flex justify-center py-8 bg-dark-400 empty-state">
56
- No profiles found
55
+ <div v-else class="flex flex-col items-center justify-center py-8 bg-dark-400 empty-state text-center">
56
+ <ProfileIcon class="w-12 h-12 text-dark-400 mb-3 opacity-50" />
57
+ <p class="text-light-400 text-sm">No profiles found</p>
58
+ <p class="text-light-500 text-xs mt-1">Create profiles to get started</p>
57
59
  </div>
58
60
  </Table>
59
61
  </template>
60
62
  <style lang="scss" scoped>
61
- .task {
63
+ .profile {
62
64
  height: 64px;
63
65
  }
64
66
  h4 {
@@ -89,15 +91,26 @@ import { useUIStore } from "@/stores/ui";
89
91
  import { computed, ref } from "vue";
90
92
 
91
93
  const props = defineProps({
92
- tasks: { type: Object }
94
+ profiles: { type: Object }
93
95
  });
94
- const i = ref({});
95
- props.tasks.forEach((t) => (i.value[t._id] = 0));
96
96
 
97
97
  const ui = useUIStore();
98
98
 
99
+ const i = ref({});
99
100
  const toRender = computed(() => {
100
101
  let c = 0;
101
- return props.tasks.map((t) => ({ ...t, index: c++ }));
102
+ const rendered = props.profiles.map((t) => ({ ...t, index: c++ }));
103
+
104
+ // Initialize reactive refs for click tracking
105
+ rendered.forEach((t) => {
106
+ if (t._id && !(t._id in i.value)) {
107
+ i.value[t._id] = 0;
108
+ }
109
+ if (!(t.index in i.value)) {
110
+ i.value[t.index] = 0;
111
+ }
112
+ });
113
+
114
+ return rendered;
102
115
  });
103
116
  </script>
@@ -13,7 +13,7 @@
13
13
  min-width: 2rem;
14
14
  max-width: 4.5rem;
15
15
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2), inset 0 1px 0 rgba(255, 255, 255, 0.05);
16
-
16
+
17
17
  &:hover {
18
18
  background: linear-gradient(145deg, #44454b, #3d3e44);
19
19
  border-color: #52535a;
@@ -36,7 +36,7 @@
36
36
  padding: 0.1rem 0.3rem;
37
37
  max-width: 3.5rem;
38
38
  }
39
-
39
+
40
40
  .tag-text {
41
41
  font-size: 0.575rem;
42
42
  }
@@ -48,7 +48,7 @@
48
48
  max-width: 3rem;
49
49
  min-width: 1.25rem;
50
50
  }
51
-
51
+
52
52
  .tag-text {
53
53
  font-size: 0.55rem;
54
54
  }
@@ -60,7 +60,7 @@
60
60
  max-width: 2.5rem;
61
61
  min-width: 1rem;
62
62
  }
63
-
63
+
64
64
  .tag-text {
65
65
  font-size: 0.5rem;
66
66
  }
@@ -71,8 +71,7 @@
71
71
  const props = defineProps({ text: { type: String } });
72
72
 
73
73
  const formatText = (text) => {
74
- if (!text) return '';
75
- // Capitalize first letter and keep rest as-is
76
- return text.charAt(0).toUpperCase() + text.slice(1);
74
+ if (!text) return "";
75
+ return text.toUpperCase();
77
76
  };
78
77
  </script>
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <div class="border-b border-dark-600 w-full px-2 md:px-4 text-white text-xs py-4 grid items-center">
2
+ <div class="border-b border-dark-600 w-full px-2 md:px-4 text-white text-xs py-4 grid items-center" style="background-color: rgb(26 27 30);">
3
3
  <slot />
4
4
  </div>
5
5
  </template>
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <div class="px-2 md:px-4 text-xs grid text-white py-4 items-center h-full bg-dark-400 even:bg-dark-350 hover:bg-dark-500 transition-colors">
2
+ <div class="px-2 md:px-4 text-xs grid text-white py-4 items-center h-full hover:bg-dark-500 transition-colors">
3
3
  <slot />
4
4
  </div>
5
5
  </template>
@@ -7,10 +7,25 @@
7
7
  .table-component {
8
8
  @apply flex-col bg-clip-padding rounded relative box-border border border-dark-600 bg-dark-500;
9
9
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
10
+ overflow: auto !important;
11
+ overscroll-behavior: auto !important;
12
+ touch-action: auto !important;
13
+ max-height: calc(100vh - 200px);
10
14
  }
11
15
 
12
16
  .table-component > .grid {
13
17
  @apply bg-dark-400;
14
18
  border-bottom: 1px solid #3d3e44;
15
19
  }
20
+
21
+ /* iPhone landscape mode table optimization */
22
+ @media screen and (max-height: 500px) and (orientation: landscape) {
23
+ .table-component {
24
+ max-height: calc(100vh - 160px) !important; // Leave even more space at bottom
25
+ width: 100% !important;
26
+ overflow-x: auto !important; // Allow horizontal scrolling if needed
27
+ overflow-y: auto !important; // Allow vertical scrolling
28
+ margin-bottom: 2rem !important; // Increase bottom margin for better spacing
29
+ }
30
+ }
16
31
  </style>
@@ -1,5 +1,5 @@
1
1
  <template>
2
- <div class="task-controls flex-row" v-once>
2
+ <div class="task-controls flex-row">
3
3
  <div class="control-buttons mb-4 xl:mb-0">
4
4
  <button @click="$emit('startAll')" class="bg-green-400 smooth-hover responsive-button border-none">
5
5
  Start <PlayIcon />
@@ -5,7 +5,6 @@
5
5
  <img src="@/assets/img/pencil.svg" class="ml-4" />
6
6
  </template>
7
7
 
8
-
9
8
  <!-- Task Form -->
10
9
  <div class="form-grid mt-4 mb-4">
11
10
  <!-- Event ID -->
@@ -25,10 +24,10 @@
25
24
  <MailIcon />
26
25
  </label>
27
26
  <div class="input-default">
28
- <input
29
- placeholder="Email"
30
- v-model="task.email"
31
- autocomplete="off"
27
+ <input
28
+ placeholder="Email"
29
+ v-model="task.email"
30
+ autocomplete="off"
32
31
  data-form-type="other"
33
32
  name="axs_email_not_for_auth"
34
33
  />
@@ -89,7 +88,7 @@
89
88
  </div>
90
89
 
91
90
  <!-- Profile Tag(s) -->
92
- <div class="input-wrapper" style="z-index: 50 !important">
91
+ <div class="input-wrapper" style="z-index: 200 !important; position: relative">
93
92
  <label class="label-override mb-2"
94
93
  >Profile Tag(s)
95
94
  <TagIcon />
@@ -107,7 +106,7 @@
107
106
  </div>
108
107
 
109
108
  <!-- Account Tag -->
110
- <div class="input-wrapper">
109
+ <div class="input-wrapper" style="z-index: 100 !important; position: relative">
111
110
  <label class="label-override mb-2"
112
111
  >Account Tag
113
112
  <ScannerIcon />
@@ -141,7 +140,7 @@
141
140
  </div>
142
141
  </div>
143
142
  </div>
144
- <div class="border border-light-300 mb-3" />
143
+ <div class="border border-dark-650 mb-3" />
145
144
  <!-- Task Switches -->
146
145
  <div class="grid grid-cols-4 gap-y-4 mb-4 justify-between task-switches">
147
146
  <div class="switch-wrapper flex flex-col">
@@ -169,14 +168,15 @@
169
168
  </div>
170
169
  <div class="switch-wrapper flex flex-col">
171
170
  <h4>
172
- <span class="hidden xs:block">Manual</span>
171
+ Manual
172
+ <HandIcon />
173
173
  </h4>
174
174
  <Switch class="mx-auto" v-model="task.manual" />
175
175
  </div>
176
176
  </div>
177
177
 
178
178
  <!-- Task prefab -->
179
- <div class="border border-light-300 my-3" />
179
+ <div class="border border-dark-650 my-3" />
180
180
  <button class="btn-action mx-auto" @click="createTask">
181
181
  Create
182
182
  <EditIcon />
@@ -268,7 +268,7 @@ watch(
268
268
  }
269
269
  );
270
270
 
271
- watch(() => task.value, (ui.modalData[`task_${ui.currentCountry.siteId}`] = task.value));
271
+ watch(() => task.value, () => (ui.modalData[`task_${ui.currentCountry.siteId}`] = task.value), { deep: true });
272
272
 
273
273
  watch(
274
274
  () => task.value.eventId,
@@ -283,7 +283,7 @@ watch(
283
283
  <style lang="scss" scoped>
284
284
  .label-override {
285
285
  @apply flex;
286
- color: #6e7084 !important;
286
+ color: #e1e1e4 !important;
287
287
 
288
288
  img {
289
289
  @apply ml-2;
@@ -292,7 +292,7 @@ watch(
292
292
 
293
293
  .task-switches {
294
294
  h4 {
295
- color: #6e7084;
295
+ color: #e1e1e4;
296
296
  @apply text-xs text-center flex items-center gap-x-2 mx-auto;
297
297
  }
298
298
 
@@ -315,7 +315,7 @@ watch(
315
315
  @apply ml-2;
316
316
 
317
317
  path {
318
- fill: #6e7084 !important;
318
+ fill: #e1e1e4 !important;
319
319
  }
320
320
  }
321
321
  @apply flex items-center;
@@ -324,7 +324,7 @@ watch(
324
324
  .switch-wrapper {
325
325
  svg {
326
326
  path {
327
- fill: #6e7084 !important;
327
+ fill: #a0a0a6 !important;
328
328
  }
329
329
  }
330
330
  }
@@ -94,7 +94,7 @@
94
94
  </div>
95
95
 
96
96
  <!-- Profile Tag(s) -->
97
- <div class="input-wrapper" style="z-index: 50 !important">
97
+ <div class="input-wrapper" style="z-index: 200 !important; position: relative">
98
98
  <label class="label-override mb-2"
99
99
  >Profile Tag(s)
100
100
  <TagIcon />
@@ -120,7 +120,7 @@
120
120
  </div>
121
121
 
122
122
  <!-- Account Tag -->
123
- <div class="input-wrapper">
123
+ <div class="input-wrapper" style="z-index: 100 !important; position: relative">
124
124
  <label class="label-override mb-2"
125
125
  >Account Tag
126
126
  <ScannerIcon />
@@ -255,7 +255,8 @@
255
255
  </div>
256
256
  <div class="switch-wrapper flex flex-col">
257
257
  <h4>
258
- Login Later
258
+ <span class="hidden xs:block">Login Later</span>
259
+ <span class="block xs:hidden">Login Lat.</span>
259
260
  <GroupIcon class="scale-90" />
260
261
  </h4>
261
262
  <Switch class="mx-auto" v-model="task.loginAfterCart" />
@@ -390,7 +391,7 @@ watch(
390
391
  }
391
392
  );
392
393
 
393
- watch(() => task.value, (ui.modalData[`task_${ui.currentCountry.siteId}`] = task.value));
394
+ watch(() => task.value, () => (ui.modalData[`task_${ui.currentCountry.siteId}`] = task.value), { deep: true });
394
395
 
395
396
  watch(
396
397
  () => task.value.eventId,
@@ -1,6 +1,6 @@
1
1
  <template>
2
2
  <Row
3
- class="relative text-white grid-cols-12 gap-2"
3
+ class="relative text-white grid-cols-10 gap-2 ipadlg:grid-cols-12"
4
4
  @click="ui.setOpenContextMenu('')"
5
5
  @click.right.prevent="ui.setOpenContextMenu('')"
6
6
  >
@@ -22,9 +22,6 @@
22
22
  {{ props.task.eventId }}
23
23
  </h4>
24
24
  </div>
25
- <div class="col-span-2 hidden lg:block">
26
- <h4 class="text-white">{{ props.task.quantity }}</h4>
27
- </div>
28
25
  <div class="col-span-2">
29
26
  <h4 class="text-white">
30
27
  <span v-if="!props.task.reservedTicketsList">-</span>
@@ -44,7 +41,7 @@
44
41
  </span>
45
42
  </h4>
46
43
  </div>
47
- <div class="col-span-6 md:col-span-4 lg:col-span-3 text-center justify-center">
44
+ <div class="col-span-5 md:col-span-4 lg:col-span-5 ipadlg:col-span-6 text-center justify-center">
48
45
  <div class="status-container">
49
46
  <div
50
47
  class="status-indicator"
@@ -56,10 +53,10 @@
56
53
  )
57
54
  "
58
55
  ></div>
59
- <span class="status-text">{{ truncate(props.task.status, statusTruncateLength) }}</span>
56
+ <span class="status-text">{{ props.task.status }}</span>
60
57
  </div>
61
58
  </div>
62
- <div class="col-span-2 flex">
59
+ <div class="col-span-2 ipadlg:col-span-3 flex">
63
60
  <ul class="task-buttons">
64
61
  <li>
65
62
  <button v-if="task.active" @click="ui.stopTask(task.taskId)">
@@ -98,7 +95,7 @@
98
95
  </div>
99
96
  <transition name="fade">
100
97
  <div
101
- class="col-span-12 flex flex-wrap gap-x-4 gap-y-4 lg:gap-x-10 pt-8 pb-2 xl:justify-around will-change-auto"
98
+ class="col-span-10 ipadlg:col-span-12 flex flex-wrap gap-x-4 gap-y-4 lg:gap-x-10 pt-8 pb-2 xl:justify-around will-change-auto"
102
99
  v-if="props.task.isExpanded"
103
100
  >
104
101
  <!-- Details -->
@@ -183,6 +180,7 @@ h4 {
183
180
  padding: 6px 12px;
184
181
  gap: 6px;
185
182
  transition: all 0.15s ease;
183
+ max-width: 100%;
186
184
 
187
185
  &:hover {
188
186
  @apply bg-dark-550 border-dark-700;
@@ -300,19 +298,23 @@ h4 {
300
298
  gap: 0;
301
299
  border-radius: 7px;
302
300
  box-shadow: 0 1px 6px rgba(0, 0, 0, 0.15), inset 0 1px 0 rgba(255, 255, 255, 0.08);
301
+ max-width: calc(100vw - 260px); /* Prevent overflow on small screens */
302
+ overflow: hidden;
303
303
 
304
304
  button {
305
- width: 22px;
306
- height: 22px;
305
+ width: 20px;
306
+ height: 20px;
307
307
  border-radius: 5px;
308
+ min-width: 20px;
309
+ flex-shrink: 0;
308
310
  }
309
311
  svg,
310
312
  img {
311
- width: 11px;
312
- height: 11px;
313
+ width: 10px;
314
+ height: 10px;
313
315
  }
314
316
  span {
315
- font-size: 10px;
317
+ font-size: 9px;
316
318
  }
317
319
  }
318
320
  }
@@ -340,12 +342,13 @@ h4 {
340
342
  .task-buttons {
341
343
  padding: 1px;
342
344
  gap: 0;
343
- border-radius: 6px;
345
+ border-radius: 5px;
344
346
 
345
347
  button {
346
- width: 18px;
347
- height: 18px;
348
- border-radius: 4px;
348
+ width: 15px;
349
+ height: 15px;
350
+ border-radius: 2px;
351
+ min-width: 15px;
349
352
 
350
353
  &:hover {
351
354
  transform: scale(1.1);
@@ -354,11 +357,11 @@ h4 {
354
357
 
355
358
  svg,
356
359
  img {
357
- width: 9px;
358
- height: 9px;
360
+ width: 8px;
361
+ height: 8px;
359
362
  }
360
363
  span {
361
- font-size: 9px;
364
+ font-size: 8px;
362
365
  }
363
366
  }
364
367
  }
@@ -372,7 +375,6 @@ import { PlayIcon, TrashIcon, BagWhiteIcon, PauseIcon, EditIcon } from "@/compon
372
375
  import Checkbox from "@/components/ui/controls/atomic/Checkbox.vue";
373
376
  import { useUIStore } from "@/stores/ui";
374
377
  import TaskLabel from "@/components/Tasks/TaskLabel.vue";
375
- import { ref } from "vue";
376
378
 
377
379
  const ui = useUIStore();
378
380
 
@@ -396,10 +398,6 @@ const colorToClass = (color) => {
396
398
  return colorMapping.get(color) || "bg-white";
397
399
  };
398
400
 
399
- const truncate = (text, after) => {
400
- if (text?.length <= after || after === -1) return text;
401
- return text?.substring(0, after) + "...";
402
- };
403
401
 
404
402
  const openInBrowser = (debug) => {
405
403
  if (!props.task.openerLink) return;
@@ -434,14 +432,4 @@ const openInNewTab = (href) => {
434
432
  }).click();
435
433
  };
436
434
 
437
- const getMaxStatusLength = (width) => {
438
- if (width > 1279) return -1;
439
- if (width > 767) return 25;
440
- if (width > 639) return 30;
441
- if (width > 540) return 18;
442
- return 13;
443
- };
444
-
445
- let statusTruncateLength = ref(getMaxStatusLength(window.innerWidth));
446
- window.addEventListener("resize", () => (statusTruncateLength.value = getMaxStatusLength(window.innerWidth)));
447
435
  </script>