diff options
Diffstat (limited to 'frontend')
25 files changed, 1227 insertions, 431 deletions
diff --git a/frontend/index.html b/frontend/index.html index 8578eba..7538ee9 100644 --- a/frontend/index.html +++ b/frontend/index.html | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | <meta name="viewport" content="width=device-width, initial-scale=1" /> | 7 | <meta name="viewport" content="width=device-width, initial-scale=1" /> |
| 8 | <meta name="theme-color" content="#000000" /> | 8 | <meta name="theme-color" content="#000000" /> |
| 9 | <link rel="apple-touch-icon" href="/logo192.png" /> | 9 | <link rel="apple-touch-icon" href="/logo192.png" /> |
| 10 | <link href="/src/style.css" rel="stylesheet"> | ||
| 10 | <link rel="manifest" href="/manifest.json" /> | 11 | <link rel="manifest" href="/manifest.json" /> |
| 11 | <title>LPHUB</title> | 12 | <title>LPHUB</title> |
| 12 | </head> | 13 | </head> |
diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 9bc560f..92fcc9b 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | "version": "0.1.0", | 9 | "version": "0.1.0", |
| 10 | "dependencies": { | 10 | "dependencies": { |
| 11 | "@nekz/sdp": "^0.9.0", | 11 | "@nekz/sdp": "^0.9.0", |
| 12 | "@tailwindcss/vite": "^4.1.11", | ||
| 12 | "@testing-library/jest-dom": "^5.17.0", | 13 | "@testing-library/jest-dom": "^5.17.0", |
| 13 | "@testing-library/react": "^13.4.0", | 14 | "@testing-library/react": "^13.4.0", |
| 14 | "@testing-library/user-event": "^13.5.0", | 15 | "@testing-library/user-event": "^13.5.0", |
| @@ -21,6 +22,7 @@ | |||
| 21 | "react-helmet": "^6.1.0", | 22 | "react-helmet": "^6.1.0", |
| 22 | "react-markdown": "^9.0.1", | 23 | "react-markdown": "^9.0.1", |
| 23 | "react-router-dom": "^6.26.1", | 24 | "react-router-dom": "^6.26.1", |
| 25 | "tailwindcss": "^4.1.11", | ||
| 24 | "typescript": "^4.9.5", | 26 | "typescript": "^4.9.5", |
| 25 | "web-vitals": "^2.1.4" | 27 | "web-vitals": "^2.1.4" |
| 26 | }, | 28 | }, |
| @@ -42,7 +44,6 @@ | |||
| 42 | "version": "2.3.0", | 44 | "version": "2.3.0", |
| 43 | "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", | 45 | "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", |
| 44 | "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", | 46 | "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", |
| 45 | "dev": true, | ||
| 46 | "license": "Apache-2.0", | 47 | "license": "Apache-2.0", |
| 47 | "dependencies": { | 48 | "dependencies": { |
| 48 | "@jridgewell/gen-mapping": "^0.3.5", | 49 | "@jridgewell/gen-mapping": "^0.3.5", |
| @@ -348,7 +349,6 @@ | |||
| 348 | "cpu": [ | 349 | "cpu": [ |
| 349 | "ppc64" | 350 | "ppc64" |
| 350 | ], | 351 | ], |
| 351 | "dev": true, | ||
| 352 | "license": "MIT", | 352 | "license": "MIT", |
| 353 | "optional": true, | 353 | "optional": true, |
| 354 | "os": [ | 354 | "os": [ |
| @@ -365,7 +365,6 @@ | |||
| 365 | "cpu": [ | 365 | "cpu": [ |
| 366 | "arm" | 366 | "arm" |
| 367 | ], | 367 | ], |
| 368 | "dev": true, | ||
| 369 | "license": "MIT", | 368 | "license": "MIT", |
| 370 | "optional": true, | 369 | "optional": true, |
| 371 | "os": [ | 370 | "os": [ |
| @@ -382,7 +381,6 @@ | |||
| 382 | "cpu": [ | 381 | "cpu": [ |
| 383 | "arm64" | 382 | "arm64" |
| 384 | ], | 383 | ], |
| 385 | "dev": true, | ||
| 386 | "license": "MIT", | 384 | "license": "MIT", |
| 387 | "optional": true, | 385 | "optional": true, |
| 388 | "os": [ | 386 | "os": [ |
| @@ -399,7 +397,6 @@ | |||
| 399 | "cpu": [ | 397 | "cpu": [ |
| 400 | "x64" | 398 | "x64" |
| 401 | ], | 399 | ], |
| 402 | "dev": true, | ||
| 403 | "license": "MIT", | 400 | "license": "MIT", |
| 404 | "optional": true, | 401 | "optional": true, |
| 405 | "os": [ | 402 | "os": [ |
| @@ -416,7 +413,6 @@ | |||
| 416 | "cpu": [ | 413 | "cpu": [ |
| 417 | "arm64" | 414 | "arm64" |
| 418 | ], | 415 | ], |
| 419 | "dev": true, | ||
| 420 | "license": "MIT", | 416 | "license": "MIT", |
| 421 | "optional": true, | 417 | "optional": true, |
| 422 | "os": [ | 418 | "os": [ |
| @@ -433,7 +429,6 @@ | |||
| 433 | "cpu": [ | 429 | "cpu": [ |
| 434 | "x64" | 430 | "x64" |
| 435 | ], | 431 | ], |
| 436 | "dev": true, | ||
| 437 | "license": "MIT", | 432 | "license": "MIT", |
| 438 | "optional": true, | 433 | "optional": true, |
| 439 | "os": [ | 434 | "os": [ |
| @@ -450,7 +445,6 @@ | |||
| 450 | "cpu": [ | 445 | "cpu": [ |
| 451 | "arm64" | 446 | "arm64" |
| 452 | ], | 447 | ], |
| 453 | "dev": true, | ||
| 454 | "license": "MIT", | 448 | "license": "MIT", |
| 455 | "optional": true, | 449 | "optional": true, |
| 456 | "os": [ | 450 | "os": [ |
| @@ -467,7 +461,6 @@ | |||
| 467 | "cpu": [ | 461 | "cpu": [ |
| 468 | "x64" | 462 | "x64" |
| 469 | ], | 463 | ], |
| 470 | "dev": true, | ||
| 471 | "license": "MIT", | 464 | "license": "MIT", |
| 472 | "optional": true, | 465 | "optional": true, |
| 473 | "os": [ | 466 | "os": [ |
| @@ -484,7 +477,6 @@ | |||
| 484 | "cpu": [ | 477 | "cpu": [ |
| 485 | "arm" | 478 | "arm" |
| 486 | ], | 479 | ], |
| 487 | "dev": true, | ||
| 488 | "license": "MIT", | 480 | "license": "MIT", |
| 489 | "optional": true, | 481 | "optional": true, |
| 490 | "os": [ | 482 | "os": [ |
| @@ -501,7 +493,6 @@ | |||
| 501 | "cpu": [ | 493 | "cpu": [ |
| 502 | "arm64" | 494 | "arm64" |
| 503 | ], | 495 | ], |
| 504 | "dev": true, | ||
| 505 | "license": "MIT", | 496 | "license": "MIT", |
| 506 | "optional": true, | 497 | "optional": true, |
| 507 | "os": [ | 498 | "os": [ |
| @@ -518,7 +509,6 @@ | |||
| 518 | "cpu": [ | 509 | "cpu": [ |
| 519 | "ia32" | 510 | "ia32" |
| 520 | ], | 511 | ], |
| 521 | "dev": true, | ||
| 522 | "license": "MIT", | 512 | "license": "MIT", |
| 523 | "optional": true, | 513 | "optional": true, |
| 524 | "os": [ | 514 | "os": [ |
| @@ -535,7 +525,6 @@ | |||
| 535 | "cpu": [ | 525 | "cpu": [ |
| 536 | "loong64" | 526 | "loong64" |
| 537 | ], | 527 | ], |
| 538 | "dev": true, | ||
| 539 | "license": "MIT", | 528 | "license": "MIT", |
| 540 | "optional": true, | 529 | "optional": true, |
| 541 | "os": [ | 530 | "os": [ |
| @@ -552,7 +541,6 @@ | |||
| 552 | "cpu": [ | 541 | "cpu": [ |
| 553 | "mips64el" | 542 | "mips64el" |
| 554 | ], | 543 | ], |
| 555 | "dev": true, | ||
| 556 | "license": "MIT", | 544 | "license": "MIT", |
| 557 | "optional": true, | 545 | "optional": true, |
| 558 | "os": [ | 546 | "os": [ |
| @@ -569,7 +557,6 @@ | |||
| 569 | "cpu": [ | 557 | "cpu": [ |
| 570 | "ppc64" | 558 | "ppc64" |
| 571 | ], | 559 | ], |
| 572 | "dev": true, | ||
| 573 | "license": "MIT", | 560 | "license": "MIT", |
| 574 | "optional": true, | 561 | "optional": true, |
| 575 | "os": [ | 562 | "os": [ |
| @@ -586,7 +573,6 @@ | |||
| 586 | "cpu": [ | 573 | "cpu": [ |
| 587 | "riscv64" | 574 | "riscv64" |
| 588 | ], | 575 | ], |
| 589 | "dev": true, | ||
| 590 | "license": "MIT", | 576 | "license": "MIT", |
| 591 | "optional": true, | 577 | "optional": true, |
| 592 | "os": [ | 578 | "os": [ |
| @@ -603,7 +589,6 @@ | |||
| 603 | "cpu": [ | 589 | "cpu": [ |
| 604 | "s390x" | 590 | "s390x" |
| 605 | ], | 591 | ], |
| 606 | "dev": true, | ||
| 607 | "license": "MIT", | 592 | "license": "MIT", |
| 608 | "optional": true, | 593 | "optional": true, |
| 609 | "os": [ | 594 | "os": [ |
| @@ -620,7 +605,6 @@ | |||
| 620 | "cpu": [ | 605 | "cpu": [ |
| 621 | "x64" | 606 | "x64" |
| 622 | ], | 607 | ], |
| 623 | "dev": true, | ||
| 624 | "license": "MIT", | 608 | "license": "MIT", |
| 625 | "optional": true, | 609 | "optional": true, |
| 626 | "os": [ | 610 | "os": [ |
| @@ -637,7 +621,6 @@ | |||
| 637 | "cpu": [ | 621 | "cpu": [ |
| 638 | "arm64" | 622 | "arm64" |
| 639 | ], | 623 | ], |
| 640 | "dev": true, | ||
| 641 | "license": "MIT", | 624 | "license": "MIT", |
| 642 | "optional": true, | 625 | "optional": true, |
| 643 | "os": [ | 626 | "os": [ |
| @@ -654,7 +637,6 @@ | |||
| 654 | "cpu": [ | 637 | "cpu": [ |
| 655 | "x64" | 638 | "x64" |
| 656 | ], | 639 | ], |
| 657 | "dev": true, | ||
| 658 | "license": "MIT", | 640 | "license": "MIT", |
| 659 | "optional": true, | 641 | "optional": true, |
| 660 | "os": [ | 642 | "os": [ |
| @@ -671,7 +653,6 @@ | |||
| 671 | "cpu": [ | 653 | "cpu": [ |
| 672 | "arm64" | 654 | "arm64" |
| 673 | ], | 655 | ], |
| 674 | "dev": true, | ||
| 675 | "license": "MIT", | 656 | "license": "MIT", |
| 676 | "optional": true, | 657 | "optional": true, |
| 677 | "os": [ | 658 | "os": [ |
| @@ -688,7 +669,6 @@ | |||
| 688 | "cpu": [ | 669 | "cpu": [ |
| 689 | "x64" | 670 | "x64" |
| 690 | ], | 671 | ], |
| 691 | "dev": true, | ||
| 692 | "license": "MIT", | 672 | "license": "MIT", |
| 693 | "optional": true, | 673 | "optional": true, |
| 694 | "os": [ | 674 | "os": [ |
| @@ -705,7 +685,6 @@ | |||
| 705 | "cpu": [ | 685 | "cpu": [ |
| 706 | "arm64" | 686 | "arm64" |
| 707 | ], | 687 | ], |
| 708 | "dev": true, | ||
| 709 | "license": "MIT", | 688 | "license": "MIT", |
| 710 | "optional": true, | 689 | "optional": true, |
| 711 | "os": [ | 690 | "os": [ |
| @@ -722,7 +701,6 @@ | |||
| 722 | "cpu": [ | 701 | "cpu": [ |
| 723 | "x64" | 702 | "x64" |
| 724 | ], | 703 | ], |
| 725 | "dev": true, | ||
| 726 | "license": "MIT", | 704 | "license": "MIT", |
| 727 | "optional": true, | 705 | "optional": true, |
| 728 | "os": [ | 706 | "os": [ |
| @@ -739,7 +717,6 @@ | |||
| 739 | "cpu": [ | 717 | "cpu": [ |
| 740 | "arm64" | 718 | "arm64" |
| 741 | ], | 719 | ], |
| 742 | "dev": true, | ||
| 743 | "license": "MIT", | 720 | "license": "MIT", |
| 744 | "optional": true, | 721 | "optional": true, |
| 745 | "os": [ | 722 | "os": [ |
| @@ -756,7 +733,6 @@ | |||
| 756 | "cpu": [ | 733 | "cpu": [ |
| 757 | "ia32" | 734 | "ia32" |
| 758 | ], | 735 | ], |
| 759 | "dev": true, | ||
| 760 | "license": "MIT", | 736 | "license": "MIT", |
| 761 | "optional": true, | 737 | "optional": true, |
| 762 | "os": [ | 738 | "os": [ |
| @@ -773,7 +749,6 @@ | |||
| 773 | "cpu": [ | 749 | "cpu": [ |
| 774 | "x64" | 750 | "x64" |
| 775 | ], | 751 | ], |
| 776 | "dev": true, | ||
| 777 | "license": "MIT", | 752 | "license": "MIT", |
| 778 | "optional": true, | 753 | "optional": true, |
| 779 | "os": [ | 754 | "os": [ |
| @@ -783,11 +758,22 @@ | |||
| 783 | "node": ">=18" | 758 | "node": ">=18" |
| 784 | } | 759 | } |
| 785 | }, | 760 | }, |
| 761 | "node_modules/@isaacs/fs-minipass": { | ||
| 762 | "version": "4.0.1", | ||
| 763 | "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", | ||
| 764 | "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", | ||
| 765 | "license": "ISC", | ||
| 766 | "dependencies": { | ||
| 767 | "minipass": "^7.0.4" | ||
| 768 | }, | ||
| 769 | "engines": { | ||
| 770 | "node": ">=18.0.0" | ||
| 771 | } | ||
| 772 | }, | ||
| 786 | "node_modules/@jridgewell/gen-mapping": { | 773 | "node_modules/@jridgewell/gen-mapping": { |
| 787 | "version": "0.3.12", | 774 | "version": "0.3.12", |
| 788 | "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz", | 775 | "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz", |
| 789 | "integrity": "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==", | 776 | "integrity": "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==", |
| 790 | "dev": true, | ||
| 791 | "license": "MIT", | 777 | "license": "MIT", |
| 792 | "dependencies": { | 778 | "dependencies": { |
| 793 | "@jridgewell/sourcemap-codec": "^1.5.0", | 779 | "@jridgewell/sourcemap-codec": "^1.5.0", |
| @@ -798,7 +784,6 @@ | |||
| 798 | "version": "3.1.2", | 784 | "version": "3.1.2", |
| 799 | "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", | 785 | "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", |
| 800 | "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", | 786 | "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", |
| 801 | "dev": true, | ||
| 802 | "license": "MIT", | 787 | "license": "MIT", |
| 803 | "engines": { | 788 | "engines": { |
| 804 | "node": ">=6.0.0" | 789 | "node": ">=6.0.0" |
| @@ -808,14 +793,12 @@ | |||
| 808 | "version": "1.5.4", | 793 | "version": "1.5.4", |
| 809 | "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz", | 794 | "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz", |
| 810 | "integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==", | 795 | "integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==", |
| 811 | "dev": true, | ||
| 812 | "license": "MIT" | 796 | "license": "MIT" |
| 813 | }, | 797 | }, |
| 814 | "node_modules/@jridgewell/trace-mapping": { | 798 | "node_modules/@jridgewell/trace-mapping": { |
| 815 | "version": "0.3.29", | 799 | "version": "0.3.29", |
| 816 | "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz", | 800 | "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz", |
| 817 | "integrity": "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==", | 801 | "integrity": "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==", |
| 818 | "dev": true, | ||
| 819 | "license": "MIT", | 802 | "license": "MIT", |
| 820 | "dependencies": { | 803 | "dependencies": { |
| 821 | "@jridgewell/resolve-uri": "^3.1.0", | 804 | "@jridgewell/resolve-uri": "^3.1.0", |
| @@ -851,7 +834,6 @@ | |||
| 851 | "cpu": [ | 834 | "cpu": [ |
| 852 | "arm" | 835 | "arm" |
| 853 | ], | 836 | ], |
| 854 | "dev": true, | ||
| 855 | "license": "MIT", | 837 | "license": "MIT", |
| 856 | "optional": true, | 838 | "optional": true, |
| 857 | "os": [ | 839 | "os": [ |
| @@ -865,7 +847,6 @@ | |||
| 865 | "cpu": [ | 847 | "cpu": [ |
| 866 | "arm64" | 848 | "arm64" |
| 867 | ], | 849 | ], |
| 868 | "dev": true, | ||
| 869 | "license": "MIT", | 850 | "license": "MIT", |
| 870 | "optional": true, | 851 | "optional": true, |
| 871 | "os": [ | 852 | "os": [ |
| @@ -879,7 +860,6 @@ | |||
| 879 | "cpu": [ | 860 | "cpu": [ |
| 880 | "arm64" | 861 | "arm64" |
| 881 | ], | 862 | ], |
| 882 | "dev": true, | ||
| 883 | "license": "MIT", | 863 | "license": "MIT", |
| 884 | "optional": true, | 864 | "optional": true, |
| 885 | "os": [ | 865 | "os": [ |
| @@ -893,7 +873,6 @@ | |||
| 893 | "cpu": [ | 873 | "cpu": [ |
| 894 | "x64" | 874 | "x64" |
| 895 | ], | 875 | ], |
| 896 | "dev": true, | ||
| 897 | "license": "MIT", | 876 | "license": "MIT", |
| 898 | "optional": true, | 877 | "optional": true, |
| 899 | "os": [ | 878 | "os": [ |
| @@ -907,7 +886,6 @@ | |||
| 907 | "cpu": [ | 886 | "cpu": [ |
| 908 | "arm64" | 887 | "arm64" |
| 909 | ], | 888 | ], |
| 910 | "dev": true, | ||
| 911 | "license": "MIT", | 889 | "license": "MIT", |
| 912 | "optional": true, | 890 | "optional": true, |
| 913 | "os": [ | 891 | "os": [ |
| @@ -921,7 +899,6 @@ | |||
| 921 | "cpu": [ | 899 | "cpu": [ |
| 922 | "x64" | 900 | "x64" |
| 923 | ], | 901 | ], |
| 924 | "dev": true, | ||
| 925 | "license": "MIT", | 902 | "license": "MIT", |
| 926 | "optional": true, | 903 | "optional": true, |
| 927 | "os": [ | 904 | "os": [ |
| @@ -935,7 +912,6 @@ | |||
| 935 | "cpu": [ | 912 | "cpu": [ |
| 936 | "arm" | 913 | "arm" |
| 937 | ], | 914 | ], |
| 938 | "dev": true, | ||
| 939 | "license": "MIT", | 915 | "license": "MIT", |
| 940 | "optional": true, | 916 | "optional": true, |
| 941 | "os": [ | 917 | "os": [ |
| @@ -949,7 +925,6 @@ | |||
| 949 | "cpu": [ | 925 | "cpu": [ |
| 950 | "arm" | 926 | "arm" |
| 951 | ], | 927 | ], |
| 952 | "dev": true, | ||
| 953 | "license": "MIT", | 928 | "license": "MIT", |
| 954 | "optional": true, | 929 | "optional": true, |
| 955 | "os": [ | 930 | "os": [ |
| @@ -963,7 +938,6 @@ | |||
| 963 | "cpu": [ | 938 | "cpu": [ |
| 964 | "arm64" | 939 | "arm64" |
| 965 | ], | 940 | ], |
| 966 | "dev": true, | ||
| 967 | "license": "MIT", | 941 | "license": "MIT", |
| 968 | "optional": true, | 942 | "optional": true, |
| 969 | "os": [ | 943 | "os": [ |
| @@ -977,7 +951,6 @@ | |||
| 977 | "cpu": [ | 951 | "cpu": [ |
| 978 | "arm64" | 952 | "arm64" |
| 979 | ], | 953 | ], |
| 980 | "dev": true, | ||
| 981 | "license": "MIT", | 954 | "license": "MIT", |
| 982 | "optional": true, | 955 | "optional": true, |
| 983 | "os": [ | 956 | "os": [ |
| @@ -991,7 +964,6 @@ | |||
| 991 | "cpu": [ | 964 | "cpu": [ |
| 992 | "loong64" | 965 | "loong64" |
| 993 | ], | 966 | ], |
| 994 | "dev": true, | ||
| 995 | "license": "MIT", | 967 | "license": "MIT", |
| 996 | "optional": true, | 968 | "optional": true, |
| 997 | "os": [ | 969 | "os": [ |
| @@ -1005,7 +977,6 @@ | |||
| 1005 | "cpu": [ | 977 | "cpu": [ |
| 1006 | "ppc64" | 978 | "ppc64" |
| 1007 | ], | 979 | ], |
| 1008 | "dev": true, | ||
| 1009 | "license": "MIT", | 980 | "license": "MIT", |
| 1010 | "optional": true, | 981 | "optional": true, |
| 1011 | "os": [ | 982 | "os": [ |
| @@ -1019,7 +990,6 @@ | |||
| 1019 | "cpu": [ | 990 | "cpu": [ |
| 1020 | "riscv64" | 991 | "riscv64" |
| 1021 | ], | 992 | ], |
| 1022 | "dev": true, | ||
| 1023 | "license": "MIT", | 993 | "license": "MIT", |
| 1024 | "optional": true, | 994 | "optional": true, |
| 1025 | "os": [ | 995 | "os": [ |
| @@ -1033,7 +1003,6 @@ | |||
| 1033 | "cpu": [ | 1003 | "cpu": [ |
| 1034 | "riscv64" | 1004 | "riscv64" |
| 1035 | ], | 1005 | ], |
| 1036 | "dev": true, | ||
| 1037 | "license": "MIT", | 1006 | "license": "MIT", |
| 1038 | "optional": true, | 1007 | "optional": true, |
| 1039 | "os": [ | 1008 | "os": [ |
| @@ -1047,7 +1016,6 @@ | |||
| 1047 | "cpu": [ | 1016 | "cpu": [ |
| 1048 | "s390x" | 1017 | "s390x" |
| 1049 | ], | 1018 | ], |
| 1050 | "dev": true, | ||
| 1051 | "license": "MIT", | 1019 | "license": "MIT", |
| 1052 | "optional": true, | 1020 | "optional": true, |
| 1053 | "os": [ | 1021 | "os": [ |
| @@ -1061,7 +1029,6 @@ | |||
| 1061 | "cpu": [ | 1029 | "cpu": [ |
| 1062 | "x64" | 1030 | "x64" |
| 1063 | ], | 1031 | ], |
| 1064 | "dev": true, | ||
| 1065 | "license": "MIT", | 1032 | "license": "MIT", |
| 1066 | "optional": true, | 1033 | "optional": true, |
| 1067 | "os": [ | 1034 | "os": [ |
| @@ -1075,7 +1042,6 @@ | |||
| 1075 | "cpu": [ | 1042 | "cpu": [ |
| 1076 | "x64" | 1043 | "x64" |
| 1077 | ], | 1044 | ], |
| 1078 | "dev": true, | ||
| 1079 | "license": "MIT", | 1045 | "license": "MIT", |
| 1080 | "optional": true, | 1046 | "optional": true, |
| 1081 | "os": [ | 1047 | "os": [ |
| @@ -1089,7 +1055,6 @@ | |||
| 1089 | "cpu": [ | 1055 | "cpu": [ |
| 1090 | "arm64" | 1056 | "arm64" |
| 1091 | ], | 1057 | ], |
| 1092 | "dev": true, | ||
| 1093 | "license": "MIT", | 1058 | "license": "MIT", |
| 1094 | "optional": true, | 1059 | "optional": true, |
| 1095 | "os": [ | 1060 | "os": [ |
| @@ -1103,7 +1068,6 @@ | |||
| 1103 | "cpu": [ | 1068 | "cpu": [ |
| 1104 | "ia32" | 1069 | "ia32" |
| 1105 | ], | 1070 | ], |
| 1106 | "dev": true, | ||
| 1107 | "license": "MIT", | 1071 | "license": "MIT", |
| 1108 | "optional": true, | 1072 | "optional": true, |
| 1109 | "os": [ | 1073 | "os": [ |
| @@ -1117,13 +1081,274 @@ | |||
| 1117 | "cpu": [ | 1081 | "cpu": [ |
| 1118 | "x64" | 1082 | "x64" |
| 1119 | ], | 1083 | ], |
| 1120 | "dev": true, | ||
| 1121 | "license": "MIT", | 1084 | "license": "MIT", |
| 1122 | "optional": true, | 1085 | "optional": true, |
| 1123 | "os": [ | 1086 | "os": [ |
| 1124 | "win32" | 1087 | "win32" |
| 1125 | ] | 1088 | ] |
| 1126 | }, | 1089 | }, |
| 1090 | "node_modules/@tailwindcss/node": { | ||
| 1091 | "version": "4.1.11", | ||
| 1092 | "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.11.tgz", | ||
| 1093 | "integrity": "sha512-yzhzuGRmv5QyU9qLNg4GTlYI6STedBWRE7NjxP45CsFYYq9taI0zJXZBMqIC/c8fViNLhmrbpSFS57EoxUmD6Q==", | ||
| 1094 | "license": "MIT", | ||
| 1095 | "dependencies": { | ||
| 1096 | "@ampproject/remapping": "^2.3.0", | ||
| 1097 | "enhanced-resolve": "^5.18.1", | ||
| 1098 | "jiti": "^2.4.2", | ||
| 1099 | "lightningcss": "1.30.1", | ||
| 1100 | "magic-string": "^0.30.17", | ||
| 1101 | "source-map-js": "^1.2.1", | ||
| 1102 | "tailwindcss": "4.1.11" | ||
| 1103 | } | ||
| 1104 | }, | ||
| 1105 | "node_modules/@tailwindcss/oxide": { | ||
| 1106 | "version": "4.1.11", | ||
| 1107 | "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.11.tgz", | ||
| 1108 | "integrity": "sha512-Q69XzrtAhuyfHo+5/HMgr1lAiPP/G40OMFAnws7xcFEYqcypZmdW8eGXaOUIeOl1dzPJBPENXgbjsOyhg2nkrg==", | ||
| 1109 | "hasInstallScript": true, | ||
| 1110 | "license": "MIT", | ||
| 1111 | "dependencies": { | ||
| 1112 | "detect-libc": "^2.0.4", | ||
| 1113 | "tar": "^7.4.3" | ||
| 1114 | }, | ||
| 1115 | "engines": { | ||
| 1116 | "node": ">= 10" | ||
| 1117 | }, | ||
| 1118 | "optionalDependencies": { | ||
| 1119 | "@tailwindcss/oxide-android-arm64": "4.1.11", | ||
| 1120 | "@tailwindcss/oxide-darwin-arm64": "4.1.11", | ||
| 1121 | "@tailwindcss/oxide-darwin-x64": "4.1.11", | ||
| 1122 | "@tailwindcss/oxide-freebsd-x64": "4.1.11", | ||
| 1123 | "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.11", | ||
| 1124 | "@tailwindcss/oxide-linux-arm64-gnu": "4.1.11", | ||
| 1125 | "@tailwindcss/oxide-linux-arm64-musl": "4.1.11", | ||
| 1126 | "@tailwindcss/oxide-linux-x64-gnu": "4.1.11", | ||
| 1127 | "@tailwindcss/oxide-linux-x64-musl": "4.1.11", | ||
| 1128 | "@tailwindcss/oxide-wasm32-wasi": "4.1.11", | ||
| 1129 | "@tailwindcss/oxide-win32-arm64-msvc": "4.1.11", | ||
| 1130 | "@tailwindcss/oxide-win32-x64-msvc": "4.1.11" | ||
| 1131 | } | ||
| 1132 | }, | ||
| 1133 | "node_modules/@tailwindcss/oxide-android-arm64": { | ||
| 1134 | "version": "4.1.11", | ||
| 1135 | "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.11.tgz", | ||
| 1136 | "integrity": "sha512-3IfFuATVRUMZZprEIx9OGDjG3Ou3jG4xQzNTvjDoKmU9JdmoCohQJ83MYd0GPnQIu89YoJqvMM0G3uqLRFtetg==", | ||
| 1137 | "cpu": [ | ||
| 1138 | "arm64" | ||
| 1139 | ], | ||
| 1140 | "license": "MIT", | ||
| 1141 | "optional": true, | ||
| 1142 | "os": [ | ||
| 1143 | "android" | ||
| 1144 | ], | ||
| 1145 | "engines": { | ||
| 1146 | "node": ">= 10" | ||
| 1147 | } | ||
| 1148 | }, | ||
| 1149 | "node_modules/@tailwindcss/oxide-darwin-arm64": { | ||
| 1150 | "version": "4.1.11", | ||
| 1151 | "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.11.tgz", | ||
| 1152 | "integrity": "sha512-ESgStEOEsyg8J5YcMb1xl8WFOXfeBmrhAwGsFxxB2CxY9evy63+AtpbDLAyRkJnxLy2WsD1qF13E97uQyP1lfQ==", | ||
| 1153 | "cpu": [ | ||
| 1154 | "arm64" | ||
| 1155 | ], | ||
| 1156 | "license": "MIT", | ||
| 1157 | "optional": true, | ||
| 1158 | "os": [ | ||
| 1159 | "darwin" | ||
| 1160 | ], | ||
| 1161 | "engines": { | ||
| 1162 | "node": ">= 10" | ||
| 1163 | } | ||
| 1164 | }, | ||
| 1165 | "node_modules/@tailwindcss/oxide-darwin-x64": { | ||
| 1166 | "version": "4.1.11", | ||
| 1167 | "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.11.tgz", | ||
| 1168 | "integrity": "sha512-EgnK8kRchgmgzG6jE10UQNaH9Mwi2n+yw1jWmof9Vyg2lpKNX2ioe7CJdf9M5f8V9uaQxInenZkOxnTVL3fhAw==", | ||
| 1169 | "cpu": [ | ||
| 1170 | "x64" | ||
| 1171 | ], | ||
| 1172 | "license": "MIT", | ||
| 1173 | "optional": true, | ||
| 1174 | "os": [ | ||
| 1175 | "darwin" | ||
| 1176 | ], | ||
| 1177 | "engines": { | ||
| 1178 | "node": ">= 10" | ||
| 1179 | } | ||
| 1180 | }, | ||
| 1181 | "node_modules/@tailwindcss/oxide-freebsd-x64": { | ||
| 1182 | "version": "4.1.11", | ||
| 1183 | "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.11.tgz", | ||
| 1184 | "integrity": "sha512-xdqKtbpHs7pQhIKmqVpxStnY1skuNh4CtbcyOHeX1YBE0hArj2romsFGb6yUmzkq/6M24nkxDqU8GYrKrz+UcA==", | ||
| 1185 | "cpu": [ | ||
| 1186 | "x64" | ||
| 1187 | ], | ||
| 1188 | "license": "MIT", | ||
| 1189 | "optional": true, | ||
| 1190 | "os": [ | ||
| 1191 | "freebsd" | ||
| 1192 | ], | ||
| 1193 | "engines": { | ||
| 1194 | "node": ">= 10" | ||
| 1195 | } | ||
| 1196 | }, | ||
| 1197 | "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { | ||
| 1198 | "version": "4.1.11", | ||
| 1199 | "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.11.tgz", | ||
| 1200 | "integrity": "sha512-ryHQK2eyDYYMwB5wZL46uoxz2zzDZsFBwfjssgB7pzytAeCCa6glsiJGjhTEddq/4OsIjsLNMAiMlHNYnkEEeg==", | ||
| 1201 | "cpu": [ | ||
| 1202 | "arm" | ||
| 1203 | ], | ||
| 1204 | "license": "MIT", | ||
| 1205 | "optional": true, | ||
| 1206 | "os": [ | ||
| 1207 | "linux" | ||
| 1208 | ], | ||
| 1209 | "engines": { | ||
| 1210 | "node": ">= 10" | ||
| 1211 | } | ||
| 1212 | }, | ||
| 1213 | "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { | ||
| 1214 | "version": "4.1.11", | ||
| 1215 | "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.11.tgz", | ||
| 1216 | "integrity": "sha512-mYwqheq4BXF83j/w75ewkPJmPZIqqP1nhoghS9D57CLjsh3Nfq0m4ftTotRYtGnZd3eCztgbSPJ9QhfC91gDZQ==", | ||
| 1217 | "cpu": [ | ||
| 1218 | "arm64" | ||
| 1219 | ], | ||
| 1220 | "license": "MIT", | ||
| 1221 | "optional": true, | ||
| 1222 | "os": [ | ||
| 1223 | "linux" | ||
| 1224 | ], | ||
| 1225 | "engines": { | ||
| 1226 | "node": ">= 10" | ||
| 1227 | } | ||
| 1228 | }, | ||
| 1229 | "node_modules/@tailwindcss/oxide-linux-arm64-musl": { | ||
| 1230 | "version": "4.1.11", | ||
| 1231 | "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.11.tgz", | ||
| 1232 | "integrity": "sha512-m/NVRFNGlEHJrNVk3O6I9ggVuNjXHIPoD6bqay/pubtYC9QIdAMpS+cswZQPBLvVvEF6GtSNONbDkZrjWZXYNQ==", | ||
| 1233 | "cpu": [ | ||
| 1234 | "arm64" | ||
| 1235 | ], | ||
| 1236 | "license": "MIT", | ||
| 1237 | "optional": true, | ||
| 1238 | "os": [ | ||
| 1239 | "linux" | ||
| 1240 | ], | ||
| 1241 | "engines": { | ||
| 1242 | "node": ">= 10" | ||
| 1243 | } | ||
| 1244 | }, | ||
| 1245 | "node_modules/@tailwindcss/oxide-linux-x64-gnu": { | ||
| 1246 | "version": "4.1.11", | ||
| 1247 | "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.11.tgz", | ||
| 1248 | "integrity": "sha512-YW6sblI7xukSD2TdbbaeQVDysIm/UPJtObHJHKxDEcW2exAtY47j52f8jZXkqE1krdnkhCMGqP3dbniu1Te2Fg==", | ||
| 1249 | "cpu": [ | ||
| 1250 | "x64" | ||
| 1251 | ], | ||
| 1252 | "license": "MIT", | ||
| 1253 | "optional": true, | ||
| 1254 | "os": [ | ||
| 1255 | "linux" | ||
| 1256 | ], | ||
| 1257 | "engines": { | ||
| 1258 | "node": ">= 10" | ||
| 1259 | } | ||
| 1260 | }, | ||
| 1261 | "node_modules/@tailwindcss/oxide-linux-x64-musl": { | ||
| 1262 | "version": "4.1.11", | ||
| 1263 | "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.11.tgz", | ||
| 1264 | "integrity": "sha512-e3C/RRhGunWYNC3aSF7exsQkdXzQ/M+aYuZHKnw4U7KQwTJotnWsGOIVih0s2qQzmEzOFIJ3+xt7iq67K/p56Q==", | ||
| 1265 | "cpu": [ | ||
| 1266 | "x64" | ||
| 1267 | ], | ||
| 1268 | "license": "MIT", | ||
| 1269 | "optional": true, | ||
| 1270 | "os": [ | ||
| 1271 | "linux" | ||
| 1272 | ], | ||
| 1273 | "engines": { | ||
| 1274 | "node": ">= 10" | ||
| 1275 | } | ||
| 1276 | }, | ||
| 1277 | "node_modules/@tailwindcss/oxide-wasm32-wasi": { | ||
| 1278 | "version": "4.1.11", | ||
| 1279 | "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.11.tgz", | ||
| 1280 | "integrity": "sha512-Xo1+/GU0JEN/C/dvcammKHzeM6NqKovG+6921MR6oadee5XPBaKOumrJCXvopJ/Qb5TH7LX/UAywbqrP4lax0g==", | ||
| 1281 | "bundleDependencies": [ | ||
| 1282 | "@napi-rs/wasm-runtime", | ||
| 1283 | "@emnapi/core", | ||
| 1284 | "@emnapi/runtime", | ||
| 1285 | "@tybys/wasm-util", | ||
| 1286 | "@emnapi/wasi-threads", | ||
| 1287 | "tslib" | ||
| 1288 | ], | ||
| 1289 | "cpu": [ | ||
| 1290 | "wasm32" | ||
| 1291 | ], | ||
| 1292 | "license": "MIT", | ||
| 1293 | "optional": true, | ||
| 1294 | "dependencies": { | ||
| 1295 | "@emnapi/core": "^1.4.3", | ||
| 1296 | "@emnapi/runtime": "^1.4.3", | ||
| 1297 | "@emnapi/wasi-threads": "^1.0.2", | ||
| 1298 | "@napi-rs/wasm-runtime": "^0.2.11", | ||
| 1299 | "@tybys/wasm-util": "^0.9.0", | ||
| 1300 | "tslib": "^2.8.0" | ||
| 1301 | }, | ||
| 1302 | "engines": { | ||
| 1303 | "node": ">=14.0.0" | ||
| 1304 | } | ||
| 1305 | }, | ||
| 1306 | "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { | ||
| 1307 | "version": "4.1.11", | ||
| 1308 | "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.11.tgz", | ||
| 1309 | "integrity": "sha512-UgKYx5PwEKrac3GPNPf6HVMNhUIGuUh4wlDFR2jYYdkX6pL/rn73zTq/4pzUm8fOjAn5L8zDeHp9iXmUGOXZ+w==", | ||
| 1310 | "cpu": [ | ||
| 1311 | "arm64" | ||
| 1312 | ], | ||
| 1313 | "license": "MIT", | ||
| 1314 | "optional": true, | ||
| 1315 | "os": [ | ||
| 1316 | "win32" | ||
| 1317 | ], | ||
| 1318 | "engines": { | ||
| 1319 | "node": ">= 10" | ||
| 1320 | } | ||
| 1321 | }, | ||
| 1322 | "node_modules/@tailwindcss/oxide-win32-x64-msvc": { | ||
| 1323 | "version": "4.1.11", | ||
| 1324 | "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.11.tgz", | ||
| 1325 | "integrity": "sha512-YfHoggn1j0LK7wR82TOucWc5LDCguHnoS879idHekmmiR7g9HUtMw9MI0NHatS28u/Xlkfi9w5RJWgz2Dl+5Qg==", | ||
| 1326 | "cpu": [ | ||
| 1327 | "x64" | ||
| 1328 | ], | ||
| 1329 | "license": "MIT", | ||
| 1330 | "optional": true, | ||
| 1331 | "os": [ | ||
| 1332 | "win32" | ||
| 1333 | ], | ||
| 1334 | "engines": { | ||
| 1335 | "node": ">= 10" | ||
| 1336 | } | ||
| 1337 | }, | ||
| 1338 | "node_modules/@tailwindcss/vite": { | ||
| 1339 | "version": "4.1.11", | ||
| 1340 | "resolved": "https://registry.npmjs.org/@tailwindcss/vite/-/vite-4.1.11.tgz", | ||
| 1341 | "integrity": "sha512-RHYhrR3hku0MJFRV+fN2gNbDNEh3dwKvY8XJvTxCSXeMOsCRSr+uKvDWQcbizrHgjML6ZmTE5OwMrl5wKcujCw==", | ||
| 1342 | "license": "MIT", | ||
| 1343 | "dependencies": { | ||
| 1344 | "@tailwindcss/node": "4.1.11", | ||
| 1345 | "@tailwindcss/oxide": "4.1.11", | ||
| 1346 | "tailwindcss": "4.1.11" | ||
| 1347 | }, | ||
| 1348 | "peerDependencies": { | ||
| 1349 | "vite": "^5.2.0 || ^6 || ^7" | ||
| 1350 | } | ||
| 1351 | }, | ||
| 1127 | "node_modules/@testing-library/dom": { | 1352 | "node_modules/@testing-library/dom": { |
| 1128 | "version": "10.4.0", | 1353 | "version": "10.4.0", |
| 1129 | "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz", | 1354 | "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz", |
| @@ -1354,7 +1579,7 @@ | |||
| 1354 | "version": "20.19.9", | 1579 | "version": "20.19.9", |
| 1355 | "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.9.tgz", | 1580 | "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.9.tgz", |
| 1356 | "integrity": "sha512-cuVNgarYWZqxRJDQHEB58GEONhOK79QVR/qYx4S7kcUObQvUwvFnYxJuuHUKm2aieN9X3yZB4LZsuYNU1Qphsw==", | 1581 | "integrity": "sha512-cuVNgarYWZqxRJDQHEB58GEONhOK79QVR/qYx4S7kcUObQvUwvFnYxJuuHUKm2aieN9X3yZB4LZsuYNU1Qphsw==", |
| 1357 | "dev": true, | 1582 | "devOptional": true, |
| 1358 | "license": "MIT", | 1583 | "license": "MIT", |
| 1359 | "dependencies": { | 1584 | "dependencies": { |
| 1360 | "undici-types": "~6.21.0" | 1585 | "undici-types": "~6.21.0" |
| @@ -1695,6 +1920,15 @@ | |||
| 1695 | "url": "https://github.com/sponsors/wooorm" | 1920 | "url": "https://github.com/sponsors/wooorm" |
| 1696 | } | 1921 | } |
| 1697 | }, | 1922 | }, |
| 1923 | "node_modules/chownr": { | ||
| 1924 | "version": "3.0.0", | ||
| 1925 | "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", | ||
| 1926 | "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", | ||
| 1927 | "license": "BlueOak-1.0.0", | ||
| 1928 | "engines": { | ||
| 1929 | "node": ">=18" | ||
| 1930 | } | ||
| 1931 | }, | ||
| 1698 | "node_modules/color-convert": { | 1932 | "node_modules/color-convert": { |
| 1699 | "version": "2.0.1", | 1933 | "version": "2.0.1", |
| 1700 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", | 1934 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", |
| @@ -1868,6 +2102,15 @@ | |||
| 1868 | "node": ">=6" | 2102 | "node": ">=6" |
| 1869 | } | 2103 | } |
| 1870 | }, | 2104 | }, |
| 2105 | "node_modules/detect-libc": { | ||
| 2106 | "version": "2.0.4", | ||
| 2107 | "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz", | ||
| 2108 | "integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==", | ||
| 2109 | "license": "Apache-2.0", | ||
| 2110 | "engines": { | ||
| 2111 | "node": ">=8" | ||
| 2112 | } | ||
| 2113 | }, | ||
| 1871 | "node_modules/devlop": { | 2114 | "node_modules/devlop": { |
| 1872 | "version": "1.1.0", | 2115 | "version": "1.1.0", |
| 1873 | "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", | 2116 | "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", |
| @@ -1917,6 +2160,19 @@ | |||
| 1917 | "dev": true, | 2160 | "dev": true, |
| 1918 | "license": "ISC" | 2161 | "license": "ISC" |
| 1919 | }, | 2162 | }, |
| 2163 | "node_modules/enhanced-resolve": { | ||
| 2164 | "version": "5.18.3", | ||
| 2165 | "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz", | ||
| 2166 | "integrity": "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==", | ||
| 2167 | "license": "MIT", | ||
| 2168 | "dependencies": { | ||
| 2169 | "graceful-fs": "^4.2.4", | ||
| 2170 | "tapable": "^2.2.0" | ||
| 2171 | }, | ||
| 2172 | "engines": { | ||
| 2173 | "node": ">=10.13.0" | ||
| 2174 | } | ||
| 2175 | }, | ||
| 1920 | "node_modules/es-define-property": { | 2176 | "node_modules/es-define-property": { |
| 1921 | "version": "1.0.1", | 2177 | "version": "1.0.1", |
| 1922 | "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", | 2178 | "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", |
| @@ -1986,7 +2242,6 @@ | |||
| 1986 | "version": "0.25.8", | 2242 | "version": "0.25.8", |
| 1987 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.8.tgz", | 2243 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.8.tgz", |
| 1988 | "integrity": "sha512-vVC0USHGtMi8+R4Kz8rt6JhEWLxsv9Rnu/lGYbPR8u47B+DCBksq9JarW0zOO7bs37hyOK1l2/oqtbciutL5+Q==", | 2244 | "integrity": "sha512-vVC0USHGtMi8+R4Kz8rt6JhEWLxsv9Rnu/lGYbPR8u47B+DCBksq9JarW0zOO7bs37hyOK1l2/oqtbciutL5+Q==", |
| 1989 | "dev": true, | ||
| 1990 | "hasInstallScript": true, | 2245 | "hasInstallScript": true, |
| 1991 | "license": "MIT", | 2246 | "license": "MIT", |
| 1992 | "bin": { | 2247 | "bin": { |
| @@ -2054,7 +2309,6 @@ | |||
| 2054 | "version": "6.4.6", | 2309 | "version": "6.4.6", |
| 2055 | "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", | 2310 | "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.6.tgz", |
| 2056 | "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", | 2311 | "integrity": "sha512-hiFoqpyZcfNm1yc4u8oWCf9A2c4D3QjCrks3zmoVKVxpQRzmPNar1hUJcBG2RQHvEVGDN+Jm81ZheVLAQMK6+w==", |
| 2057 | "dev": true, | ||
| 2058 | "license": "MIT", | 2312 | "license": "MIT", |
| 2059 | "peerDependencies": { | 2313 | "peerDependencies": { |
| 2060 | "picomatch": "^3 || ^4" | 2314 | "picomatch": "^3 || ^4" |
| @@ -2120,7 +2374,6 @@ | |||
| 2120 | "version": "2.3.3", | 2374 | "version": "2.3.3", |
| 2121 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", | 2375 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", |
| 2122 | "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", | 2376 | "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", |
| 2123 | "dev": true, | ||
| 2124 | "hasInstallScript": true, | 2377 | "hasInstallScript": true, |
| 2125 | "license": "MIT", | 2378 | "license": "MIT", |
| 2126 | "optional": true, | 2379 | "optional": true, |
| @@ -2208,6 +2461,12 @@ | |||
| 2208 | "url": "https://github.com/sponsors/ljharb" | 2461 | "url": "https://github.com/sponsors/ljharb" |
| 2209 | } | 2462 | } |
| 2210 | }, | 2463 | }, |
| 2464 | "node_modules/graceful-fs": { | ||
| 2465 | "version": "4.2.11", | ||
| 2466 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", | ||
| 2467 | "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", | ||
| 2468 | "license": "ISC" | ||
| 2469 | }, | ||
| 2211 | "node_modules/has-bigints": { | 2470 | "node_modules/has-bigints": { |
| 2212 | "version": "1.1.0", | 2471 | "version": "1.1.0", |
| 2213 | "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", | 2472 | "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", |
| @@ -2686,6 +2945,15 @@ | |||
| 2686 | "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" | 2945 | "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" |
| 2687 | } | 2946 | } |
| 2688 | }, | 2947 | }, |
| 2948 | "node_modules/jiti": { | ||
| 2949 | "version": "2.5.1", | ||
| 2950 | "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.5.1.tgz", | ||
| 2951 | "integrity": "sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w==", | ||
| 2952 | "license": "MIT", | ||
| 2953 | "bin": { | ||
| 2954 | "jiti": "lib/jiti-cli.mjs" | ||
| 2955 | } | ||
| 2956 | }, | ||
| 2689 | "node_modules/js-tokens": { | 2957 | "node_modules/js-tokens": { |
| 2690 | "version": "4.0.0", | 2958 | "version": "4.0.0", |
| 2691 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", | 2959 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", |
| @@ -2718,6 +2986,234 @@ | |||
| 2718 | "node": ">=6" | 2986 | "node": ">=6" |
| 2719 | } | 2987 | } |
| 2720 | }, | 2988 | }, |
| 2989 | "node_modules/lightningcss": { | ||
| 2990 | "version": "1.30.1", | ||
| 2991 | "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz", | ||
| 2992 | "integrity": "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==", | ||
| 2993 | "license": "MPL-2.0", | ||
| 2994 | "dependencies": { | ||
| 2995 | "detect-libc": "^2.0.3" | ||
| 2996 | }, | ||
| 2997 | "engines": { | ||
| 2998 | "node": ">= 12.0.0" | ||
| 2999 | }, | ||
| 3000 | "funding": { | ||
| 3001 | "type": "opencollective", | ||
| 3002 | "url": "https://opencollective.com/parcel" | ||
| 3003 | }, | ||
| 3004 | "optionalDependencies": { | ||
| 3005 | "lightningcss-darwin-arm64": "1.30.1", | ||
| 3006 | "lightningcss-darwin-x64": "1.30.1", | ||
| 3007 | "lightningcss-freebsd-x64": "1.30.1", | ||
| 3008 | "lightningcss-linux-arm-gnueabihf": "1.30.1", | ||
| 3009 | "lightningcss-linux-arm64-gnu": "1.30.1", | ||
| 3010 | "lightningcss-linux-arm64-musl": "1.30.1", | ||
| 3011 | "lightningcss-linux-x64-gnu": "1.30.1", | ||
| 3012 | "lightningcss-linux-x64-musl": "1.30.1", | ||
| 3013 | "lightningcss-win32-arm64-msvc": "1.30.1", | ||
| 3014 | "lightningcss-win32-x64-msvc": "1.30.1" | ||
| 3015 | } | ||
| 3016 | }, | ||
| 3017 | "node_modules/lightningcss-darwin-arm64": { | ||
| 3018 | "version": "1.30.1", | ||
| 3019 | "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.1.tgz", | ||
| 3020 | "integrity": "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==", | ||
| 3021 | "cpu": [ | ||
| 3022 | "arm64" | ||
| 3023 | ], | ||
| 3024 | "license": "MPL-2.0", | ||
| 3025 | "optional": true, | ||
| 3026 | "os": [ | ||
| 3027 | "darwin" | ||
| 3028 | ], | ||
| 3029 | "engines": { | ||
| 3030 | "node": ">= 12.0.0" | ||
| 3031 | }, | ||
| 3032 | "funding": { | ||
| 3033 | "type": "opencollective", | ||
| 3034 | "url": "https://opencollective.com/parcel" | ||
| 3035 | } | ||
| 3036 | }, | ||
| 3037 | "node_modules/lightningcss-darwin-x64": { | ||
| 3038 | "version": "1.30.1", | ||
| 3039 | "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.1.tgz", | ||
| 3040 | "integrity": "sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==", | ||
| 3041 | "cpu": [ | ||
| 3042 | "x64" | ||
| 3043 | ], | ||
| 3044 | "license": "MPL-2.0", | ||
| 3045 | "optional": true, | ||
| 3046 | "os": [ | ||
| 3047 | "darwin" | ||
| 3048 | ], | ||
| 3049 | "engines": { | ||
| 3050 | "node": ">= 12.0.0" | ||
| 3051 | }, | ||
| 3052 | "funding": { | ||
| 3053 | "type": "opencollective", | ||
| 3054 | "url": "https://opencollective.com/parcel" | ||
| 3055 | } | ||
| 3056 | }, | ||
| 3057 | "node_modules/lightningcss-freebsd-x64": { | ||
| 3058 | "version": "1.30.1", | ||
| 3059 | "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.1.tgz", | ||
| 3060 | "integrity": "sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==", | ||
| 3061 | "cpu": [ | ||
| 3062 | "x64" | ||
| 3063 | ], | ||
| 3064 | "license": "MPL-2.0", | ||
| 3065 | "optional": true, | ||
| 3066 | "os": [ | ||
| 3067 | "freebsd" | ||
| 3068 | ], | ||
| 3069 | "engines": { | ||
| 3070 | "node": ">= 12.0.0" | ||
| 3071 | }, | ||
| 3072 | "funding": { | ||
| 3073 | "type": "opencollective", | ||
| 3074 | "url": "https://opencollective.com/parcel" | ||
| 3075 | } | ||
| 3076 | }, | ||
| 3077 | "node_modules/lightningcss-linux-arm-gnueabihf": { | ||
| 3078 | "version": "1.30.1", | ||
| 3079 | "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.1.tgz", | ||
| 3080 | "integrity": "sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==", | ||
| 3081 | "cpu": [ | ||
| 3082 | "arm" | ||
| 3083 | ], | ||
| 3084 | "license": "MPL-2.0", | ||
| 3085 | "optional": true, | ||
| 3086 | "os": [ | ||
| 3087 | "linux" | ||
| 3088 | ], | ||
| 3089 | "engines": { | ||
| 3090 | "node": ">= 12.0.0" | ||
| 3091 | }, | ||
| 3092 | "funding": { | ||
| 3093 | "type": "opencollective", | ||
| 3094 | "url": "https://opencollective.com/parcel" | ||
| 3095 | } | ||
| 3096 | }, | ||
| 3097 | "node_modules/lightningcss-linux-arm64-gnu": { | ||
| 3098 | "version": "1.30.1", | ||
| 3099 | "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.1.tgz", | ||
| 3100 | "integrity": "sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==", | ||
| 3101 | "cpu": [ | ||
| 3102 | "arm64" | ||
| 3103 | ], | ||
| 3104 | "license": "MPL-2.0", | ||
| 3105 | "optional": true, | ||
| 3106 | "os": [ | ||
| 3107 | "linux" | ||
| 3108 | ], | ||
| 3109 | "engines": { | ||
| 3110 | "node": ">= 12.0.0" | ||
| 3111 | }, | ||
| 3112 | "funding": { | ||
| 3113 | "type": "opencollective", | ||
| 3114 | "url": "https://opencollective.com/parcel" | ||
| 3115 | } | ||
| 3116 | }, | ||
| 3117 | "node_modules/lightningcss-linux-arm64-musl": { | ||
| 3118 | "version": "1.30.1", | ||
| 3119 | "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.1.tgz", | ||
| 3120 | "integrity": "sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==", | ||
| 3121 | "cpu": [ | ||
| 3122 | "arm64" | ||
| 3123 | ], | ||
| 3124 | "license": "MPL-2.0", | ||
| 3125 | "optional": true, | ||
| 3126 | "os": [ | ||
| 3127 | "linux" | ||
| 3128 | ], | ||
| 3129 | "engines": { | ||
| 3130 | "node": ">= 12.0.0" | ||
| 3131 | }, | ||
| 3132 | "funding": { | ||
| 3133 | "type": "opencollective", | ||
| 3134 | "url": "https://opencollective.com/parcel" | ||
| 3135 | } | ||
| 3136 | }, | ||
| 3137 | "node_modules/lightningcss-linux-x64-gnu": { | ||
| 3138 | "version": "1.30.1", | ||
| 3139 | "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.1.tgz", | ||
| 3140 | "integrity": "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==", | ||
| 3141 | "cpu": [ | ||
| 3142 | "x64" | ||
| 3143 | ], | ||
| 3144 | "license": "MPL-2.0", | ||
| 3145 | "optional": true, | ||
| 3146 | "os": [ | ||
| 3147 | "linux" | ||
| 3148 | ], | ||
| 3149 | "engines": { | ||
| 3150 | "node": ">= 12.0.0" | ||
| 3151 | }, | ||
| 3152 | "funding": { | ||
| 3153 | "type": "opencollective", | ||
| 3154 | "url": "https://opencollective.com/parcel" | ||
| 3155 | } | ||
| 3156 | }, | ||
| 3157 | "node_modules/lightningcss-linux-x64-musl": { | ||
| 3158 | "version": "1.30.1", | ||
| 3159 | "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.1.tgz", | ||
| 3160 | "integrity": "sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==", | ||
| 3161 | "cpu": [ | ||
| 3162 | "x64" | ||
| 3163 | ], | ||
| 3164 | "license": "MPL-2.0", | ||
| 3165 | "optional": true, | ||
| 3166 | "os": [ | ||
| 3167 | "linux" | ||
| 3168 | ], | ||
| 3169 | "engines": { | ||
| 3170 | "node": ">= 12.0.0" | ||
| 3171 | }, | ||
| 3172 | "funding": { | ||
| 3173 | "type": "opencollective", | ||
| 3174 | "url": "https://opencollective.com/parcel" | ||
| 3175 | } | ||
| 3176 | }, | ||
| 3177 | "node_modules/lightningcss-win32-arm64-msvc": { | ||
| 3178 | "version": "1.30.1", | ||
| 3179 | "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.1.tgz", | ||
| 3180 | "integrity": "sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==", | ||
| 3181 | "cpu": [ | ||
| 3182 | "arm64" | ||
| 3183 | ], | ||
| 3184 | "license": "MPL-2.0", | ||
| 3185 | "optional": true, | ||
| 3186 | "os": [ | ||
| 3187 | "win32" | ||
| 3188 | ], | ||
| 3189 | "engines": { | ||
| 3190 | "node": ">= 12.0.0" | ||
| 3191 | }, | ||
| 3192 | "funding": { | ||
| 3193 | "type": "opencollective", | ||
| 3194 | "url": "https://opencollective.com/parcel" | ||
| 3195 | } | ||
| 3196 | }, | ||
| 3197 | "node_modules/lightningcss-win32-x64-msvc": { | ||
| 3198 | "version": "1.30.1", | ||
| 3199 | "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.1.tgz", | ||
| 3200 | "integrity": "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==", | ||
| 3201 | "cpu": [ | ||
| 3202 | "x64" | ||
| 3203 | ], | ||
| 3204 | "license": "MPL-2.0", | ||
| 3205 | "optional": true, | ||
| 3206 | "os": [ | ||
| 3207 | "win32" | ||
| 3208 | ], | ||
| 3209 | "engines": { | ||
| 3210 | "node": ">= 12.0.0" | ||
| 3211 | }, | ||
| 3212 | "funding": { | ||
| 3213 | "type": "opencollective", | ||
| 3214 | "url": "https://opencollective.com/parcel" | ||
| 3215 | } | ||
| 3216 | }, | ||
| 2721 | "node_modules/lodash": { | 3217 | "node_modules/lodash": { |
| 2722 | "version": "4.17.21", | 3218 | "version": "4.17.21", |
| 2723 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", | 3219 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", |
| @@ -2765,6 +3261,15 @@ | |||
| 2765 | "lz-string": "bin/bin.js" | 3261 | "lz-string": "bin/bin.js" |
| 2766 | } | 3262 | } |
| 2767 | }, | 3263 | }, |
| 3264 | "node_modules/magic-string": { | ||
| 3265 | "version": "0.30.17", | ||
| 3266 | "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", | ||
| 3267 | "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", | ||
| 3268 | "license": "MIT", | ||
| 3269 | "dependencies": { | ||
| 3270 | "@jridgewell/sourcemap-codec": "^1.5.0" | ||
| 3271 | } | ||
| 3272 | }, | ||
| 2768 | "node_modules/math-intrinsics": { | 3273 | "node_modules/math-intrinsics": { |
| 2769 | "version": "1.1.0", | 3274 | "version": "1.1.0", |
| 2770 | "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", | 3275 | "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", |
| @@ -3399,6 +3904,42 @@ | |||
| 3399 | "node": ">=4" | 3904 | "node": ">=4" |
| 3400 | } | 3905 | } |
| 3401 | }, | 3906 | }, |
| 3907 | "node_modules/minipass": { | ||
| 3908 | "version": "7.1.2", | ||
| 3909 | "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", | ||
| 3910 | "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", | ||
| 3911 | "license": "ISC", | ||
| 3912 | "engines": { | ||
| 3913 | "node": ">=16 || 14 >=14.17" | ||
| 3914 | } | ||
| 3915 | }, | ||
| 3916 | "node_modules/minizlib": { | ||
| 3917 | "version": "3.0.2", | ||
| 3918 | "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.2.tgz", | ||
| 3919 | "integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==", | ||
| 3920 | "license": "MIT", | ||
| 3921 | "dependencies": { | ||
| 3922 | "minipass": "^7.1.2" | ||
| 3923 | }, | ||
| 3924 | "engines": { | ||
| 3925 | "node": ">= 18" | ||
| 3926 | } | ||
| 3927 | }, | ||
| 3928 | "node_modules/mkdirp": { | ||
| 3929 | "version": "3.0.1", | ||
| 3930 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", | ||
| 3931 | "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", | ||
| 3932 | "license": "MIT", | ||
| 3933 | "bin": { | ||
| 3934 | "mkdirp": "dist/cjs/src/bin.js" | ||
| 3935 | }, | ||
| 3936 | "engines": { | ||
| 3937 | "node": ">=10" | ||
| 3938 | }, | ||
| 3939 | "funding": { | ||
| 3940 | "url": "https://github.com/sponsors/isaacs" | ||
| 3941 | } | ||
| 3942 | }, | ||
| 3402 | "node_modules/ms": { | 3943 | "node_modules/ms": { |
| 3403 | "version": "2.1.3", | 3944 | "version": "2.1.3", |
| 3404 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", | 3945 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", |
| @@ -3409,7 +3950,6 @@ | |||
| 3409 | "version": "3.3.11", | 3950 | "version": "3.3.11", |
| 3410 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", | 3951 | "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", |
| 3411 | "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", | 3952 | "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", |
| 3412 | "dev": true, | ||
| 3413 | "funding": [ | 3953 | "funding": [ |
| 3414 | { | 3954 | { |
| 3415 | "type": "github", | 3955 | "type": "github", |
| @@ -3532,7 +4072,6 @@ | |||
| 3532 | "version": "4.0.3", | 4072 | "version": "4.0.3", |
| 3533 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", | 4073 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", |
| 3534 | "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", | 4074 | "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", |
| 3535 | "dev": true, | ||
| 3536 | "license": "MIT", | 4075 | "license": "MIT", |
| 3537 | "engines": { | 4076 | "engines": { |
| 3538 | "node": ">=12" | 4077 | "node": ">=12" |
| @@ -3554,7 +4093,6 @@ | |||
| 3554 | "version": "8.5.6", | 4093 | "version": "8.5.6", |
| 3555 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", | 4094 | "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", |
| 3556 | "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", | 4095 | "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", |
| 3557 | "dev": true, | ||
| 3558 | "funding": [ | 4096 | "funding": [ |
| 3559 | { | 4097 | { |
| 3560 | "type": "opencollective", | 4098 | "type": "opencollective", |
| @@ -3853,7 +4391,6 @@ | |||
| 3853 | "version": "4.46.2", | 4391 | "version": "4.46.2", |
| 3854 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.46.2.tgz", | 4392 | "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.46.2.tgz", |
| 3855 | "integrity": "sha512-WMmLFI+Boh6xbop+OAGo9cQ3OgX9MIg7xOQjn+pTCwOkk+FNDAeAemXkJ3HzDJrVXleLOFVa1ipuc1AmEx1Dwg==", | 4393 | "integrity": "sha512-WMmLFI+Boh6xbop+OAGo9cQ3OgX9MIg7xOQjn+pTCwOkk+FNDAeAemXkJ3HzDJrVXleLOFVa1ipuc1AmEx1Dwg==", |
| 3856 | "dev": true, | ||
| 3857 | "license": "MIT", | 4394 | "license": "MIT", |
| 3858 | "dependencies": { | 4395 | "dependencies": { |
| 3859 | "@types/estree": "1.0.8" | 4396 | "@types/estree": "1.0.8" |
| @@ -4033,7 +4570,6 @@ | |||
| 4033 | "version": "1.2.1", | 4570 | "version": "1.2.1", |
| 4034 | "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", | 4571 | "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", |
| 4035 | "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", | 4572 | "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", |
| 4036 | "dev": true, | ||
| 4037 | "license": "BSD-3-Clause", | 4573 | "license": "BSD-3-Clause", |
| 4038 | "engines": { | 4574 | "engines": { |
| 4039 | "node": ">=0.10.0" | 4575 | "node": ">=0.10.0" |
| @@ -4109,11 +4645,51 @@ | |||
| 4109 | "node": ">=8" | 4645 | "node": ">=8" |
| 4110 | } | 4646 | } |
| 4111 | }, | 4647 | }, |
| 4648 | "node_modules/tailwindcss": { | ||
| 4649 | "version": "4.1.11", | ||
| 4650 | "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.11.tgz", | ||
| 4651 | "integrity": "sha512-2E9TBm6MDD/xKYe+dvJZAmg3yxIEDNRc0jwlNyDg/4Fil2QcSLjFKGVff0lAf1jjeaArlG/M75Ey/EYr/OJtBA==", | ||
| 4652 | "license": "MIT" | ||
| 4653 | }, | ||
| 4654 | "node_modules/tapable": { | ||
| 4655 | "version": "2.2.2", | ||
| 4656 | "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.2.tgz", | ||
| 4657 | "integrity": "sha512-Re10+NauLTMCudc7T5WLFLAwDhQ0JWdrMK+9B2M8zR5hRExKmsRDCBA7/aV/pNJFltmBFO5BAMlQFi/vq3nKOg==", | ||
| 4658 | "license": "MIT", | ||
| 4659 | "engines": { | ||
| 4660 | "node": ">=6" | ||
| 4661 | } | ||
| 4662 | }, | ||
| 4663 | "node_modules/tar": { | ||
| 4664 | "version": "7.4.3", | ||
| 4665 | "resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz", | ||
| 4666 | "integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==", | ||
| 4667 | "license": "ISC", | ||
| 4668 | "dependencies": { | ||
| 4669 | "@isaacs/fs-minipass": "^4.0.0", | ||
| 4670 | "chownr": "^3.0.0", | ||
| 4671 | "minipass": "^7.1.2", | ||
| 4672 | "minizlib": "^3.0.1", | ||
| 4673 | "mkdirp": "^3.0.1", | ||
| 4674 | "yallist": "^5.0.0" | ||
| 4675 | }, | ||
| 4676 | "engines": { | ||
| 4677 | "node": ">=18" | ||
| 4678 | } | ||
| 4679 | }, | ||
| 4680 | "node_modules/tar/node_modules/yallist": { | ||
| 4681 | "version": "5.0.0", | ||
| 4682 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", | ||
| 4683 | "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", | ||
| 4684 | "license": "BlueOak-1.0.0", | ||
| 4685 | "engines": { | ||
| 4686 | "node": ">=18" | ||
| 4687 | } | ||
| 4688 | }, | ||
| 4112 | "node_modules/tinyglobby": { | 4689 | "node_modules/tinyglobby": { |
| 4113 | "version": "0.2.14", | 4690 | "version": "0.2.14", |
| 4114 | "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", | 4691 | "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", |
| 4115 | "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", | 4692 | "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", |
| 4116 | "dev": true, | ||
| 4117 | "license": "MIT", | 4693 | "license": "MIT", |
| 4118 | "dependencies": { | 4694 | "dependencies": { |
| 4119 | "fdir": "^6.4.4", | 4695 | "fdir": "^6.4.4", |
| @@ -4163,7 +4739,7 @@ | |||
| 4163 | "version": "6.21.0", | 4739 | "version": "6.21.0", |
| 4164 | "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", | 4740 | "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", |
| 4165 | "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", | 4741 | "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", |
| 4166 | "dev": true, | 4742 | "devOptional": true, |
| 4167 | "license": "MIT" | 4743 | "license": "MIT" |
| 4168 | }, | 4744 | }, |
| 4169 | "node_modules/unified": { | 4745 | "node_modules/unified": { |
| @@ -4316,7 +4892,6 @@ | |||
| 4316 | "version": "7.1.1", | 4892 | "version": "7.1.1", |
| 4317 | "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.1.tgz", | 4893 | "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.1.tgz", |
| 4318 | "integrity": "sha512-yJ+Mp7OyV+4S+afWo+QyoL9jFWD11QFH0i5i7JypnfTcA1rmgxCbiA8WwAICDEtZ1Z1hzrVhN8R8rGTqkTY8ZQ==", | 4894 | "integrity": "sha512-yJ+Mp7OyV+4S+afWo+QyoL9jFWD11QFH0i5i7JypnfTcA1rmgxCbiA8WwAICDEtZ1Z1hzrVhN8R8rGTqkTY8ZQ==", |
| 4319 | "dev": true, | ||
| 4320 | "license": "MIT", | 4895 | "license": "MIT", |
| 4321 | "dependencies": { | 4896 | "dependencies": { |
| 4322 | "esbuild": "^0.25.0", | 4897 | "esbuild": "^0.25.0", |
diff --git a/frontend/package.json b/frontend/package.json index f9cab6b..e7b16f7 100644 --- a/frontend/package.json +++ b/frontend/package.json | |||
| @@ -1,9 +1,11 @@ | |||
| 1 | { | 1 | { |
| 2 | "name": "frontend", | 2 | "name": "frontend", |
| 3 | "version": "0.1.0", | 3 | "version": "0.1.0", |
| 4 | "type": "module", | ||
| 4 | "private": true, | 5 | "private": true, |
| 5 | "dependencies": { | 6 | "dependencies": { |
| 6 | "@nekz/sdp": "^0.9.0", | 7 | "@nekz/sdp": "^0.9.0", |
| 8 | "@tailwindcss/vite": "^4.1.11", | ||
| 7 | "@testing-library/jest-dom": "^5.17.0", | 9 | "@testing-library/jest-dom": "^5.17.0", |
| 8 | "@testing-library/react": "^13.4.0", | 10 | "@testing-library/react": "^13.4.0", |
| 9 | "@testing-library/user-event": "^13.5.0", | 11 | "@testing-library/user-event": "^13.5.0", |
| @@ -16,6 +18,7 @@ | |||
| 16 | "react-helmet": "^6.1.0", | 18 | "react-helmet": "^6.1.0", |
| 17 | "react-markdown": "^9.0.1", | 19 | "react-markdown": "^9.0.1", |
| 18 | "react-router-dom": "^6.26.1", | 20 | "react-router-dom": "^6.26.1", |
| 21 | "tailwindcss": "^4.1.11", | ||
| 19 | "typescript": "^4.9.5", | 22 | "typescript": "^4.9.5", |
| 20 | "web-vitals": "^2.1.4" | 23 | "web-vitals": "^2.1.4" |
| 21 | }, | 24 | }, |
diff --git a/frontend/src/App.css b/frontend/src/App.css index 14a9972..a4c058b 100644 --- a/frontend/src/App.css +++ b/frontend/src/App.css | |||
| @@ -1,3 +1,54 @@ | |||
| 1 | @import url('https://fonts.googleapis.com/css2?family=Barlow+Condensed:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&family=Montserrat+Alternates:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap'); | ||
| 2 | @import "tailwindcss"; | ||
| 3 | |||
| 4 | @theme { | ||
| 5 | --color-rosewater: #f2d5cf; | ||
| 6 | --color-flamingo: #eebebe; | ||
| 7 | --color-pink: #f4b8e4; | ||
| 8 | --color-mauve: #ca9ee6; | ||
| 9 | --color-red: #e78284; | ||
| 10 | --color-maroon: #ea999c; | ||
| 11 | --color-peach: #ef9f76; | ||
| 12 | --color-yellow: #e5c890; | ||
| 13 | --color-green: #a6d189; | ||
| 14 | --color-teal: #81c8be; | ||
| 15 | --color-sky: #99d1db; | ||
| 16 | --color-sapphire: #85c1dc; | ||
| 17 | --color-blue: #8caaee; | ||
| 18 | --color-lavender: #babbf1; | ||
| 19 | --color-text: #c6d0f5; | ||
| 20 | --color-subtext1: #b5bfe2; | ||
| 21 | --color-subtext0: #a5adce; | ||
| 22 | --color-overlay2: #949cbb; | ||
| 23 | --color-overlay1: #838ba7; | ||
| 24 | --color-overlay0: #737994; | ||
| 25 | --color-surface2: #626880; | ||
| 26 | --color-surface1: #51576d; | ||
| 27 | --color-surface0: #414559; | ||
| 28 | --color-base: #303446; | ||
| 29 | --color-mantle: #292c3c; | ||
| 30 | --color-crust: #232634; | ||
| 31 | |||
| 32 | --color-primary: var(--color-mauve); | ||
| 33 | --color-secondary: var(--color-blue); | ||
| 34 | --color-accent: var(--color-peach); | ||
| 35 | --color-background: var(--color-base); | ||
| 36 | --color-surface: var(--color-surface0); | ||
| 37 | --color-muted: var(--color-overlay0); | ||
| 38 | --color-border: var(--color-surface2); | ||
| 39 | --color-input: var(--color-surface1); | ||
| 40 | --color-foreground: var(--color-text); | ||
| 41 | --color-success: var(--color-green); | ||
| 42 | --color-warning: var(--color-yellow); | ||
| 43 | --color-error: var(--color-red); | ||
| 44 | --color-info: var(--color-blue); | ||
| 45 | |||
| 46 | --font-barlow-condensed-regular: 'BarlowCondensed-Regular'; | ||
| 47 | --font-barlow-condensed-bold: 'BarlowCondensed-Bold'; | ||
| 48 | --font-barlow-semicondensed-regular: 'BarlowSemiCondensed-Regular'; | ||
| 49 | --font-barlow-semicondensed-semibold: 'BarlowSemiCondensed-SemiBold'; | ||
| 50 | } | ||
| 51 | |||
| 1 | main { | 52 | main { |
| 2 | overflow: auto; | 53 | overflow: auto; |
| 3 | overflow-x: hidden; | 54 | overflow-x: hidden; |
| @@ -10,33 +61,32 @@ main { | |||
| 10 | padding-right: 30px; | 61 | padding-right: 30px; |
| 11 | 62 | ||
| 12 | font-size: 40px; | 63 | font-size: 40px; |
| 13 | font-family: BarlowSemiCondensed-Regular; | 64 | font-family: var(--font-barlow-semicondensed-regular); |
| 14 | color: #cdcfdf; | 65 | color: var(--color-text); |
| 15 | 66 | ||
| 16 | } | 67 | } |
| 17 | 68 | ||
| 18 | a { | 69 | a { |
| 19 | color: inherit; | 70 | color: inherit; |
| 20 | width: fit-content; | ||
| 21 | } | 71 | } |
| 22 | 72 | ||
| 23 | body { | 73 | body { |
| 24 | overflow: hidden; | 74 | overflow: hidden; |
| 25 | background-color: #141520; | 75 | background-color: var(--color-crust); |
| 26 | margin: 0; | 76 | margin: 0; |
| 27 | } | 77 | } |
| 28 | 78 | ||
| 29 | .loader { | 79 | .loader { |
| 30 | animation: loader 1.2s ease infinite; | 80 | animation: loader 1.2s ease infinite; |
| 31 | background-size: 400% 300%; | 81 | background-size: 400% 300%; |
| 32 | background-image: linear-gradient(-90deg, #202232 0%, #202232 25%, #2a2c41 50%, #202232 75%, #202232 100%); | 82 | background-image: linear-gradient(-90deg, var(--color-mantle) 0%, var(--color-mantle) 25%, var(--color-surface1) 50%, var(--color-mantle) 75%, var(--color-mantle) 100%); |
| 33 | user-select: none; | 83 | user-select: none; |
| 34 | } | 84 | } |
| 35 | 85 | ||
| 36 | .loader-text { | 86 | .loader-text { |
| 37 | animation: loader 1.2s ease infinite; | 87 | animation: loader 1.2s ease infinite; |
| 38 | background-size: 400% 300%; | 88 | background-size: 400% 300%; |
| 39 | background-image: linear-gradient(-90deg, #202232 0%, #202232 25%, #2a2c41 50%, #202232 75%, #202232 100%); | 89 | background-image: linear-gradient(-90deg, var(--color-mantle) 0%, var(--color-mantle) 25%, var(--color-surface1) 50%, var(--color-mantle) 75%, var(--color-mantle) 100%); |
| 40 | user-select: none; | 90 | user-select: none; |
| 41 | color: #00000000; | 91 | color: #00000000; |
| 42 | border-radius: 1000px; | 92 | border-radius: 1000px; |
| @@ -76,6 +126,173 @@ body { | |||
| 76 | } | 126 | } |
| 77 | } | 127 | } |
| 78 | 128 | ||
| 129 | /* Custom Tailwind utilities for Catppuccin Frappe theme */ | ||
| 130 | @layer utilities { | ||
| 131 | .bg-primary { | ||
| 132 | background-color: var(--color-primary); | ||
| 133 | } | ||
| 134 | |||
| 135 | .bg-secondary { | ||
| 136 | background-color: var(--color-secondary); | ||
| 137 | } | ||
| 138 | |||
| 139 | .bg-accent { | ||
| 140 | background-color: var(--color-accent); | ||
| 141 | } | ||
| 142 | |||
| 143 | .bg-background { | ||
| 144 | background-color: var(--color-background); | ||
| 145 | } | ||
| 146 | |||
| 147 | .bg-surface { | ||
| 148 | background-color: var(--color-surface); | ||
| 149 | } | ||
| 150 | |||
| 151 | .bg-muted { | ||
| 152 | background-color: var(--color-muted); | ||
| 153 | } | ||
| 154 | |||
| 155 | .text-primary { | ||
| 156 | color: var(--color-primary); | ||
| 157 | } | ||
| 158 | |||
| 159 | .text-secondary { | ||
| 160 | color: var(--color-secondary); | ||
| 161 | } | ||
| 162 | |||
| 163 | .text-accent { | ||
| 164 | color: var(--color-accent); | ||
| 165 | } | ||
| 166 | |||
| 167 | .text-foreground { | ||
| 168 | color: var(--color-foreground); | ||
| 169 | } | ||
| 170 | |||
| 171 | .text-muted { | ||
| 172 | color: var(--color-muted); | ||
| 173 | } | ||
| 174 | |||
| 175 | .border-primary { | ||
| 176 | border-color: var(--color-primary); | ||
| 177 | } | ||
| 178 | |||
| 179 | .border-secondary { | ||
| 180 | border-color: var(--color-secondary); | ||
| 181 | } | ||
| 182 | |||
| 183 | .border-muted { | ||
| 184 | border-color: var(--color-border); | ||
| 185 | } | ||
| 186 | |||
| 187 | .hover\:bg-primary:hover { | ||
| 188 | background-color: var(--color-primary); | ||
| 189 | } | ||
| 190 | |||
| 191 | .hover\:bg-secondary:hover { | ||
| 192 | background-color: var(--color-secondary); | ||
| 193 | } | ||
| 194 | |||
| 195 | .hover\:bg-surface:hover { | ||
| 196 | background-color: var(--color-surface); | ||
| 197 | } | ||
| 198 | |||
| 199 | .hover\:text-primary:hover { | ||
| 200 | color: var(--color-primary); | ||
| 201 | } | ||
| 202 | |||
| 203 | .focus\:ring-primary:focus { | ||
| 204 | --tw-ring-color: var(--color-primary); | ||
| 205 | } | ||
| 206 | |||
| 207 | .triangle { | ||
| 208 | width: 0; | ||
| 209 | height: 0; | ||
| 210 | border-left: 5px solid transparent; | ||
| 211 | border-right: 5px solid transparent; | ||
| 212 | border-bottom: 8px solid var(--color-foreground); | ||
| 213 | display: inline-block; | ||
| 214 | } | ||
| 215 | |||
| 216 | .sidebar-button-selected { | ||
| 217 | background-color: var(--color-primary) !important; | ||
| 218 | color: var(--color-background) !important; | ||
| 219 | } | ||
| 220 | |||
| 221 | .sidebar-button-deselected { | ||
| 222 | background-color: var(--color-surface) !important; | ||
| 223 | color: var(--color-foreground) !important; | ||
| 224 | } | ||
| 225 | |||
| 226 | .profileboard-record { | ||
| 227 | background-color: var(--color-surface); | ||
| 228 | border: 1px solid var(--color-border); | ||
| 229 | border-radius: 0.5rem; | ||
| 230 | padding: 0.75rem; | ||
| 231 | margin-bottom: 0.5rem; | ||
| 232 | transition: all 0.2s ease; | ||
| 233 | } | ||
| 234 | |||
| 235 | .profileboard-record:hover { | ||
| 236 | background-color: var(--color-surface1); | ||
| 237 | } | ||
| 238 | |||
| 239 | .difficulty-rating { | ||
| 240 | width: 20px; | ||
| 241 | height: 20px; | ||
| 242 | background-color: var(--color-muted); | ||
| 243 | border-radius: 50%; | ||
| 244 | margin: 0 2px; | ||
| 245 | display: inline-block; | ||
| 246 | } | ||
| 247 | |||
| 248 | .nav-button { | ||
| 249 | background-color: var(--color-surface); | ||
| 250 | color: var(--color-foreground); | ||
| 251 | border: 1px solid var(--color-border); | ||
| 252 | border-radius: 0.5rem; | ||
| 253 | padding: 0.5rem 1rem; | ||
| 254 | transition: all 0.2s ease; | ||
| 255 | display: inline-flex; | ||
| 256 | align-items: center; | ||
| 257 | gap: 0.5rem; | ||
| 258 | text-decoration: none; | ||
| 259 | } | ||
| 260 | |||
| 261 | .nav-button:hover { | ||
| 262 | background-color: var(--color-surface1); | ||
| 263 | } | ||
| 264 | |||
| 265 | .record { | ||
| 266 | background-color: var(--color-surface); | ||
| 267 | border: 1px solid var(--color-border); | ||
| 268 | border-radius: 0.5rem; | ||
| 269 | padding: 0.5rem; | ||
| 270 | margin: 0.25rem; | ||
| 271 | cursor: pointer; | ||
| 272 | transition: all 0.2s ease; | ||
| 273 | } | ||
| 274 | |||
| 275 | .record:hover { | ||
| 276 | background-color: var(--color-surface1); | ||
| 277 | } | ||
| 278 | |||
| 279 | .portal-count { | ||
| 280 | font-size: 3rem; | ||
| 281 | font-weight: bold; | ||
| 282 | color: var(--color-primary); | ||
| 283 | } | ||
| 284 | |||
| 285 | .titles { | ||
| 286 | background-color: var(--color-accent); | ||
| 287 | color: var(--color-background); | ||
| 288 | padding: 0.25rem 0.5rem; | ||
| 289 | border-radius: 1rem; | ||
| 290 | font-size: 0.875rem; | ||
| 291 | margin-right: 0.5rem; | ||
| 292 | display: inline-block; | ||
| 293 | } | ||
| 294 | } | ||
| 295 | |||
| 79 | @font-face { | 296 | @font-face { |
| 80 | font-family: 'BarlowCondensed-Bold'; | 297 | font-family: 'BarlowCondensed-Bold'; |
| 81 | src: local('BarlowCondensed-Bold'), url(./fonts/BarlowCondensed-Bold.ttf) format('truetype'); | 298 | src: local('BarlowCondensed-Bold'), url(./fonts/BarlowCondensed-Bold.ttf) format('truetype'); |
diff --git a/frontend/src/api/Api.ts b/frontend/src/api/Api.ts index 0e1658c..b782d17 100644 --- a/frontend/src/api/Api.ts +++ b/frontend/src/api/Api.ts | |||
| @@ -91,7 +91,7 @@ export const API = { | |||
| 91 | delete_map_summary(token, map_id, route_id), | 91 | delete_map_summary(token, map_id, route_id), |
| 92 | }; | 92 | }; |
| 93 | 93 | ||
| 94 | const BASE_API_URL: string = "/api/v1/"; | 94 | const BASE_API_URL: string = "https://lp.portal2.sr/api/v1/" |
| 95 | 95 | ||
| 96 | export function url(path: string): string { | 96 | export function url(path: string): string { |
| 97 | return BASE_API_URL + path; | 97 | return BASE_API_URL + path; |
diff --git a/frontend/src/components/ConfirmDialog.tsx b/frontend/src/components/ConfirmDialog.tsx index c89d9ea..8f2ce7a 100644 --- a/frontend/src/components/ConfirmDialog.tsx +++ b/frontend/src/components/ConfirmDialog.tsx | |||
| @@ -1,7 +1,5 @@ | |||
| 1 | import React from "react"; | 1 | import React from "react"; |
| 2 | 2 | ||
| 3 | import "@css/Dialog.css"; | ||
| 4 | |||
| 5 | interface ConfirmDialogProps { | 3 | interface ConfirmDialogProps { |
| 6 | title: string; | 4 | title: string; |
| 7 | subtitle: string; | 5 | subtitle: string; |
| @@ -16,17 +14,17 @@ const ConfirmDialog: React.FC<ConfirmDialogProps> = ({ | |||
| 16 | onCancel, | 14 | onCancel, |
| 17 | }) => { | 15 | }) => { |
| 18 | return ( | 16 | return ( |
| 19 | <div className="dimmer"> | 17 | <div className="fixed w-[200%] h-full bg-black bg-opacity-50 z-[4]"> |
| 20 | <div className="dialog"> | 18 | <div className="fixed z-[4] top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 bg-surface rounded-3xl overflow-hidden min-w-[350px] border border-border animate-[dialog_in_0.2s_cubic-bezier(0.075,0.82,0.165,1.1)] text-foreground font-[--font-barlow-semicondensed-regular]"> |
| 21 | <div className="dialog-element dialog-header"> | 19 | <div className="p-2 text-2xl bg-mantle"> |
| 22 | <span>{title}</span> | 20 | <span>{title}</span> |
| 23 | </div> | 21 | </div> |
| 24 | <div className="dialog-element dialog-description"> | 22 | <div className="p-2"> |
| 25 | <span>{subtitle}</span> | 23 | <span>{subtitle}</span> |
| 26 | </div> | 24 | </div> |
| 27 | <div className="dialog-element dialog-btns-container"> | 25 | <div className="p-2 flex justify-end border-t-2 border-border bg-mantle"> |
| 28 | <button onClick={onCancel}>Cancel</button> | 26 | <button className="mr-2 px-4 py-2 bg-muted text-foreground rounded hover:bg-overlay1 transition-colors" onClick={onCancel}>Cancel</button> |
| 29 | <button onClick={onConfirm}>Confirm</button> | 27 | <button className="px-4 py-2 bg-primary text-background rounded hover:bg-mauve transition-colors" onClick={onConfirm}>Confirm</button> |
| 30 | </div> | 28 | </div> |
| 31 | </div> | 29 | </div> |
| 32 | </div> | 30 | </div> |
diff --git a/frontend/src/components/GameCategory.tsx b/frontend/src/components/GameCategory.tsx index 2bb6d42..b18c9d9 100644 --- a/frontend/src/components/GameCategory.tsx +++ b/frontend/src/components/GameCategory.tsx | |||
| @@ -2,7 +2,6 @@ import React from "react"; | |||
| 2 | import { Link } from "react-router-dom"; | 2 | import { Link } from "react-router-dom"; |
| 3 | 3 | ||
| 4 | import { Game, GameCategoryPortals } from "@customTypes/Game"; | 4 | import { Game, GameCategoryPortals } from "@customTypes/Game"; |
| 5 | import "@css/Games.css"; | ||
| 6 | 5 | ||
| 7 | interface GameCategoryProps { | 6 | interface GameCategoryProps { |
| 8 | game: Game; | 7 | game: Game; |
| @@ -12,18 +11,12 @@ interface GameCategoryProps { | |||
| 12 | const GameCategory: React.FC<GameCategoryProps> = ({ cat, game }) => { | 11 | const GameCategory: React.FC<GameCategoryProps> = ({ cat, game }) => { |
| 13 | return ( | 12 | return ( |
| 14 | <Link | 13 | <Link |
| 15 | className="games-page-item-body-item" | 14 | className="bg-surface text-center w-full h-[100px] rounded-3xl text-foreground m-3 hover:bg-surface1 transition-colors flex flex-col justify-between p-4" |
| 16 | to={"/games/" + game.id + "?cat=" + cat.category.id} | 15 | to={"/games/" + game.id + "?cat=" + cat.category.id} |
| 17 | > | 16 | > |
| 18 | <div> | 17 | <p className="text-3xl font-semibold">{cat.category.name}</p> |
| 19 | <span className="games-page-item-body-item-title"> | 18 | <br /> |
| 20 | {cat.category.name} | 19 | <p className="font-bold text-4xl">{cat.portal_count}</p> |
| 21 | </span> | ||
| 22 | <br /> | ||
| 23 | <span className="games-page-item-body-item-num"> | ||
| 24 | {cat.portal_count} | ||
| 25 | </span> | ||
| 26 | </div> | ||
| 27 | </Link> | 20 | </Link> |
| 28 | ); | 21 | ); |
| 29 | }; | 22 | }; |
diff --git a/frontend/src/components/GameEntry.tsx b/frontend/src/components/GameEntry.tsx index 04c3483..f8fd179 100644 --- a/frontend/src/components/GameEntry.tsx +++ b/frontend/src/components/GameEntry.tsx | |||
| @@ -2,7 +2,6 @@ import React from "react"; | |||
| 2 | import { Link } from "react-router-dom"; | 2 | import { Link } from "react-router-dom"; |
| 3 | 3 | ||
| 4 | import { Game, GameCategoryPortals } from "@customTypes/Game"; | 4 | import { Game, GameCategoryPortals } from "@customTypes/Game"; |
| 5 | import "@css/Games.css"; | ||
| 6 | 5 | ||
| 7 | import GameCategory from "@components/GameCategory"; | 6 | import GameCategory from "@components/GameCategory"; |
| 8 | 7 | ||
| @@ -18,23 +17,25 @@ const GameEntry: React.FC<GameEntryProps> = ({ game }) => { | |||
| 18 | }, [game.category_portals]); | 17 | }, [game.category_portals]); |
| 19 | 18 | ||
| 20 | return ( | 19 | return ( |
| 21 | <Link to={"/games/" + game.id}> | 20 | <Link to={"/games/" + game.id} className="w-full"> |
| 22 | <div className="games-page-item"> | 21 | <div className="w-full h-64 bg-mantle rounded-3xl overflow-hidden my-6"> |
| 23 | <div className="games-page-item-header"> | 22 | <div className="w-full h-1/2 bg-cover overflow-hidden relative"> |
| 24 | <div | 23 | <div |
| 25 | style={{ backgroundImage: `url(${game.image})` }} | 24 | style={{ backgroundImage: `url(${game.image})` }} |
| 26 | className="games-page-item-header-img" | 25 | className="w-full h-full backdrop-blur-sm blur-sm bg-cover" |
| 27 | ></div> | 26 | ></div> |
| 28 | <span> | 27 | <span className="absolute inset-0 flex justify-center items-center"> |
| 29 | <b>{game.name}</b> | 28 | <b className="text-[56px] font-[--font-barlow-condensed-bold] text-white">{game.name}</b> |
| 30 | </span> | 29 | </span> |
| 31 | </div> | 30 | </div> |
| 32 | <div id={game.id as any as string} className="games-page-item-body"> | 31 | <div className="flex justify-center items-center h-1/2"> |
| 33 | {catInfo.map((cat, index) => { | 32 | <div className="flex flex-row justify-between w-full"> |
| 34 | return ( | 33 | {catInfo.map((cat, index) => { |
| 35 | <GameCategory cat={cat} game={game} key={index}></GameCategory> | 34 | return ( |
| 36 | ); | 35 | <GameCategory key={index} cat={cat} game={game} /> |
| 37 | })} | 36 | ); |
| 37 | })} | ||
| 38 | </div> | ||
| 38 | </div> | 39 | </div> |
| 39 | </div> | 40 | </div> |
| 40 | </Link> | 41 | </Link> |
diff --git a/frontend/src/components/Leaderboards.tsx b/frontend/src/components/Leaderboards.tsx index b388aba..99481a2 100644 --- a/frontend/src/components/Leaderboards.tsx +++ b/frontend/src/components/Leaderboards.tsx | |||
| @@ -36,7 +36,7 @@ const Leaderboards: React.FC<LeaderboardsProps> = ({ mapID }) => { | |||
| 36 | return ( | 36 | return ( |
| 37 | <section id="section6" className="summary2"> | 37 | <section id="section6" className="summary2"> |
| 38 | <h1 style={{ textAlign: "center" }}> | 38 | <h1 style={{ textAlign: "center" }}> |
| 39 | Map is not available for competitive boards. | 39 | Loading... |
| 40 | </h1> | 40 | </h1> |
| 41 | </section> | 41 | </section> |
| 42 | ); | 42 | ); |
| @@ -195,6 +195,7 @@ const Leaderboards: React.FC<LeaderboardsProps> = ({ mapID }) => { | |||
| 195 | filter: | 195 | filter: |
| 196 | "hue-rotate(160deg) contrast(60%) saturate(1000%)", | 196 | "hue-rotate(160deg) contrast(60%) saturate(1000%)", |
| 197 | }} | 197 | }} |
| 198 | className="w-6 h-6 mx-4" | ||
| 198 | /> | 199 | /> |
| 199 | </button> | 200 | </button> |
| 200 | <button | 201 | <button |
| @@ -209,6 +210,7 @@ const Leaderboards: React.FC<LeaderboardsProps> = ({ mapID }) => { | |||
| 209 | filter: | 210 | filter: |
| 210 | "hue-rotate(300deg) contrast(60%) saturate(1000%)", | 211 | "hue-rotate(300deg) contrast(60%) saturate(1000%)", |
| 211 | }} | 212 | }} |
| 213 | className="w-6 h-6" | ||
| 212 | /> | 214 | /> |
| 213 | </button> | 215 | </button> |
| 214 | </span> | 216 | </span> |
| @@ -227,7 +229,7 @@ const Leaderboards: React.FC<LeaderboardsProps> = ({ mapID }) => { | |||
| 227 | (window.location.href = `/api/v1/demos?uuid=${r.demo_id}`) | 229 | (window.location.href = `/api/v1/demos?uuid=${r.demo_id}`) |
| 228 | } | 230 | } |
| 229 | > | 231 | > |
| 230 | <img src={DownloadIcon} alt="download" /> | 232 | <img src={DownloadIcon} alt="download" className="w-6 h-6 mr-4" /> |
| 231 | </button> | 233 | </button> |
| 232 | </span> | 234 | </span> |
| 233 | ) | 235 | ) |
diff --git a/frontend/src/components/Login.tsx b/frontend/src/components/Login.tsx index 1858c48..ba85aeb 100644 --- a/frontend/src/components/Login.tsx +++ b/frontend/src/components/Login.tsx | |||
| @@ -1,18 +1,18 @@ | |||
| 1 | import React from "react"; | 1 | import React from "react"; |
| 2 | import { Link, useNavigate } from "react-router-dom"; | 2 | import { Link, useNavigate } from "react-router-dom"; |
| 3 | 3 | ||
| 4 | import { ExitIcon, UserIcon, LoginIcon } from "@images/Images"; | 4 | import { ExitIcon, UserIcon, LoginIcon } from "../images/Images"; |
| 5 | import { UserProfile } from "@customTypes/Profile"; | 5 | import { UserProfile } from "@customTypes/Profile"; |
| 6 | import { API } from "@api/Api"; | 6 | import { API } from "@api/Api"; |
| 7 | import "@css/Login.css"; | ||
| 8 | 7 | ||
| 9 | interface LoginProps { | 8 | interface LoginProps { |
| 10 | setToken: React.Dispatch<React.SetStateAction<string | undefined>>; | 9 | setToken: React.Dispatch<React.SetStateAction<string | undefined>>; |
| 11 | profile?: UserProfile; | 10 | profile?: UserProfile; |
| 12 | setProfile: React.Dispatch<React.SetStateAction<UserProfile | undefined>>; | 11 | setProfile: React.Dispatch<React.SetStateAction<UserProfile | undefined>>; |
| 12 | isOpen: boolean; | ||
| 13 | } | 13 | } |
| 14 | 14 | ||
| 15 | const Login: React.FC<LoginProps> = ({ setToken, profile, setProfile }) => { | 15 | const Login: React.FC<LoginProps> = ({ setToken, profile, setProfile, isOpen }) => { |
| 16 | const navigate = useNavigate(); | 16 | const navigate = useNavigate(); |
| 17 | 17 | ||
| 18 | const _login = () => { | 18 | const _login = () => { |
| @@ -32,16 +32,16 @@ const Login: React.FC<LoginProps> = ({ setToken, profile, setProfile }) => { | |||
| 32 | <> | 32 | <> |
| 33 | {profile.profile ? ( | 33 | {profile.profile ? ( |
| 34 | <> | 34 | <> |
| 35 | <Link to="/profile" tabIndex={-1} className="login"> | 35 | <Link to="/profile" tabIndex={-1} className="grid grid-cols-[50px_auto_200px]"> |
| 36 | <button className="sidebar-button"> | 36 | <button className="grid grid-cols-[50px_auto] place-items-start text-left bg-inherit cursor-pointer border-none w-[310px] h-10 rounded-[20px] py-[0.3em] px-0 pl-[11px] transition-all duration-300"> |
| 37 | <img | 37 | <img |
| 38 | className="avatar-img" | 38 | className="rounded-[50px]" |
| 39 | src={profile.avatar_link} | 39 | src={profile.avatar_link} |
| 40 | alt="" | 40 | alt="" |
| 41 | /> | 41 | /> |
| 42 | <span>{profile.user_name}</span> | 42 | <span className="font-[--font-barlow-semicondensed-regular] text-lg text-foreground h-8 leading-7 transition-opacity duration-100 max-w-[22ch] overflow-hidden">{profile.user_name}</span> |
| 43 | </button> | 43 | </button> |
| 44 | <button className="logout-button" onClick={_logout}> | 44 | <button className="relative left-[210px] w-[50px] !pl-[10px] !bg-transparent" onClick={_logout}> |
| 45 | <img src={ExitIcon} alt="" /> | 45 | <img src={ExitIcon} alt="" /> |
| 46 | <span /> | 46 | <span /> |
| 47 | </button> | 47 | </button> |
| @@ -49,16 +49,16 @@ const Login: React.FC<LoginProps> = ({ setToken, profile, setProfile }) => { | |||
| 49 | </> | 49 | </> |
| 50 | ) : ( | 50 | ) : ( |
| 51 | <> | 51 | <> |
| 52 | <Link to="/" tabIndex={-1} className="login"> | 52 | <Link to="/" tabIndex={-1} className="grid grid-cols-[50px_auto_200px]"> |
| 53 | <button className="sidebar-button"> | 53 | <button className="grid grid-cols-[50px_auto] place-items-start text-left bg-inherit cursor-pointer border-none w-[310px] h-10 rounded-[20px] py-[0.3em] px-0 pl-[11px] transition-all duration-300"> |
| 54 | <img | 54 | <img |
| 55 | className="avatar-img" | 55 | className="rounded-[50px]" |
| 56 | src={profile.avatar_link} | 56 | src={profile.avatar_link} |
| 57 | alt="" | 57 | alt="" |
| 58 | /> | 58 | /> |
| 59 | <span>Loading Profile...</span> | 59 | <span className="font-[--font-barlow-semicondensed-regular] text-lg text-foreground h-8 leading-7 transition-opacity duration-100 max-w-[22ch] overflow-hidden">Loading Profile...</span> |
| 60 | </button> | 60 | </button> |
| 61 | <button disabled className="logout-button" onClick={_logout}> | 61 | <button disabled className="relative left-[210px] w-[50px] !pl-[10px] !bg-transparent hidden" onClick={_logout}> |
| 62 | <img src={ExitIcon} alt="" /> | 62 | <img src={ExitIcon} alt="" /> |
| 63 | <span /> | 63 | <span /> |
| 64 | </button> | 64 | </button> |
| @@ -67,11 +67,28 @@ const Login: React.FC<LoginProps> = ({ setToken, profile, setProfile }) => { | |||
| 67 | )} | 67 | )} |
| 68 | </> | 68 | </> |
| 69 | ) : ( | 69 | ) : ( |
| 70 | <Link to="/api/v1/login" tabIndex={-1} className="login"> | 70 | <Link to="/api/v1/login" tabIndex={-1}> |
| 71 | <button className="sidebar-button" onClick={_login}> | 71 | <button |
| 72 | <img className="avatar-img" src={UserIcon} alt="" /> | 72 | className={`${ |
| 73 | <span> | 73 | isOpen |
| 74 | <img src={LoginIcon} alt="Sign in through Steam" /> | 74 | ? "grid grid-cols-[50px_auto] place-items-start pl-[11px]" |
| 75 | : "flex items-center justify-center" | ||
| 76 | } text-left bg-inherit cursor-pointer border-none w-[310px] h-16 rounded-[20px] py-[0.3em] px-0 transition-all duration-300 ${isOpen ? "text-white" : "text-gray-400"}`} | ||
| 77 | onClick={_login} | ||
| 78 | > | ||
| 79 | <span className={`font-[--font-barlow-semicondensed-regular] text-lg h-12 leading-7 transition-opacity duration-100 ${isOpen ? " overflow-hidden" : ""}`}> | ||
| 80 | {isOpen ? ( | ||
| 81 | <div className="bg-neutral-800 p-2 rounded-lg w-64 flex flex-row items-center justifyt-start gap-2 font-semibold"> | ||
| 82 | <LoginIcon /> | ||
| 83 | <span> | ||
| 84 | Login with Steam | ||
| 85 | </span> | ||
| 86 | </div> | ||
| 87 | ) : ( | ||
| 88 | <div className="bg-neutral-800 p-2 rounded-lg w-"> | ||
| 89 | <LoginIcon /> | ||
| 90 | </div> | ||
| 91 | )} | ||
| 75 | </span> | 92 | </span> |
| 76 | </button> | 93 | </button> |
| 77 | </Link> | 94 | </Link> |
diff --git a/frontend/src/components/ModMenu.tsx b/frontend/src/components/ModMenu.tsx index 618d1a7..a0d7eb7 100644 --- a/frontend/src/components/ModMenu.tsx +++ b/frontend/src/components/ModMenu.tsx | |||
| @@ -5,7 +5,6 @@ import { useNavigate } from "react-router-dom"; | |||
| 5 | import { MapSummary } from "@customTypes/Map"; | 5 | import { MapSummary } from "@customTypes/Map"; |
| 6 | import { ModMenuContent } from "@customTypes/Content"; | 6 | import { ModMenuContent } from "@customTypes/Content"; |
| 7 | import { API } from "@api/Api"; | 7 | import { API } from "@api/Api"; |
| 8 | import "@css/ModMenu.css"; | ||
| 9 | import useConfirm from "@hooks/UseConfirm"; | 8 | import useConfirm from "@hooks/UseConfirm"; |
| 10 | 9 | ||
| 11 | interface ModMenuProps { | 10 | interface ModMenuProps { |
diff --git a/frontend/src/components/Sidebar.tsx b/frontend/src/components/Sidebar.tsx index b55d56b..88a5297 100644 --- a/frontend/src/components/Sidebar.tsx +++ b/frontend/src/components/Sidebar.tsx | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | import React, { useCallback } from "react"; | 1 | import React, { useCallback, useRef } from "react"; |
| 2 | import { Link, useLocation } from "react-router-dom"; | 2 | import { Link, useLocation } from "react-router-dom"; |
| 3 | 3 | ||
| 4 | import { | 4 | import { |
| @@ -10,12 +10,11 @@ import { | |||
| 10 | PortalIcon, | 10 | PortalIcon, |
| 11 | SearchIcon, | 11 | SearchIcon, |
| 12 | UploadIcon, | 12 | UploadIcon, |
| 13 | } from "@images/Images"; | 13 | } from "../images/Images"; |
| 14 | import Login from "@components/Login"; | 14 | import Login from "@components/Login"; |
| 15 | import { UserProfile } from "@customTypes/Profile"; | 15 | import { UserProfile } from "@customTypes/Profile"; |
| 16 | import { Search } from "@customTypes/Search"; | 16 | import { Search } from "@customTypes/Search"; |
| 17 | import { API } from "@api/Api"; | 17 | import { API } from "@api/Api"; |
| 18 | import "@css/Sidebar.css"; | ||
| 19 | 18 | ||
| 20 | interface SidebarProps { | 19 | interface SidebarProps { |
| 21 | setToken: React.Dispatch<React.SetStateAction<string | undefined>>; | 20 | setToken: React.Dispatch<React.SetStateAction<string | undefined>>; |
| @@ -24,6 +23,17 @@ interface SidebarProps { | |||
| 24 | onUploadRun: () => void; | 23 | onUploadRun: () => void; |
| 25 | } | 24 | } |
| 26 | 25 | ||
| 26 | function OpenSidebarIcon(){ | ||
| 27 | return ( | ||
| 28 | <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="lucide lucide-panel-right-close-icon lucide-panel-right-close"><rect width="18" height="18" x="3" y="3" rx="2"/><path d="M15 3v18"/><path d="m8 9 3 3-3 3"/></svg> | ||
| 29 | ) | ||
| 30 | } | ||
| 31 | |||
| 32 | function ClosedSidebarIcon(){ | ||
| 33 | return ( | ||
| 34 | <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className="lucide lucide-panel-right-open-icon lucide-panel-right-open"><rect width="18" height="18" x="3" y="3" rx="2"/><path d="M15 3v18"/><path d="m10 15-3-3 3-3"/></svg> ) | ||
| 35 | } | ||
| 36 | |||
| 27 | const Sidebar: React.FC<SidebarProps> = ({ | 37 | const Sidebar: React.FC<SidebarProps> = ({ |
| 28 | setToken, | 38 | setToken, |
| 29 | profile, | 39 | profile, |
| @@ -34,100 +44,38 @@ const Sidebar: React.FC<SidebarProps> = ({ | |||
| 34 | undefined | 44 | undefined |
| 35 | ); | 45 | ); |
| 36 | const [isSidebarLocked, setIsSidebarLocked] = React.useState<boolean>(false); | 46 | const [isSidebarLocked, setIsSidebarLocked] = React.useState<boolean>(false); |
| 37 | const [isSidebarOpen, setSidebarOpen] = React.useState<boolean>(true); | 47 | const [isSidebarOpen, setSidebarOpen] = React.useState<boolean>(false); |
| 48 | const [selectedButtonIndex, setSelectedButtonIndex] = React.useState<number>(1); | ||
| 38 | 49 | ||
| 39 | const location = useLocation(); | 50 | const location = useLocation(); |
| 40 | const path = location.pathname; | 51 | const path = location.pathname; |
| 41 | 52 | ||
| 42 | const _handle_sidebar_hide = useCallback(() => { | 53 | const sidebarRef = useRef<HTMLDivElement>(null); |
| 43 | var btn = document.querySelectorAll( | 54 | const searchbarRef = useRef<HTMLInputElement>(null); |
| 44 | "button.sidebar-button" | 55 | const uploadRunRef = useRef<HTMLButtonElement>(null); |
| 45 | ) as NodeListOf<HTMLElement>; | 56 | const sidebarButtonRefs = useRef<(HTMLButtonElement | null)[]>([]); |
| 46 | const span = document.querySelectorAll( | 57 | |
| 47 | "button.sidebar-button>span" | 58 | const _handle_sidebar_toggle = useCallback(() => { |
| 48 | ) as NodeListOf<HTMLElement>; | 59 | if (!sidebarRef.current) return; |
| 49 | const side = document.querySelector("#sidebar-list") as HTMLElement; | ||
| 50 | const searchbar = document.querySelector("#searchbar") as HTMLInputElement; | ||
| 51 | const uploadRunBtn = document.querySelector( | ||
| 52 | "#upload-run" | ||
| 53 | ) as HTMLInputElement; | ||
| 54 | const uploadRunSpan = document.querySelector( | ||
| 55 | "#upload-run>span" | ||
| 56 | ) as HTMLInputElement; | ||
| 57 | 60 | ||
| 58 | if (isSidebarOpen) { | 61 | if (isSidebarOpen) { |
| 59 | if (profile) { | ||
| 60 | const login = document.querySelectorAll( | ||
| 61 | ".login>button" | ||
| 62 | )[1] as HTMLElement; | ||
| 63 | login.style.opacity = "1"; | ||
| 64 | uploadRunBtn.style.width = "310px"; | ||
| 65 | uploadRunBtn.style.padding = "0.4em 0 0 11px"; | ||
| 66 | uploadRunSpan.style.opacity = "0"; | ||
| 67 | setTimeout(() => { | ||
| 68 | uploadRunSpan.style.opacity = "1"; | ||
| 69 | }, 100); | ||
| 70 | } | ||
| 71 | setSidebarOpen(false); | 62 | setSidebarOpen(false); |
| 72 | side.style.width = "320px"; | ||
| 73 | btn.forEach((e, i) => { | ||
| 74 | e.style.width = "310px"; | ||
| 75 | e.style.padding = "0.4em 0 0 11px"; | ||
| 76 | setTimeout(() => { | ||
| 77 | span[i].style.opacity = "1"; | ||
| 78 | }, 100); | ||
| 79 | }); | ||
| 80 | side.style.zIndex = "2"; | ||
| 81 | } else { | 63 | } else { |
| 82 | if (profile) { | ||
| 83 | const login = document.querySelectorAll( | ||
| 84 | ".login>button" | ||
| 85 | )[1] as HTMLElement; | ||
| 86 | login.style.opacity = "0"; | ||
| 87 | uploadRunBtn.style.width = "40px"; | ||
| 88 | uploadRunBtn.style.padding = "0.4em 0 0 5px"; | ||
| 89 | uploadRunSpan.style.opacity = "0"; | ||
| 90 | } | ||
| 91 | setSidebarOpen(true); | 64 | setSidebarOpen(true); |
| 92 | side.style.width = "40px"; | 65 | searchbarRef.current?.focus(); |
| 93 | searchbar.focus(); | ||
| 94 | btn.forEach((e, i) => { | ||
| 95 | e.style.width = "40px"; | ||
| 96 | e.style.padding = "0.4em 0 0 5px"; | ||
| 97 | span[i].style.opacity = "0"; | ||
| 98 | }); | ||
| 99 | setTimeout(() => { | ||
| 100 | side.style.zIndex = "0"; | ||
| 101 | }, 300); | ||
| 102 | } | 66 | } |
| 103 | }, [isSidebarOpen, profile]); | 67 | }, [isSidebarOpen]); |
| 104 | 68 | ||
| 105 | const handle_sidebar_click = useCallback( | 69 | const handle_sidebar_click = useCallback( |
| 106 | (clicked_sidebar_idx: number) => { | 70 | (clicked_sidebar_idx: number) => { |
| 107 | const btn = document.querySelectorAll("button.sidebar-button"); | 71 | setSelectedButtonIndex(clicked_sidebar_idx); |
| 108 | if (isSidebarOpen) { | 72 | if (isSidebarOpen) { |
| 109 | setSidebarOpen(false); | 73 | setSidebarOpen(false); |
| 110 | _handle_sidebar_hide(); | ||
| 111 | } | 74 | } |
| 112 | // clusterfuck | ||
| 113 | btn.forEach((e, i) => { | ||
| 114 | btn[i].classList.remove("sidebar-button-selected"); | ||
| 115 | btn[i].classList.add("sidebar-button-deselected"); | ||
| 116 | }); | ||
| 117 | btn[clicked_sidebar_idx].classList.add("sidebar-button-selected"); | ||
| 118 | btn[clicked_sidebar_idx].classList.remove("sidebar-button-deselected"); | ||
| 119 | }, | 75 | }, |
| 120 | [isSidebarOpen, _handle_sidebar_hide] | 76 | [isSidebarOpen] |
| 121 | ); | 77 | ); |
| 122 | 78 | ||
| 123 | const _handle_sidebar_lock = () => { | ||
| 124 | if (!isSidebarLocked) { | ||
| 125 | _handle_sidebar_hide(); | ||
| 126 | setIsSidebarLocked(true); | ||
| 127 | setTimeout(() => setIsSidebarLocked(false), 300); | ||
| 128 | } | ||
| 129 | }; | ||
| 130 | |||
| 131 | const _handle_search_change = async (q: string) => { | 79 | const _handle_search_change = async (q: string) => { |
| 132 | const searchResponse = await API.get_search(q); | 80 | const searchResponse = await API.get_search(q); |
| 133 | setSearchData(searchResponse); | 81 | setSearchData(searchResponse); |
| @@ -135,149 +83,199 @@ const Sidebar: React.FC<SidebarProps> = ({ | |||
| 135 | 83 | ||
| 136 | React.useEffect(() => { | 84 | React.useEffect(() => { |
| 137 | if (path === "/") { | 85 | if (path === "/") { |
| 138 | handle_sidebar_click(1); | 86 | setSelectedButtonIndex(1); |
| 139 | } else if (path.includes("games")) { | 87 | } else if (path.includes("games")) { |
| 140 | handle_sidebar_click(2); | 88 | setSelectedButtonIndex(2); |
| 141 | } else if (path.includes("rankings")) { | 89 | } else if (path.includes("rankings")) { |
| 142 | handle_sidebar_click(3); | 90 | setSelectedButtonIndex(3); |
| 143 | } | 91 | } else if (path.includes("profile")) { |
| 144 | // else if (path.includes("news")) { handle_sidebar_click(4) } | 92 | setSelectedButtonIndex(4); |
| 145 | // else if (path.includes("scorelog")) { handle_sidebar_click(5) } | ||
| 146 | else if (path.includes("profile")) { | ||
| 147 | handle_sidebar_click(4); | ||
| 148 | } else if (path.includes("rules")) { | 93 | } else if (path.includes("rules")) { |
| 149 | handle_sidebar_click(5); | 94 | setSelectedButtonIndex(5); |
| 150 | } else if (path.includes("about")) { | 95 | } else if (path.includes("about")) { |
| 151 | handle_sidebar_click(6); | 96 | setSelectedButtonIndex(6); |
| 152 | } | 97 | } |
| 153 | }, [path, handle_sidebar_click]); | 98 | }, [path]); |
| 99 | |||
| 100 | const getButtonClasses = (buttonIndex: number) => { | ||
| 101 | const baseClasses = "flex items-center gap-3 w-full text-left bg-inherit cursor-pointer border-none rounded-lg py-3 px-3 transition-all duration-300 hover:bg-surface1"; | ||
| 102 | const selectedClasses = selectedButtonIndex === buttonIndex ? "bg-primary text-background" : "bg-transparent text-foreground"; | ||
| 103 | |||
| 104 | return `${baseClasses} ${selectedClasses}`; | ||
| 105 | }; | ||
| 106 | |||
| 107 | const iconClasses = "w-6 h-6 flex-shrink-0"; | ||
| 154 | 108 | ||
| 155 | return ( | 109 | return ( |
| 156 | <div id="sidebar"> | 110 | <div className={`fixed top-0 left-0 h-screen bg-surface border-r border-border transition-all duration-300 z-10 overflow-hidden ${ |
| 157 | <Link to="/" tabIndex={-1}> | 111 | isSidebarOpen ? 'w-80' : 'w-20' |
| 158 | <div id="logo"> | 112 | }`}> |
| 159 | {" "} | 113 | <div className="flex items-center h-20 px-4 border-b border-border"> |
| 160 | {/* logo */} | 114 | <Link to="/" tabIndex={-1} className="flex items-center flex-1 cursor-pointer select-none min-w-0"> |
| 161 | <img src={LogoIcon} alt="" height={"80px"} /> | 115 | <img src={LogoIcon} alt="Logo" className="w-12 h-12 flex-shrink-0" /> |
| 162 | <div id="logo-text"> | 116 | {isSidebarOpen && ( |
| 163 | <span> | 117 | <div className="ml-3 font-[--font-barlow-condensed-regular] text-white min-w-0 overflow-hidden"> |
| 164 | <b>PORTAL 2</b> | 118 | <div className="font-[--font-barlow-condensed-bold] text-2xl leading-6 truncate"> |
| 165 | </span> | 119 | PORTAL 2 |
| 166 | <br /> | 120 | </div> |
| 167 | <span>Least Portals Hub</span> | 121 | <div className="text-sm leading-4 truncate"> |
| 122 | Least Portals Hub | ||
| 123 | </div> | ||
| 124 | </div> | ||
| 125 | )} | ||
| 126 | </Link> | ||
| 127 | |||
| 128 | <button | ||
| 129 | onClick={_handle_sidebar_toggle} | ||
| 130 | className="ml-2 p-2 rounded-lg hover:bg-surface1 transition-colors text-foreground" | ||
| 131 | title={isSidebarOpen ? "Close sidebar" : "Open sidebar"} | ||
| 132 | > | ||
| 133 | {isSidebarOpen ? <ClosedSidebarIcon /> : <OpenSidebarIcon />} | ||
| 134 | </button> | ||
| 135 | </div> | ||
| 136 | |||
| 137 | {/* Sidebar Content */} | ||
| 138 | <div | ||
| 139 | ref={sidebarRef} | ||
| 140 | className="flex flex-col h-[calc(100vh-80px)] overflow-y-auto overflow-x-hidden" | ||
| 141 | > | ||
| 142 | {isSidebarOpen && ( | ||
| 143 | <div className="p-4 border-b border-border min-w-0"> | ||
| 144 | <div className="flex items-center gap-3 mb-3"> | ||
| 145 | <img src={SearchIcon} alt="Search" className={iconClasses} /> | ||
| 146 | <span className="text-white font-[--font-barlow-semicondensed-regular] truncate">Search</span> | ||
| 147 | </div> | ||
| 148 | |||
| 149 | <div className="min-w-0"> | ||
| 150 | <input | ||
| 151 | ref={searchbarRef} | ||
| 152 | type="text" | ||
| 153 | id="searchbar" | ||
| 154 | placeholder="Search for map or a player..." | ||
| 155 | onChange={e => _handle_search_change(e.target.value)} | ||
| 156 | className="w-full p-2 bg-input text-foreground border border-border rounded-lg text-sm min-w-0" | ||
| 157 | /> | ||
| 158 | |||
| 159 | {searchData && ( | ||
| 160 | <div className="mt-2 max-h-40 overflow-y-auto min-w-0"> | ||
| 161 | {searchData?.maps.map((q, index) => ( | ||
| 162 | <Link to={`/maps/${q.id}`} className="block p-2 mb-1 bg-surface1 rounded hover:bg-surface2 transition-colors min-w-0" key={index}> | ||
| 163 | <span className="block text-xs text-subtext1 truncate">{q.game}</span> | ||
| 164 | <span className="block text-xs text-subtext1 truncate">{q.chapter}</span> | ||
| 165 | <span className="block text-sm text-foreground truncate">{q.map}</span> | ||
| 166 | </Link> | ||
| 167 | ))} | ||
| 168 | {searchData?.players.map((q, index) => ( | ||
| 169 | <Link | ||
| 170 | to={ | ||
| 171 | profile && q.steam_id === profile.steam_id | ||
| 172 | ? `/profile` | ||
| 173 | : `/users/${q.steam_id}` | ||
| 174 | } | ||
| 175 | className="flex items-center p-2 mb-1 bg-surface1 rounded hover:bg-surface2 transition-colors min-w-0" | ||
| 176 | key={index} | ||
| 177 | > | ||
| 178 | <img src={q.avatar_link} alt="pfp" className="w-6 h-6 rounded-full mr-2 flex-shrink-0" /> | ||
| 179 | <span className="text-sm text-foreground truncate"> | ||
| 180 | {q.user_name} | ||
| 181 | </span> | ||
| 182 | </Link> | ||
| 183 | ))} | ||
| 184 | </div> | ||
| 185 | )} | ||
| 186 | </div> | ||
| 168 | </div> | 187 | </div> |
| 188 | )} | ||
| 189 | |||
| 190 | <div className="flex-1 p-4 min-w-0"> | ||
| 191 | <nav className="space-y-2"> | ||
| 192 | {[ | ||
| 193 | { | ||
| 194 | to: "/", | ||
| 195 | refIndex: 1, | ||
| 196 | icon: HomeIcon, | ||
| 197 | alt: "Home", | ||
| 198 | label: "Home Page", | ||
| 199 | }, | ||
| 200 | { | ||
| 201 | to: "/games", | ||
| 202 | refIndex: 2, | ||
| 203 | icon: PortalIcon, | ||
| 204 | alt: "Games", | ||
| 205 | label: "Games", | ||
| 206 | }, | ||
| 207 | { | ||
| 208 | to: "/rankings", | ||
| 209 | refIndex: 3, | ||
| 210 | icon: FlagIcon, | ||
| 211 | alt: "Rankings", | ||
| 212 | label: "Rankings", | ||
| 213 | }, | ||
| 214 | ].map(({ to, refIndex, icon, alt, label }) => ( | ||
| 215 | <Link to={to} tabIndex={-1} key={refIndex}> | ||
| 216 | <button | ||
| 217 | ref={el => sidebarButtonRefs.current[refIndex] = el} | ||
| 218 | className={getButtonClasses(refIndex)} | ||
| 219 | onClick={() => handle_sidebar_click(refIndex)} | ||
| 220 | > | ||
| 221 | <img src={icon} alt={alt} className={iconClasses} /> | ||
| 222 | {isSidebarOpen && ( | ||
| 223 | <span className="text-white font-[--font-barlow-semicondensed-regular] truncate"> | ||
| 224 | {label} | ||
| 225 | </span> | ||
| 226 | )} | ||
| 227 | </button> | ||
| 228 | </Link> | ||
| 229 | ))} | ||
| 230 | </nav> | ||
| 169 | </div> | 231 | </div> |
| 170 | </Link> | ||
| 171 | <div id="sidebar-list"> | ||
| 172 | {" "} | ||
| 173 | {/* List */} | ||
| 174 | <div id="sidebar-toplist"> | ||
| 175 | {" "} | ||
| 176 | {/* Top */} | ||
| 177 | <button | ||
| 178 | className="sidebar-button" | ||
| 179 | onClick={() => _handle_sidebar_lock()} | ||
| 180 | > | ||
| 181 | <img src={SearchIcon} alt="" /> | ||
| 182 | <span>Search</span> | ||
| 183 | </button> | ||
| 184 | <span></span> | ||
| 185 | <Link to="/" tabIndex={-1}> | ||
| 186 | <button className="sidebar-button"> | ||
| 187 | <img src={HomeIcon} alt="homepage" /> | ||
| 188 | <span>Home Page</span> | ||
| 189 | </button> | ||
| 190 | </Link> | ||
| 191 | <Link to="/games" tabIndex={-1}> | ||
| 192 | <button className="sidebar-button"> | ||
| 193 | <img src={PortalIcon} alt="games" /> | ||
| 194 | <span>Games</span> | ||
| 195 | </button> | ||
| 196 | </Link> | ||
| 197 | <Link to="/rankings" tabIndex={-1}> | ||
| 198 | <button className="sidebar-button"> | ||
| 199 | <img src={FlagIcon} alt="rankings" /> | ||
| 200 | <span>Rankings</span> | ||
| 201 | </button> | ||
| 202 | </Link> | ||
| 203 | {/* <Link to="/news" tabIndex={-1}> | ||
| 204 | <button className='sidebar-button'><img src={NewsIcon} alt="news" /><span>News</span></button> | ||
| 205 | </Link> */} | ||
| 206 | {/* <Link to="/scorelog" tabIndex={-1}> | ||
| 207 | <button className='sidebar-button'><img src={TableIcon} alt="scorelogs" /><span>Score Logs</span></button> | ||
| 208 | </Link> */} | ||
| 209 | </div> | ||
| 210 | <div id="sidebar-bottomlist"> | ||
| 211 | <span></span> | ||
| 212 | 232 | ||
| 213 | {profile && profile.profile ? ( | 233 | {/* Bottom Section */} |
| 234 | <div className="p-4 border-t border-border space-y-2 min-w-0"> | ||
| 235 | {profile && profile.profile && ( | ||
| 214 | <button | 236 | <button |
| 237 | ref={uploadRunRef} | ||
| 215 | id="upload-run" | 238 | id="upload-run" |
| 216 | className="submit-run-button" | 239 | className={getButtonClasses(-1)} |
| 217 | onClick={() => onUploadRun()} | 240 | onClick={() => onUploadRun()} |
| 218 | > | 241 | > |
| 219 | <img src={UploadIcon} alt="upload" /> | 242 | <img src={UploadIcon} alt="Upload" className={iconClasses} /> |
| 220 | <span>Upload Record</span> | 243 | {isSidebarOpen && <span className="font-[--font-barlow-semicondensed-regular] truncate">Upload Record</span>} |
| 221 | </button> | 244 | </button> |
| 222 | ) : ( | ||
| 223 | <span></span> | ||
| 224 | )} | 245 | )} |
| 225 | 246 | ||
| 226 | <Login | 247 | <div className={isSidebarOpen ? 'min-w-0' : 'flex justify-center'}> |
| 227 | setToken={setToken} | 248 | <Login |
| 228 | profile={profile} | 249 | setToken={setToken} |
| 229 | setProfile={setProfile} | 250 | profile={profile} |
| 230 | /> | 251 | setProfile={setProfile} |
| 252 | isOpen={isSidebarOpen} | ||
| 253 | /> | ||
| 254 | </div> | ||
| 231 | 255 | ||
| 232 | <Link to="/rules" tabIndex={-1}> | 256 | <Link to="/rules" tabIndex={-1}> |
| 233 | <button className="sidebar-button"> | 257 | <button |
| 234 | <img src={BookIcon} alt="rules" /> | 258 | ref={el => sidebarButtonRefs.current[5] = el} |
| 235 | <span>Leaderboard Rules</span> | 259 | className={getButtonClasses(5)} |
| 260 | onClick={() => handle_sidebar_click(5)} | ||
| 261 | > | ||
| 262 | <img src={BookIcon} alt="Rules" className={iconClasses} /> | ||
| 263 | {isSidebarOpen && <span className="font-[--font-barlow-semicondensed-regular] truncate">Leaderboard Rules</span>} | ||
| 236 | </button> | 264 | </button> |
| 237 | </Link> | 265 | </Link> |
| 238 | 266 | ||
| 239 | <Link to="/about" tabIndex={-1}> | 267 | <Link to="/about" tabIndex={-1}> |
| 240 | <button className="sidebar-button"> | 268 | <button |
| 241 | <img src={HelpIcon} alt="about" /> | 269 | ref={el => sidebarButtonRefs.current[6] = el} |
| 242 | <span>About LPHUB</span> | 270 | className={getButtonClasses(6)} |
| 271 | onClick={() => handle_sidebar_click(6)} | ||
| 272 | > | ||
| 273 | <img src={HelpIcon} alt="About" className={iconClasses} /> | ||
| 274 | {isSidebarOpen && <span className="font-[--font-barlow-semicondensed-regular] truncate">About LPHUB</span>} | ||
| 243 | </button> | 275 | </button> |
| 244 | </Link> | 276 | </Link> |
| 245 | </div> | 277 | </div> |
| 246 | </div> | 278 | </div> |
| 247 | <div> | ||
| 248 | <input | ||
| 249 | type="text" | ||
| 250 | id="searchbar" | ||
| 251 | placeholder="Search for map or a player..." | ||
| 252 | onChange={e => _handle_search_change(e.target.value)} | ||
| 253 | /> | ||
| 254 | |||
| 255 | <div id="search-data"> | ||
| 256 | {searchData?.maps.map((q, index) => ( | ||
| 257 | <Link to={`/maps/${q.id}`} className="search-map" key={index}> | ||
| 258 | <span>{q.game}</span> | ||
| 259 | <span>{q.chapter}</span> | ||
| 260 | <span>{q.map}</span> | ||
| 261 | </Link> | ||
| 262 | ))} | ||
| 263 | {searchData?.players.map((q, index) => ( | ||
| 264 | <Link | ||
| 265 | to={ | ||
| 266 | profile && q.steam_id === profile.steam_id | ||
| 267 | ? `/profile` | ||
| 268 | : `/users/${q.steam_id}` | ||
| 269 | } | ||
| 270 | className="search-player" | ||
| 271 | key={index} | ||
| 272 | > | ||
| 273 | <img src={q.avatar_link} alt="pfp"></img> | ||
| 274 | <span style={{ fontSize: `${36 - q.user_name.length * 0.8}px` }}> | ||
| 275 | {q.user_name} | ||
| 276 | </span> | ||
| 277 | </Link> | ||
| 278 | ))} | ||
| 279 | </div> | ||
| 280 | </div> | ||
| 281 | </div> | 279 | </div> |
| 282 | ); | 280 | ); |
| 283 | }; | 281 | }; |
diff --git a/frontend/src/components/Summary.tsx b/frontend/src/components/Summary.tsx index 61e52d4..cdecf30 100644 --- a/frontend/src/components/Summary.tsx +++ b/frontend/src/components/Summary.tsx | |||
| @@ -2,7 +2,6 @@ import React from "react"; | |||
| 2 | import ReactMarkdown from "react-markdown"; | 2 | import ReactMarkdown from "react-markdown"; |
| 3 | 3 | ||
| 4 | import { MapSummary } from "@customTypes/Map"; | 4 | import { MapSummary } from "@customTypes/Map"; |
| 5 | import "@css/Maps.css"; | ||
| 6 | 5 | ||
| 7 | interface SummaryProps { | 6 | interface SummaryProps { |
| 8 | selectedRun: number; | 7 | selectedRun: number; |
diff --git a/frontend/src/components/UploadRunDialog.tsx b/frontend/src/components/UploadRunDialog.tsx index d5eabcd..0034019 100644 --- a/frontend/src/components/UploadRunDialog.tsx +++ b/frontend/src/components/UploadRunDialog.tsx | |||
| @@ -2,7 +2,6 @@ import React from "react"; | |||
| 2 | import { UploadRunContent } from "@customTypes/Content"; | 2 | import { UploadRunContent } from "@customTypes/Content"; |
| 3 | import { ScoreboardTempUpdate, SourceDemoParser, NetMessages } from "@nekz/sdp"; | 3 | import { ScoreboardTempUpdate, SourceDemoParser, NetMessages } from "@nekz/sdp"; |
| 4 | 4 | ||
| 5 | import "@css/UploadRunDialog.css"; | ||
| 6 | import { Game } from "@customTypes/Game"; | 5 | import { Game } from "@customTypes/Game"; |
| 7 | import { API } from "@api/Api"; | 6 | import { API } from "@api/Api"; |
| 8 | import { useNavigate } from "react-router-dom"; | 7 | import { useNavigate } from "react-router-dom"; |
diff --git a/frontend/src/images/Images.tsx b/frontend/src/images/Images.tsx index eb12588..6b46893 100644 --- a/frontend/src/images/Images.tsx +++ b/frontend/src/images/Images.tsx | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | import logo from "./png/logo.png"; | 1 | import logo from "./png/logo.png"; |
| 2 | import login from "./png/login.png"; | 2 | import { LoginIcon as Login } from "./svgs/steam.tsx"; |
| 3 | import img1 from "./png/1.png"; | 3 | import img1 from "./png/1.png"; |
| 4 | import img2 from "./png/2.png"; | 4 | import img2 from "./png/2.png"; |
| 5 | import img3 from "./png/3.png"; | 5 | import img3 from "./png/3.png"; |
| @@ -23,7 +23,7 @@ import img20 from "./png/20.png"; | |||
| 23 | import img21 from "./png/21.png"; | 23 | import img21 from "./png/21.png"; |
| 24 | 24 | ||
| 25 | export const LogoIcon = logo; | 25 | export const LogoIcon = logo; |
| 26 | export const LoginIcon = login; | 26 | export const LoginIcon = Login; |
| 27 | 27 | ||
| 28 | export const SearchIcon = img1; | 28 | export const SearchIcon = img1; |
| 29 | export const HomeIcon = img2; | 29 | export const HomeIcon = img2; |
diff --git a/frontend/src/images/svgs/steam.tsx b/frontend/src/images/svgs/steam.tsx new file mode 100644 index 0000000..0dc9a04 --- /dev/null +++ b/frontend/src/images/svgs/steam.tsx | |||
| @@ -0,0 +1,7 @@ | |||
| 1 | export function LoginIcon(){ | ||
| 2 | return ( | ||
| 3 | <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" className="text-white" height={32} width={32}> | ||
| 4 | <path d="M504 256c0 137-111.2 248-248.4 248-113.8 0-209.6-76.3-239-180.4l95.2 39.3c6.4 32.1 34.9 56.4 68.9 56.4 39.2 0 71.9-32.4 70.2-73.5l84.5-60.2c52.1 1.3 95.8-40.9 95.8-93.5 0-51.6-42-93.5-93.7-93.5s-93.7 42-93.7 93.5l0 1.2-59.2 85.7c-15.5-.9-30.7 3.4-43.5 12.1L8 236.1C18.2 108.4 125.1 8 255.6 8 392.8 8 504 119 504 256zM163.7 384.3l-30.5-12.6c5.6 11.6 15.3 20.8 27.2 25.8 26.9 11.2 57.8-1.6 69-28.4 5.4-13 5.5-27.3 .1-40.3S214 305.6 201 300.2c-12.9-5.4-26.7-5.2-38.9-.6l31.5 13c19.8 8.2 29.2 30.9 20.9 50.7-8.3 19.9-31 29.2-50.8 21zM337.5 129.8a62.3 62.3 0 1 1 0 124.6 62.3 62.3 0 1 1 0-124.6zm.1 109a46.8 46.8 0 1 0 0-93.6 46.8 46.8 0 1 0 0 93.6z" fill="currentColor"/> | ||
| 5 | </svg> | ||
| 6 | ) | ||
| 7 | } \ No newline at end of file | ||
diff --git a/frontend/src/pages/About.tsx b/frontend/src/pages/About.tsx index 5a69bfe..a5bb291 100644 --- a/frontend/src/pages/About.tsx +++ b/frontend/src/pages/About.tsx | |||
| @@ -2,8 +2,6 @@ import React from "react"; | |||
| 2 | import ReactMarkdown from "react-markdown"; | 2 | import ReactMarkdown from "react-markdown"; |
| 3 | import { Helmet } from "react-helmet"; | 3 | import { Helmet } from "react-helmet"; |
| 4 | 4 | ||
| 5 | import "@css/About.css"; | ||
| 6 | |||
| 7 | const About: React.FC = () => { | 5 | const About: React.FC = () => { |
| 8 | const [aboutText, setAboutText] = React.useState<string>(""); | 6 | const [aboutText, setAboutText] = React.useState<string>(""); |
| 9 | 7 | ||
| @@ -26,7 +24,7 @@ const About: React.FC = () => { | |||
| 26 | }, []); | 24 | }, []); |
| 27 | 25 | ||
| 28 | return ( | 26 | return ( |
| 29 | <div id="about"> | 27 | <div className="p-8 text-foreground font-[--font-barlow-semicondensed-regular] prose prose-invert max-w-none"> |
| 30 | <Helmet> | 28 | <Helmet> |
| 31 | <title>LPHUB | About</title> | 29 | <title>LPHUB | About</title> |
| 32 | </Helmet> | 30 | </Helmet> |
diff --git a/frontend/src/pages/Games.tsx b/frontend/src/pages/Games.tsx index d7dacde..1ef0f57 100644 --- a/frontend/src/pages/Games.tsx +++ b/frontend/src/pages/Games.tsx | |||
| @@ -3,41 +3,23 @@ import { Helmet } from "react-helmet"; | |||
| 3 | 3 | ||
| 4 | import GameEntry from "@components/GameEntry"; | 4 | import GameEntry from "@components/GameEntry"; |
| 5 | import { Game } from "@customTypes/Game"; | 5 | import { Game } from "@customTypes/Game"; |
| 6 | import "@css/Maps.css"; | ||
| 7 | 6 | ||
| 8 | interface GamesProps { | 7 | interface GamesProps { |
| 9 | games: Game[]; | 8 | games: Game[]; |
| 10 | } | 9 | } |
| 11 | 10 | ||
| 12 | const Games: React.FC<GamesProps> = ({ games }) => { | 11 | const Games: React.FC<GamesProps> = ({ games }) => { |
| 13 | const _page_load = () => { | ||
| 14 | const loaders = document.querySelectorAll(".loader"); | ||
| 15 | loaders.forEach(loader => { | ||
| 16 | (loader as HTMLElement).style.display = "none"; | ||
| 17 | }); | ||
| 18 | }; | ||
| 19 | |||
| 20 | React.useEffect(() => { | ||
| 21 | document | ||
| 22 | .querySelectorAll(".games-page-item-body") | ||
| 23 | .forEach((game, index) => { | ||
| 24 | game.innerHTML = ""; | ||
| 25 | }); | ||
| 26 | _page_load(); | ||
| 27 | }, []); | ||
| 28 | |||
| 29 | return ( | 12 | return ( |
| 30 | <div className="games-page"> | 13 | <div className="ml-10 min-h-screen w-[calc(100%-320px)] text-foreground font-[--font-barlow-semicondensed-regular] overflow-y-auto scrollbar-thin"> |
| 31 | <Helmet> | 14 | <Helmet> |
| 32 | <title>LPHUB | Games</title> | 15 | <title>LPHUB | Games</title> |
| 33 | </Helmet> | 16 | </Helmet> |
| 34 | <section> | 17 | <section className="py-12 px-12 w-full"> |
| 35 | <div className="games-page-content"> | 18 | <h1 className="text-3xl font-bold mb-8">Games</h1> |
| 36 | <div className="games-page-item-content"> | 19 | <div className="flex flex-col w-full"> |
| 37 | {games.map((game, index) => ( | 20 | {games.map((game, index) => ( |
| 38 | <GameEntry game={game} key={index} /> | 21 | <GameEntry game={game} key={index} /> |
| 39 | ))} | 22 | ))} |
| 40 | </div> | ||
| 41 | </div> | 23 | </div> |
| 42 | </section> | 24 | </section> |
| 43 | </div> | 25 | </div> |
diff --git a/frontend/src/pages/Homepage.tsx b/frontend/src/pages/Homepage.tsx index f0c5821..2d16b8d 100644 --- a/frontend/src/pages/Homepage.tsx +++ b/frontend/src/pages/Homepage.tsx | |||
| @@ -3,23 +3,23 @@ import { Helmet } from "react-helmet"; | |||
| 3 | 3 | ||
| 4 | const Homepage: React.FC = () => { | 4 | const Homepage: React.FC = () => { |
| 5 | return ( | 5 | return ( |
| 6 | <main> | 6 | <main className="text-foreground font-[--font-barlow-semicondensed-regular]"> |
| 7 | <Helmet> | 7 | <Helmet> |
| 8 | <title>LPHUB | Homepage</title> | 8 | <title>LPHUB | Homepage</title> |
| 9 | </Helmet> | 9 | </Helmet> |
| 10 | <section> | 10 | <section className="p-8"> |
| 11 | <p /> | 11 | <p /> |
| 12 | <h1>Welcome to Least Portals Hub!</h1> | 12 | <h1 className="text-5xl font-[--font-barlow-condensed-bold] mb-6 text-primary">Welcome to Least Portals Hub!</h1> |
| 13 | <p> | 13 | <p className="text-lg mb-4 leading-relaxed"> |
| 14 | At the moment, LPHUB is in beta state. This means that the site has | 14 | At the moment, LPHUB is in beta state. This means that the site has |
| 15 | only the core functionalities enabled for providing both collaborative | 15 | only the core functionalities enabled for providing both collaborative |
| 16 | information and competitive leaderboards. | 16 | information and competitive leaderboards. |
| 17 | </p> | 17 | </p> |
| 18 | <p> | 18 | <p className="text-lg mb-4 leading-relaxed"> |
| 19 | The website should feel intuitive to navigate around. For any type of | 19 | The website should feel intuitive to navigate around. For any type of |
| 20 | feedback, reach us at LPHUB Discord server. | 20 | feedback, reach us at LPHUB Discord server. |
| 21 | </p> | 21 | </p> |
| 22 | <p> | 22 | <p className="text-lg mb-4 leading-relaxed"> |
| 23 | By using LPHUB, you agree that you have read the 'Leaderboard Rules' | 23 | By using LPHUB, you agree that you have read the 'Leaderboard Rules' |
| 24 | and the 'About LPHUB' pages. | 24 | and the 'About LPHUB' pages. |
| 25 | </p> | 25 | </p> |
diff --git a/frontend/src/pages/Maplist.tsx b/frontend/src/pages/Maplist.tsx index a7242ef..8343129 100644 --- a/frontend/src/pages/Maplist.tsx +++ b/frontend/src/pages/Maplist.tsx | |||
| @@ -2,7 +2,6 @@ import React, { useEffect } from "react"; | |||
| 2 | import { Link, useLocation, useNavigate, useParams } from "react-router-dom"; | 2 | import { Link, useLocation, useNavigate, useParams } from "react-router-dom"; |
| 3 | import { Helmet } from "react-helmet"; | 3 | import { Helmet } from "react-helmet"; |
| 4 | 4 | ||
| 5 | import "@css/Maplist.css"; | ||
| 6 | import { API } from "@api/Api"; | 5 | import { API } from "@api/Api"; |
| 7 | import { Game } from "@customTypes/Game"; | 6 | import { Game } from "@customTypes/Game"; |
| 8 | import { GameChapter, GamesChapters } from "@customTypes/Chapters"; | 7 | import { GameChapter, GamesChapters } from "@customTypes/Chapters"; |
| @@ -92,44 +91,52 @@ const Maplist: React.FC = () => { | |||
| 92 | <Helmet> | 91 | <Helmet> |
| 93 | <title>LPHUB | Maplist</title> | 92 | <title>LPHUB | Maplist</title> |
| 94 | </Helmet> | 93 | </Helmet> |
| 95 | <section style={{ marginTop: "20px" }}> | 94 | |
| 95 | <section className="mt-5"> | ||
| 96 | <Link to="/games"> | 96 | <Link to="/games"> |
| 97 | <button className="nav-button" style={{ borderRadius: "20px" }}> | 97 | <button className="nav-button rounded-[20px] h-10 bg-surface border-0 text-foreground text-lg font-[--font-barlow-semicondensed-regular] transition-colors duration-100 hover:bg-surface2 flex items-center px-2"> |
| 98 | <i className="triangle"></i> | 98 | <i className="triangle mr-2"></i> |
| 99 | <span>Games List</span> | 99 | <span className="px-2">Games List</span> |
| 100 | </button> | 100 | </button> |
| 101 | </Link> | 101 | </Link> |
| 102 | </section> | 102 | </section> |
| 103 | |||
| 103 | {load ? ( | 104 | {load ? ( |
| 104 | <div></div> | 105 | <div></div> |
| 105 | ) : ( | 106 | ) : ( |
| 106 | <section> | 107 | <section> |
| 107 | <h1>{game?.name}</h1> | 108 | <h1 className="font-[--font-barlow-condensed-bold] text-6xl my-0 text-foreground"> |
| 109 | {game?.name} | ||
| 110 | </h1> | ||
| 111 | |||
| 108 | <div | 112 | <div |
| 113 | className="text-center rounded-3xl overflow-hidden bg-cover bg-[25%] mt-3 relative" | ||
| 109 | style={{ backgroundImage: `url(${game?.image})` }} | 114 | style={{ backgroundImage: `url(${game?.image})` }} |
| 110 | className="game-header" | ||
| 111 | > | 115 | > |
| 112 | <div className="blur"> | 116 | <div className="backdrop-blur-sm flex flex-col w-full"> |
| 113 | <div className="game-header-portal-count"> | 117 | <div className="h-full flex flex-col justify-center items-center"> |
| 114 | <h2 className="portal-count"> | 118 | <h2 className="my-5 font-[--font-barlow-semicondensed-semibold] text-8xl text-foreground"> |
| 115 | { | 119 | { |
| 116 | game?.category_portals.find( | 120 | game?.category_portals.find( |
| 117 | obj => obj.category.id === catNum + 1 | 121 | obj => obj.category.id === catNum + 1 |
| 118 | )?.portal_count | 122 | )?.portal_count |
| 119 | } | 123 | } |
| 120 | </h2> | 124 | </h2> |
| 121 | <h3>portals</h3> | 125 | <h3 className="font-[--font-barlow-semicondensed-regular] mx-2.5 text-4xl my-0 text-foreground"> |
| 126 | portals | ||
| 127 | </h3> | ||
| 122 | </div> | 128 | </div> |
| 123 | <div className="game-header-categories"> | 129 | |
| 130 | <div className="flex h-12 bg-surface gap-0.5"> | ||
| 124 | {game?.category_portals.map((cat, index) => ( | 131 | {game?.category_portals.map((cat, index) => ( |
| 125 | <button | 132 | <button |
| 126 | key={index} | 133 | key={index} |
| 127 | className={ | 134 | className={`border-0 text-foreground font-[--font-barlow-semicondensed-regular] text-xl cursor-pointer transition-all duration-100 w-full ${ |
| 128 | currentlySelected === cat.category.id || | 135 | currentlySelected === cat.category.id || |
| 129 | (cat.category.id - 1 === catNum && !hasClicked) | 136 | (cat.category.id - 1 === catNum && !hasClicked) |
| 130 | ? "game-cat-button selected" | 137 | ? "bg-surface" |
| 131 | : "game-cat-button" | 138 | : "bg-surface1 hover:bg-surface" |
| 132 | } | 139 | }`} |
| 133 | onClick={() => { | 140 | onClick={() => { |
| 134 | setCatNum(cat.category.id - 1); | 141 | setCatNum(cat.category.id - 1); |
| 135 | _update_currently_selected(cat.category.id); | 142 | _update_currently_selected(cat.category.id); |
| @@ -143,31 +150,32 @@ const Maplist: React.FC = () => { | |||
| 143 | </div> | 150 | </div> |
| 144 | 151 | ||
| 145 | <div> | 152 | <div> |
| 146 | <section className="chapter-select-container"> | 153 | <section> |
| 147 | <div> | 154 | <div> |
| 148 | <span | 155 | <span className="text-lg translate-y-1.5 block mt-2.5 text-foreground"> |
| 149 | style={{ | ||
| 150 | fontSize: "18px", | ||
| 151 | transform: "translateY(5px)", | ||
| 152 | display: "block", | ||
| 153 | marginTop: "10px", | ||
| 154 | }} | ||
| 155 | > | ||
| 156 | {curChapter?.chapter.name.split(" - ")[0]} | 156 | {curChapter?.chapter.name.split(" - ")[0]} |
| 157 | </span> | 157 | </span> |
| 158 | </div> | 158 | </div> |
| 159 | <div onClick={_handle_dropdown_click} className="dropdown"> | 159 | <div |
| 160 | <span>{curChapter?.chapter.name.split(" - ")[1]}</span> | 160 | onClick={_handle_dropdown_click} |
| 161 | <i className="triangle"></i> | 161 | className="cursor-pointer select-none flex w-fit items-center" |
| 162 | > | ||
| 163 | <span className="text-foreground text-2xl"> | ||
| 164 | {curChapter?.chapter.name.split(" - ")[1]} | ||
| 165 | </span> | ||
| 166 | <i className="triangle translate-x-1.5 translate-y-2 -rotate-90"></i> | ||
| 162 | </div> | 167 | </div> |
| 168 | \ | ||
| 163 | <div | 169 | <div |
| 164 | className="dropdown-elements" | 170 | className={`absolute z-[1000] bg-surface1 rounded-2xl overflow-hidden p-1 animate-in fade-in duration-100 ${ |
| 165 | style={{ display: dropdownActive }} | 171 | dropdownActive === "none" ? "hidden" : "block" |
| 172 | }`} | ||
| 166 | > | 173 | > |
| 167 | {gameChapters?.chapters.map((chapter, i) => { | 174 | {gameChapters?.chapters.map((chapter, i) => { |
| 168 | return ( | 175 | return ( |
| 169 | <div | 176 | <div |
| 170 | className="dropdown-element" | 177 | key={i} |
| 178 | className="cursor-pointer text-xl rounded-[2000px] p-1 hover:bg-surface text-foreground" | ||
| 171 | onClick={() => { | 179 | onClick={() => { |
| 172 | _fetch_chapters(chapter.id.toString()); | 180 | _fetch_chapters(chapter.id.toString()); |
| 173 | _handle_dropdown_click(); | 181 | _handle_dropdown_click(); |
| @@ -179,49 +187,52 @@ const Maplist: React.FC = () => { | |||
| 179 | })} | 187 | })} |
| 180 | </div> | 188 | </div> |
| 181 | </section> | 189 | </section> |
| 182 | <section className="maplist"> | 190 | |
| 191 | <section className="grid grid-cols-4 gap-5 my-5"> | ||
| 183 | {curChapter?.maps.map((map, i) => { | 192 | {curChapter?.maps.map((map, i) => { |
| 184 | return ( | 193 | return ( |
| 185 | <div className="maplist-entry"> | 194 | <div key={i} className="bg-surface rounded-3xl overflow-hidden"> |
| 186 | <Link to={`/maps/${map.id}`}> | 195 | <Link to={`/maps/${map.id}`}> |
| 187 | <span>{map.name}</span> | 196 | <span className="text-center text-xl w-full block my-1.5 text-foreground"> |
| 197 | {map.name} | ||
| 198 | </span> | ||
| 188 | <div | 199 | <div |
| 189 | className="map-entry-image" | 200 | className="flex h-48 bg-cover relative" |
| 190 | style={{ backgroundImage: `url(${map.image})` }} | 201 | style={{ backgroundImage: `url(${map.image})` }} |
| 191 | > | 202 | > |
| 192 | <div className="blur map"> | 203 | <div className="backdrop-blur-sm w-full flex items-center justify-center"> |
| 193 | <span> | 204 | <span className="text-4xl font-[--font-barlow-semicondensed-semibold] text-white mr-1.5"> |
| 194 | {map.is_disabled | 205 | {map.is_disabled |
| 195 | ? map.category_portals[0].portal_count | 206 | ? map.category_portals[0].portal_count |
| 196 | : map.category_portals.find( | 207 | : map.category_portals.find( |
| 197 | obj => obj.category.id === catNum + 1 | 208 | obj => obj.category.id === catNum + 1 |
| 198 | )?.portal_count} | 209 | )?.portal_count} |
| 199 | </span> | 210 | </span> |
| 200 | <span>portals</span> | 211 | <span className="text-4xl font-[--font-barlow-semicondensed-regular] text-white"> |
| 212 | portals | ||
| 213 | </span> | ||
| 201 | </div> | 214 | </div> |
| 202 | </div> | 215 | </div> |
| 203 | <div className="difficulty-bar"> | 216 | |
| 204 | {/* <span>Difficulty:</span> */} | 217 | {/* Difficulty rating */} |
| 205 | <div | 218 | <div className="flex mx-2.5 my-4"> |
| 206 | className={ | 219 | <div className="flex w-full items-center justify-center gap-1.5 rounded-[2000px] ml-0.5 translate-y-px"> |
| 207 | map.difficulty === 0 | 220 | {[1, 2, 3, 4, 5].map((point) => ( |
| 208 | ? "one" | 221 | <div |
| 209 | : map.difficulty === 1 | 222 | key={point} |
| 210 | ? "two" | 223 | className={`flex h-0.5 w-full rounded-3xl ${ |
| 211 | : map.difficulty === 2 | 224 | point <= (map.difficulty + 1) |
| 212 | ? "three" | 225 | ? map.difficulty === 0 |
| 213 | : map.difficulty === 3 | 226 | ? "bg-green-500" |
| 214 | ? "four" | 227 | : map.difficulty === 1 || map.difficulty === 2 |
| 215 | : map.difficulty === 4 | 228 | ? "bg-lime-500" |
| 216 | ? "five" | 229 | : map.difficulty === 3 |
| 217 | : "one" | 230 | ? "bg-red-400" |
| 218 | } | 231 | : "bg-red-600" |
| 219 | > | 232 | : "bg-surface1" |
| 220 | <div className="difficulty-point"></div> | 233 | }`} |
| 221 | <div className="difficulty-point"></div> | 234 | /> |
| 222 | <div className="difficulty-point"></div> | 235 | ))} |
| 223 | <div className="difficulty-point"></div> | ||
| 224 | <div className="difficulty-point"></div> | ||
| 225 | </div> | 236 | </div> |
| 226 | </div> | 237 | </div> |
| 227 | </Link> | 238 | </Link> |
diff --git a/frontend/src/pages/Maps.tsx b/frontend/src/pages/Maps.tsx index fbdb8f3..75753ac 100644 --- a/frontend/src/pages/Maps.tsx +++ b/frontend/src/pages/Maps.tsx | |||
| @@ -2,14 +2,13 @@ import React from "react"; | |||
| 2 | import { Link, useLocation } from "react-router-dom"; | 2 | import { Link, useLocation } from "react-router-dom"; |
| 3 | import { Helmet } from "react-helmet"; | 3 | import { Helmet } from "react-helmet"; |
| 4 | 4 | ||
| 5 | import { PortalIcon, FlagIcon, ChatIcon } from "@images/Images"; | 5 | import { PortalIcon, FlagIcon, ChatIcon } from "../images/Images"; |
| 6 | import Summary from "@components/Summary"; | 6 | import Summary from "@components/Summary"; |
| 7 | import Leaderboards from "@components/Leaderboards"; | 7 | import Leaderboards from "@components/Leaderboards"; |
| 8 | import Discussions from "@components/Discussions"; | 8 | import Discussions from "@components/Discussions"; |
| 9 | import ModMenu from "@components/ModMenu"; | 9 | import ModMenu from "@components/ModMenu"; |
| 10 | import { MapDiscussions, MapLeaderboard, MapSummary } from "@customTypes/Map"; | 10 | import { MapDiscussions, MapLeaderboard, MapSummary } from "@customTypes/Map"; |
| 11 | import { API } from "@api/Api"; | 11 | import { API } from "@api/Api"; |
| 12 | import "@css/Maps.css"; | ||
| 13 | 12 | ||
| 14 | interface MapProps { | 13 | interface MapProps { |
| 15 | token?: string; | 14 | token?: string; |
| @@ -82,15 +81,15 @@ const Maps: React.FC<MapProps> = ({ token, isModerator }) => { | |||
| 82 | 81 | ||
| 83 | <section id="section2" className="summary1"> | 82 | <section id="section2" className="summary1"> |
| 84 | <button className="nav-button"> | 83 | <button className="nav-button"> |
| 85 | <img src={PortalIcon} alt="" /> | 84 | <img src={PortalIcon} alt="" className="w-6 h-6" /> |
| 86 | <span>Summary</span> | 85 | <span>Summary</span> |
| 87 | </button> | 86 | </button> |
| 88 | <button className="nav-button"> | 87 | <button className="nav-button"> |
| 89 | <img src={FlagIcon} alt="" /> | 88 | <img src={FlagIcon} alt="" className="w-6 h-6" /> |
| 90 | <span>Leaderboards</span> | 89 | <span>Leaderboards</span> |
| 91 | </button> | 90 | </button> |
| 92 | <button className="nav-button"> | 91 | <button className="nav-button"> |
| 93 | <img src={ChatIcon} alt="" /> | 92 | <img src={ChatIcon} alt="" className="w-6 h-6" /> |
| 94 | <span>Discussions</span> | 93 | <span>Discussions</span> |
| 95 | </button> | 94 | </button> |
| 96 | </section> | 95 | </section> |
| @@ -151,15 +150,15 @@ const Maps: React.FC<MapProps> = ({ token, isModerator }) => { | |||
| 151 | 150 | ||
| 152 | <section id="section2" className="summary1"> | 151 | <section id="section2" className="summary1"> |
| 153 | <button className="nav-button" onClick={() => setNavState(0)}> | 152 | <button className="nav-button" onClick={() => setNavState(0)}> |
| 154 | <img src={PortalIcon} alt="" /> | 153 | <img src={PortalIcon} alt="" className="w-6 h-6" /> |
| 155 | <span>Summary</span> | 154 | <span>Summary</span> |
| 156 | </button> | 155 | </button> |
| 157 | <button className="nav-button" onClick={() => setNavState(1)}> | 156 | <button className="nav-button" onClick={() => setNavState(1)}> |
| 158 | <img src={FlagIcon} alt="" /> | 157 | <img src={FlagIcon} alt="" className="w-6 h-6" /> |
| 159 | <span>Leaderboards</span> | 158 | <span>Leaderboards</span> |
| 160 | </button> | 159 | </button> |
| 161 | <button className="nav-button" onClick={() => setNavState(2)}> | 160 | <button className="nav-button" onClick={() => setNavState(2)}> |
| 162 | <img src={ChatIcon} alt="" /> | 161 | <img src={ChatIcon} alt="" className="w-6 h-6" /> |
| 163 | <span>Discussions</span> | 162 | <span>Discussions</span> |
| 164 | </button> | 163 | </button> |
| 165 | </section> | 164 | </section> |
diff --git a/frontend/src/pages/Profile.tsx b/frontend/src/pages/Profile.tsx index e2d6000..f44f587 100644 --- a/frontend/src/pages/Profile.tsx +++ b/frontend/src/pages/Profile.tsx | |||
| @@ -19,7 +19,6 @@ import { UserProfile } from "@customTypes/Profile"; | |||
| 19 | import { Game, GameChapters } from "@customTypes/Game"; | 19 | import { Game, GameChapters } from "@customTypes/Game"; |
| 20 | import { Map } from "@customTypes/Map"; | 20 | import { Map } from "@customTypes/Map"; |
| 21 | import { ticks_to_time } from "@utils/Time"; | 21 | import { ticks_to_time } from "@utils/Time"; |
| 22 | import "@css/Profile.css"; | ||
| 23 | import { API } from "@api/Api"; | 22 | import { API } from "@api/Api"; |
| 24 | import useConfirm from "@hooks/UseConfirm"; | 23 | import useConfirm from "@hooks/UseConfirm"; |
| 25 | import useMessage from "@hooks/UseMessage"; | 24 | import useMessage from "@hooks/UseMessage"; |
diff --git a/frontend/src/pages/Rules.tsx b/frontend/src/pages/Rules.tsx index 91027a0..7cdc08b 100644 --- a/frontend/src/pages/Rules.tsx +++ b/frontend/src/pages/Rules.tsx | |||
| @@ -2,8 +2,6 @@ import React from "react"; | |||
| 2 | import ReactMarkdown from "react-markdown"; | 2 | import ReactMarkdown from "react-markdown"; |
| 3 | import { Helmet } from "react-helmet"; | 3 | import { Helmet } from "react-helmet"; |
| 4 | 4 | ||
| 5 | import "@css/Rules.css"; | ||
| 6 | |||
| 7 | const Rules: React.FC = () => { | 5 | const Rules: React.FC = () => { |
| 8 | const [rulesText, setRulesText] = React.useState<string>(""); | 6 | const [rulesText, setRulesText] = React.useState<string>(""); |
| 9 | 7 | ||
| @@ -27,7 +25,7 @@ const Rules: React.FC = () => { | |||
| 27 | }, []); | 25 | }, []); |
| 28 | 26 | ||
| 29 | return ( | 27 | return ( |
| 30 | <main> | 28 | <main className="p-8 text-foreground font-[--font-barlow-semicondensed-regular] prose prose-invert max-w-none"> |
| 31 | <Helmet> | 29 | <Helmet> |
| 32 | <title>LPHUB | Rules</title> | 30 | <title>LPHUB | Rules</title> |
| 33 | </Helmet> | 31 | </Helmet> |
diff --git a/frontend/src/pages/User.tsx b/frontend/src/pages/User.tsx index 0198034..4b8a456 100644 --- a/frontend/src/pages/User.tsx +++ b/frontend/src/pages/User.tsx | |||
| @@ -19,7 +19,6 @@ import { Game, GameChapters } from "@customTypes/Game"; | |||
| 19 | import { Map } from "@customTypes/Map"; | 19 | import { Map } from "@customTypes/Map"; |
| 20 | import { API } from "@api/Api"; | 20 | import { API } from "@api/Api"; |
| 21 | import { ticks_to_time } from "@utils/Time"; | 21 | import { ticks_to_time } from "@utils/Time"; |
| 22 | import "@css/Profile.css"; | ||
| 23 | import useMessage from "@hooks/UseMessage"; | 22 | import useMessage from "@hooks/UseMessage"; |
| 24 | 23 | ||
| 25 | interface UserProps { | 24 | interface UserProps { |
diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index 3c2c9bd..aa41236 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts | |||
| @@ -1,9 +1,10 @@ | |||
| 1 | import { defineConfig } from 'vite' | 1 | import { defineConfig } from 'vite' |
| 2 | import react from '@vitejs/plugin-react' | 2 | import react from '@vitejs/plugin-react' |
| 3 | import tailwindcss from '@tailwindcss/vite' | ||
| 3 | import path from 'path' | 4 | import path from 'path' |
| 4 | 5 | ||
| 5 | export default defineConfig({ | 6 | export default defineConfig({ |
| 6 | plugins: [react()], | 7 | plugins: [react(), tailwindcss()], |
| 7 | resolve: { | 8 | resolve: { |
| 8 | alias: { | 9 | alias: { |
| 9 | '@api': path.resolve(__dirname, './src/api'), | 10 | '@api': path.resolve(__dirname, './src/api'), |
| @@ -20,7 +21,7 @@ export default defineConfig({ | |||
| 20 | port: 3000, | 21 | port: 3000, |
| 21 | proxy: { | 22 | proxy: { |
| 22 | '/api': { | 23 | '/api': { |
| 23 | target: 'http://localhost:8080', | 24 | target: 'https://lp.pektezol.dev/', |
| 24 | changeOrigin: true, | 25 | changeOrigin: true, |
| 25 | }, | 26 | }, |
| 26 | }, | 27 | }, |