@necrolab/dashboard 0.5.15 → 0.5.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/backend/api.js +2 -3
- package/eslint.config.js +46 -0
- package/index.html +2 -1
- package/package.json +5 -2
- package/src/App.vue +70 -566
- package/src/assets/css/base/mixins.scss +72 -0
- package/src/assets/css/base/reset.scss +0 -2
- package/src/assets/css/base/scroll.scss +43 -36
- package/src/assets/css/base/typography.scss +9 -10
- package/src/assets/css/base/variables.scss +43 -0
- package/src/assets/css/components/accessibility.scss +37 -0
- package/src/assets/css/components/buttons.scss +61 -74
- package/src/assets/css/components/forms.scss +31 -32
- package/src/assets/css/components/headers.scss +13 -21
- package/src/assets/css/components/modals.scss +2 -2
- package/src/assets/css/components/search-groups.scss +28 -22
- package/src/assets/css/components/tables.scss +5 -7
- package/src/assets/css/components/toasts.scss +7 -7
- package/src/assets/css/components/utilities.scss +295 -0
- package/src/assets/css/main.scss +55 -139
- package/src/components/Auth/LoginForm.vue +7 -86
- package/src/components/Console/ConsoleToolbar.vue +123 -0
- package/src/components/Editors/Account/Account.vue +12 -12
- package/src/components/Editors/Account/AccountView.vue +38 -111
- package/src/components/Editors/Account/CreateAccount.vue +11 -61
- package/src/components/Editors/Account/{AccountCreator.vue → CreateAccountBatch.vue} +28 -59
- package/src/components/Editors/AdminFileEditor.vue +179 -0
- package/src/components/Editors/Profile/CreateProfile.vue +77 -150
- package/src/components/Editors/Profile/Profile.vue +20 -21
- package/src/components/Editors/Profile/ProfileCountryChooser.vue +16 -60
- package/src/components/Editors/Profile/ProfileView.vue +41 -116
- package/src/components/Editors/ProxyFileEditor.vue +86 -0
- package/src/components/Editors/TagLabel.vue +16 -55
- package/src/components/Editors/TagToggle.vue +20 -8
- package/src/components/Filter/Filter.vue +66 -79
- package/src/components/Filter/FilterPreview.vue +153 -135
- package/src/components/Filter/PriceSortToggle.vue +36 -43
- package/src/components/Table/Header.vue +1 -1
- package/src/components/Table/Table.vue +45 -51
- package/src/components/Tasks/CheckStock.vue +7 -16
- package/src/components/Tasks/Controls/DesktopControls.vue +15 -60
- package/src/components/Tasks/Controls/MobileControls.vue +5 -20
- package/src/components/Tasks/CreateTaskAXS.vue +20 -118
- package/src/components/Tasks/CreateTaskTM.vue +33 -189
- package/src/components/Tasks/EventDetailRow.vue +21 -0
- package/src/components/Tasks/MassEdit.vue +6 -16
- package/src/components/Tasks/QuickSettings.vue +140 -216
- package/src/components/Tasks/ScrapeVenue.vue +4 -13
- package/src/components/Tasks/Stats.vue +20 -39
- package/src/components/Tasks/Task.vue +64 -270
- package/src/components/Tasks/TaskLabel.vue +9 -3
- package/src/components/Tasks/TaskView.vue +45 -64
- package/src/components/Tasks/Utilities.vue +10 -44
- package/src/components/Tasks/ViewTask.vue +23 -107
- package/src/components/icons/Close.vue +2 -8
- package/src/components/icons/Gear.vue +8 -8
- package/src/components/icons/Hash.vue +5 -0
- package/src/components/icons/Key.vue +2 -8
- package/src/components/icons/Pencil.vue +2 -8
- package/src/components/icons/Profile.vue +2 -8
- package/src/components/icons/Sell.vue +2 -8
- package/src/components/icons/Spinner.vue +4 -7
- package/src/components/icons/Wildcard.vue +2 -8
- package/src/components/icons/index.js +3 -5
- package/src/components/ui/ActionButtonGroup.vue +113 -52
- package/src/components/ui/BalanceIndicator.vue +60 -0
- package/src/components/ui/EmptyState.vue +24 -0
- package/src/components/ui/EnableDisableToggle.vue +23 -0
- package/src/components/ui/FormField.vue +49 -49
- package/src/components/ui/IconLabel.vue +23 -0
- package/src/components/ui/InfoRow.vue +21 -54
- package/src/components/ui/Modal.vue +161 -54
- package/src/components/ui/Navbar.vue +63 -44
- package/src/components/ui/ReadonlyFieldsSection.vue +31 -0
- package/src/components/ui/ReconnectIndicator.vue +111 -124
- package/src/components/ui/SectionCard.vue +6 -14
- package/src/components/ui/Splash.vue +2 -10
- package/src/components/ui/StatusBadge.vue +26 -28
- package/src/components/ui/TaskToggle.vue +54 -0
- package/src/components/ui/controls/CountryChooser.vue +29 -66
- package/src/components/ui/controls/EyeToggle.vue +1 -1
- package/src/components/ui/controls/atomic/Checkbox.vue +40 -121
- package/src/components/ui/controls/atomic/Dropdown.vue +103 -139
- package/src/components/ui/controls/atomic/MultiDropdown.vue +72 -120
- package/src/components/ui/controls/atomic/Switch.vue +21 -84
- package/src/composables/useCodeEditor.js +117 -0
- package/src/composables/useColorMapping.js +15 -0
- package/src/composables/useCopyToClipboard.js +1 -1
- package/src/composables/useDateFormatting.js +21 -0
- package/src/composables/useDeviceDetection.js +14 -0
- package/src/composables/useDropdownPosition.js +1 -4
- package/src/composables/useDynamicTableHeight.js +31 -0
- package/src/composables/useEnableDisable.js +6 -0
- package/src/composables/useFilterCSS.js +71 -0
- package/src/composables/useFormValidation.js +92 -0
- package/src/composables/useGetAllTags.js +9 -0
- package/src/composables/useIOSViewportHandling.js +76 -0
- package/src/composables/useNotchHandling.js +306 -0
- package/src/composables/useRowSelection.js +0 -3
- package/src/composables/useTableRender.js +23 -0
- package/src/composables/useTicketPricing.js +16 -0
- package/src/composables/useWindowDimensions.js +21 -0
- package/src/composables/useZoomPrevention.js +96 -0
- package/src/constants/tableLayout.js +14 -0
- package/src/libs/Filter.js +14 -20
- package/src/libs/panzoom.js +1 -5
- package/src/libs/utils/array.js +58 -0
- package/src/{stores/utils.js → libs/utils/dataGeneration.js} +2 -250
- package/src/libs/utils/eventUrl.js +40 -0
- package/src/libs/utils/string.js +3 -0
- package/src/libs/utils/time.js +20 -0
- package/src/libs/utils/validation.js +64 -0
- package/src/main.js +0 -2
- package/src/stores/connection.js +1 -29
- package/src/stores/logger.js +6 -12
- package/src/stores/sampleData.js +1 -2
- package/src/stores/ui.js +80 -71
- package/src/utils/tableHelpers.js +1 -0
- package/src/views/Accounts.vue +19 -38
- package/src/views/Console.vue +74 -253
- package/src/views/Editor.vue +47 -1114
- package/src/views/FilterBuilder.vue +190 -461
- package/src/views/Login.vue +3 -28
- package/src/views/Profiles.vue +17 -32
- package/src/views/Tasks.vue +51 -38
- package/tailwind.config.js +82 -71
- package/workbox-config.cjs +47 -5
- package/docs/plans/2026-02-08-tailwind-consolidation.md +0 -2438
- package/exit +0 -209
- package/run +0 -177
- package/src/assets/css/base/color-fallbacks.scss +0 -10
- package/src/assets/img/background.svg.backup +0 -11
- package/src/components/icons/SquareCheck.vue +0 -18
- package/src/components/icons/SquareUncheck.vue +0 -18
- package/src/components/ui/controls/atomic/LoadingButton.vue +0 -45
- package/switch-branch.sh +0 -41
- /package/public/{reconnect-logo.png → img/reconnect-logo.png} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import cities from "
|
|
1
|
+
import cities from "@/stores/cities.json";
|
|
2
2
|
|
|
3
3
|
function generateStreetAddress() {
|
|
4
4
|
const streetTypes = [
|
|
@@ -47,8 +47,6 @@ function generateStreetAddress() {
|
|
|
47
47
|
"Pleasant View",
|
|
48
48
|
"Rolling",
|
|
49
49
|
"Scenic",
|
|
50
|
-
"Shady Grove",
|
|
51
|
-
"Stone Gate",
|
|
52
50
|
"Sunset",
|
|
53
51
|
"Valley View",
|
|
54
52
|
"Willow Brook",
|
|
@@ -315,93 +313,6 @@ function generateStreetAddress() {
|
|
|
315
313
|
return `${houseNumber} ${streetName} ${streetType}`.trim().replace(/\s+/g, " ");
|
|
316
314
|
}
|
|
317
315
|
|
|
318
|
-
const sortAlphaNum = (a, b) => {
|
|
319
|
-
var reA = /[^a-zA-Z]/g;
|
|
320
|
-
var reN = /[^0-9]/g;
|
|
321
|
-
var AInt = parseInt(a, 10);
|
|
322
|
-
var BInt = parseInt(b, 10);
|
|
323
|
-
|
|
324
|
-
if (isNaN(AInt) && isNaN(BInt)) {
|
|
325
|
-
var aA = a.replace(reA, "");
|
|
326
|
-
var bA = b.replace(reA, "");
|
|
327
|
-
if (aA === bA) {
|
|
328
|
-
var aN = parseInt(a.replace(reN, ""), 10);
|
|
329
|
-
var bN = parseInt(b.replace(reN, ""), 10);
|
|
330
|
-
return aN === bN ? 0 : aN > bN ? 1 : -1;
|
|
331
|
-
} else {
|
|
332
|
-
return aA > bA ? 1 : -1;
|
|
333
|
-
}
|
|
334
|
-
} else if (isNaN(AInt)) {
|
|
335
|
-
//A is not an Int
|
|
336
|
-
return 1; //to make alphanumeric sort first return -1 here
|
|
337
|
-
} else if (isNaN(BInt)) {
|
|
338
|
-
//B is not an Int
|
|
339
|
-
return -1; //to make alphanumeric sort first return 1 here
|
|
340
|
-
} else {
|
|
341
|
-
return AInt > BInt ? 1 : -1;
|
|
342
|
-
}
|
|
343
|
-
};
|
|
344
|
-
|
|
345
|
-
const timeDifference = (date1, date2) => {
|
|
346
|
-
let dif = date1 - date2;
|
|
347
|
-
if (dif < 0) return "00:00";
|
|
348
|
-
|
|
349
|
-
const dayDif = Math.floor(dif / 1000 / 60 / 60 / 24);
|
|
350
|
-
dif -= dayDif * 1000 * 60 * 60 * 24;
|
|
351
|
-
const hourDif = Math.floor(dif / 1000 / 60 / 60);
|
|
352
|
-
dif -= hourDif * 1000 * 60 * 60;
|
|
353
|
-
const minDif = Math.floor(dif / 1000 / 60);
|
|
354
|
-
dif -= minDif * 1000 * 60;
|
|
355
|
-
const secDif = Math.floor(dif / 1000);
|
|
356
|
-
|
|
357
|
-
const strMin = String(minDif).padStart(2, "0");
|
|
358
|
-
const strSec = String(secDif).padStart(2, "0");
|
|
359
|
-
const str = `${strMin}:${strSec}`;
|
|
360
|
-
if (str === "NaN:NaN") return "00:00";
|
|
361
|
-
return str;
|
|
362
|
-
};
|
|
363
|
-
|
|
364
|
-
const parseAxsEventUrl = (url) => {
|
|
365
|
-
const HOST = "www.axs.com";
|
|
366
|
-
|
|
367
|
-
if (!url.startsWith("https://")) return { eventId: url };
|
|
368
|
-
if (!url.includes(`https://${HOST}`)) return {};
|
|
369
|
-
|
|
370
|
-
const siteMatch = url.match(new RegExp(`https://${HOST}(/uk)?`));
|
|
371
|
-
const eventMatch = url.match(/\/events\/(\d+)/);
|
|
372
|
-
const promoMatch = url.match(/\/promopage\/(\d+)/);
|
|
373
|
-
|
|
374
|
-
if (!siteMatch || !eventMatch) return {};
|
|
375
|
-
|
|
376
|
-
const siteId = siteMatch[1] === "/uk" ? "AXS_UK" : "AXS_US";
|
|
377
|
-
const eventId = eventMatch[1];
|
|
378
|
-
const promoId = promoMatch?.[1];
|
|
379
|
-
|
|
380
|
-
const result = { eventId, siteId };
|
|
381
|
-
if (promoId) result.promoId = promoId;
|
|
382
|
-
|
|
383
|
-
return result;
|
|
384
|
-
};
|
|
385
|
-
|
|
386
|
-
const parseTmEventUrl = (url) => {
|
|
387
|
-
if (!url.includes("https://")) {
|
|
388
|
-
return { eventId: url };
|
|
389
|
-
}
|
|
390
|
-
const urlRegex = /^.*?\/([^/?]+)(?:\?(.*))?$/i;
|
|
391
|
-
const [, eventId, queryString = ""] = url.match(urlRegex) || [];
|
|
392
|
-
const queryParams = new URLSearchParams(queryString);
|
|
393
|
-
|
|
394
|
-
return {
|
|
395
|
-
eventId: eventId,
|
|
396
|
-
eventDid: queryParams.get("did"),
|
|
397
|
-
clOrigin: queryParams.get("subchannel_id") || queryParams.get("CL_ORIGIN")
|
|
398
|
-
};
|
|
399
|
-
};
|
|
400
|
-
|
|
401
|
-
const isEU = (siteId) => !["US", "AU", "UK", "CA", "NZ", "IE"].includes(siteId.split("_")?.[1] || siteId);
|
|
402
|
-
|
|
403
|
-
const removeDuplicates = (arr) => [...new Set(arr)];
|
|
404
|
-
|
|
405
316
|
const pickRandom = (arr) => arr[Math.floor(Math.random() * arr.length)];
|
|
406
317
|
|
|
407
318
|
const fakeId = () => {
|
|
@@ -418,163 +329,4 @@ const fakeId = () => {
|
|
|
418
329
|
return profile;
|
|
419
330
|
};
|
|
420
331
|
|
|
421
|
-
|
|
422
|
-
const CARD_TYPES = {
|
|
423
|
-
visa: {
|
|
424
|
-
pattern: /^4\d{12}(?:\d{3})?$/,
|
|
425
|
-
gaps: [4, 8, 12]
|
|
426
|
-
},
|
|
427
|
-
mastercard: {
|
|
428
|
-
pattern: /^5[1-5]\d{14}$/,
|
|
429
|
-
gaps: [4, 8, 12]
|
|
430
|
-
},
|
|
431
|
-
amex: {
|
|
432
|
-
pattern: /^3[47]\d{13}$/,
|
|
433
|
-
gaps: [4, 10]
|
|
434
|
-
}
|
|
435
|
-
};
|
|
436
|
-
|
|
437
|
-
// Implementation of Luhn algorithm for card number validation
|
|
438
|
-
function luhnCheck(cardNumber) {
|
|
439
|
-
const digits = cardNumber.replace(/\D/g, "");
|
|
440
|
-
let sum = 0;
|
|
441
|
-
let isEven = false;
|
|
442
|
-
|
|
443
|
-
// Loop from right to left
|
|
444
|
-
for (let i = digits.length - 1; i >= 0; i--) {
|
|
445
|
-
let digit = parseInt(digits[i], 10);
|
|
446
|
-
|
|
447
|
-
if (isEven) {
|
|
448
|
-
digit *= 2;
|
|
449
|
-
if (digit > 9) {
|
|
450
|
-
digit -= 9;
|
|
451
|
-
}
|
|
452
|
-
}
|
|
453
|
-
|
|
454
|
-
sum += digit;
|
|
455
|
-
isEven = !isEven;
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
return sum % 10 === 0;
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
const getCardType = (str) => {
|
|
462
|
-
switch (str?.[0]) {
|
|
463
|
-
default:
|
|
464
|
-
case "4":
|
|
465
|
-
return "Visa";
|
|
466
|
-
case "3":
|
|
467
|
-
return "Amex";
|
|
468
|
-
case "5":
|
|
469
|
-
return "Master";
|
|
470
|
-
}
|
|
471
|
-
};
|
|
472
|
-
|
|
473
|
-
// Format card number with proper spacing
|
|
474
|
-
function formatCardNumber(cardNumber, gaps) {
|
|
475
|
-
try {
|
|
476
|
-
const cleanNumber = cardNumber.replace(/\D/g, "");
|
|
477
|
-
const formatted = cleanNumber.split("");
|
|
478
|
-
|
|
479
|
-
// Insert spaces at the specified gaps
|
|
480
|
-
gaps.forEach((gap, index) => {
|
|
481
|
-
if (formatted.length > gap + index) {
|
|
482
|
-
formatted.splice(gap + index, 0, " ");
|
|
483
|
-
}
|
|
484
|
-
});
|
|
485
|
-
|
|
486
|
-
return formatted.join("");
|
|
487
|
-
} catch {
|
|
488
|
-
return cardNumber;
|
|
489
|
-
}
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
// Main validation function
|
|
493
|
-
function validateCard(cardNumber) {
|
|
494
|
-
const cleanNumber = cardNumber.replace(/\s+/g, "");
|
|
495
|
-
const type = getCardType(cleanNumber);
|
|
496
|
-
const cardTypeInfo = CARD_TYPES[type] || CARD_TYPES.visa; // Default to visa gaps if unknown
|
|
497
|
-
|
|
498
|
-
const isValid =
|
|
499
|
-
cleanNumber.length >= 13 && cleanNumber.length <= 19 && /^\d+$/.test(cleanNumber) && luhnCheck(cleanNumber);
|
|
500
|
-
|
|
501
|
-
return {
|
|
502
|
-
type,
|
|
503
|
-
invalid: !isValid,
|
|
504
|
-
formatted: formatCardNumber(cleanNumber, cardTypeInfo.gaps)
|
|
505
|
-
};
|
|
506
|
-
}
|
|
507
|
-
|
|
508
|
-
function sortTaskIds(a, b) {
|
|
509
|
-
const parseId = (id) => {
|
|
510
|
-
if (!id) return { prefix: "", num: -1 };
|
|
511
|
-
|
|
512
|
-
if (/^\d+$/.test(id)) {
|
|
513
|
-
return { prefix: "", num: parseInt(id, 10) };
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
const match = id.match(/^([A-Za-z-]+)(\d+)$/);
|
|
517
|
-
if (match) {
|
|
518
|
-
return { prefix: match[1], num: parseInt(match[2], 10) };
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
return { prefix: id, num: -1 };
|
|
522
|
-
};
|
|
523
|
-
|
|
524
|
-
const aInfo = parseId(a);
|
|
525
|
-
const bInfo = parseId(b);
|
|
526
|
-
|
|
527
|
-
if (aInfo.prefix !== bInfo.prefix) {
|
|
528
|
-
return aInfo.prefix.localeCompare(bInfo.prefix);
|
|
529
|
-
}
|
|
530
|
-
|
|
531
|
-
return aInfo.num - bInfo.num;
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
const firstUpper = (str) => `${str[0].toUpperCase()}${str.slice(1).toLowerCase()}`;
|
|
535
|
-
|
|
536
|
-
function betterSort(a, b) {
|
|
537
|
-
if (a === undefined || a === null) return b === undefined || b === null ? 0 : -1;
|
|
538
|
-
if (b === undefined || b === null) return 1;
|
|
539
|
-
|
|
540
|
-
const aStr = String(a);
|
|
541
|
-
const bStr = String(b);
|
|
542
|
-
|
|
543
|
-
if (!isNaN(aStr) && !isNaN(bStr)) {
|
|
544
|
-
return Number(aStr) - Number(bStr);
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
const aParts = aStr.split(/(\d+)/).filter(Boolean);
|
|
548
|
-
const bParts = bStr.split(/(\d+)/).filter(Boolean);
|
|
549
|
-
|
|
550
|
-
const len = Math.min(aParts.length, bParts.length);
|
|
551
|
-
for (let i = 0; i < len; i++) {
|
|
552
|
-
if (!isNaN(aParts[i]) && !isNaN(bParts[i])) {
|
|
553
|
-
const numA = parseInt(aParts[i], 10);
|
|
554
|
-
const numB = parseInt(bParts[i], 10);
|
|
555
|
-
if (numA !== numB) return numA - numB;
|
|
556
|
-
} else {
|
|
557
|
-
const cmp = aParts[i].localeCompare(bParts[i]);
|
|
558
|
-
if (cmp !== 0) return cmp;
|
|
559
|
-
}
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
return aParts.length - bParts.length;
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
export {
|
|
566
|
-
generateStreetAddress,
|
|
567
|
-
timeDifference,
|
|
568
|
-
sortAlphaNum,
|
|
569
|
-
parseAxsEventUrl,
|
|
570
|
-
parseTmEventUrl,
|
|
571
|
-
isEU,
|
|
572
|
-
removeDuplicates,
|
|
573
|
-
pickRandom,
|
|
574
|
-
fakeId,
|
|
575
|
-
getCardType,
|
|
576
|
-
validateCard,
|
|
577
|
-
sortTaskIds,
|
|
578
|
-
firstUpper,
|
|
579
|
-
betterSort
|
|
580
|
-
};
|
|
332
|
+
export { fakeId };
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
const parseAxsEventUrl = (url) => {
|
|
2
|
+
const HOST = "www.axs.com";
|
|
3
|
+
|
|
4
|
+
if (!url.startsWith("https://")) return { eventId: url };
|
|
5
|
+
if (!url.includes(`https://${HOST}`)) return {};
|
|
6
|
+
|
|
7
|
+
const siteMatch = url.match(new RegExp(`https://${HOST}(/uk)?`));
|
|
8
|
+
const eventMatch = url.match(/\/events\/(\d+)/);
|
|
9
|
+
const promoMatch = url.match(/\/promopage\/(\d+)/);
|
|
10
|
+
|
|
11
|
+
if (!siteMatch || !eventMatch) return {};
|
|
12
|
+
|
|
13
|
+
const siteId = siteMatch[1] === "/uk" ? "AXS_UK" : "AXS_US";
|
|
14
|
+
const eventId = eventMatch[1];
|
|
15
|
+
const promoId = promoMatch?.[1];
|
|
16
|
+
|
|
17
|
+
const result = { eventId, siteId };
|
|
18
|
+
if (promoId) result.promoId = promoId;
|
|
19
|
+
|
|
20
|
+
return result;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const parseTmEventUrl = (url) => {
|
|
24
|
+
if (!url.includes("https://")) {
|
|
25
|
+
return { eventId: url };
|
|
26
|
+
}
|
|
27
|
+
const urlRegex = /^.*?\/([^/?]+)(?:\?(.*))?$/i;
|
|
28
|
+
const [, eventId, queryString = ""] = url.match(urlRegex) || [];
|
|
29
|
+
const queryParams = new URLSearchParams(queryString);
|
|
30
|
+
|
|
31
|
+
return {
|
|
32
|
+
eventId: eventId,
|
|
33
|
+
eventDid: queryParams.get("did"),
|
|
34
|
+
clOrigin: queryParams.get("subchannel_id") || queryParams.get("CL_ORIGIN")
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const isEU = (siteId) => !["US", "AU", "UK", "CA", "NZ", "IE"].includes(siteId.split("_")?.[1] || siteId);
|
|
39
|
+
|
|
40
|
+
export { parseAxsEventUrl, parseTmEventUrl, isEU };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
const timeDifference = (date1, date2) => {
|
|
2
|
+
let dif = date1 - date2;
|
|
3
|
+
if (dif < 0) return "00:00";
|
|
4
|
+
|
|
5
|
+
const dayDif = Math.floor(dif / 1000 / 60 / 60 / 24);
|
|
6
|
+
dif -= dayDif * 1000 * 60 * 60 * 24;
|
|
7
|
+
const hourDif = Math.floor(dif / 1000 / 60 / 60);
|
|
8
|
+
dif -= hourDif * 1000 * 60 * 60;
|
|
9
|
+
const minDif = Math.floor(dif / 1000 / 60);
|
|
10
|
+
dif -= minDif * 1000 * 60;
|
|
11
|
+
const secDif = Math.floor(dif / 1000);
|
|
12
|
+
|
|
13
|
+
const strMin = String(minDif).padStart(2, "0");
|
|
14
|
+
const strSec = String(secDif).padStart(2, "0");
|
|
15
|
+
const str = `${strMin}:${strSec}`;
|
|
16
|
+
if (str === "NaN:NaN") return "00:00";
|
|
17
|
+
return str;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export { timeDifference };
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// Card type definitions with their patterns and gaps
|
|
2
|
+
const CARD_TYPES = {
|
|
3
|
+
visa: {
|
|
4
|
+
pattern: /^4\d{12}(?:\d{3})?$/,
|
|
5
|
+
gaps: [4, 8, 12]
|
|
6
|
+
},
|
|
7
|
+
mastercard: {
|
|
8
|
+
pattern: /^5[1-5]\d{14}$/,
|
|
9
|
+
gaps: [4, 8, 12]
|
|
10
|
+
},
|
|
11
|
+
amex: {
|
|
12
|
+
pattern: /^3[47]\d{13}$/,
|
|
13
|
+
gaps: [4, 10]
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const getCardType = (str) => {
|
|
18
|
+
switch (str?.[0]) {
|
|
19
|
+
default:
|
|
20
|
+
case "4":
|
|
21
|
+
return "Visa";
|
|
22
|
+
case "3":
|
|
23
|
+
return "Amex";
|
|
24
|
+
case "5":
|
|
25
|
+
return "Master";
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
// Format card number with proper spacing
|
|
30
|
+
function formatCardNumber(cardNumber, gaps) {
|
|
31
|
+
try {
|
|
32
|
+
const cleanNumber = cardNumber.replace(/\D/g, "");
|
|
33
|
+
const formatted = cleanNumber.split("");
|
|
34
|
+
|
|
35
|
+
// Insert spaces at the specified gaps
|
|
36
|
+
gaps.forEach((gap, index) => {
|
|
37
|
+
if (formatted.length > gap + index) {
|
|
38
|
+
formatted.splice(gap + index, 0, " ");
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
return formatted.join("");
|
|
43
|
+
} catch {
|
|
44
|
+
return cardNumber;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Main validation function
|
|
49
|
+
function validateCard(cardNumber) {
|
|
50
|
+
const cleanNumber = cardNumber.replace(/\s+/g, "");
|
|
51
|
+
const type = getCardType(cleanNumber);
|
|
52
|
+
const cardTypeInfo = CARD_TYPES[type] || CARD_TYPES.visa; // Default to visa gaps if unknown
|
|
53
|
+
|
|
54
|
+
const isValid =
|
|
55
|
+
cleanNumber.length >= 13 && cleanNumber.length <= 19 && /^\d+$/.test(cleanNumber);
|
|
56
|
+
|
|
57
|
+
return {
|
|
58
|
+
type,
|
|
59
|
+
invalid: !isValid,
|
|
60
|
+
formatted: formatCardNumber(cleanNumber, cardTypeInfo.gaps)
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export { validateCard };
|
package/src/main.js
CHANGED
package/src/stores/connection.js
CHANGED
|
@@ -2,7 +2,7 @@ import { useUIStore } from "@/stores/ui";
|
|
|
2
2
|
import WebsocketHeartbeatJs from "websocket-heartbeat-js";
|
|
3
3
|
import { decode } from "@msgpack/msgpack";
|
|
4
4
|
import router from "@/router/index";
|
|
5
|
-
import { sortTaskIds } from "@/
|
|
5
|
+
import { sortTaskIds } from "@/libs/utils/array";
|
|
6
6
|
|
|
7
7
|
export class ConnectionHandler {
|
|
8
8
|
handleWebsocketMessages(msg) {
|
|
@@ -118,7 +118,6 @@ export class ConnectionHandler {
|
|
|
118
118
|
} else if (msg.update) {
|
|
119
119
|
try {
|
|
120
120
|
Object.entries(msg.update).forEach((change) => (this.ui.tasks[msg.id][change[0]] = change[1]));
|
|
121
|
-
// eslint-disable-next-line no-empty
|
|
122
121
|
} catch {}
|
|
123
122
|
} else {
|
|
124
123
|
if (!this.ui.tasks[msg.id]) this.ui.tasks[msg.id] = msg.task;
|
|
@@ -148,7 +147,6 @@ export class ConnectionHandler {
|
|
|
148
147
|
break;
|
|
149
148
|
|
|
150
149
|
case "auth":
|
|
151
|
-
// redirect to / if on login page, but successfully logged in
|
|
152
150
|
if (router.currentRoute.value.name === "login") router.push("/");
|
|
153
151
|
this.ui.setProfile(msg);
|
|
154
152
|
break;
|
|
@@ -230,7 +228,6 @@ export class ConnectionHandler {
|
|
|
230
228
|
hasShownDisconnect = true;
|
|
231
229
|
};
|
|
232
230
|
|
|
233
|
-
// this.socket.addEventListener('message', );
|
|
234
231
|
}
|
|
235
232
|
|
|
236
233
|
sendContinueTask(taskId, continueType) {
|
|
@@ -243,24 +240,6 @@ export class ConnectionHandler {
|
|
|
243
240
|
});
|
|
244
241
|
}
|
|
245
242
|
|
|
246
|
-
sendTasksChange(taskId) {
|
|
247
|
-
this.sendMessage({
|
|
248
|
-
event: "tasks/change",
|
|
249
|
-
data: {
|
|
250
|
-
id: taskId
|
|
251
|
-
}
|
|
252
|
-
});
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
sendTasksOpen(taskId) {
|
|
256
|
-
this.sendMessage({
|
|
257
|
-
event: "tasks/open",
|
|
258
|
-
data: {
|
|
259
|
-
id: taskId
|
|
260
|
-
}
|
|
261
|
-
});
|
|
262
|
-
}
|
|
263
|
-
|
|
264
243
|
sendDeleteTask(taskId) {
|
|
265
244
|
this.sendMessage({
|
|
266
245
|
event: "tasks/delete",
|
|
@@ -270,13 +249,6 @@ export class ConnectionHandler {
|
|
|
270
249
|
});
|
|
271
250
|
}
|
|
272
251
|
|
|
273
|
-
sendGetTasks() {
|
|
274
|
-
this.sendMessage({
|
|
275
|
-
event: "tasks/get",
|
|
276
|
-
data: {}
|
|
277
|
-
});
|
|
278
|
-
}
|
|
279
|
-
|
|
280
252
|
sendStartTask(taskId) {
|
|
281
253
|
this.sendMessage({
|
|
282
254
|
event: "tasks/start",
|
package/src/stores/logger.js
CHANGED
|
@@ -44,20 +44,15 @@ class Logger {
|
|
|
44
44
|
|
|
45
45
|
args.unshift(timestamp);
|
|
46
46
|
|
|
47
|
-
// Format objects for console output
|
|
48
|
-
const formattedArgs = args.map((arg) => {
|
|
49
|
-
if (typeof arg === "object" && arg !== null) {
|
|
50
|
-
console.log(arg._value ? arg._value : arg);
|
|
51
|
-
return arg;
|
|
52
|
-
}
|
|
53
|
-
return arg;
|
|
54
|
-
});
|
|
55
|
-
|
|
56
47
|
// For styled console output in browser
|
|
57
48
|
if (style) {
|
|
58
|
-
console
|
|
49
|
+
/* eslint-disable no-console */
|
|
50
|
+
console.log(`%c${args.join(" ")}`, style);
|
|
51
|
+
/* eslint-enable no-console */
|
|
59
52
|
} else {
|
|
60
|
-
console
|
|
53
|
+
/* eslint-disable no-console */
|
|
54
|
+
console.log(...args);
|
|
55
|
+
/* eslint-enable no-console */
|
|
61
56
|
}
|
|
62
57
|
}
|
|
63
58
|
|
|
@@ -95,7 +90,6 @@ class Logger {
|
|
|
95
90
|
}
|
|
96
91
|
}
|
|
97
92
|
|
|
98
|
-
// Export as an object instead of using module.exports
|
|
99
93
|
export const createLogger = (args) => {
|
|
100
94
|
const logger = new Logger();
|
|
101
95
|
logger.defaultArgs = typeof args === "string" ? [args] : Array.isArray(args) ? args : undefined;
|
package/src/stores/sampleData.js
CHANGED
|
@@ -19,14 +19,13 @@ export default {
|
|
|
19
19
|
email: "grantelam@hotmail.com",
|
|
20
20
|
password: "Dkstrhf4srth56Gksj",
|
|
21
21
|
status: "Event already happened long long long long long long longlong long long long",
|
|
22
|
-
inQueue: queueStats,
|
|
23
22
|
statusColor: "red",
|
|
24
23
|
manual: false,
|
|
25
24
|
quickQueue: false,
|
|
26
25
|
loginAfterCart: false,
|
|
27
26
|
quantity: 8,
|
|
28
27
|
proxy: "http://events1597:yEXBe4Hs@23.26.22.61:61234",
|
|
29
|
-
eventId: "
|
|
28
|
+
eventId: "grantelam@hotmail.com",
|
|
30
29
|
reservedTicketsList: "• 2x 301/E ($86.47) \n• 2x 306/U ($86.47) \n$345.88",
|
|
31
30
|
expirationTime: null,
|
|
32
31
|
doNotPay: false,
|