feat(client): profile improvements
Signed-off-by: Noa Virellia <noa@requiem.garden>
This commit is contained in:
@@ -3,7 +3,7 @@ import pluginQuery from '@tanstack/eslint-plugin-query';
|
|||||||
|
|
||||||
export default antfu({
|
export default antfu({
|
||||||
gitignore: true,
|
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,
|
react: true,
|
||||||
stylistic: {
|
stylistic: {
|
||||||
semi: true,
|
semi: true,
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
"type": "module",
|
"type": "module",
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
|
"packageManager": "pnpm@10.28.1+sha512.7d7dbbca9e99447b7c3bf7a73286afaaf6be99251eb9498baefa7d406892f67b879adb3a1d7e687fc4ccc1a388c7175fbaae567a26ab44d1067b54fcb0d6a316",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "tsc -b && vite build",
|
"build": "tsc -b && vite build",
|
||||||
@@ -11,6 +12,10 @@
|
|||||||
"gen": "openapi-ts"
|
"gen": "openapi-ts"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"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/core": "^6.3.1",
|
||||||
"@dnd-kit/modifiers": "^9.0.0",
|
"@dnd-kit/modifiers": "^9.0.0",
|
||||||
"@dnd-kit/sortable": "^10.0.0",
|
"@dnd-kit/sortable": "^10.0.0",
|
||||||
@@ -25,6 +30,7 @@
|
|||||||
"@radix-ui/react-select": "^2.2.6",
|
"@radix-ui/react-select": "^2.2.6",
|
||||||
"@radix-ui/react-separator": "^1.1.8",
|
"@radix-ui/react-separator": "^1.1.8",
|
||||||
"@radix-ui/react-slot": "^1.2.4",
|
"@radix-ui/react-slot": "^1.2.4",
|
||||||
|
"@radix-ui/react-switch": "^1.2.6",
|
||||||
"@radix-ui/react-tabs": "^1.1.13",
|
"@radix-ui/react-tabs": "^1.1.13",
|
||||||
"@radix-ui/react-toggle": "^1.1.10",
|
"@radix-ui/react-toggle": "^1.1.10",
|
||||||
"@radix-ui/react-toggle-group": "^1.1.11",
|
"@radix-ui/react-toggle-group": "^1.1.11",
|
||||||
@@ -98,6 +104,5 @@
|
|||||||
},
|
},
|
||||||
"lint-staged": {
|
"lint-staged": {
|
||||||
"*": "eslint --fix"
|
"*": "eslint --fix"
|
||||||
},
|
}
|
||||||
"packageManager": "pnpm@10.28.1+sha512.7d7dbbca9e99447b7c3bf7a73286afaaf6be99251eb9498baefa7d406892f67b879adb3a1d7e687fc4ccc1a388c7175fbaae567a26ab44d1067b54fcb0d6a316"
|
|
||||||
}
|
}
|
||||||
|
|||||||
458
client/cms/pnpm-lock.yaml
generated
458
client/cms/pnpm-lock.yaml
generated
@@ -8,6 +8,18 @@ importers:
|
|||||||
|
|
||||||
.:
|
.:
|
||||||
dependencies:
|
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':
|
'@dnd-kit/core':
|
||||||
specifier: ^6.3.1
|
specifier: ^6.3.1
|
||||||
version: 6.3.1(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
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':
|
'@radix-ui/react-slot':
|
||||||
specifier: ^1.2.4
|
specifier: ^1.2.4
|
||||||
version: 1.2.4(@types/react@19.2.8)(react@19.2.3)
|
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':
|
'@radix-ui/react-tabs':
|
||||||
specifier: ^1.1.13
|
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)
|
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==}
|
resolution: {integrity: sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==}
|
||||||
engines: {node: '>=6.9.0'}
|
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':
|
'@clack/core@0.5.0':
|
||||||
resolution: {integrity: sha512-p3y0FIOwaYRUPRcMO7+dlmLh8PSRcrjuTndsiA0WAFbWES0mLZlrjVoBRZ9DzkPFJZG6KGkJmoEAY0ZcVWTkow==}
|
resolution: {integrity: sha512-p3y0FIOwaYRUPRcMO7+dlmLh8PSRcrjuTndsiA0WAFbWES0mLZlrjVoBRZ9DzkPFJZG6KGkJmoEAY0ZcVWTkow==}
|
||||||
|
|
||||||
'@clack/prompts@0.11.0':
|
'@clack/prompts@0.11.0':
|
||||||
resolution: {integrity: sha512-pMN5FcrEw9hUkZA4f+zLlzivQSeQf5dRGJjSUbvVYDLvpKCdQx5OaknvKzgbtXOizhP+SJJJjqEbOe55uKKfAw==}
|
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':
|
'@dnd-kit/accessibility@3.1.1':
|
||||||
resolution: {integrity: sha512-2P+YgaXF+gRsIihwwY1gCsQSYnu9Zyj2py8kY5fFvUM1qm2WA2u639R6YNVfU4GWr+ZM5mqEsfHZZLoRONbemw==}
|
resolution: {integrity: sha512-2P+YgaXF+gRsIihwwY1gCsQSYnu9Zyj2py8kY5fFvUM1qm2WA2u639R6YNVfU4GWr+ZM5mqEsfHZZLoRONbemw==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -1105,6 +1337,19 @@ packages:
|
|||||||
'@types/react':
|
'@types/react':
|
||||||
optional: true
|
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':
|
'@radix-ui/react-tabs@1.1.13':
|
||||||
resolution: {integrity: sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A==}
|
resolution: {integrity: sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -3793,6 +4038,9 @@ packages:
|
|||||||
require-main-filename@2.0.0:
|
require-main-filename@2.0.0:
|
||||||
resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==}
|
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:
|
reserved-identifiers@1.2.0:
|
||||||
resolution: {integrity: sha512-yE7KUfFvaBFzGPs5H3Ops1RevfUEsDc5Iz65rOwWg4lE8HJSYtle77uul3+573457oHvBKuHYDl/xqUkKpEEdw==}
|
resolution: {integrity: sha512-yE7KUfFvaBFzGPs5H3Ops1RevfUEsDc5Iz65rOwWg4lE8HJSYtle77uul3+573457oHvBKuHYDl/xqUkKpEEdw==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
@@ -3960,6 +4208,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ==}
|
resolution: {integrity: sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ==}
|
||||||
engines: {node: ^14.18.0 || >=16.0.0}
|
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:
|
tagged-tag@1.0.0:
|
||||||
resolution: {integrity: sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==}
|
resolution: {integrity: sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==}
|
||||||
engines: {node: '>=20'}
|
engines: {node: '>=20'}
|
||||||
@@ -4470,6 +4721,31 @@ snapshots:
|
|||||||
'@babel/helper-string-parser': 7.27.1
|
'@babel/helper-string-parser': 7.27.1
|
||||||
'@babel/helper-validator-identifier': 7.28.5
|
'@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':
|
'@clack/core@0.5.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
picocolors: 1.1.1
|
picocolors: 1.1.1
|
||||||
@@ -4481,6 +4757,169 @@ snapshots:
|
|||||||
picocolors: 1.1.1
|
picocolors: 1.1.1
|
||||||
sisteransi: 1.0.5
|
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)':
|
'@dnd-kit/accessibility@3.1.1(react@19.2.3)':
|
||||||
dependencies:
|
dependencies:
|
||||||
react: 19.2.3
|
react: 19.2.3
|
||||||
@@ -5166,6 +5605,21 @@ snapshots:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@types/react': 19.2.8
|
'@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)':
|
'@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:
|
dependencies:
|
||||||
'@radix-ui/primitive': 1.1.3
|
'@radix-ui/primitive': 1.1.3
|
||||||
@@ -8263,6 +8717,8 @@ snapshots:
|
|||||||
|
|
||||||
require-main-filename@2.0.0: {}
|
require-main-filename@2.0.0: {}
|
||||||
|
|
||||||
|
reselect@5.1.1: {}
|
||||||
|
|
||||||
reserved-identifiers@1.2.0: {}
|
reserved-identifiers@1.2.0: {}
|
||||||
|
|
||||||
resolve-from@4.0.0: {}
|
resolve-from@4.0.0: {}
|
||||||
@@ -8429,6 +8885,8 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@pkgr/core': 0.2.9
|
'@pkgr/core': 0.2.9
|
||||||
|
|
||||||
|
tabbable@6.4.0: {}
|
||||||
|
|
||||||
tagged-tag@1.0.0: {}
|
tagged-tag@1.0.0: {}
|
||||||
|
|
||||||
tailwind-merge@3.4.0: {}
|
tailwind-merge@3.4.0: {}
|
||||||
|
|||||||
@@ -38,20 +38,20 @@ function QrSection({ eventId, enabled }: { eventId: string; enabled: boolean })
|
|||||||
const data = { data: { checkin_code: `dummy${eventId}${enabled}` } };
|
const data = { data: { checkin_code: `dummy${eventId}${enabled}` } };
|
||||||
return data
|
return data
|
||||||
? (
|
? (
|
||||||
<>
|
<>
|
||||||
<div className="border-2 px-4 py-8 border-muted rounded-xl flex flex-col items-center justify-center p-4">
|
<div className="border-2 px-4 py-8 border-muted rounded-xl flex flex-col items-center justify-center p-4">
|
||||||
<QRCode data={data.data.checkin_code} className="size-60" />
|
<QRCode data={data.data.checkin_code} className="size-60" />
|
||||||
</div>
|
|
||||||
<DialogFooter>
|
|
||||||
<div className="flex flex-1 items-center ml-2 font-mono text-3xl tracking-widest text-primary/80 justify-center">
|
|
||||||
{data.data.checkin_code}
|
|
||||||
</div>
|
</div>
|
||||||
</DialogFooter>
|
<DialogFooter>
|
||||||
</>
|
<div className="flex flex-1 items-center ml-2 font-mono text-3xl tracking-widest text-primary/80 justify-center">
|
||||||
)
|
{data.data.checkin_code}
|
||||||
|
</div>
|
||||||
|
</DialogFooter>
|
||||||
|
</>
|
||||||
|
)
|
||||||
: (
|
: (
|
||||||
<QrSectionSkeleton />
|
<QrSectionSkeleton />
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function QrSectionSkeleton() {
|
function QrSectionSkeleton() {
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { useForm } from '@tanstack/react-form';
|
import { useForm } from '@tanstack/react-form';
|
||||||
|
import { useState } from 'react';
|
||||||
import { toast } from 'sonner';
|
import { toast } from 'sonner';
|
||||||
import z from 'zod';
|
import z from 'zod';
|
||||||
import { Button } from '@/components/ui/button';
|
import { Button } from '@/components/ui/button';
|
||||||
@@ -21,12 +22,14 @@ import {
|
|||||||
} from '@/components/ui/input';
|
} from '@/components/ui/input';
|
||||||
import { useUpdateUser } from '@/hooks/data/useUpdateUser';
|
import { useUpdateUser } from '@/hooks/data/useUpdateUser';
|
||||||
import { useUserInfo } from '@/hooks/data/useUserInfo';
|
import { useUserInfo } from '@/hooks/data/useUserInfo';
|
||||||
|
import { Switch } from '../ui/switch';
|
||||||
|
|
||||||
const formSchema = z.object({
|
const formSchema = z.object({
|
||||||
username: z.string().min(5),
|
username: z.string().min(5),
|
||||||
nickname: z.string().min(1),
|
nickname: z.string(),
|
||||||
subtitle: z.string().min(1),
|
subtitle: z.string(),
|
||||||
avatar: z.url().min(1),
|
avatar: z.url().or(z.literal('')),
|
||||||
|
allow_public: z.boolean(),
|
||||||
});
|
});
|
||||||
export function EditProfileDialog() {
|
export function EditProfileDialog() {
|
||||||
const { data } = useUserInfo();
|
const { data } = useUserInfo();
|
||||||
@@ -39,6 +42,7 @@ export function EditProfileDialog() {
|
|||||||
username: user.username,
|
username: user.username,
|
||||||
nickname: user.nickname,
|
nickname: user.nickname,
|
||||||
subtitle: user.subtitle,
|
subtitle: user.subtitle,
|
||||||
|
allow_public: user.allow_public,
|
||||||
},
|
},
|
||||||
validators: {
|
validators: {
|
||||||
onBlur: formSchema,
|
onBlur: formSchema,
|
||||||
@@ -57,8 +61,16 @@ export function EditProfileDialog() {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const [open, setOpen] = useState(false);
|
||||||
|
|
||||||
|
if (!open) {
|
||||||
|
setTimeout(() => {
|
||||||
|
form.reset();
|
||||||
|
}, 200);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog>
|
<Dialog open={open} onOpenChange={setOpen}>
|
||||||
<DialogTrigger asChild>
|
<DialogTrigger asChild>
|
||||||
<Button variant="outline" className="w-full" size="lg">编辑个人资料</Button>
|
<Button variant="outline" className="w-full" size="lg">编辑个人资料</Button>
|
||||||
</DialogTrigger>
|
</DialogTrigger>
|
||||||
@@ -67,7 +79,7 @@ export function EditProfileDialog() {
|
|||||||
onSubmit={(e) => {
|
onSubmit={(e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
void form.handleSubmit();
|
form.handleSubmit().then(() => setOpen(false));
|
||||||
}}
|
}}
|
||||||
className="grid gap-4"
|
className="grid gap-4"
|
||||||
>
|
>
|
||||||
@@ -138,13 +150,24 @@ export function EditProfileDialog() {
|
|||||||
</Field>
|
</Field>
|
||||||
)}
|
)}
|
||||||
</form.Field>
|
</form.Field>
|
||||||
|
<form.Field name="allow_public">
|
||||||
|
{field => (
|
||||||
|
<Field orientation="horizontal" className="my-2">
|
||||||
|
<FieldLabel htmlFor="allow_public">公开个人资料</FieldLabel>
|
||||||
|
<Switch id="allow_public" onCheckedChange={e => field.handleChange(e)} defaultChecked={user.allow_public} />
|
||||||
|
</Field>
|
||||||
|
)}
|
||||||
|
</form.Field>
|
||||||
<DialogFooter>
|
<DialogFooter>
|
||||||
<DialogClose asChild>
|
<DialogClose asChild>
|
||||||
<Button variant="outline">取消</Button>
|
<Button variant="outline">取消</Button>
|
||||||
</DialogClose>
|
</DialogClose>
|
||||||
<DialogClose asChild>
|
<form.Subscribe
|
||||||
<Button type="submit">保存</Button>
|
selector={state => [state.canSubmit]}
|
||||||
</DialogClose>
|
children={([canSubmit]) => (
|
||||||
|
<Button type="submit" disabled={!canSubmit}>保存</Button>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
</DialogFooter>
|
</DialogFooter>
|
||||||
</form>
|
</form>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
|
import { identicon } from '@dicebear/collection';
|
||||||
|
import { createAvatar } from '@dicebear/core';
|
||||||
import MDEditor from '@uiw/react-md-editor';
|
import MDEditor from '@uiw/react-md-editor';
|
||||||
import { isNil } from 'lodash-es';
|
import { isNil } from 'lodash-es';
|
||||||
import { Mail, Pencil } from 'lucide-react';
|
import { Mail, Pencil } from 'lucide-react';
|
||||||
import { useState } from 'react';
|
import { useMemo, useState } from 'react';
|
||||||
import Markdown from 'react-markdown';
|
import Markdown from 'react-markdown';
|
||||||
import { toast } from 'sonner';
|
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 { useUpdateUser } from '@/hooks/data/useUpdateUser';
|
||||||
import { useUserInfo } from '@/hooks/data/useUserInfo';
|
import { useUserInfo } from '@/hooks/data/useUserInfo';
|
||||||
import { base64ToUtf8, utf8ToBase64 } from '@/lib/utils';
|
import { base64ToUtf8, utf8ToBase64 } from '@/lib/utils';
|
||||||
@@ -18,6 +20,14 @@ export function MainProfile() {
|
|||||||
const [enableBioEdit, setEnableBioEdit] = useState(false);
|
const [enableBioEdit, setEnableBioEdit] = useState(false);
|
||||||
const { mutateAsync } = useUpdateUser();
|
const { mutateAsync } = useUpdateUser();
|
||||||
|
|
||||||
|
const IdentIcon = useMemo(() => {
|
||||||
|
const avatar = createAvatar(identicon, {
|
||||||
|
size: 128,
|
||||||
|
seed: user.user_id,
|
||||||
|
}).toDataUri();
|
||||||
|
return <img src={avatar} alt="Avatar" />;
|
||||||
|
}, [user.user_id]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col justify-center w-full lg:w-auto h-full lg:h-auto lg:flex-row lg:gap-8">
|
<div className="flex flex-col justify-center w-full lg:w-auto h-full lg:h-auto lg:flex-row lg:gap-8">
|
||||||
<div className="flex w-full flex-row mt-2 lg:mt-0 lg:flex-col lg:w-max">
|
<div className="flex w-full flex-row mt-2 lg:mt-0 lg:flex-col lg:w-max">
|
||||||
@@ -25,8 +35,7 @@ export function MainProfile() {
|
|||||||
<div className="flex flex-col w-full gap-3">
|
<div className="flex flex-col w-full gap-3">
|
||||||
<div className="flex flex-row gap-3 w-full lg:flex-col">
|
<div className="flex flex-row gap-3 w-full lg:flex-col">
|
||||||
<Avatar className="size-16 rounded-full border-2 border-muted lg:size-64">
|
<Avatar className="size-16 rounded-full border-2 border-muted lg:size-64">
|
||||||
<AvatarImage src={user.avatar} alt={user.nickname} />
|
{user.avatar ? <AvatarImage src={user.avatar} alt={user.nickname} /> : IdentIcon}
|
||||||
<AvatarFallback className="rounded-lg">CN</AvatarFallback>
|
|
||||||
</Avatar>
|
</Avatar>
|
||||||
<div className="flex flex-1 flex-col justify-center lg:mt-3">
|
<div className="flex flex-1 flex-col justify-center lg:mt-3">
|
||||||
<span className="font-semibold text-2xl" aria-hidden="true">{user.nickname}</span>
|
<span className="font-semibold text-2xl" aria-hidden="true">{user.nickname}</span>
|
||||||
@@ -45,12 +54,12 @@ export function MainProfile() {
|
|||||||
{/* Bio */}
|
{/* Bio */}
|
||||||
{enableBioEdit
|
{enableBioEdit
|
||||||
? (
|
? (
|
||||||
<MDEditor
|
<MDEditor
|
||||||
value={bio}
|
value={bio}
|
||||||
onChange={setBio}
|
onChange={setBio}
|
||||||
height="100%"
|
height="100%"
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
: <div className="p-6 prose dark:prose-invert"><Markdown>{bio}</Markdown></div>}
|
: <div className="p-6 prose dark:prose-invert"><Markdown>{bio}</Markdown></div>}
|
||||||
<Button
|
<Button
|
||||||
className="absolute bottom-4 right-4"
|
className="absolute bottom-4 right-4"
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
|
import { identicon } from '@dicebear/collection';
|
||||||
|
|
||||||
|
import { createAvatar } from '@dicebear/core';
|
||||||
import {
|
import {
|
||||||
IconDotsVertical,
|
IconDotsVertical,
|
||||||
IconLogout,
|
IconLogout,
|
||||||
} from '@tabler/icons-react';
|
} from '@tabler/icons-react';
|
||||||
|
import { useMemo } from 'react';
|
||||||
import {
|
import {
|
||||||
Avatar,
|
Avatar,
|
||||||
AvatarFallback,
|
|
||||||
AvatarImage,
|
AvatarImage,
|
||||||
} from '@/components/ui/avatar';
|
} from '@/components/ui/avatar';
|
||||||
import {
|
import {
|
||||||
@@ -33,6 +35,14 @@ function NavUser_() {
|
|||||||
const user = data.data!;
|
const user = data.data!;
|
||||||
const { logout } = useLogout();
|
const { logout } = useLogout();
|
||||||
|
|
||||||
|
const IdentIcon = useMemo(() => {
|
||||||
|
const avatar = createAvatar(identicon, {
|
||||||
|
size: 128,
|
||||||
|
seed: user.user_id,
|
||||||
|
}).toDataUri();
|
||||||
|
return <img src={avatar} alt="Avatar" />;
|
||||||
|
}, [user.user_id]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SidebarMenu>
|
<SidebarMenu>
|
||||||
<SidebarMenuItem>
|
<SidebarMenuItem>
|
||||||
@@ -43,8 +53,7 @@ function NavUser_() {
|
|||||||
className="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground"
|
className="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground"
|
||||||
>
|
>
|
||||||
<Avatar className="h-8 w-8 rounded-lg">
|
<Avatar className="h-8 w-8 rounded-lg">
|
||||||
<AvatarImage src={user.avatar} alt={user.nickname} />
|
{user.avatar ? <AvatarImage src={user.avatar} alt={user.nickname} /> : IdentIcon}
|
||||||
<AvatarFallback className="rounded-lg">CN</AvatarFallback>
|
|
||||||
</Avatar>
|
</Avatar>
|
||||||
<div className="grid flex-1 text-left text-sm leading-tight">
|
<div className="grid flex-1 text-left text-sm leading-tight">
|
||||||
<span className="truncate font-medium">{user.nickname}</span>
|
<span className="truncate font-medium">{user.nickname}</span>
|
||||||
@@ -64,8 +73,7 @@ function NavUser_() {
|
|||||||
<DropdownMenuLabel className="p-0 font-normal">
|
<DropdownMenuLabel className="p-0 font-normal">
|
||||||
<div className="flex items-center gap-2 px-1 py-1.5 text-left text-sm">
|
<div className="flex items-center gap-2 px-1 py-1.5 text-left text-sm">
|
||||||
<Avatar className="h-8 w-8 rounded-lg">
|
<Avatar className="h-8 w-8 rounded-lg">
|
||||||
<AvatarImage src={user.avatar} alt={user.nickname} />
|
{user.avatar ? <AvatarImage src={user.avatar} alt={user.nickname} /> : IdentIcon}
|
||||||
<AvatarFallback className="rounded-lg">CN</AvatarFallback>
|
|
||||||
</Avatar>
|
</Avatar>
|
||||||
<div className="grid flex-1 text-left text-sm leading-tight">
|
<div className="grid flex-1 text-left text-sm leading-tight">
|
||||||
<span className="truncate font-medium">{user.nickname}</span>
|
<span className="truncate font-medium">{user.nickname}</span>
|
||||||
|
|||||||
@@ -36,7 +36,6 @@ export function ThemeProvider({
|
|||||||
root.classList.add(theme);
|
root.classList.add(theme);
|
||||||
}, [theme]);
|
}, [theme]);
|
||||||
|
|
||||||
// eslint-disable-next-line react/no-unstable-context-value
|
|
||||||
const value = {
|
const value = {
|
||||||
theme,
|
theme,
|
||||||
setTheme: (theme: Theme) => {
|
setTheme: (theme: Theme) => {
|
||||||
|
|||||||
310
client/cms/src/components/ui/combobox.tsx
Normal file
310
client/cms/src/components/ui/combobox.tsx
Normal file
@@ -0,0 +1,310 @@
|
|||||||
|
"use client"
|
||||||
|
|
||||||
|
import * as React from "react"
|
||||||
|
import { Combobox as ComboboxPrimitive } from "@base-ui/react"
|
||||||
|
import { CheckIcon, ChevronDownIcon, XIcon } from "lucide-react"
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import {
|
||||||
|
InputGroup,
|
||||||
|
InputGroupAddon,
|
||||||
|
InputGroupButton,
|
||||||
|
InputGroupInput,
|
||||||
|
} from "@/components/ui/input-group"
|
||||||
|
|
||||||
|
const Combobox = ComboboxPrimitive.Root
|
||||||
|
|
||||||
|
function ComboboxValue({ ...props }: ComboboxPrimitive.Value.Props) {
|
||||||
|
return <ComboboxPrimitive.Value data-slot="combobox-value" {...props} />
|
||||||
|
}
|
||||||
|
|
||||||
|
function ComboboxTrigger({
|
||||||
|
className,
|
||||||
|
children,
|
||||||
|
...props
|
||||||
|
}: ComboboxPrimitive.Trigger.Props) {
|
||||||
|
return (
|
||||||
|
<ComboboxPrimitive.Trigger
|
||||||
|
data-slot="combobox-trigger"
|
||||||
|
className={cn("[&_svg:not([class*='size-'])]:size-4", className)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
<ChevronDownIcon
|
||||||
|
data-slot="combobox-trigger-icon"
|
||||||
|
className="text-muted-foreground pointer-events-none size-4"
|
||||||
|
/>
|
||||||
|
</ComboboxPrimitive.Trigger>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function ComboboxClear({ className, ...props }: ComboboxPrimitive.Clear.Props) {
|
||||||
|
return (
|
||||||
|
<ComboboxPrimitive.Clear
|
||||||
|
data-slot="combobox-clear"
|
||||||
|
render={<InputGroupButton variant="ghost" size="icon-xs" />}
|
||||||
|
className={cn(className)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<XIcon className="pointer-events-none" />
|
||||||
|
</ComboboxPrimitive.Clear>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function ComboboxInput({
|
||||||
|
className,
|
||||||
|
children,
|
||||||
|
disabled = false,
|
||||||
|
showTrigger = true,
|
||||||
|
showClear = false,
|
||||||
|
...props
|
||||||
|
}: ComboboxPrimitive.Input.Props & {
|
||||||
|
showTrigger?: boolean
|
||||||
|
showClear?: boolean
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<InputGroup className={cn("w-auto", className)}>
|
||||||
|
<ComboboxPrimitive.Input
|
||||||
|
render={<InputGroupInput disabled={disabled} />}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
<InputGroupAddon align="inline-end">
|
||||||
|
{showTrigger && (
|
||||||
|
<InputGroupButton
|
||||||
|
size="icon-xs"
|
||||||
|
variant="ghost"
|
||||||
|
asChild
|
||||||
|
data-slot="input-group-button"
|
||||||
|
className="group-has-data-[slot=combobox-clear]/input-group:hidden data-pressed:bg-transparent"
|
||||||
|
disabled={disabled}
|
||||||
|
>
|
||||||
|
<ComboboxTrigger />
|
||||||
|
</InputGroupButton>
|
||||||
|
)}
|
||||||
|
{showClear && <ComboboxClear disabled={disabled} />}
|
||||||
|
</InputGroupAddon>
|
||||||
|
{children}
|
||||||
|
</InputGroup>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function ComboboxContent({
|
||||||
|
className,
|
||||||
|
side = "bottom",
|
||||||
|
sideOffset = 6,
|
||||||
|
align = "start",
|
||||||
|
alignOffset = 0,
|
||||||
|
anchor,
|
||||||
|
...props
|
||||||
|
}: ComboboxPrimitive.Popup.Props &
|
||||||
|
Pick<
|
||||||
|
ComboboxPrimitive.Positioner.Props,
|
||||||
|
"side" | "align" | "sideOffset" | "alignOffset" | "anchor"
|
||||||
|
>) {
|
||||||
|
return (
|
||||||
|
<ComboboxPrimitive.Portal>
|
||||||
|
<ComboboxPrimitive.Positioner
|
||||||
|
side={side}
|
||||||
|
sideOffset={sideOffset}
|
||||||
|
align={align}
|
||||||
|
alignOffset={alignOffset}
|
||||||
|
anchor={anchor}
|
||||||
|
className="isolate z-50"
|
||||||
|
>
|
||||||
|
<ComboboxPrimitive.Popup
|
||||||
|
data-slot="combobox-content"
|
||||||
|
data-chips={!!anchor}
|
||||||
|
className={cn(
|
||||||
|
"bg-popover text-popover-foreground data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ring-foreground/10 *:data-[slot=input-group]:bg-input/30 *:data-[slot=input-group]:border-input/30 group/combobox-content relative max-h-96 w-(--anchor-width) max-w-(--available-width) min-w-[calc(var(--anchor-width)+--spacing(7))] origin-(--transform-origin) overflow-hidden rounded-md shadow-md ring-1 duration-100 data-[chips=true]:min-w-(--anchor-width) *:data-[slot=input-group]:m-1 *:data-[slot=input-group]:mb-0 *:data-[slot=input-group]:h-8 *:data-[slot=input-group]:shadow-none",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
</ComboboxPrimitive.Positioner>
|
||||||
|
</ComboboxPrimitive.Portal>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function ComboboxList({ className, ...props }: ComboboxPrimitive.List.Props) {
|
||||||
|
return (
|
||||||
|
<ComboboxPrimitive.List
|
||||||
|
data-slot="combobox-list"
|
||||||
|
className={cn(
|
||||||
|
"max-h-[min(calc(--spacing(96)---spacing(9)),calc(var(--available-height)---spacing(9)))] scroll-py-1 overflow-y-auto p-1 data-empty:p-0",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function ComboboxItem({
|
||||||
|
className,
|
||||||
|
children,
|
||||||
|
...props
|
||||||
|
}: ComboboxPrimitive.Item.Props) {
|
||||||
|
return (
|
||||||
|
<ComboboxPrimitive.Item
|
||||||
|
data-slot="combobox-item"
|
||||||
|
className={cn(
|
||||||
|
"data-highlighted:bg-accent data-highlighted:text-accent-foreground relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
<ComboboxPrimitive.ItemIndicator
|
||||||
|
data-slot="combobox-item-indicator"
|
||||||
|
render={
|
||||||
|
<span className="pointer-events-none absolute right-2 flex size-4 items-center justify-center" />
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<CheckIcon className="pointer-events-none size-4 pointer-coarse:size-5" />
|
||||||
|
</ComboboxPrimitive.ItemIndicator>
|
||||||
|
</ComboboxPrimitive.Item>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function ComboboxGroup({ className, ...props }: ComboboxPrimitive.Group.Props) {
|
||||||
|
return (
|
||||||
|
<ComboboxPrimitive.Group
|
||||||
|
data-slot="combobox-group"
|
||||||
|
className={cn(className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function ComboboxLabel({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: ComboboxPrimitive.GroupLabel.Props) {
|
||||||
|
return (
|
||||||
|
<ComboboxPrimitive.GroupLabel
|
||||||
|
data-slot="combobox-label"
|
||||||
|
className={cn(
|
||||||
|
"text-muted-foreground px-2 py-1.5 text-xs pointer-coarse:px-3 pointer-coarse:py-2 pointer-coarse:text-sm",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function ComboboxCollection({ ...props }: ComboboxPrimitive.Collection.Props) {
|
||||||
|
return (
|
||||||
|
<ComboboxPrimitive.Collection data-slot="combobox-collection" {...props} />
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function ComboboxEmpty({ className, ...props }: ComboboxPrimitive.Empty.Props) {
|
||||||
|
return (
|
||||||
|
<ComboboxPrimitive.Empty
|
||||||
|
data-slot="combobox-empty"
|
||||||
|
className={cn(
|
||||||
|
"text-muted-foreground hidden w-full justify-center py-2 text-center text-sm group-data-empty/combobox-content:flex",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function ComboboxSeparator({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: ComboboxPrimitive.Separator.Props) {
|
||||||
|
return (
|
||||||
|
<ComboboxPrimitive.Separator
|
||||||
|
data-slot="combobox-separator"
|
||||||
|
className={cn("bg-border -mx-1 my-1 h-px", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function ComboboxChips({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.ComponentPropsWithRef<typeof ComboboxPrimitive.Chips> &
|
||||||
|
ComboboxPrimitive.Chips.Props) {
|
||||||
|
return (
|
||||||
|
<ComboboxPrimitive.Chips
|
||||||
|
data-slot="combobox-chips"
|
||||||
|
className={cn(
|
||||||
|
"dark:bg-input/30 border-input focus-within:border-ring focus-within:ring-ring/50 has-aria-invalid:ring-destructive/20 dark:has-aria-invalid:ring-destructive/40 has-aria-invalid:border-destructive dark:has-aria-invalid:border-destructive/50 flex min-h-9 flex-wrap items-center gap-1.5 rounded-md border bg-transparent bg-clip-padding px-2.5 py-1.5 text-sm shadow-xs transition-[color,box-shadow] focus-within:ring-[3px] has-aria-invalid:ring-[3px] has-data-[slot=combobox-chip]:px-1.5",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function ComboboxChip({
|
||||||
|
className,
|
||||||
|
children,
|
||||||
|
showRemove = true,
|
||||||
|
...props
|
||||||
|
}: ComboboxPrimitive.Chip.Props & {
|
||||||
|
showRemove?: boolean
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<ComboboxPrimitive.Chip
|
||||||
|
data-slot="combobox-chip"
|
||||||
|
className={cn(
|
||||||
|
"bg-muted text-foreground flex h-[calc(--spacing(5.5))] w-fit items-center justify-center gap-1 rounded-sm px-1.5 text-xs font-medium whitespace-nowrap has-disabled:pointer-events-none has-disabled:cursor-not-allowed has-disabled:opacity-50 has-data-[slot=combobox-chip-remove]:pr-0",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
{showRemove && (
|
||||||
|
<ComboboxPrimitive.ChipRemove
|
||||||
|
render={<Button variant="ghost" size="icon-xs" />}
|
||||||
|
className="-ml-1 opacity-50 hover:opacity-100"
|
||||||
|
data-slot="combobox-chip-remove"
|
||||||
|
>
|
||||||
|
<XIcon className="pointer-events-none" />
|
||||||
|
</ComboboxPrimitive.ChipRemove>
|
||||||
|
)}
|
||||||
|
</ComboboxPrimitive.Chip>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function ComboboxChipsInput({
|
||||||
|
className,
|
||||||
|
children,
|
||||||
|
...props
|
||||||
|
}: ComboboxPrimitive.Input.Props) {
|
||||||
|
return (
|
||||||
|
<ComboboxPrimitive.Input
|
||||||
|
data-slot="combobox-chip-input"
|
||||||
|
className={cn("min-w-16 flex-1 outline-none", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function useComboboxAnchor() {
|
||||||
|
return React.useRef<HTMLDivElement | null>(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
Combobox,
|
||||||
|
ComboboxInput,
|
||||||
|
ComboboxContent,
|
||||||
|
ComboboxList,
|
||||||
|
ComboboxItem,
|
||||||
|
ComboboxGroup,
|
||||||
|
ComboboxLabel,
|
||||||
|
ComboboxCollection,
|
||||||
|
ComboboxEmpty,
|
||||||
|
ComboboxSeparator,
|
||||||
|
ComboboxChips,
|
||||||
|
ComboboxChip,
|
||||||
|
ComboboxChipsInput,
|
||||||
|
ComboboxTrigger,
|
||||||
|
ComboboxValue,
|
||||||
|
useComboboxAnchor,
|
||||||
|
}
|
||||||
168
client/cms/src/components/ui/input-group.tsx
Normal file
168
client/cms/src/components/ui/input-group.tsx
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
import * as React from "react"
|
||||||
|
import { cva, type VariantProps } from "class-variance-authority"
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
import { Button } from "@/components/ui/button"
|
||||||
|
import { Input } from "@/components/ui/input"
|
||||||
|
import { Textarea } from "@/components/ui/textarea"
|
||||||
|
|
||||||
|
function InputGroup({ className, ...props }: React.ComponentProps<"div">) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
data-slot="input-group"
|
||||||
|
role="group"
|
||||||
|
className={cn(
|
||||||
|
"group/input-group border-input dark:bg-input/30 relative flex w-full items-center rounded-md border shadow-xs transition-[color,box-shadow] outline-none",
|
||||||
|
"h-9 min-w-0 has-[>textarea]:h-auto",
|
||||||
|
|
||||||
|
// Variants based on alignment.
|
||||||
|
"has-[>[data-align=inline-start]]:[&>input]:pl-2",
|
||||||
|
"has-[>[data-align=inline-end]]:[&>input]:pr-2",
|
||||||
|
"has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>[data-align=block-start]]:[&>input]:pb-3",
|
||||||
|
"has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-end]]:[&>input]:pt-3",
|
||||||
|
|
||||||
|
// Focus state.
|
||||||
|
"has-[[data-slot=input-group-control]:focus-visible]:border-ring has-[[data-slot=input-group-control]:focus-visible]:ring-ring/50 has-[[data-slot=input-group-control]:focus-visible]:ring-[3px]",
|
||||||
|
|
||||||
|
// Error state.
|
||||||
|
"has-[[data-slot][aria-invalid=true]]:ring-destructive/20 has-[[data-slot][aria-invalid=true]]:border-destructive dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40",
|
||||||
|
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const inputGroupAddonVariants = cva(
|
||||||
|
"text-muted-foreground flex h-auto cursor-text items-center justify-center gap-2 py-1.5 text-sm font-medium select-none [&>svg:not([class*='size-'])]:size-4 [&>kbd]:rounded-[calc(var(--radius)-5px)] group-data-[disabled=true]/input-group:opacity-50",
|
||||||
|
{
|
||||||
|
variants: {
|
||||||
|
align: {
|
||||||
|
"inline-start":
|
||||||
|
"order-first pl-3 has-[>button]:ml-[-0.45rem] has-[>kbd]:ml-[-0.35rem]",
|
||||||
|
"inline-end":
|
||||||
|
"order-last pr-3 has-[>button]:mr-[-0.45rem] has-[>kbd]:mr-[-0.35rem]",
|
||||||
|
"block-start":
|
||||||
|
"order-first w-full justify-start px-3 pt-3 [.border-b]:pb-3 group-has-[>input]/input-group:pt-2.5",
|
||||||
|
"block-end":
|
||||||
|
"order-last w-full justify-start px-3 pb-3 [.border-t]:pt-3 group-has-[>input]/input-group:pb-2.5",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
defaultVariants: {
|
||||||
|
align: "inline-start",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
function InputGroupAddon({
|
||||||
|
className,
|
||||||
|
align = "inline-start",
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<"div"> & VariantProps<typeof inputGroupAddonVariants>) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
role="group"
|
||||||
|
data-slot="input-group-addon"
|
||||||
|
data-align={align}
|
||||||
|
className={cn(inputGroupAddonVariants({ align }), className)}
|
||||||
|
onClick={(e) => {
|
||||||
|
if ((e.target as HTMLElement).closest("button")) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
e.currentTarget.parentElement?.querySelector("input")?.focus()
|
||||||
|
}}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const inputGroupButtonVariants = cva(
|
||||||
|
"text-sm shadow-none flex gap-2 items-center",
|
||||||
|
{
|
||||||
|
variants: {
|
||||||
|
size: {
|
||||||
|
xs: "h-6 gap-1 px-2 rounded-[calc(var(--radius)-5px)] [&>svg:not([class*='size-'])]:size-3.5 has-[>svg]:px-2",
|
||||||
|
sm: "h-8 px-2.5 gap-1.5 rounded-md has-[>svg]:px-2.5",
|
||||||
|
"icon-xs":
|
||||||
|
"size-6 rounded-[calc(var(--radius)-5px)] p-0 has-[>svg]:p-0",
|
||||||
|
"icon-sm": "size-8 p-0 has-[>svg]:p-0",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
defaultVariants: {
|
||||||
|
size: "xs",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
function InputGroupButton({
|
||||||
|
className,
|
||||||
|
type = "button",
|
||||||
|
variant = "ghost",
|
||||||
|
size = "xs",
|
||||||
|
...props
|
||||||
|
}: Omit<React.ComponentProps<typeof Button>, "size"> &
|
||||||
|
VariantProps<typeof inputGroupButtonVariants>) {
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
type={type}
|
||||||
|
data-size={size}
|
||||||
|
variant={variant}
|
||||||
|
className={cn(inputGroupButtonVariants({ size }), className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function InputGroupText({ className, ...props }: React.ComponentProps<"span">) {
|
||||||
|
return (
|
||||||
|
<span
|
||||||
|
className={cn(
|
||||||
|
"text-muted-foreground flex items-center gap-2 text-sm [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function InputGroupInput({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<"input">) {
|
||||||
|
return (
|
||||||
|
<Input
|
||||||
|
data-slot="input-group-control"
|
||||||
|
className={cn(
|
||||||
|
"flex-1 rounded-none border-0 bg-transparent shadow-none focus-visible:ring-0 dark:bg-transparent",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function InputGroupTextarea({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<"textarea">) {
|
||||||
|
return (
|
||||||
|
<Textarea
|
||||||
|
data-slot="input-group-control"
|
||||||
|
className={cn(
|
||||||
|
"flex-1 resize-none rounded-none border-0 bg-transparent py-3 shadow-none focus-visible:ring-0 dark:bg-transparent",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
InputGroup,
|
||||||
|
InputGroupAddon,
|
||||||
|
InputGroupButton,
|
||||||
|
InputGroupText,
|
||||||
|
InputGroupInput,
|
||||||
|
InputGroupTextarea,
|
||||||
|
}
|
||||||
33
client/cms/src/components/ui/switch.tsx
Normal file
33
client/cms/src/components/ui/switch.tsx
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
import * as React from "react"
|
||||||
|
import * as SwitchPrimitive from "@radix-ui/react-switch"
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
|
function Switch({
|
||||||
|
className,
|
||||||
|
size = "default",
|
||||||
|
...props
|
||||||
|
}: React.ComponentProps<typeof SwitchPrimitive.Root> & {
|
||||||
|
size?: "sm" | "default"
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<SwitchPrimitive.Root
|
||||||
|
data-slot="switch"
|
||||||
|
data-size={size}
|
||||||
|
className={cn(
|
||||||
|
"peer data-[state=checked]:bg-primary data-[state=unchecked]:bg-input focus-visible:border-ring focus-visible:ring-ring/50 dark:data-[state=unchecked]:bg-input/80 group/switch inline-flex shrink-0 items-center rounded-full border border-transparent shadow-xs transition-all outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-[1.15rem] data-[size=default]:w-8 data-[size=sm]:h-3.5 data-[size=sm]:w-6",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<SwitchPrimitive.Thumb
|
||||||
|
data-slot="switch-thumb"
|
||||||
|
className={cn(
|
||||||
|
"bg-background dark:data-[state=unchecked]:bg-foreground dark:data-[state=checked]:bg-primary-foreground pointer-events-none block rounded-full ring-0 transition-transform group-data-[size=default]/switch:size-4 group-data-[size=sm]/switch:size-3 data-[state=checked]:translate-x-[calc(100%-2px)] data-[state=unchecked]:translate-x-0"
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</SwitchPrimitive.Root>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export { Switch }
|
||||||
18
client/cms/src/components/ui/textarea.tsx
Normal file
18
client/cms/src/components/ui/textarea.tsx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
import * as React from "react"
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
|
function Textarea({ className, ...props }: React.ComponentProps<"textarea">) {
|
||||||
|
return (
|
||||||
|
<textarea
|
||||||
|
data-slot="textarea"
|
||||||
|
className={cn(
|
||||||
|
"border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export { Textarea }
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import { postAuthExchangeMutation } from "@/client/@tanstack/react-query.gen";
|
import { useMutation } from '@tanstack/react-query';
|
||||||
import { useMutation } from "@tanstack/react-query";
|
import { toast } from 'sonner';
|
||||||
import { toast } from "sonner";
|
import { postAuthExchangeMutation } from '@/client/@tanstack/react-query.gen';
|
||||||
|
|
||||||
export function useExchangeToken() {
|
export function useExchangeToken() {
|
||||||
return useMutation({
|
return useMutation({
|
||||||
@@ -10,7 +10,7 @@ export function useExchangeToken() {
|
|||||||
},
|
},
|
||||||
onError: (error) => {
|
onError: (error) => {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
toast("An error occurred while exchanging the token. Please login manually.");
|
toast('An error occurred while exchanging the token. Please login manually.');
|
||||||
}
|
},
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
import { postAuthMagicMutation } from '@/client/@tanstack/react-query.gen';
|
|
||||||
import { useMutation } from '@tanstack/react-query';
|
import { useMutation } from '@tanstack/react-query';
|
||||||
|
import { postAuthMagicMutation } from '@/client/@tanstack/react-query.gen';
|
||||||
|
|
||||||
export function useGetMagicLink() {
|
export function useGetMagicLink() {
|
||||||
return useMutation({
|
return useMutation({
|
||||||
...postAuthMagicMutation()
|
...postAuthMagicMutation(),
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { getUserInfoQueryKey, patchUserUpdateMutation } from '@/client/@tanstack/react-query.gen';
|
|
||||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||||
|
import { getUserInfoQueryKey, patchUserUpdateMutation } from '@/client/@tanstack/react-query.gen';
|
||||||
|
|
||||||
export function useUpdateUser() {
|
export function useUpdateUser() {
|
||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
@@ -8,5 +8,5 @@ export function useUpdateUser() {
|
|||||||
onSuccess: async () => {
|
onSuccess: async () => {
|
||||||
await queryClient.invalidateQueries({ queryKey: getUserInfoQueryKey() });
|
await queryClient.invalidateQueries({ queryKey: getUserInfoQueryKey() });
|
||||||
},
|
},
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import { getUserInfoOptions } from '@/client/@tanstack/react-query.gen';
|
|
||||||
import { useSuspenseQuery } from '@tanstack/react-query';
|
import { useSuspenseQuery } from '@tanstack/react-query';
|
||||||
|
import { getUserInfoOptions } from '@/client/@tanstack/react-query.gen';
|
||||||
|
|
||||||
export function useUserInfo() {
|
export function useUserInfo() {
|
||||||
return useSuspenseQuery({
|
return useSuspenseQuery({
|
||||||
...getUserInfoOptions(),
|
...getUserInfoOptions(),
|
||||||
staleTime: 10 * 60 * 1000
|
staleTime: 10 * 60 * 1000,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,14 @@
|
|||||||
|
import { isEmpty, isNil } from 'lodash-es';
|
||||||
|
import { client } from '@/client/client.gen';
|
||||||
|
import { router } from './router';
|
||||||
import {
|
import {
|
||||||
getToken,
|
|
||||||
getRefreshToken,
|
|
||||||
setToken,
|
|
||||||
setRefreshToken,
|
|
||||||
clearTokens,
|
clearTokens,
|
||||||
doRefreshToken
|
doRefreshToken,
|
||||||
} from "./token";
|
getRefreshToken,
|
||||||
import { router } from "./router";
|
getToken,
|
||||||
import { isEmpty,
|
setRefreshToken,
|
||||||
isNil } from "lodash-es";
|
setToken,
|
||||||
import { client } from "@/client/client.gen";
|
} from './token';
|
||||||
|
|
||||||
export function configInternalApiClient() {
|
export function configInternalApiClient() {
|
||||||
client.setConfig({
|
client.setConfig({
|
||||||
@@ -50,7 +49,8 @@ export function configInternalApiClient() {
|
|||||||
signal: request.signal,
|
signal: request.signal,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
} catch (e) {
|
}
|
||||||
|
catch (e) {
|
||||||
clearTokens();
|
clearTokens();
|
||||||
await router.navigate({ to: '/authorize' });
|
await router.navigate({ to: '/authorize' });
|
||||||
return response;
|
return response;
|
||||||
@@ -59,5 +59,4 @@ export function configInternalApiClient() {
|
|||||||
}
|
}
|
||||||
return response;
|
return response;
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { postAuthRefresh, type ServiceAuthTokenResponse } from '@/client';
|
import type { ServiceAuthTokenResponse } from '@/client';
|
||||||
|
import { postAuthRefresh } from '@/client';
|
||||||
|
|
||||||
export function setToken(token: string) {
|
export function setToken(token: string) {
|
||||||
localStorage.setItem('token', token);
|
localStorage.setItem('token', token);
|
||||||
@@ -32,8 +33,8 @@ export function clearTokens() {
|
|||||||
export async function doRefreshToken(): Promise<ServiceAuthTokenResponse | undefined> {
|
export async function doRefreshToken(): Promise<ServiceAuthTokenResponse | undefined> {
|
||||||
const { data } = await postAuthRefresh({
|
const { data } = await postAuthRefresh({
|
||||||
body: {
|
body: {
|
||||||
refresh_token: getRefreshToken()!
|
refresh_token: getRefreshToken()!,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
return data?.data;
|
return data?.data;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
import { createFileRoute } from '@tanstack/react-router';
|
import { createFileRoute } from '@tanstack/react-router';
|
||||||
import { zodValidator } from '@tanstack/zod-adapter';
|
import { zodValidator } from '@tanstack/zod-adapter';
|
||||||
import { isNil } from 'lodash-es';
|
import { isNil } from 'lodash-es';
|
||||||
|
import { useEffect } from 'react';
|
||||||
import z from 'zod';
|
import z from 'zod';
|
||||||
import { LoginForm } from '@/components/login-form';
|
import { LoginForm } from '@/components/login-form';
|
||||||
|
import { useExchangeToken } from '@/hooks/data/useExchangeToken';
|
||||||
import { generateOAuthState } from '@/lib/random';
|
import { generateOAuthState } from '@/lib/random';
|
||||||
import { getToken } from '@/lib/token';
|
import { getToken } from '@/lib/token';
|
||||||
import { useExchangeToken } from '@/hooks/data/useExchangeToken';
|
|
||||||
import { useEffect } from 'react';
|
|
||||||
|
|
||||||
|
|
||||||
const baseUrl = import.meta.env.VITE_APP_BASE_URL;
|
const baseUrl = import.meta.env.VITE_APP_BASE_URL;
|
||||||
|
|
||||||
@@ -39,7 +38,7 @@ function RouteComponent() {
|
|||||||
client_id: oauthParams.client_id,
|
client_id: oauthParams.client_id,
|
||||||
redirect_uri: oauthParams.redirect_uri,
|
redirect_uri: oauthParams.redirect_uri,
|
||||||
state: oauthParams.state,
|
state: oauthParams.state,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, [token, mutation.isIdle]);
|
}, [token, mutation.isIdle]);
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
|
import { useMutation } from '@tanstack/react-query';
|
||||||
import { createFileRoute, useNavigate } from '@tanstack/react-router';
|
import { createFileRoute, useNavigate } from '@tanstack/react-router';
|
||||||
import {
|
import {
|
||||||
useEffect,
|
useEffect,
|
||||||
useState } from 'react';
|
useState,
|
||||||
|
} from 'react';
|
||||||
import z from 'zod';
|
import z from 'zod';
|
||||||
import { postAuthTokenMutation } from '@/client/@tanstack/react-query.gen';
|
import { postAuthTokenMutation } from '@/client/@tanstack/react-query.gen';
|
||||||
import { useMutation } from '@tanstack/react-query';
|
|
||||||
import { setRefreshToken, setToken } from '@/lib/token';
|
import { setRefreshToken, setToken } from '@/lib/token';
|
||||||
|
|
||||||
const tokenCodeSchema = z.object({
|
const tokenCodeSchema = z.object({
|
||||||
@@ -24,20 +25,20 @@ function RouteComponent() {
|
|||||||
const mutation = useMutation({
|
const mutation = useMutation({
|
||||||
...postAuthTokenMutation(),
|
...postAuthTokenMutation(),
|
||||||
onSuccess: (data) => {
|
onSuccess: (data) => {
|
||||||
setToken(data.data?.access_token!)
|
setToken(data.data?.access_token!);
|
||||||
setRefreshToken(data.data?.refresh_token!)
|
setRefreshToken(data.data?.refresh_token!);
|
||||||
void navigate({ to: '/' });
|
void navigate({ to: '/' });
|
||||||
},
|
},
|
||||||
onError: () => {
|
onError: () => {
|
||||||
setStatus('Error getting token');
|
setStatus('Error getting token');
|
||||||
}
|
},
|
||||||
})
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (mutation.isIdle) {
|
if (mutation.isIdle) {
|
||||||
mutation.mutate({ body: { code } })
|
mutation.mutate({ body: { code } });
|
||||||
}
|
}
|
||||||
}, [])
|
}, []);
|
||||||
|
|
||||||
return <div>{status}</div>;
|
return <div>{status}</div>;
|
||||||
}
|
}
|
||||||
|
|||||||
6
client/cms/src/vite.env.d.ts
vendored
6
client/cms/src/vite.env.d.ts
vendored
@@ -1,11 +1,11 @@
|
|||||||
interface ViteTypeOptions {
|
interface ViteTypeOptions {
|
||||||
strictImportMetaEnv: unknown
|
strictImportMetaEnv: unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ImportMetaEnv {
|
interface ImportMetaEnv {
|
||||||
readonly VITE_APP_BASE_URL: string
|
readonly VITE_APP_BASE_URL: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ImportMeta {
|
interface ImportMeta {
|
||||||
readonly env: ImportMetaEnv
|
readonly env: ImportMetaEnv;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user