From 8d0fdab607eaa00a44c56340fbae76a470b6866a Mon Sep 17 00:00:00 2001 From: zkldi Date: Fri, 27 Aug 2021 08:38:57 +0100 Subject: [PATCH] User Page works --- client/package.json | 1 + client/pnpm-lock.yaml | 450 +++++++++++++++++- .../pages/dashboard/users/UserGamesPage.tsx | 89 ++++ .../app/pages/dashboard/users/UserPage.tsx | 109 ++++- .../_game/_playtype/LeaderboardsPage.tsx | 7 +- .../games/_game/_playtype/OverviewPage.tsx | 337 +------------ .../games/_game/_playtype/ScoresPage.tsx | 1 - client/src/app/routes/UserRoutes.tsx | 4 + .../layout/misc/BackgroundImage.tsx | 2 +- .../src/components/tables/cells/TitleCell.tsx | 6 +- .../tables/dropdowns/GenericScoreDropdown.tsx | 7 +- .../GenericScoreContentDropdown.tsx | 8 +- .../tables/dropdowns/components/PBCompare.tsx | 21 + client/src/components/user/UGPTHeader.tsx | 55 +-- .../src/components/user/UGPTRankingData.tsx | 15 + .../src/components/user/UGPTStatShowcase.tsx | 363 ++++++++++++++ .../src/components/user/UGPTStatsOverview.tsx | 52 ++ client/src/components/user/UserHeader.tsx | 7 +- client/src/components/util/GentleLink.tsx | 17 + client/src/components/util/Muted.tsx | 6 + client/src/types/api-returns.ts | 4 + 21 files changed, 1153 insertions(+), 408 deletions(-) create mode 100644 client/src/app/pages/dashboard/users/UserGamesPage.tsx create mode 100644 client/src/components/tables/dropdowns/components/PBCompare.tsx create mode 100644 client/src/components/user/UGPTRankingData.tsx create mode 100644 client/src/components/user/UGPTStatShowcase.tsx create mode 100644 client/src/components/user/UGPTStatsOverview.tsx create mode 100644 client/src/components/util/GentleLink.tsx create mode 100644 client/src/components/util/Muted.tsx diff --git a/client/package.json b/client/package.json index 1d4d5ac32..46c5e4b13 100644 --- a/client/package.json +++ b/client/package.json @@ -66,6 +66,7 @@ "react-bootstrap": "1.0.1", "react-dom": "16.12.0", "react-hot-toast": "2.0.0", + "react-markdown": "^7.0.1", "react-perfect-scrollbar": "1.5.8", "react-query": "3.18.1", "react-router": "5.2.0", diff --git a/client/pnpm-lock.yaml b/client/pnpm-lock.yaml index 8c1e5c475..10b4f4324 100644 --- a/client/pnpm-lock.yaml +++ b/client/pnpm-lock.yaml @@ -65,6 +65,7 @@ specifiers: react-dev-utils: ^9.1.0 react-dom: 16.12.0 react-hot-toast: 2.0.0 + react-markdown: ^7.0.1 react-perfect-scrollbar: 1.5.8 react-query: 3.18.1 react-router: 5.2.0 @@ -132,6 +133,7 @@ dependencies: react-bootstrap: 1.0.1_react-dom@16.12.0+react@17.0.2 react-dom: 16.12.0_react@17.0.2 react-hot-toast: 2.0.0_react-dom@16.12.0+react@17.0.2 + react-markdown: 7.0.1_43559efe81628b42e1e465743e6a3ffa react-perfect-scrollbar: 1.5.8_react-dom@16.12.0+react@17.0.2 react-query: 3.18.1_react-dom@16.12.0+react@17.0.2 react-router: 5.2.0_react@17.0.2 @@ -2923,6 +2925,18 @@ packages: '@types/node': 16.0.0 dev: false + /@types/debug/4.1.7: + resolution: {integrity: sha512-9AonUzyTjXXhEOa0DnqpzZi6VHlqKMswga9EXjpXnnqxwLtdvPPtlO8evrI5D9S6asFRCQ6v+wpiUKbw+vKqyg==} + dependencies: + '@types/ms': 0.7.31 + dev: false + + /@types/hast/2.3.4: + resolution: {integrity: sha512-wLEm0QvaoawEDoTRwzTXp4b4jpwiJDvR5KMnFnVodm3scufTlBOWRD6N1OBf9TZMhjlNsSfcO5V+7AF4+Vy+9g==} + dependencies: + '@types/unist': 2.0.6 + dev: false + /@types/history/4.7.9: resolution: {integrity: sha512-MUc6zSmU3tEVnkQ78q0peeEjKWPUADMlC/t++2bI8WnAG2tvYRPIgHG8lWkXwqc8MsUF6Z2MOf+Mh5sazOmhiQ==} dev: true @@ -2966,6 +2980,16 @@ packages: resolution: {integrity: sha512-cPiXpOvPFDr2edMnOXlz3UBDApwUfR+cpizvxCy0n3vp9bz/qe8BWzHPIEFcy+ogUOyjKuCISgyq77ELZPmkkg==} dev: true + /@types/mdast/3.0.10: + resolution: {integrity: sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA==} + dependencies: + '@types/unist': 2.0.6 + dev: false + + /@types/mdurl/1.0.2: + resolution: {integrity: sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==} + dev: false + /@types/mongodb/3.6.20: resolution: {integrity: sha512-WcdpPJCakFzcWWD9juKoZbRtQxKIMYF/JIAM4JrNHrMcnJL6/a2NWjXxW7fo9hxboxxkg+icff8d7+WIEvKgYQ==} dependencies: @@ -2973,6 +2997,10 @@ packages: '@types/node': 16.0.0 dev: false + /@types/ms/0.7.31: + resolution: {integrity: sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==} + dev: false + /@types/node/16.0.0: resolution: {integrity: sha512-TmCW5HoZ2o2/z2EYi109jLqIaPIi9y/lc2LmDCWzuCi35bcaQ+OtUh6nwBiFK7SOu25FAU5+YKdqFZUwtqGSdg==} @@ -3057,6 +3085,10 @@ packages: source-map: 0.6.1 dev: false + /@types/unist/2.0.6: + resolution: {integrity: sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==} + dev: false + /@types/warning/3.0.0: resolution: {integrity: sha1-DSUBJorY+ZYrdA04fEZU9fjiPlI=} dev: false @@ -3838,6 +3870,10 @@ packages: hasBin: true dev: true + /bail/2.0.1: + resolution: {integrity: sha512-d5FoTAr2S5DSUPKl85WNm2yUwsINN8eidIdIwsOge2t33DaOfOdSmmsI11jMN3GmALCXaw+Y6HMVHDzePshFAA==} + dev: false + /balanced-match/1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} @@ -4276,6 +4312,18 @@ packages: supports-color: 7.2.0 dev: true + /character-entities-legacy/2.0.0: + resolution: {integrity: sha512-YwaEtEvWLpFa6Wh3uVLrvirA/ahr9fki/NUd/Bd4OR6EdJ8D22hovYQEOUCBfQfcqnC4IAMGMsHXY1eXgL4ZZA==} + dev: false + + /character-entities/2.0.0: + resolution: {integrity: sha512-oHqMj3eAuJ77/P5PaIRcqk+C3hdfNwyCD2DAUcD5gyXkegAuF2USC40CEqPscDk4I8FRGMTojGJQkXDsN5QlJA==} + dev: false + + /character-reference-invalid/2.0.0: + resolution: {integrity: sha512-pE3Z15lLRxDzWJy7bBHBopRwfI20sbrMVLQTC7xsPglCHf4Wv1e167OgYAFP78co2XlhojDyAqA+IAJse27//g==} + dev: false + /chardet/0.7.0: resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} dev: true @@ -4496,6 +4544,10 @@ packages: delayed-stream: 1.0.0 dev: false + /comma-separated-tokens/2.0.2: + resolution: {integrity: sha512-G5yTt3KQN4Yn7Yk4ed73hlZ1evrFKXeUW3086p3PRFNp7m2vIjI6Pg+Kgb+oyzhd9F2qdcoj67+y3SdxL5XWsg==} + dev: false + /commander/2.1.0: resolution: {integrity: sha1-0SG7roYNmZKj1Re6lvVliOR8Z4E=} engines: {node: '>= 0.6.x'} @@ -7040,6 +7092,10 @@ packages: resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} dev: true + /inline-style-parser/0.1.1: + resolution: {integrity: sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q==} + dev: false + /inquirer/6.5.0: resolution: {integrity: sha512-scfHejeG/lVZSpvCXpsB4j/wQNPM5JC8kiElOI0OUTwmc1RTpXr4H32/HOlQHcZiYl2z2VElwuCVDRG8vFmbnA==} engines: {node: '>=6.0.0'} @@ -7127,6 +7183,17 @@ packages: kind-of: 6.0.3 dev: true + /is-alphabetical/2.0.0: + resolution: {integrity: sha512-5OV8Toyq3oh4eq6sbWTYzlGdnMT/DPI5I0zxUBxjiigQsZycpkKF3kskkao3JyYGuYDHvhgJF+DrjMQp9SX86w==} + dev: false + + /is-alphanumerical/2.0.0: + resolution: {integrity: sha512-t+2GlJ+hO9yagJ+jU3+HSh80VKvz/3cG2cxbGGm4S0hjKuhWQXgPVUVOZz3tqZzMjhmphZ+1TIJTlRZRoe6GCQ==} + dependencies: + is-alphabetical: 2.0.0 + is-decimal: 2.0.0 + dev: false + /is-arguments/1.1.1: resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} engines: {node: '>= 0.4'} @@ -7169,6 +7236,11 @@ packages: /is-buffer/1.1.6: resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==} + /is-buffer/2.0.5: + resolution: {integrity: sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==} + engines: {node: '>=4'} + dev: false + /is-callable/1.2.4: resolution: {integrity: sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==} engines: {node: '>= 0.4'} @@ -7208,6 +7280,10 @@ packages: dependencies: has-tostringtag: 1.0.0 + /is-decimal/2.0.0: + resolution: {integrity: sha512-QfrfjQV0LjoWQ1K1XSoEZkTAzSa14RKVMa5zg3SdAfzEmQzRM4+tbSFWb78creCeA9rNBzaZal92opi1TwPWZw==} + dev: false + /is-descriptor/0.1.6: resolution: {integrity: sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==} engines: {node: '>=0.10.0'} @@ -7272,6 +7348,10 @@ packages: dependencies: is-extglob: 2.1.1 + /is-hexadecimal/2.0.0: + resolution: {integrity: sha512-vGOtYkiaxwIiR0+Ng/zNId+ZZehGfINwTzdrDqc6iubbnQWhnPuYymOzOKUDqa2cSl59yHnEh2h6MvRLQsyNug==} + dev: false + /is-in-browser/1.1.3: resolution: {integrity: sha1-Vv9NtoOgeMYILrldrX3GLh0E+DU=} dev: false @@ -7330,6 +7410,11 @@ packages: engines: {node: '>=0.10.0'} dev: false + /is-plain-obj/4.0.0: + resolution: {integrity: sha512-NXRbBtUdBioI73y/HmOhogw/U5msYPC9DAtGkJXeFcFWSFZw0mCUsPxk/snTuJHzNKA8kLBK4rH97RMB1BfCXw==} + engines: {node: '>=12'} + dev: false + /is-plain-object/2.0.4: resolution: {integrity: sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==} engines: {node: '>=0.10.0'} @@ -8004,12 +8089,59 @@ packages: safe-buffer: 5.2.1 dev: true + /mdast-util-definitions/5.1.0: + resolution: {integrity: sha512-5hcR7FL2EuZ4q6lLMUK5w4lHT2H3vqL9quPvYZ/Ku5iifrirfMHiGdhxdXMUbUkDmz5I+TYMd7nbaxUhbQkfpQ==} + dependencies: + '@types/mdast': 3.0.10 + '@types/unist': 2.0.6 + unist-util-visit: 3.1.0 + dev: false + + /mdast-util-from-markdown/1.0.0: + resolution: {integrity: sha512-uj2G60sb7z1PNOeElFwCC9b/Se/lFXuLhVKFOAY2EHz/VvgbupTQRNXPoZl7rGpXYL6BNZgcgaybrlSWbo7n/g==} + dependencies: + '@types/mdast': 3.0.10 + '@types/unist': 2.0.6 + mdast-util-to-string: 3.1.0 + micromark: 3.0.5 + micromark-util-decode-numeric-character-reference: 1.0.0 + micromark-util-normalize-identifier: 1.0.0 + micromark-util-symbol: 1.0.0 + micromark-util-types: 1.0.1 + parse-entities: 3.0.0 + unist-util-stringify-position: 3.0.0 + transitivePeerDependencies: + - supports-color + dev: false + + /mdast-util-to-hast/11.2.0: + resolution: {integrity: sha512-KSYbg4PA9wk5YwoCZCPxbUAjdYunNN5TqTXoZp/9taRDGQS65cL2fFgKc78l0f3deg4p1LP9xdhmMuUrhAUSZA==} + dependencies: + '@types/hast': 2.3.4 + '@types/mdast': 3.0.10 + '@types/mdurl': 1.0.2 + mdast-util-definitions: 5.1.0 + mdurl: 1.0.1 + unist-builder: 3.0.0 + unist-util-generated: 2.0.0 + unist-util-position: 4.0.1 + unist-util-visit: 3.1.0 + dev: false + + /mdast-util-to-string/3.1.0: + resolution: {integrity: sha512-n4Vypz/DZgwo0iMHLQL49dJzlp7YtAJP+N07MZHpjPf/5XJuHUWstviF4Mn2jEiR/GNmtnRRqnwsXExk3igfFA==} + dev: false + /mdn-data/2.0.14: resolution: {integrity: sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==} /mdn-data/2.0.4: resolution: {integrity: sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==} + /mdurl/1.0.1: + resolution: {integrity: sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=} + dev: false + /media-typer/0.3.0: resolution: {integrity: sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=} engines: {node: '>= 0.6'} @@ -8071,6 +8203,168 @@ packages: resolution: {integrity: sha512-jo1OfR4TaEwd5HOrt5+tAZ9mqT4jmpNAusXtyfNzqVm9uiSYFZlKM1wYL4oU7azZW/PxQW53wM0S6OR1JHNa2g==} dev: true + /micromark-core-commonmark/1.0.1: + resolution: {integrity: sha512-vEOw8hcQ3nwHkKKNIyP9wBi8M50zjNajtmI+cCUWcVfJS+v5/3WCh4PLKf7PPRZFUutjzl4ZjlHwBWUKfb/SkA==} + dependencies: + micromark-factory-destination: 1.0.0 + micromark-factory-label: 1.0.0 + micromark-factory-space: 1.0.0 + micromark-factory-title: 1.0.0 + micromark-factory-whitespace: 1.0.0 + micromark-util-character: 1.1.0 + micromark-util-chunked: 1.0.0 + micromark-util-classify-character: 1.0.0 + micromark-util-html-tag-name: 1.0.0 + micromark-util-normalize-identifier: 1.0.0 + micromark-util-resolve-all: 1.0.0 + micromark-util-subtokenize: 1.0.0 + micromark-util-symbol: 1.0.0 + micromark-util-types: 1.0.1 + parse-entities: 3.0.0 + dev: false + + /micromark-factory-destination/1.0.0: + resolution: {integrity: sha512-eUBA7Rs1/xtTVun9TmV3gjfPz2wEwgK5R5xcbIM5ZYAtvGF6JkyaDsj0agx8urXnO31tEO6Ug83iVH3tdedLnw==} + dependencies: + micromark-util-character: 1.1.0 + micromark-util-symbol: 1.0.0 + micromark-util-types: 1.0.1 + dev: false + + /micromark-factory-label/1.0.0: + resolution: {integrity: sha512-XWEucVZb+qBCe2jmlOnWr6sWSY6NHx+wtpgYFsm4G+dufOf6tTQRRo0bdO7XSlGPu5fyjpJenth6Ksnc5Mwfww==} + dependencies: + micromark-util-character: 1.1.0 + micromark-util-symbol: 1.0.0 + micromark-util-types: 1.0.1 + dev: false + + /micromark-factory-space/1.0.0: + resolution: {integrity: sha512-qUmqs4kj9a5yBnk3JMLyjtWYN6Mzfcx8uJfi5XAveBniDevmZasdGBba5b4QsvRcAkmvGo5ACmSUmyGiKTLZew==} + dependencies: + micromark-util-character: 1.1.0 + micromark-util-types: 1.0.1 + dev: false + + /micromark-factory-title/1.0.0: + resolution: {integrity: sha512-flvC7Gx0dWVWorXuBl09Cr3wB5FTuYec8pMGVySIp2ZlqTcIjN/lFohZcP0EG//krTptm34kozHk7aK/CleCfA==} + dependencies: + micromark-factory-space: 1.0.0 + micromark-util-character: 1.1.0 + micromark-util-symbol: 1.0.0 + micromark-util-types: 1.0.1 + dev: false + + /micromark-factory-whitespace/1.0.0: + resolution: {integrity: sha512-Qx7uEyahU1lt1RnsECBiuEbfr9INjQTGa6Err+gF3g0Tx4YEviPbqqGKNv/NrBaE7dVHdn1bVZKM/n5I/Bak7A==} + dependencies: + micromark-factory-space: 1.0.0 + micromark-util-character: 1.1.0 + micromark-util-symbol: 1.0.0 + micromark-util-types: 1.0.1 + dev: false + + /micromark-util-character/1.1.0: + resolution: {integrity: sha512-agJ5B3unGNJ9rJvADMJ5ZiYjBRyDpzKAOk01Kpi1TKhlT1APx3XZk6eN7RtSz1erbWHC2L8T3xLZ81wdtGRZzg==} + dependencies: + micromark-util-symbol: 1.0.0 + micromark-util-types: 1.0.1 + dev: false + + /micromark-util-chunked/1.0.0: + resolution: {integrity: sha512-5e8xTis5tEZKgesfbQMKRCyzvffRRUX+lK/y+DvsMFdabAicPkkZV6gO+FEWi9RfuKKoxxPwNL+dFF0SMImc1g==} + dependencies: + micromark-util-symbol: 1.0.0 + dev: false + + /micromark-util-classify-character/1.0.0: + resolution: {integrity: sha512-F8oW2KKrQRb3vS5ud5HIqBVkCqQi224Nm55o5wYLzY/9PwHGXC01tr3d7+TqHHz6zrKQ72Okwtvm/xQm6OVNZA==} + dependencies: + micromark-util-character: 1.1.0 + micromark-util-symbol: 1.0.0 + micromark-util-types: 1.0.1 + dev: false + + /micromark-util-combine-extensions/1.0.0: + resolution: {integrity: sha512-J8H058vFBdo/6+AsjHp2NF7AJ02SZtWaVUjsayNFeAiydTxUwViQPxN0Hf8dp4FmCQi0UUFovFsEyRSUmFH3MA==} + dependencies: + micromark-util-chunked: 1.0.0 + micromark-util-types: 1.0.1 + dev: false + + /micromark-util-decode-numeric-character-reference/1.0.0: + resolution: {integrity: sha512-OzO9AI5VUtrTD7KSdagf4MWgHMtET17Ua1fIpXTpuhclCqD8egFWo85GxSGvxgkGS74bEahvtM0WP0HjvV0e4w==} + dependencies: + micromark-util-symbol: 1.0.0 + dev: false + + /micromark-util-encode/1.0.0: + resolution: {integrity: sha512-cJpFVM768h6zkd8qJ1LNRrITfY4gwFt+tziPcIf71Ui8yFzY9wG3snZQqiWVq93PG4Sw6YOtcNiKJfVIs9qfGg==} + dev: false + + /micromark-util-html-tag-name/1.0.0: + resolution: {integrity: sha512-NenEKIshW2ZI/ERv9HtFNsrn3llSPZtY337LID/24WeLqMzeZhBEE6BQ0vS2ZBjshm5n40chKtJ3qjAbVV8S0g==} + dev: false + + /micromark-util-normalize-identifier/1.0.0: + resolution: {integrity: sha512-yg+zrL14bBTFrQ7n35CmByWUTFsgst5JhA4gJYoty4Dqzj4Z4Fr/DHekSS5aLfH9bdlfnSvKAWsAgJhIbogyBg==} + dependencies: + micromark-util-symbol: 1.0.0 + dev: false + + /micromark-util-resolve-all/1.0.0: + resolution: {integrity: sha512-CB/AGk98u50k42kvgaMM94wzBqozSzDDaonKU7P7jwQIuH2RU0TeBqGYJz2WY1UdihhjweivStrJ2JdkdEmcfw==} + dependencies: + micromark-util-types: 1.0.1 + dev: false + + /micromark-util-sanitize-uri/1.0.0: + resolution: {integrity: sha512-cCxvBKlmac4rxCGx6ejlIviRaMKZc0fWm5HdCHEeDWRSkn44l6NdYVRyU+0nT1XC72EQJMZV8IPHF+jTr56lAg==} + dependencies: + micromark-util-character: 1.1.0 + micromark-util-encode: 1.0.0 + micromark-util-symbol: 1.0.0 + dev: false + + /micromark-util-subtokenize/1.0.0: + resolution: {integrity: sha512-EsnG2qscmcN5XhkqQBZni/4oQbLFjz9yk3ZM/P8a3YUjwV6+6On2wehr1ALx0MxK3+XXXLTzuBKHDFeDFYRdgQ==} + dependencies: + micromark-util-chunked: 1.0.0 + micromark-util-symbol: 1.0.0 + micromark-util-types: 1.0.1 + dev: false + + /micromark-util-symbol/1.0.0: + resolution: {integrity: sha512-NZA01jHRNCt4KlOROn8/bGi6vvpEmlXld7EHcRH+aYWUfL3Wc8JLUNNlqUMKa0hhz6GrpUWsHtzPmKof57v0gQ==} + dev: false + + /micromark-util-types/1.0.1: + resolution: {integrity: sha512-UT0ylWEEy80RFYzK9pEaugTqaxoD/j0Y9WhHpSyitxd99zjoQz7JJ+iKuhPAgOW2MiPSUAx+c09dcqokeyaROA==} + dev: false + + /micromark/3.0.5: + resolution: {integrity: sha512-QfjERBnPw0G9mxhOCkkbRP0n8SX8lIBLrEKeEVceviUukqVMv3hWE4AgNTOK/W6GWqtPvvIHg2Apl3j1Dxm6aQ==} + dependencies: + '@types/debug': 4.1.7 + debug: 4.3.2 + micromark-core-commonmark: 1.0.1 + micromark-factory-space: 1.0.0 + micromark-util-character: 1.1.0 + micromark-util-chunked: 1.0.0 + micromark-util-combine-extensions: 1.0.0 + micromark-util-decode-numeric-character-reference: 1.0.0 + micromark-util-encode: 1.0.0 + micromark-util-normalize-identifier: 1.0.0 + micromark-util-resolve-all: 1.0.0 + micromark-util-sanitize-uri: 1.0.0 + micromark-util-subtokenize: 1.0.0 + micromark-util-symbol: 1.0.0 + micromark-util-types: 1.0.1 + parse-entities: 3.0.0 + transitivePeerDependencies: + - supports-color + dev: false + /micromatch/3.1.10: resolution: {integrity: sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==} engines: {node: '>=0.10.0'} @@ -8916,6 +9210,17 @@ packages: safe-buffer: 5.2.1 dev: true + /parse-entities/3.0.0: + resolution: {integrity: sha512-AJlcIFDNPEP33KyJLguv0xJc83BNvjxwpuUIcetyXUsLpVXAUCePJ5kIoYtEN2R1ac0cYaRu/vk9dVFkewHQhQ==} + dependencies: + character-entities: 2.0.0 + character-entities-legacy: 2.0.0 + character-reference-invalid: 2.0.0 + is-alphanumerical: 2.0.0 + is-decimal: 2.0.0 + is-hexadecimal: 2.0.0 + dev: false + /parse-json/4.0.0: resolution: {integrity: sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=} engines: {node: '>=4'} @@ -9845,6 +10150,10 @@ packages: object-assign: 4.1.1 react-is: 16.13.1 + /property-information/6.0.1: + resolution: {integrity: sha512-F4WUUAF7fMeF4/JUFHNBWDaKDXi2jbvqBW/y6o5wsf3j19wTZ7S60TmtB5HoBhtgw7NKQRMWuz5vk2PR0CygUg==} + dev: false + /proxy-addr/2.0.7: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} engines: {node: '>= 0.10'} @@ -10101,12 +10410,36 @@ packages: /react-is/17.0.2: resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} - dev: true /react-lifecycles-compat/3.0.4: resolution: {integrity: sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==} dev: false + /react-markdown/7.0.1_43559efe81628b42e1e465743e6a3ffa: + resolution: {integrity: sha512-pthNPaoiwg0q7hukoE04F2ENwSzijIlWHJ4UMs/96LUe/G/P3FnbP4qHzx3FoNqae+2SqDG8vzniTLnJDeWneg==} + peerDependencies: + '@types/react': '>=16' + react: '>=16' + dependencies: + '@types/hast': 2.3.4 + '@types/react': 17.0.13 + '@types/unist': 2.0.6 + comma-separated-tokens: 2.0.2 + prop-types: 15.7.2 + property-information: 6.0.1 + react: 17.0.2 + react-is: 17.0.2 + remark-parse: 10.0.0 + remark-rehype: 9.0.0 + space-separated-tokens: 2.0.1 + style-to-object: 0.3.0 + unified: 10.1.0 + unist-util-visit: 4.0.0 + vfile: 5.1.0 + transitivePeerDependencies: + - supports-color + dev: false + /react-motion/0.5.2_react@17.0.2: resolution: {integrity: sha512-9q3YAvHoUiWlP3cK0v+w1N5Z23HXMj4IF4YuvjvWegWqNPfLXsOBE/V7UvQGpXxHFKRQQcNcVQE31g9SB/6qgQ==} peerDependencies: @@ -10415,6 +10748,25 @@ packages: es6-error: 4.1.1 dev: false + /remark-parse/10.0.0: + resolution: {integrity: sha512-07ei47p2Xl7Bqbn9H2VYQYirnAFJPwdMuypdozWsSbnmrkgA2e2sZLZdnDNrrsxR4onmIzH/J6KXqKxCuqHtPQ==} + dependencies: + '@types/mdast': 3.0.10 + mdast-util-from-markdown: 1.0.0 + unified: 10.1.0 + transitivePeerDependencies: + - supports-color + dev: false + + /remark-rehype/9.0.0: + resolution: {integrity: sha512-SFA+mPWu45ynFPKeT3h5eNNVAYoMp3wizr3KSKh1IQ9L6dLSyD25/df6/vv8EW8ji3O3dnZGdbLQl592Tn+ydg==} + dependencies: + '@types/hast': 2.3.4 + '@types/mdast': 3.0.10 + mdast-util-to-hast: 11.2.0 + unified: 10.1.0 + dev: false + /remove-accents/0.4.2: resolution: {integrity: sha1-CkPTqq4egNuRngeuJUsoXZ4ce7U=} dev: false @@ -11054,6 +11406,10 @@ packages: engines: {node: '>= 8'} dev: false + /space-separated-tokens/2.0.1: + resolution: {integrity: sha512-ekwEbFp5aqSPKaqeY1PGrlGQxPNaq+Cnx4+bE2D8sciBQrHpbwoBbawqTN2+6jPs9IdWxxiUcN0K2pkczD3zmw==} + dev: false + /sparse-bitfield/3.0.3: resolution: {integrity: sha1-/0rm5oZWBWuks+eSqzM004JzyhE=} dependencies: @@ -11346,6 +11702,12 @@ packages: webpack: 4.41.0 dev: true + /style-to-object/0.3.0: + resolution: {integrity: sha512-CzFnRRXhzWIdItT3OmF8SQfWyahHhjq3HwcMNCNLn+N7klOOqPjMeG/4JSu77D7ypZdGvSzvkrbyeTMizz2VrA==} + dependencies: + inline-style-parser: 0.1.1 + dev: false + /stylehacks/4.0.3: resolution: {integrity: sha512-7GlLk9JwlElY4Y6a/rmbH2MhVlTyVmiJd1PfTCqFaIBEGMYNsrO/v3SeGTdhBThLg4Z+NbOk/qFMwCa+J+3p/g==} engines: {node: '>=6.9.0'} @@ -11733,6 +12095,10 @@ packages: resolution: {integrity: sha1-N21NKdlR1jaKb3oK6FwvTV4GWPM=} dev: false + /trough/2.0.2: + resolution: {integrity: sha512-FnHq5sTMxC0sk957wHDzRnemFnNBvt/gSY99HzK8F7UP5WAbvP70yX5bd7CjEQkN+TjdxwI7g7lJ6podqrG2/w==} + dev: false + /ts-pnp/1.1.4_typescript@4.3.5: resolution: {integrity: sha512-1J/vefLC+BWSo+qe8OnJQfWTYRS6ingxjwqmHMqaMxXMj7kFtKLgAaYW3JeX3mktjgUL+etlU8/B4VUAUI9QGw==} engines: {node: '>=6'} @@ -11887,6 +12253,18 @@ packages: engines: {node: '>=4'} dev: false + /unified/10.1.0: + resolution: {integrity: sha512-4U3ru/BRXYYhKbwXV6lU6bufLikoAavTwev89H5UxY8enDFaAT2VXmIXYNm6hb5oHPng/EXr77PVyDFcptbk5g==} + dependencies: + '@types/unist': 2.0.6 + bail: 2.0.1 + extend: 3.0.2 + is-buffer: 2.0.5 + is-plain-obj: 4.0.0 + trough: 2.0.2 + vfile: 5.1.0 + dev: false + /union-value/1.0.1: resolution: {integrity: sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==} engines: {node: '>=0.10.0'} @@ -11915,6 +12293,60 @@ packages: imurmurhash: 0.1.4 dev: true + /unist-builder/3.0.0: + resolution: {integrity: sha512-GFxmfEAa0vi9i5sd0R2kcrI9ks0r82NasRq5QHh2ysGngrc6GiqD5CDf1FjPenY4vApmFASBIIlk/jj5J5YbmQ==} + dependencies: + '@types/unist': 2.0.6 + dev: false + + /unist-util-generated/2.0.0: + resolution: {integrity: sha512-TiWE6DVtVe7Ye2QxOVW9kqybs6cZexNwTwSMVgkfjEReqy/xwGpAXb99OxktoWwmL+Z+Epb0Dn8/GNDYP1wnUw==} + dev: false + + /unist-util-is/5.1.1: + resolution: {integrity: sha512-F5CZ68eYzuSvJjGhCLPL3cYx45IxkqXSetCcRgUXtbcm50X2L9oOWQlfUfDdAf+6Pd27YDblBfdtmsThXmwpbQ==} + dev: false + + /unist-util-position/4.0.1: + resolution: {integrity: sha512-mgy/zI9fQ2HlbOtTdr2w9lhVaiFUHWQnZrFF2EUoVOqtAUdzqMtNiD99qA5a1IcjWVR8O6aVYE9u7Z2z1v0SQA==} + dev: false + + /unist-util-stringify-position/3.0.0: + resolution: {integrity: sha512-SdfAl8fsDclywZpfMDTVDxA2V7LjtRDTOFd44wUJamgl6OlVngsqWjxvermMYf60elWHbxhuRCZml7AnuXCaSA==} + dependencies: + '@types/unist': 2.0.6 + dev: false + + /unist-util-visit-parents/4.1.1: + resolution: {integrity: sha512-1xAFJXAKpnnJl8G7K5KgU7FY55y3GcLIXqkzUj5QF/QVP7biUm0K0O2oqVkYsdjzJKifYeWn9+o6piAK2hGSHw==} + dependencies: + '@types/unist': 2.0.6 + unist-util-is: 5.1.1 + dev: false + + /unist-util-visit-parents/5.0.0: + resolution: {integrity: sha512-CVaLOYPM/EaFTYMytbaju3Tw4QI3DHnHFnL358FkEu0hZOzSm/hqBdVwOQDR60jF5ZzhB1tlZlRH0ll/yekZIQ==} + dependencies: + '@types/unist': 2.0.6 + unist-util-is: 5.1.1 + dev: false + + /unist-util-visit/3.1.0: + resolution: {integrity: sha512-Szoh+R/Ll68QWAyQyZZpQzZQm2UPbxibDvaY8Xc9SUtYgPsDzx5AWSk++UUt2hJuow8mvwR+rG+LQLw+KsuAKA==} + dependencies: + '@types/unist': 2.0.6 + unist-util-is: 5.1.1 + unist-util-visit-parents: 4.1.1 + dev: false + + /unist-util-visit/4.0.0: + resolution: {integrity: sha512-3HWTvrtU10/E7qgPznBfiOyG0TXj9W8c1GSfaI8L9GkaG1pLePiQPZ7E35a0R3ToQ/zcy4Im6aZ9WBgOTnv1MQ==} + dependencies: + '@types/unist': 2.0.6 + unist-util-is: 5.1.1 + unist-util-visit-parents: 5.0.0 + dev: false + /universalify/0.1.2: resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} engines: {node: '>= 4.0.0'} @@ -12073,6 +12505,22 @@ packages: extsprintf: 1.3.0 dev: false + /vfile-message/3.0.2: + resolution: {integrity: sha512-UUjZYIOg9lDRwwiBAuezLIsu9KlXntdxwG+nXnjuQAHvBpcX3x0eN8h+I7TkY5nkCXj+cWVp4ZqebtGBvok8ww==} + dependencies: + '@types/unist': 2.0.6 + unist-util-stringify-position: 3.0.0 + dev: false + + /vfile/5.1.0: + resolution: {integrity: sha512-4o7/DJjEaFPYSh0ckv5kcYkJTHQgCKdL8ozMM1jLAxO9ox95IzveDPXCZp08HamdWq8JXTkClDvfAKaeLQeKtg==} + dependencies: + '@types/unist': 2.0.6 + is-buffer: 2.0.5 + unist-util-stringify-position: 3.0.0 + vfile-message: 3.0.2 + dev: false + /vm-browserify/1.1.2: resolution: {integrity: sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==} dev: true diff --git a/client/src/app/pages/dashboard/users/UserGamesPage.tsx b/client/src/app/pages/dashboard/users/UserGamesPage.tsx new file mode 100644 index 000000000..17b809c8f --- /dev/null +++ b/client/src/app/pages/dashboard/users/UserGamesPage.tsx @@ -0,0 +1,89 @@ +import React, { useContext, useState, useMemo, useEffect } from "react"; +import { FormatGame, PublicUserDocument, UserGameStats } from "tachi-common"; +import useSetSubheader from "components/layout/header/useSetSubheader"; +import Card from "components/layout/page/Card"; +import ReactMarkdown from "react-markdown"; +import { UserContext } from "context/UserContext"; +import { Button } from "react-bootstrap"; +import { APIFetchV1 } from "util/api"; +import Divider from "components/util/Divider"; +import Muted from "components/util/Muted"; +import ExternalLink from "components/util/ExternalLink"; +import AsyncLoader from "components/util/AsyncLoader"; +import UGPTRatingsTable from "components/user/UGPTStatsOverview"; +import LinkButton from "components/util/LinkButton"; +import { UGSWithRankingData } from "types/api-returns"; +import RankingData from "components/user/UGPTRankingData"; + +interface Props { + reqUser: PublicUserDocument; +} + +export default function UserGamesPage({ reqUser }: Props) { + useSetSubheader(["Users", reqUser.username], [reqUser], `${reqUser.username}'s Profile`); + + return ( +
+ { + const res = await APIFetchV1( + `/users/${reqUser.id}/game-stats` + ); + + if (!res.success) { + throw new Error(res.description); + } + + return res.body; + }} + > + {ugs => + ugs.map((e, i) => { + // uses modulo to determine whether we're on the + // last row or not + // to do sizing like [12] or [6][6] instead of [3][3][3] + let mdSize = "6"; + let lgSize = "4"; + if (ugs.length - i <= ugs.length % 3) { + lgSize = (12 / (ugs.length % 3)).toString(); + } + + if (ugs.length - i <= ugs.length % 2) { + mdSize = (12 / (ugs.length % 2)).toString(); + } + + return ( +
+ +
+ ); + }) + } +
+
+ ); +} + +function GameStatContainer({ ugs, reqUser }: { ugs: UGSWithRankingData } & Props) { + return ( + + + View Game Profile + + + } + header={FormatGame(ugs.game, ugs.playtype)} + > + + + + ); +} diff --git a/client/src/app/pages/dashboard/users/UserPage.tsx b/client/src/app/pages/dashboard/users/UserPage.tsx index 215f7aa57..861806018 100644 --- a/client/src/app/pages/dashboard/users/UserPage.tsx +++ b/client/src/app/pages/dashboard/users/UserPage.tsx @@ -1,16 +1,109 @@ -import Loading from "components/util/Loading"; -import React from "react"; +import React, { useContext, useState, useMemo, useEffect } from "react"; import { PublicUserDocument } from "tachi-common"; -import { ToAPIURL } from "util/api"; -import Divider from "components/util/Divider"; import useSetSubheader from "components/layout/header/useSetSubheader"; +import Card from "components/layout/page/Card"; +import ReactMarkdown from "react-markdown"; +import { UserContext } from "context/UserContext"; +import { Button } from "react-bootstrap"; +import { APIFetchV1 } from "util/api"; +import Divider from "components/util/Divider"; +import Muted from "components/util/Muted"; +import ExternalLink from "components/util/ExternalLink"; -export default function UserPage({ reqUser }: { reqUser: PublicUserDocument }) { +interface Props { + reqUser: PublicUserDocument; +} + +export default function UserPage({ reqUser }: Props) { useSetSubheader(["Users", reqUser.username], [reqUser], `${reqUser.username}'s Profile`); - if (!reqUser) { - return ; + return ; +} + +function AboutMeCard({ reqUser }: Props) { + const { user } = useContext(UserContext); + + const [editMode, setEditMode] = useState(false); + const [content, setContent] = useState(reqUser.about); + + async function SubmitNewAboutMe(text: string) { + const res = await APIFetchV1( + `/users/${user!.id}`, + { + method: "PATCH", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ about: text }), + }, + true, + true + ); + + setEditMode(!res.success); } - return <>; + useEffect(() => { + if ( + editMode && + (content === "" || content === "") + ) { + alert(`1\n\n\n...Just kidding, this is an easter egg :)`); + } + }, [content]); + + const footer = useMemo(() => { + if (user?.id !== reqUser.id) { + return <>; + } + + if (!editMode) { + return ( +
+ +
+ ); + } + + return ( +
+ + +
+ ); + }, [editMode, reqUser]); + + return ( + + {editMode && ( + <> +