From b70095c99ed7933d9c011aa19273246021909472 Mon Sep 17 00:00:00 2001 From: Noa Virellia Date: Thu, 29 Jan 2026 22:17:16 +0800 Subject: [PATCH] feat(client): profile improvements Signed-off-by: Noa Virellia --- client/cms/eslint.config.js | 2 +- client/cms/package.json | 9 +- client/cms/pnpm-lock.yaml | 458 ++++++++++++++++++ .../cms/src/components/checkin/qr-dialog.tsx | 24 +- .../profile/edit-profile-dialog.tsx | 39 +- .../src/components/profile/main-profile.tsx | 29 +- .../cms/src/components/sidebar/nav-user.tsx | 20 +- client/cms/src/components/theme-provider.tsx | 1 - client/cms/src/components/ui/combobox.tsx | 310 ++++++++++++ client/cms/src/components/ui/input-group.tsx | 168 +++++++ client/cms/src/components/ui/switch.tsx | 33 ++ client/cms/src/components/ui/textarea.tsx | 18 + client/cms/src/hooks/data/useExchangeToken.ts | 12 +- client/cms/src/hooks/data/useGetMagicLink.ts | 6 +- client/cms/src/hooks/data/useUpdateUser.ts | 4 +- client/cms/src/hooks/data/useUserInfo.ts | 4 +- client/cms/src/lib/client.ts | 23 +- client/cms/src/lib/token.ts | 7 +- client/cms/src/routes/authorize.tsx | 7 +- client/cms/src/routes/token.tsx | 17 +- client/cms/src/vite.env.d.ts | 6 +- 21 files changed, 1114 insertions(+), 83 deletions(-) create mode 100644 client/cms/src/components/ui/combobox.tsx create mode 100644 client/cms/src/components/ui/input-group.tsx create mode 100644 client/cms/src/components/ui/switch.tsx create mode 100644 client/cms/src/components/ui/textarea.tsx diff --git a/client/cms/eslint.config.js b/client/cms/eslint.config.js index 75e958b..377f8ce 100644 --- a/client/cms/eslint.config.js +++ b/client/cms/eslint.config.js @@ -3,7 +3,7 @@ import pluginQuery from '@tanstack/eslint-plugin-query'; export default antfu({ gitignore: true, - ignores: ['**/node_modules/**', '**/dist/**', 'bun.lock', '**/routeTree.gen.ts', '**/ui/**', 'src/components/editor/**/*'], + ignores: ['**/node_modules/**', '**/dist/**', 'bun.lock', '**/routeTree.gen.ts', '**/ui/**', 'src/components/editor/**/*', 'src/client/**/*'], react: true, stylistic: { semi: true, diff --git a/client/cms/package.json b/client/cms/package.json index b01e804..7350502 100644 --- a/client/cms/package.json +++ b/client/cms/package.json @@ -3,6 +3,7 @@ "type": "module", "version": "0.0.0", "private": true, + "packageManager": "pnpm@10.28.1+sha512.7d7dbbca9e99447b7c3bf7a73286afaaf6be99251eb9498baefa7d406892f67b879adb3a1d7e687fc4ccc1a388c7175fbaae567a26ab44d1067b54fcb0d6a316", "scripts": { "dev": "vite", "build": "tsc -b && vite build", @@ -11,6 +12,10 @@ "gen": "openapi-ts" }, "dependencies": { + "@base-ui/react": "^1.1.0", + "@dicebear/collection": "^9.3.1", + "@dicebear/core": "^9.3.1", + "@dicebear/identicon": "^9.3.1", "@dnd-kit/core": "^6.3.1", "@dnd-kit/modifiers": "^9.0.0", "@dnd-kit/sortable": "^10.0.0", @@ -25,6 +30,7 @@ "@radix-ui/react-select": "^2.2.6", "@radix-ui/react-separator": "^1.1.8", "@radix-ui/react-slot": "^1.2.4", + "@radix-ui/react-switch": "^1.2.6", "@radix-ui/react-tabs": "^1.1.13", "@radix-ui/react-toggle": "^1.1.10", "@radix-ui/react-toggle-group": "^1.1.11", @@ -98,6 +104,5 @@ }, "lint-staged": { "*": "eslint --fix" - }, - "packageManager": "pnpm@10.28.1+sha512.7d7dbbca9e99447b7c3bf7a73286afaaf6be99251eb9498baefa7d406892f67b879adb3a1d7e687fc4ccc1a388c7175fbaae567a26ab44d1067b54fcb0d6a316" + } } diff --git a/client/cms/pnpm-lock.yaml b/client/cms/pnpm-lock.yaml index 1f4dcea..412997d 100644 --- a/client/cms/pnpm-lock.yaml +++ b/client/cms/pnpm-lock.yaml @@ -8,6 +8,18 @@ importers: .: dependencies: + '@base-ui/react': + specifier: ^1.1.0 + version: 1.1.0(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@dicebear/collection': + specifier: ^9.3.1 + version: 9.3.1(@dicebear/core@9.3.1) + '@dicebear/core': + specifier: ^9.3.1 + version: 9.3.1 + '@dicebear/identicon': + specifier: ^9.3.1 + version: 9.3.1(@dicebear/core@9.3.1) '@dnd-kit/core': specifier: ^6.3.1 version: 6.3.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3) @@ -50,6 +62,9 @@ importers: '@radix-ui/react-slot': specifier: ^1.2.4 version: 1.2.4(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-switch': + specifier: ^1.2.6 + version: 1.2.6(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@radix-ui/react-tabs': specifier: ^1.1.13 version: 1.1.13(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) @@ -406,12 +421,229 @@ packages: resolution: {integrity: sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==} engines: {node: '>=6.9.0'} + '@base-ui/react@1.1.0': + resolution: {integrity: sha512-ikcJRNj1mOiF2HZ5jQHrXoVoHcNHdBU5ejJljcBl+VTLoYXR6FidjTN86GjO6hyshi6TZFuNvv0dEOgaOFv6Lw==} + engines: {node: '>=14.0.0'} + peerDependencies: + '@types/react': ^17 || ^18 || ^19 + react: ^17 || ^18 || ^19 + react-dom: ^17 || ^18 || ^19 + peerDependenciesMeta: + '@types/react': + optional: true + + '@base-ui/utils@0.2.4': + resolution: {integrity: sha512-smZwpMhjO29v+jrZusBSc5T+IJ3vBb9cjIiBjtKcvWmRj9Z4DWGVR3efr1eHR56/bqY5a4qyY9ElkOY5ljo3ng==} + peerDependencies: + '@types/react': ^17 || ^18 || ^19 + react: ^17 || ^18 || ^19 + react-dom: ^17 || ^18 || ^19 + peerDependenciesMeta: + '@types/react': + optional: true + '@clack/core@0.5.0': resolution: {integrity: sha512-p3y0FIOwaYRUPRcMO7+dlmLh8PSRcrjuTndsiA0WAFbWES0mLZlrjVoBRZ9DzkPFJZG6KGkJmoEAY0ZcVWTkow==} '@clack/prompts@0.11.0': resolution: {integrity: sha512-pMN5FcrEw9hUkZA4f+zLlzivQSeQf5dRGJjSUbvVYDLvpKCdQx5OaknvKzgbtXOizhP+SJJJjqEbOe55uKKfAw==} + '@dicebear/adventurer-neutral@9.3.1': + resolution: {integrity: sha512-MKrzLkAGx0cdBVD+XJu6ERhdJjWsjoFS+0nF9MZT17h/m/Q12FSoj+ACoKTEXBS/LBQfQqjA9HstBlSxMzmBdw==} + engines: {node: '>=18.0.0'} + peerDependencies: + '@dicebear/core': ^9.0.0 + + '@dicebear/adventurer@9.3.1': + resolution: {integrity: sha512-MBCA8QtRC4mWbYncFDxI67LxxXMccsORqJS8osD4F/MgOPMJsdoN9QrRfsY/MjO+4NbTSxsVzOhn2nf1WzoLbA==} + engines: {node: '>=18.0.0'} + peerDependencies: + '@dicebear/core': ^9.0.0 + + '@dicebear/avataaars-neutral@9.3.1': + resolution: {integrity: sha512-d9enbUJcRfMui0ZESJ9ofJXKJPdqrzKgqefT9fcC8EfOvP0WqVtsUzcPj9l6FYhG1fMDdTsx+A8e//1lCynbQQ==} + engines: {node: '>=18.0.0'} + peerDependencies: + '@dicebear/core': ^9.0.0 + + '@dicebear/avataaars@9.3.1': + resolution: {integrity: sha512-gQwtaTfPVwNAvVktdTjyhGnQtt5ifeE/6XyMX/fUJTTo/uI2NLy4LedzjsibA/DW8xi+TbgUyXlyTaJs0H6MGA==} + engines: {node: '>=18.0.0'} + peerDependencies: + '@dicebear/core': ^9.0.0 + + '@dicebear/big-ears-neutral@9.3.1': + resolution: {integrity: sha512-Fvw/GoT+3q77zwUbHOujGujQ4oVgtoOXE7ByfxcPeVcaUUTRARpWXlNwUBg0zt+o/Dfv875awpt3sIgKuecGsw==} + engines: {node: '>=18.0.0'} + peerDependencies: + '@dicebear/core': ^9.0.0 + + '@dicebear/big-ears@9.3.1': + resolution: {integrity: sha512-JN2ZlrSvpKJNyRAFzyeg+Y5wBG0EZQc8Ds5bZIHkf2/uaLUQIeDT1At2Sr7hSJDKSYZ8z83H6ckbzpDl5b9MzQ==} + engines: {node: '>=18.0.0'} + peerDependencies: + '@dicebear/core': ^9.0.0 + + '@dicebear/big-smile@9.3.1': + resolution: {integrity: sha512-c5USb4n3Zw32WIJUZqc2+mCe3vbN6XJtZjKtFbisFujMAX6I3avRf6S1JBbm5oT86ynGH6P1/EZ2K7WkThfEBg==} + engines: {node: '>=18.0.0'} + peerDependencies: + '@dicebear/core': ^9.0.0 + + '@dicebear/bottts-neutral@9.3.1': + resolution: {integrity: sha512-Ea3dZ7/absDmedpFIZp+yoeS6Dq0sZ8W87xw39SS45Mr1s3i4lVd/0XWc9U5QBl0XrP4CQKB7b2QpcSY4tIYtg==} + engines: {node: '>=18.0.0'} + peerDependencies: + '@dicebear/core': ^9.0.0 + + '@dicebear/bottts@9.3.1': + resolution: {integrity: sha512-qIPokserYLIwpScbsvFADwspBfa1Mg8JFEtYcXYcbPLnNek8bZiAhpQSc1bHSqHjm10bFEjvTr0opSNr72CBzw==} + engines: {node: '>=18.0.0'} + peerDependencies: + '@dicebear/core': ^9.0.0 + + '@dicebear/collection@9.3.1': + resolution: {integrity: sha512-3hDYu9K4quu9jiXQTno2e0AyBzmrqm1PE6Mw7u2gYOZZ5GsSqrDdNHQODShyzqDF1LuyypZY4XN4YjFJ6fWqig==} + engines: {node: '>=18.0.0'} + peerDependencies: + '@dicebear/core': ^9.0.0 + + '@dicebear/core@9.3.1': + resolution: {integrity: sha512-N6Gl9z3SxYp1OVtOzQegtURFqr0D62l3QcXgvshDAVXDNjkziZ5gWj//JxYJRWldNZfVp9/pm97V3ExKI5AXPg==} + engines: {node: '>=18.0.0'} + + '@dicebear/croodles-neutral@9.3.1': + resolution: {integrity: sha512-NEOV/j+pqxhFmxSC4EFjPgjbTsnOXkX3WgLLVz0PZBpVpS2kPOwBQXZT2fUGZIq7zHucWWatnMaKBvd2LYmFhA==} + engines: {node: '>=18.0.0'} + peerDependencies: + '@dicebear/core': ^9.0.0 + + '@dicebear/croodles@9.3.1': + resolution: {integrity: sha512-p40OXll38AYpWh7vOVuapv6ClQuzaMh77e++QJjJGNr6n1OE6YmmQbp6XzE7iELzz2yGoCPIm/FjI+zcH0aAwA==} + engines: {node: '>=18.0.0'} + peerDependencies: + '@dicebear/core': ^9.0.0 + + '@dicebear/dylan@9.3.1': + resolution: {integrity: sha512-CWP8S9heivya/KSSF72IJ6QKE5bUsoxKSlnLD21uO+NAm5Mzkw00PM0cgA4RvnPNf0Et7HmoJXrrvOBavWE65A==} + engines: {node: '>=18.0.0'} + peerDependencies: + '@dicebear/core': ^9.0.0 + + '@dicebear/fun-emoji@9.3.1': + resolution: {integrity: sha512-oSJPxHvAnORxa3FJYwYGQcUuP5LIFRKzMJJ9RP4D5GTYmpjsdG0K895eo4vKkXrY/BVNVROBlfK0KcTX1xOU8g==} + engines: {node: '>=18.0.0'} + peerDependencies: + '@dicebear/core': ^9.0.0 + + '@dicebear/glass@9.3.1': + resolution: {integrity: sha512-yNxDgIE9A+/n5VgOMH8P0qb1EGsMhMSSrl0s6ZnTBpHLGwRv1iGXezJaZrkx/ZSPsp8KlOOfTodeqi2vkVdFHg==} + engines: {node: '>=18.0.0'} + peerDependencies: + '@dicebear/core': ^9.0.0 + + '@dicebear/icons@9.3.1': + resolution: {integrity: sha512-p8BrJ/6C2smLKU8vFFu+B54zD/GFbdjumVubzcURjvbOh1YOWU2CD4TruSBZ4d2zbAwgJIAjE+5oANB0a1gfdg==} + engines: {node: '>=18.0.0'} + peerDependencies: + '@dicebear/core': ^9.0.0 + + '@dicebear/identicon@9.3.1': + resolution: {integrity: sha512-P3TmN7pRqlS8S9/1E+lGEMrBbQvjjXGNgXnw+Okviq+41172iLVg6Wv0nbNsOyF9QjRTjrJMq4VT3XgOuU4JAg==} + engines: {node: '>=18.0.0'} + peerDependencies: + '@dicebear/core': ^9.0.0 + + '@dicebear/initials@9.3.1': + resolution: {integrity: sha512-1O61oYxKVeeGL6QcNCcxH7zsqbp37NmHbR/Y5CVqr6AVv0bBswvCzVzUv/Zmmsp70DoYQB+lbX+oNIdcqUWAaw==} + engines: {node: '>=18.0.0'} + peerDependencies: + '@dicebear/core': ^9.0.0 + + '@dicebear/lorelei-neutral@9.3.1': + resolution: {integrity: sha512-GP2EX3w8Di4b3XN0uM7lARbg1iZ9r0zaZHlUbCE2CzFy3xxrKSrRDYf2BvVt7x76doijXR5SLm4DMbEA9ARJWA==} + engines: {node: '>=18.0.0'} + peerDependencies: + '@dicebear/core': ^9.0.0 + + '@dicebear/lorelei@9.3.1': + resolution: {integrity: sha512-4btARyv+ITuL3GWKA68/h6hAPL52lN1034JHx+dJCjy7zXrsXvFKkQj62LbCkQKHQOihTkAW1dfccVQ7mlGn4w==} + engines: {node: '>=18.0.0'} + peerDependencies: + '@dicebear/core': ^9.0.0 + + '@dicebear/micah@9.3.1': + resolution: {integrity: sha512-LAPY6Zlw/nh0Xts4aIY5d0hlaJEfSah+M5GoBRzKFKlieYdee7hvE8gsCE+OZ4pZUc98Dh7h0XXqVt/ojYW3jw==} + engines: {node: '>=18.0.0'} + peerDependencies: + '@dicebear/core': ^9.0.0 + + '@dicebear/miniavs@9.3.1': + resolution: {integrity: sha512-LRLKxDAIk8fW/88YB0vbYiJ850FaO2EcdznOfyW0izDp0ghTGZXsO5B5RUiLTunH8ZCnDdA+DtaugaFTdvOx/Q==} + engines: {node: '>=18.0.0'} + peerDependencies: + '@dicebear/core': ^9.0.0 + + '@dicebear/notionists-neutral@9.3.1': + resolution: {integrity: sha512-Z9dikJjibAc94EtFnHQb1+ADMISLedgLls5+ARiKwKjPcYZcuRm4U8kR9tMLmqggro10uJlT7YrLSCC/5abUXA==} + engines: {node: '>=18.0.0'} + peerDependencies: + '@dicebear/core': ^9.0.0 + + '@dicebear/notionists@9.3.1': + resolution: {integrity: sha512-xSukD2J+iKaKq/kEOZ6svwon9sQYRpgIeNC7Gfskb7uyC+iUHQmCy6hSxLFGIOFVqEbw6Ow8uNpn9NqaFpQA4w==} + engines: {node: '>=18.0.0'} + peerDependencies: + '@dicebear/core': ^9.0.0 + + '@dicebear/open-peeps@9.3.1': + resolution: {integrity: sha512-g4A3XcLrKPy44ajlhWfmGXYUDzXfogzB/H7Z46k+mxvrhVSF0jsmReYjX80jqHNeEZ9ikIpR5g4Hbo6vmOmjGQ==} + engines: {node: '>=18.0.0'} + peerDependencies: + '@dicebear/core': ^9.0.0 + + '@dicebear/personas@9.3.1': + resolution: {integrity: sha512-2xqaiY0/uHKFNhC+ZEBINJZM9/fC8gUMFCqP4N6QuXkFbqNZn4RjgbTITkGtRE5Z4m2q9hEfPey4Dc9jep5lzA==} + engines: {node: '>=18.0.0'} + peerDependencies: + '@dicebear/core': ^9.0.0 + + '@dicebear/pixel-art-neutral@9.3.1': + resolution: {integrity: sha512-N3mcC4CFTAMk3TqRvZVsZAGY2NONnQwoGpP+MD4E2GF+kVWoQYpvzOybVgFoOz2G0Oe4HAwSO5Qt7KTbAiD7KA==} + engines: {node: '>=18.0.0'} + peerDependencies: + '@dicebear/core': ^9.0.0 + + '@dicebear/pixel-art@9.3.1': + resolution: {integrity: sha512-yUufylvVqkb9wpG/sYRzNTeSk1YbzVgSq/ZSMyxy1kx/R4BhOkiZBSs6Ra3VjeKWVNDBzUWERaVdylLbFvAQaw==} + engines: {node: '>=18.0.0'} + peerDependencies: + '@dicebear/core': ^9.0.0 + + '@dicebear/rings@9.3.1': + resolution: {integrity: sha512-1bQTKJbVzpBPbhSyHS5bzlRjYIRQKO1hR0JGmC/ZWFiE9+ySk/NNwkNghvcDxvDUaz02NLSJXlSp2T8nrsdNHg==} + engines: {node: '>=18.0.0'} + peerDependencies: + '@dicebear/core': ^9.0.0 + + '@dicebear/shapes@9.3.1': + resolution: {integrity: sha512-xzw/BWSQCznRDFBp8DKQtg1Jxawq+R3upOM2pURwbCPC+9bi8f8CAz1SExA3tlAbbrVx0HQdRKIYS3GW6/GBBA==} + engines: {node: '>=18.0.0'} + peerDependencies: + '@dicebear/core': ^9.0.0 + + '@dicebear/thumbs@9.3.1': + resolution: {integrity: sha512-HS14oyT9HXLT8OPqEz8n0Bdob3oRWoNZ5PSZrxT4nyYXxh0rDSxCCOFwPKanXznk1qCAngtAvuzzID3vo7UG3A==} + engines: {node: '>=18.0.0'} + peerDependencies: + '@dicebear/core': ^9.0.0 + + '@dicebear/toon-head@9.3.1': + resolution: {integrity: sha512-9a9ydhbrVG57NuscH92yzIMQ0yxEPgJtzOMG1QR6jWctgbeEuzQvJDPvJQTxtfFjx71VlQNsSL40/5rnMtCaTw==} + engines: {node: '>=16.0.0'} + peerDependencies: + '@dicebear/core': ^9.0.0 + '@dnd-kit/accessibility@3.1.1': resolution: {integrity: sha512-2P+YgaXF+gRsIihwwY1gCsQSYnu9Zyj2py8kY5fFvUM1qm2WA2u639R6YNVfU4GWr+ZM5mqEsfHZZLoRONbemw==} peerDependencies: @@ -1105,6 +1337,19 @@ packages: '@types/react': optional: true + '@radix-ui/react-switch@1.2.6': + resolution: {integrity: sha512-bByzr1+ep1zk4VubeEVViV592vu2lHE2BZY5OnzehZqOOgogN80+mNtCqPkhn2gklJqOpxWgPoYTSnhBCqpOXQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + '@radix-ui/react-tabs@1.1.13': resolution: {integrity: sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A==} peerDependencies: @@ -3793,6 +4038,9 @@ packages: require-main-filename@2.0.0: resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} + reselect@5.1.1: + resolution: {integrity: sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==} + reserved-identifiers@1.2.0: resolution: {integrity: sha512-yE7KUfFvaBFzGPs5H3Ops1RevfUEsDc5Iz65rOwWg4lE8HJSYtle77uul3+573457oHvBKuHYDl/xqUkKpEEdw==} engines: {node: '>=18'} @@ -3960,6 +4208,9 @@ packages: resolution: {integrity: sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ==} engines: {node: ^14.18.0 || >=16.0.0} + tabbable@6.4.0: + resolution: {integrity: sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==} + tagged-tag@1.0.0: resolution: {integrity: sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==} engines: {node: '>=20'} @@ -4470,6 +4721,31 @@ snapshots: '@babel/helper-string-parser': 7.27.1 '@babel/helper-validator-identifier': 7.28.5 + '@base-ui/react@1.1.0(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + dependencies: + '@babel/runtime': 7.28.6 + '@base-ui/utils': 0.2.4(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@floating-ui/react-dom': 2.1.6(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@floating-ui/utils': 0.2.10 + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + reselect: 5.1.1 + tabbable: 6.4.0 + use-sync-external-store: 1.6.0(react@19.2.3) + optionalDependencies: + '@types/react': 19.2.8 + + '@base-ui/utils@0.2.4(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + dependencies: + '@babel/runtime': 7.28.6 + '@floating-ui/utils': 0.2.10 + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + reselect: 5.1.1 + use-sync-external-store: 1.6.0(react@19.2.3) + optionalDependencies: + '@types/react': 19.2.8 + '@clack/core@0.5.0': dependencies: picocolors: 1.1.1 @@ -4481,6 +4757,169 @@ snapshots: picocolors: 1.1.1 sisteransi: 1.0.5 + '@dicebear/adventurer-neutral@9.3.1(@dicebear/core@9.3.1)': + dependencies: + '@dicebear/core': 9.3.1 + + '@dicebear/adventurer@9.3.1(@dicebear/core@9.3.1)': + dependencies: + '@dicebear/core': 9.3.1 + + '@dicebear/avataaars-neutral@9.3.1(@dicebear/core@9.3.1)': + dependencies: + '@dicebear/core': 9.3.1 + + '@dicebear/avataaars@9.3.1(@dicebear/core@9.3.1)': + dependencies: + '@dicebear/core': 9.3.1 + + '@dicebear/big-ears-neutral@9.3.1(@dicebear/core@9.3.1)': + dependencies: + '@dicebear/core': 9.3.1 + + '@dicebear/big-ears@9.3.1(@dicebear/core@9.3.1)': + dependencies: + '@dicebear/core': 9.3.1 + + '@dicebear/big-smile@9.3.1(@dicebear/core@9.3.1)': + dependencies: + '@dicebear/core': 9.3.1 + + '@dicebear/bottts-neutral@9.3.1(@dicebear/core@9.3.1)': + dependencies: + '@dicebear/core': 9.3.1 + + '@dicebear/bottts@9.3.1(@dicebear/core@9.3.1)': + dependencies: + '@dicebear/core': 9.3.1 + + '@dicebear/collection@9.3.1(@dicebear/core@9.3.1)': + dependencies: + '@dicebear/adventurer': 9.3.1(@dicebear/core@9.3.1) + '@dicebear/adventurer-neutral': 9.3.1(@dicebear/core@9.3.1) + '@dicebear/avataaars': 9.3.1(@dicebear/core@9.3.1) + '@dicebear/avataaars-neutral': 9.3.1(@dicebear/core@9.3.1) + '@dicebear/big-ears': 9.3.1(@dicebear/core@9.3.1) + '@dicebear/big-ears-neutral': 9.3.1(@dicebear/core@9.3.1) + '@dicebear/big-smile': 9.3.1(@dicebear/core@9.3.1) + '@dicebear/bottts': 9.3.1(@dicebear/core@9.3.1) + '@dicebear/bottts-neutral': 9.3.1(@dicebear/core@9.3.1) + '@dicebear/core': 9.3.1 + '@dicebear/croodles': 9.3.1(@dicebear/core@9.3.1) + '@dicebear/croodles-neutral': 9.3.1(@dicebear/core@9.3.1) + '@dicebear/dylan': 9.3.1(@dicebear/core@9.3.1) + '@dicebear/fun-emoji': 9.3.1(@dicebear/core@9.3.1) + '@dicebear/glass': 9.3.1(@dicebear/core@9.3.1) + '@dicebear/icons': 9.3.1(@dicebear/core@9.3.1) + '@dicebear/identicon': 9.3.1(@dicebear/core@9.3.1) + '@dicebear/initials': 9.3.1(@dicebear/core@9.3.1) + '@dicebear/lorelei': 9.3.1(@dicebear/core@9.3.1) + '@dicebear/lorelei-neutral': 9.3.1(@dicebear/core@9.3.1) + '@dicebear/micah': 9.3.1(@dicebear/core@9.3.1) + '@dicebear/miniavs': 9.3.1(@dicebear/core@9.3.1) + '@dicebear/notionists': 9.3.1(@dicebear/core@9.3.1) + '@dicebear/notionists-neutral': 9.3.1(@dicebear/core@9.3.1) + '@dicebear/open-peeps': 9.3.1(@dicebear/core@9.3.1) + '@dicebear/personas': 9.3.1(@dicebear/core@9.3.1) + '@dicebear/pixel-art': 9.3.1(@dicebear/core@9.3.1) + '@dicebear/pixel-art-neutral': 9.3.1(@dicebear/core@9.3.1) + '@dicebear/rings': 9.3.1(@dicebear/core@9.3.1) + '@dicebear/shapes': 9.3.1(@dicebear/core@9.3.1) + '@dicebear/thumbs': 9.3.1(@dicebear/core@9.3.1) + '@dicebear/toon-head': 9.3.1(@dicebear/core@9.3.1) + + '@dicebear/core@9.3.1': + dependencies: + '@types/json-schema': 7.0.15 + + '@dicebear/croodles-neutral@9.3.1(@dicebear/core@9.3.1)': + dependencies: + '@dicebear/core': 9.3.1 + + '@dicebear/croodles@9.3.1(@dicebear/core@9.3.1)': + dependencies: + '@dicebear/core': 9.3.1 + + '@dicebear/dylan@9.3.1(@dicebear/core@9.3.1)': + dependencies: + '@dicebear/core': 9.3.1 + + '@dicebear/fun-emoji@9.3.1(@dicebear/core@9.3.1)': + dependencies: + '@dicebear/core': 9.3.1 + + '@dicebear/glass@9.3.1(@dicebear/core@9.3.1)': + dependencies: + '@dicebear/core': 9.3.1 + + '@dicebear/icons@9.3.1(@dicebear/core@9.3.1)': + dependencies: + '@dicebear/core': 9.3.1 + + '@dicebear/identicon@9.3.1(@dicebear/core@9.3.1)': + dependencies: + '@dicebear/core': 9.3.1 + + '@dicebear/initials@9.3.1(@dicebear/core@9.3.1)': + dependencies: + '@dicebear/core': 9.3.1 + + '@dicebear/lorelei-neutral@9.3.1(@dicebear/core@9.3.1)': + dependencies: + '@dicebear/core': 9.3.1 + + '@dicebear/lorelei@9.3.1(@dicebear/core@9.3.1)': + dependencies: + '@dicebear/core': 9.3.1 + + '@dicebear/micah@9.3.1(@dicebear/core@9.3.1)': + dependencies: + '@dicebear/core': 9.3.1 + + '@dicebear/miniavs@9.3.1(@dicebear/core@9.3.1)': + dependencies: + '@dicebear/core': 9.3.1 + + '@dicebear/notionists-neutral@9.3.1(@dicebear/core@9.3.1)': + dependencies: + '@dicebear/core': 9.3.1 + + '@dicebear/notionists@9.3.1(@dicebear/core@9.3.1)': + dependencies: + '@dicebear/core': 9.3.1 + + '@dicebear/open-peeps@9.3.1(@dicebear/core@9.3.1)': + dependencies: + '@dicebear/core': 9.3.1 + + '@dicebear/personas@9.3.1(@dicebear/core@9.3.1)': + dependencies: + '@dicebear/core': 9.3.1 + + '@dicebear/pixel-art-neutral@9.3.1(@dicebear/core@9.3.1)': + dependencies: + '@dicebear/core': 9.3.1 + + '@dicebear/pixel-art@9.3.1(@dicebear/core@9.3.1)': + dependencies: + '@dicebear/core': 9.3.1 + + '@dicebear/rings@9.3.1(@dicebear/core@9.3.1)': + dependencies: + '@dicebear/core': 9.3.1 + + '@dicebear/shapes@9.3.1(@dicebear/core@9.3.1)': + dependencies: + '@dicebear/core': 9.3.1 + + '@dicebear/thumbs@9.3.1(@dicebear/core@9.3.1)': + dependencies: + '@dicebear/core': 9.3.1 + + '@dicebear/toon-head@9.3.1(@dicebear/core@9.3.1)': + dependencies: + '@dicebear/core': 9.3.1 + '@dnd-kit/accessibility@3.1.1(react@19.2.3)': dependencies: react: 19.2.3 @@ -5166,6 +5605,21 @@ snapshots: optionalDependencies: '@types/react': 19.2.8 + '@radix-ui/react-switch@1.2.6(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-context': 1.1.2(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-use-previous': 1.1.1(@types/react@19.2.8)(react@19.2.3) + '@radix-ui/react-use-size': 1.1.1(@types/react@19.2.8)(react@19.2.3) + react: 19.2.3 + react-dom: 19.2.3(react@19.2.3) + optionalDependencies: + '@types/react': 19.2.8 + '@types/react-dom': 19.2.3(@types/react@19.2.8) + '@radix-ui/react-tabs@1.1.13(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': dependencies: '@radix-ui/primitive': 1.1.3 @@ -8263,6 +8717,8 @@ snapshots: require-main-filename@2.0.0: {} + reselect@5.1.1: {} + reserved-identifiers@1.2.0: {} resolve-from@4.0.0: {} @@ -8429,6 +8885,8 @@ snapshots: dependencies: '@pkgr/core': 0.2.9 + tabbable@6.4.0: {} + tagged-tag@1.0.0: {} tailwind-merge@3.4.0: {} diff --git a/client/cms/src/components/checkin/qr-dialog.tsx b/client/cms/src/components/checkin/qr-dialog.tsx index a1fa442..df2a81c 100644 --- a/client/cms/src/components/checkin/qr-dialog.tsx +++ b/client/cms/src/components/checkin/qr-dialog.tsx @@ -38,20 +38,20 @@ function QrSection({ eventId, enabled }: { eventId: string; enabled: boolean }) const data = { data: { checkin_code: `dummy${eventId}${enabled}` } }; return data ? ( - <> -
- -
- -
- {data.data.checkin_code} + <> +
+
- - - ) + +
+ {data.data.checkin_code} +
+
+ + ) : ( - - ); + + ); } function QrSectionSkeleton() { diff --git a/client/cms/src/components/profile/edit-profile-dialog.tsx b/client/cms/src/components/profile/edit-profile-dialog.tsx index c98d4c7..47be953 100644 --- a/client/cms/src/components/profile/edit-profile-dialog.tsx +++ b/client/cms/src/components/profile/edit-profile-dialog.tsx @@ -1,4 +1,5 @@ import { useForm } from '@tanstack/react-form'; +import { useState } from 'react'; import { toast } from 'sonner'; import z from 'zod'; import { Button } from '@/components/ui/button'; @@ -21,12 +22,14 @@ import { } from '@/components/ui/input'; import { useUpdateUser } from '@/hooks/data/useUpdateUser'; import { useUserInfo } from '@/hooks/data/useUserInfo'; +import { Switch } from '../ui/switch'; const formSchema = z.object({ username: z.string().min(5), - nickname: z.string().min(1), - subtitle: z.string().min(1), - avatar: z.url().min(1), + nickname: z.string(), + subtitle: z.string(), + avatar: z.url().or(z.literal('')), + allow_public: z.boolean(), }); export function EditProfileDialog() { const { data } = useUserInfo(); @@ -39,6 +42,7 @@ export function EditProfileDialog() { username: user.username, nickname: user.nickname, subtitle: user.subtitle, + allow_public: user.allow_public, }, validators: { onBlur: formSchema, @@ -57,8 +61,16 @@ export function EditProfileDialog() { }, }); + const [open, setOpen] = useState(false); + + if (!open) { + setTimeout(() => { + form.reset(); + }, 200); + } + return ( - + @@ -67,7 +79,7 @@ export function EditProfileDialog() { onSubmit={(e) => { e.preventDefault(); e.stopPropagation(); - void form.handleSubmit(); + form.handleSubmit().then(() => setOpen(false)); }} className="grid gap-4" > @@ -138,13 +150,24 @@ export function EditProfileDialog() { )} + + {field => ( + + 公开个人资料 + field.handleChange(e)} defaultChecked={user.allow_public} /> + + )} + - - - + [state.canSubmit]} + children={([canSubmit]) => ( + + )} + /> diff --git a/client/cms/src/components/profile/main-profile.tsx b/client/cms/src/components/profile/main-profile.tsx index 425d632..28d4adf 100644 --- a/client/cms/src/components/profile/main-profile.tsx +++ b/client/cms/src/components/profile/main-profile.tsx @@ -1,10 +1,12 @@ +import { identicon } from '@dicebear/collection'; +import { createAvatar } from '@dicebear/core'; import MDEditor from '@uiw/react-md-editor'; import { isNil } from 'lodash-es'; import { Mail, Pencil } from 'lucide-react'; -import { useState } from 'react'; +import { useMemo, useState } from 'react'; import Markdown from 'react-markdown'; import { toast } from 'sonner'; -import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'; +import { Avatar, AvatarImage } from '@/components/ui/avatar'; import { useUpdateUser } from '@/hooks/data/useUpdateUser'; import { useUserInfo } from '@/hooks/data/useUserInfo'; import { base64ToUtf8, utf8ToBase64 } from '@/lib/utils'; @@ -18,6 +20,14 @@ export function MainProfile() { const [enableBioEdit, setEnableBioEdit] = useState(false); const { mutateAsync } = useUpdateUser(); + const IdentIcon = useMemo(() => { + const avatar = createAvatar(identicon, { + size: 128, + seed: user.user_id, + }).toDataUri(); + return Avatar; + }, [user.user_id]); + return (
@@ -25,8 +35,7 @@ export function MainProfile() {
- - CN + {user.avatar ? : IdentIcon}
@@ -45,12 +54,12 @@ export function MainProfile() { {/* Bio */} {enableBioEdit ? ( - - ) + + ) :
{bio}
}