From 0c615b75d2bf372712979b673dda753b06128f02 Mon Sep 17 00:00:00 2001 From: Arik Chakma Date: Wed, 14 Jun 2023 00:27:05 +0600 Subject: [PATCH] chore: roadmap select --- astro.config.mjs | 4 +- package.json | 7 + pnpm-lock.yaml | 339 ++++++++++++++++++++++ src/components/RoadCard/RoadCardPage.tsx | 101 ++++--- src/components/RoadCard/RoadmapSelect.tsx | 122 ++++++++ src/components/RoadCard/TallBadgeTab.tsx | 23 +- src/components/RoadCard/WideBadgeTab.tsx | 21 +- src/helper/get-badge-link.ts | 36 +++ src/lib/home-progress.ts | 3 +- src/pages/account/road-card.astro | 1 + 10 files changed, 595 insertions(+), 62 deletions(-) create mode 100644 src/components/RoadCard/RoadmapSelect.tsx create mode 100644 src/helper/get-badge-link.ts diff --git a/astro.config.mjs b/astro.config.mjs index e6f458986..ae782c390 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -58,6 +58,8 @@ export default defineConfig({ css: false, js: false, }), - preact(), + preact({ + compat: true, + }), ], }); diff --git a/package.json b/package.json index c6c0d5401..726d89d83 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "node-html-parser": "^6.1.5", "npm-check-updates": "^16.10.12", "preact": "^10.15.1", + "react-select": "^5.7.3", "rehype-external-links": "^2.1.0", "roadmap-renderer": "^1.0.6", "tailwindcss": "^3.3.2" @@ -50,5 +51,11 @@ "prettier": "^2.8.8", "prettier-plugin-astro": "^0.10.0", "prettier-plugin-tailwindcss": "^0.3.0" + }, + "pnpm": { + "overrides": { + "react": "npm:@preact/compat@latest", + "react-dom": "npm:@preact/compat@latest" + } } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 973b61e89..84dd95453 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -25,6 +25,7 @@ specifiers: prettier: ^2.8.8 prettier-plugin-astro: ^0.10.0 prettier-plugin-tailwindcss: ^0.3.0 + react-select: ^5.7.3 rehype-external-links: ^2.1.0 roadmap-renderer: ^1.0.6 tailwindcss: ^3.3.2 @@ -43,6 +44,7 @@ dependencies: node-html-parser: 6.1.5 npm-check-updates: 16.10.12 preact: 10.15.1 + react-select: 5.7.3_biqbaboplfbrettd7655fr4n2y rehype-external-links: 2.1.0 roadmap-renderer: 1.0.6 tailwindcss: 3.3.2 @@ -503,6 +505,13 @@ packages: '@babel/types': 7.21.5 dev: false + /@babel/runtime/7.22.5: + resolution: {integrity: sha512-ecjvYlnAaZ/KVneE/OdKYBYfgXV3Ptu6zQWmgEF7vwKhQnvVS6bjMD2XYgj+SNvQ1GfK/pjgokfPkC/2CO8CuA==} + engines: {node: '>=6.9.0'} + dependencies: + regenerator-runtime: 0.13.11 + dev: false + /@babel/template/7.20.7: resolution: {integrity: sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==} engines: {node: '>=6.9.0'} @@ -598,6 +607,94 @@ packages: resolution: {integrity: sha512-1ESCGgXRgn1r29hRmz8K0G4Ywr5jDWezMgRnICComBCWmg3znLWU8+tmakuM1og1Vn4W/sauvlABl/oq2pve8w==} dev: false + /@emotion/babel-plugin/11.11.0: + resolution: {integrity: sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==} + dependencies: + '@babel/helper-module-imports': 7.21.4 + '@babel/runtime': 7.22.5 + '@emotion/hash': 0.9.1 + '@emotion/memoize': 0.8.1 + '@emotion/serialize': 1.1.2 + babel-plugin-macros: 3.1.0 + convert-source-map: 1.9.0 + escape-string-regexp: 4.0.0 + find-root: 1.1.0 + source-map: 0.5.7 + stylis: 4.2.0 + dev: false + + /@emotion/cache/11.11.0: + resolution: {integrity: sha512-P34z9ssTCBi3e9EI1ZsWpNHcfY1r09ZO0rZbRO2ob3ZQMnFI35jB536qoXbkdesr5EUhYi22anuEJuyxifaqAQ==} + dependencies: + '@emotion/memoize': 0.8.1 + '@emotion/sheet': 1.2.2 + '@emotion/utils': 1.2.1 + '@emotion/weak-memoize': 0.3.1 + stylis: 4.2.0 + dev: false + + /@emotion/hash/0.9.1: + resolution: {integrity: sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==} + dev: false + + /@emotion/memoize/0.8.1: + resolution: {integrity: sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==} + dev: false + + /@emotion/react/11.11.1_react@18.2.0: + resolution: {integrity: sha512-5mlW1DquU5HaxjLkfkGN1GA/fvVGdyHURRiX/0FHl2cfIfRxSOfmxEH5YS43edp0OldZrZ+dkBKbngxcNCdZvA==} + peerDependencies: + '@types/react': '*' + react: '>=16.8.0' + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@babel/runtime': 7.22.5 + '@emotion/babel-plugin': 11.11.0 + '@emotion/cache': 11.11.0 + '@emotion/serialize': 1.1.2 + '@emotion/use-insertion-effect-with-fallbacks': 1.0.1_react@18.2.0 + '@emotion/utils': 1.2.1 + '@emotion/weak-memoize': 0.3.1 + hoist-non-react-statics: 3.3.2 + react: 18.2.0 + dev: false + + /@emotion/serialize/1.1.2: + resolution: {integrity: sha512-zR6a/fkFP4EAcCMQtLOhIgpprZOwNmCldtpaISpvz348+DP4Mz8ZoKaGGCQpbzepNIUWbq4w6hNZkwDyKoS+HA==} + dependencies: + '@emotion/hash': 0.9.1 + '@emotion/memoize': 0.8.1 + '@emotion/unitless': 0.8.1 + '@emotion/utils': 1.2.1 + csstype: 3.1.2 + dev: false + + /@emotion/sheet/1.2.2: + resolution: {integrity: sha512-0QBtGvaqtWi+nx6doRwDdBIzhNdZrXUppvTM4dtZZWEGTXL/XE/yJxLMGlDT1Gt+UHH5IX1n+jkXyytE/av7OA==} + dev: false + + /@emotion/unitless/0.8.1: + resolution: {integrity: sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==} + dev: false + + /@emotion/use-insertion-effect-with-fallbacks/1.0.1_react@18.2.0: + resolution: {integrity: sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==} + peerDependencies: + react: '>=16.8.0' + dependencies: + react: 18.2.0 + dev: false + + /@emotion/utils/1.2.1: + resolution: {integrity: sha512-Y2tGf3I+XVnajdItskUCn6LX+VUDmP6lTL4fcqsXAv43dnlbZiuW4MWQW38rW/BVWSE7Q/7+XQocmpnRYILUmg==} + dev: false + + /@emotion/weak-memoize/0.3.1: + resolution: {integrity: sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww==} + dev: false + /@esbuild/android-arm/0.17.18: resolution: {integrity: sha512-EmwL+vUBZJ7mhFCs5lA4ZimpUH3WMAoqvOIYhVQwdIgSpHC8ImHdsRyhHAVxpDYUSm0lWvd63z0XH1IlImS2Qw==} engines: {node: '>=12'} @@ -802,6 +899,16 @@ packages: tslib: 2.5.0 dev: false + /@floating-ui/core/1.3.0: + resolution: {integrity: sha512-vX1WVAdPjZg9DkDkC+zEx/tKtnST6/qcNpwcjeBgco3XRNHz5PUA+ivi/yr6G3o0kMR60uKBJcfOdfzOFI7PMQ==} + dev: false + + /@floating-ui/dom/1.3.0: + resolution: {integrity: sha512-qIAwejE3r6NeA107u4ELDKkH8+VtgRKdXqtSPaKflL2S2V+doyN+Wt9s5oHKXPDo4E8TaVXaHT3+6BbagH31xw==} + dependencies: + '@floating-ui/core': 1.3.0 + dev: false + /@gar/promisify/1.1.3: resolution: {integrity: sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==} dev: false @@ -1162,10 +1269,32 @@ packages: /@types/node/18.16.3: resolution: {integrity: sha512-OPs5WnnT1xkCBiuQrZA4+YAV4HEJejmHneyraIaxsbev5yCEr6KMwINNFP9wQeFIw8FWcoTqF3vQsa5CDaI+8Q==} + /@types/parse-json/4.0.0: + resolution: {integrity: sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==} + dev: false + /@types/parse5/6.0.3: resolution: {integrity: sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g==} dev: false + /@types/prop-types/15.7.5: + resolution: {integrity: sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==} + dev: false + + /@types/react-transition-group/4.4.6: + resolution: {integrity: sha512-VnCdSxfcm08KjsJVQcfBmhEQAPnLB8G08hAxn39azX1qYBQ/5RVQuoHuKIcfKOdncuaUvEpFKFzEvbtIMsfVew==} + dependencies: + '@types/react': 18.2.12 + dev: false + + /@types/react/18.2.12: + resolution: {integrity: sha512-ndmBMLCgn38v3SntMeoJaIrO6tGHYKMEBohCUmw8HoLLQdRMOIGXfeYaBTLe2lsFaSB3MOK1VXscYFnmLtTSmw==} + dependencies: + '@types/prop-types': 15.7.5 + '@types/scheduler': 0.16.3 + csstype: 3.1.2 + dev: false + /@types/resolve/1.20.2: resolution: {integrity: sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==} dev: false @@ -1176,6 +1305,10 @@ packages: '@types/node': 18.16.3 dev: false + /@types/scheduler/0.16.3: + resolution: {integrity: sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==} + dev: false + /@types/unist/2.0.6: resolution: {integrity: sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ==} dev: false @@ -1451,6 +1584,15 @@ packages: - debug dev: true + /babel-plugin-macros/3.1.0: + resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==} + engines: {node: '>=10', npm: '>=6'} + dependencies: + '@babel/runtime': 7.22.5 + cosmiconfig: 7.1.0 + resolve: 1.22.2 + dev: false + /babel-plugin-module-resolver/5.0.0: resolution: {integrity: sha512-g0u+/ChLSJ5+PzYwLwP8Rp8Rcfowz58TJNCe+L/ui4rpzE/mg//JVX0EWBUYoxaextqnwuGHzfGp2hh0PPV25Q==} engines: {node: '>= 16'} @@ -1650,6 +1792,11 @@ packages: responselike: 3.0.0 dev: false + /callsites/3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + dev: false + /camel-case/4.1.2: resolution: {integrity: sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==} dependencies: @@ -1904,6 +2051,17 @@ packages: engines: {node: '>= 0.6'} dev: false + /cosmiconfig/7.1.0: + resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==} + engines: {node: '>=10'} + dependencies: + '@types/parse-json': 4.0.0 + import-fresh: 3.3.0 + parse-json: 5.2.0 + path-type: 4.0.0 + yaml: 1.10.2 + dev: false + /cross-spawn/7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} @@ -1963,6 +2121,10 @@ packages: css-tree: 2.2.1 dev: false + /csstype/3.1.2: + resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==} + dev: false + /csv-parser/3.0.0: resolution: {integrity: sha512-s6OYSXAK3IdKqYO33y09jhypG/bSDHPuyCme/IdEHfWpLf/jKcpitVFyOC6UemgGk8v7Q5u2XE0vvwmanxhGlQ==} engines: {node: '>= 10'} @@ -2078,6 +2240,13 @@ packages: /dlv/1.1.3: resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} + /dom-helpers/5.2.1: + resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==} + dependencies: + '@babel/runtime': 7.22.5 + csstype: 3.1.2 + dev: false + /dom-serializer/2.0.0: resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} dependencies: @@ -2184,6 +2353,12 @@ packages: resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==} dev: false + /error-ex/1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + dependencies: + is-arrayish: 0.2.1 + dev: false + /es-module-lexer/1.2.1: resolution: {integrity: sha512-9978wrXM50Y4rTMmW5kXIC09ZdXQZqkE4mxhwkd8VbzsGkXGPgV4zWuqQJgCEzYngdo2dYDa0l8xhX4fkSwJSg==} dev: false @@ -2232,6 +2407,11 @@ packages: resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} engines: {node: '>=0.8.0'} + /escape-string-regexp/4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + dev: false + /escape-string-regexp/5.0.0: resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} engines: {node: '>=12'} @@ -2346,6 +2526,10 @@ packages: pkg-dir: 4.2.0 dev: true + /find-root/1.1.0: + resolution: {integrity: sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==} + dev: false + /find-up/3.0.0: resolution: {integrity: sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==} engines: {node: '>=6'} @@ -2761,6 +2945,12 @@ packages: hasBin: true dev: false + /hoist-non-react-statics/3.3.2: + resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} + dependencies: + react-is: 16.13.1 + dev: false + /hosted-git-info/5.2.1: resolution: {integrity: sha512-xIcQYMnhcx2Nr4JTjsFmwwnr9vldugPy9uVm0o87bjqqWMv9GaqsTeT+i99wTl0mk1uLxJtHxLb8kymqTENQsw==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} @@ -2865,6 +3055,14 @@ packages: engines: {node: '>= 4'} dev: false + /import-fresh/3.3.0: + resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + engines: {node: '>=6'} + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + dev: false + /import-lazy/4.0.0: resolution: {integrity: sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==} engines: {node: '>=8'} @@ -2920,6 +3118,10 @@ packages: engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dev: false + /is-arrayish/0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + dev: false + /is-arrayish/0.3.2: resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} dev: false @@ -3104,6 +3306,10 @@ packages: resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} dev: false + /json-parse-even-better-errors/2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + dev: false + /json-parse-even-better-errors/3.0.0: resolution: {integrity: sha512-iZbGHafX/59r39gPwVPRBGw0QQKnA7tte5pSMrhWOW7swGsVvVTjmfyAV9pNqk8YGT7tRCdxRu8uzcgZwoDooA==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} @@ -3244,6 +3450,13 @@ packages: resolution: {integrity: sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==} dev: false + /loose-envify/1.4.0: + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + hasBin: true + dependencies: + js-tokens: 4.0.0 + dev: false + /lower-case/2.0.2: resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} dependencies: @@ -3499,6 +3712,10 @@ packages: resolution: {integrity: sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==} dev: true + /memoize-one/6.0.0: + resolution: {integrity: sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==} + dev: false + /merge-stream/2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} dev: false @@ -4333,12 +4550,29 @@ packages: tslib: 2.5.0 dev: false + /parent-module/1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + dependencies: + callsites: 3.1.0 + dev: false + /parse-github-url/1.0.2: resolution: {integrity: sha512-kgBf6avCbO3Cn6+RnzRGLkUsv4ZVqv/VfAYkRsyBcgkshNvVBkRn1FEZcW0Jb+npXQWm2vHPnnOqFteZxRRGNw==} engines: {node: '>=0.10.0'} hasBin: true dev: false + /parse-json/5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + dependencies: + '@babel/code-frame': 7.21.4 + error-ex: 1.3.2 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + dev: false + /parse-latin/5.0.1: resolution: {integrity: sha512-b/K8ExXaWC9t34kKeDV8kGXBkXZ1HCSAZRYE7HR14eA1GlXX5L8iWhs8USJNhQU9q5ci413jCKF0gOyovvyRBg==} dependencies: @@ -4697,6 +4931,14 @@ packages: sisteransi: 1.0.5 dev: false + /prop-types/15.8.1: + resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} + dependencies: + loose-envify: 1.4.0 + object-assign: 4.1.1 + react-is: 16.13.1 + dev: false + /property-information/6.2.0: resolution: {integrity: sha512-kma4U7AFCTwpqq5twzC1YVIDXSqg6qQK6JN0smOw8fgRy1OkMi0CYSzFmsy6dnqSenamAtj0CyXMUJ1Mf6oROg==} dev: false @@ -4748,6 +4990,62 @@ packages: strip-json-comments: 2.0.1 dev: false + /react-dom/18.2.0_react@18.2.0: + resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==} + peerDependencies: + react: ^18.2.0 + dependencies: + loose-envify: 1.4.0 + react: 18.2.0 + scheduler: 0.23.0 + dev: false + + /react-is/16.13.1: + resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} + dev: false + + /react-select/5.7.3_biqbaboplfbrettd7655fr4n2y: + resolution: {integrity: sha512-z8i3NCuFFWL3w27xq92rBkVI2onT0jzIIPe480HlBjXJ3b5o6Q+Clp4ydyeKrj9DZZ3lrjawwLC5NGl0FSvUDg==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 + dependencies: + '@babel/runtime': 7.22.5 + '@emotion/cache': 11.11.0 + '@emotion/react': 11.11.1_react@18.2.0 + '@floating-ui/dom': 1.3.0 + '@types/react-transition-group': 4.4.6 + memoize-one: 6.0.0 + prop-types: 15.8.1 + react: 18.2.0 + react-dom: 18.2.0_react@18.2.0 + react-transition-group: 4.4.5_biqbaboplfbrettd7655fr4n2y + use-isomorphic-layout-effect: 1.1.2_react@18.2.0 + transitivePeerDependencies: + - '@types/react' + dev: false + + /react-transition-group/4.4.5_biqbaboplfbrettd7655fr4n2y: + resolution: {integrity: sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==} + peerDependencies: + react: '>=16.6.0' + react-dom: '>=16.6.0' + dependencies: + '@babel/runtime': 7.22.5 + dom-helpers: 5.2.1 + loose-envify: 1.4.0 + prop-types: 15.8.1 + react: 18.2.0 + react-dom: 18.2.0_react@18.2.0 + dev: false + + /react/18.2.0: + resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==} + engines: {node: '>=0.10.0'} + dependencies: + loose-envify: 1.4.0 + dev: false + /read-cache/1.0.0: resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} dependencies: @@ -4786,6 +5084,10 @@ packages: dependencies: picomatch: 2.3.1 + /regenerator-runtime/0.13.11: + resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==} + dev: false + /registry-auth-token/5.0.2: resolution: {integrity: sha512-o/3ikDxtXaA59BmZuZrJZDJv8NMDGSj+6j6XaeBmHw8eY1i1qd9+6H+LjVvQXx3HN6aRCGa1cUdJ9RaJZUugnQ==} engines: {node: '>=14'} @@ -4908,6 +5210,11 @@ packages: resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==} dev: false + /resolve-from/4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + dev: false + /resolve/1.22.2: resolution: {integrity: sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==} hasBin: true @@ -5035,6 +5342,12 @@ packages: resolution: {integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==} dev: false + /scheduler/0.23.0: + resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==} + dependencies: + loose-envify: 1.4.0 + dev: false + /section-matter/1.0.0: resolution: {integrity: sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==} engines: {node: '>=4'} @@ -5210,6 +5523,11 @@ packages: source-map: 0.6.1 dev: false + /source-map/0.5.7: + resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} + engines: {node: '>=0.10.0'} + dev: false + /source-map/0.6.1: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} @@ -5360,6 +5678,10 @@ packages: escape-string-regexp: 1.0.5 dev: true + /stylis/4.2.0: + resolution: {integrity: sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==} + dev: false + /sucrase/3.32.0: resolution: {integrity: sha512-ydQOU34rpSyj2TGyz4D2p8rbktIOZ8QY9s+DGLvFU1i5pWJE8vkpruCjGCMHsdXwnD7JDcS+noSwM/a7zyNFDQ==} engines: {node: '>=8'} @@ -5756,6 +6078,18 @@ packages: xdg-basedir: 5.1.0 dev: false + /use-isomorphic-layout-effect/1.1.2_react@18.2.0: + resolution: {integrity: sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + react: 18.2.0 + dev: false + /util-deprecate/1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} @@ -6006,6 +6340,11 @@ packages: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} dev: false + /yaml/1.10.2: + resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} + engines: {node: '>= 6'} + dev: false + /yaml/2.2.2: resolution: {integrity: sha512-CBKFWExMn46Foo4cldiChEzn7S7SRV+wqiluAb6xmueD/fGyRHIhX8m14vVGgeFWjN540nKCNVj6P21eQjgTuA==} engines: {node: '>= 14'} diff --git a/src/components/RoadCard/RoadCardPage.tsx b/src/components/RoadCard/RoadCardPage.tsx index e88373ffe..842b8b857 100644 --- a/src/components/RoadCard/RoadCardPage.tsx +++ b/src/components/RoadCard/RoadCardPage.tsx @@ -1,38 +1,14 @@ -import { useState } from 'preact/hooks'; +import { useEffect, useState } from 'preact/hooks'; import { useCopyText } from '../../hooks/use-copy-text'; import { useAuth } from '../../hooks/use-auth'; import { TallBadgeTab } from './TallBadgeTab'; -import WideBadgeTab from './WideBadgeTab'; +import { WideBadgeTab } from './WideBadgeTab'; import CopyIcon from '../../icons/copy.svg'; - -export type GetBadgeLinkProps = { - user: ReturnType; - variant: 'dark' | 'light'; - badge: 'tall' | 'wide'; -}; - -export function getBadgeLink({ user, variant, badge }: GetBadgeLinkProps) { - const badgeUrl = `${import.meta.env.PUBLIC_API_URL}/v1-badge/${badge}/${ - user?.id - }${variant ? `?variant=${variant}` : ''}`; - const textareaContent = ` - - ${user?.name}${user?.name && - - `.trim(); - const markdownSnippet = ` - [![${user?.name}${ - user?.name && "'s" - } Road Card](${badgeUrl})](${badgeUrl}) - `.trim(); - - return { - badgeUrl, - textareaContent, - markdownSnippet, - }; -} +import { RoadmapSelect, RoadmapSelectProps } from './RoadmapSelect'; +import { httpGet } from '../../lib/http'; +import { pageProgressMessage } from '../../stores/page'; +import type { UserProgressResponse } from '../../lib/home-progress'; type EditorProps = { title: string; @@ -45,7 +21,7 @@ export function Editor(props: EditorProps) { const { isCopied, copyText } = useCopyText(); return ( -
+
{title} @@ -76,12 +52,45 @@ export type BadgeProps = { export function RoadCardPage() { const [selectedBadge, setSelectedBadge] = useState<'tall' | 'wide'>('tall'); + const [progress, setProgress] = useState([]); + const [selectedRoadmaps, setSelectedRoadmap] = useState< + RoadmapSelectProps['options'] + >([]); const user = useAuth(); if (!user) { return null; } + const fetchProgress = async () => { + const { response: progressList, error } = + await httpGet( + `${import.meta.env.PUBLIC_API_URL}/v1-get-user-all-progress` + ); + + if (error || !progressList) { + return; + } + + const enrichedRoadmaps = []; + for (const progress of progressList) { + if (progress.resourceType !== 'roadmap') return; + + enrichedRoadmaps.push({ + label: progress.resourceTitle, + value: progress.resourceId, + }); + } + + setProgress(enrichedRoadmaps); + }; + + useEffect(() => { + fetchProgress().finally(() => { + pageProgressMessage.set(''); + }); + }, []); + return ( <>
@@ -95,11 +104,10 @@ export function RoadCardPage() {
- {selectedBadge === 'tall' && } - {selectedBadge === 'wide' && } + + +
+ {selectedBadge === 'tall' && } + {selectedBadge === 'wide' && } +
); } diff --git a/src/components/RoadCard/RoadmapSelect.tsx b/src/components/RoadCard/RoadmapSelect.tsx new file mode 100644 index 000000000..838564c13 --- /dev/null +++ b/src/components/RoadCard/RoadmapSelect.tsx @@ -0,0 +1,122 @@ +import Select, { ActionMeta, OnChangeValue } from 'react-select'; + +export type RoadmapOptionProps = { + value: string; + label: string; +}; + +export interface RoadmapSelectProps { + options: RoadmapOptionProps[]; + selectedRoadmaps: RoadmapOptionProps[]; + setSelectedRoadmap: (roadmap: RoadmapOptionProps[]) => void; +} + +const controlStyles = { + base: 'border rounded-lg bg-white hover:cursor-pointer', + focus: 'border-primary-600 ring-1 ring-primary-500', + nonFocus: 'border-gray-300 hover:border-gray-400', +}; +const placeholderStyles = 'text-gray-500 pl-1 py-0.5'; +const selectInputStyles = 'pl-1 py-0.5'; +const valueContainerStyles = 'p-1 gap-1'; +const singleValueStyles = 'text-sm ml-1'; +const multiValueStyles = + 'bg-gray-100 rounded items-center py-0.5 pl-2 pr-1 gap-1.5'; +const multiValueLabelStyles = 'leading-none py-1 text-sm'; +const multiValueRemoveStyles = + 'border border-gray-200 bg-white hover:bg-red-50 hover:text-red-800 text-gray-500 hover:border-red-300 rounded-md p-0.5'; +const indicatorsContainerStyles = 'py-0 px-1 gap-1'; +const clearIndicatorStyles = + 'text-gray-500 p-1 rounded-md hover:bg-red-50 hover:text-red-800'; +const indicatorSeparatorStyles = 'bg-gray-300'; +const dropdownIndicatorStyles = + 'p-1 hover:bg-gray-100 text-gray-500 rounded-md hover:text-black'; +const menuStyles = + 'p-1 mt-2 border border-gray-200 bg-white rounded-lg shadow-lg'; +const groupHeadingStyles = 'ml-3 mt-2 mb-1 text-gray-500 text-sm'; +const optionStyles = { + base: 'hover:cursor-pointer px-3 text-sm py-2 rounded', + focus: 'bg-gray-100 active:bg-gray-200', + selected: "after:content-['✔'] after:ml-2 after:text-green-500 text-gray-500", +}; +const noOptionsMessageStyles = + 'text-gray-500 p-2 bg-gray-50 border border-dashed border-gray-200 rounded-sm'; + +export function RoadmapSelect({ + options, + selectedRoadmaps, + setSelectedRoadmap, +}: RoadmapSelectProps) { + const onChange = ( + newValue: OnChangeValue, + actionMeta: ActionMeta + ) => { + if (actionMeta.action === 'clear') { + setSelectedRoadmap([]); + return; + } + // Only allow selecting up to 4 roadmaps. + if (newValue.length > 4) { + return; + } + setSelectedRoadmap(Array.isArray(newValue) ? newValue : [newValue]); + }; + + return ( +
+ {/* @ts-ignore */} +