From 87e637604d147ad7aeb128c63a4a7d68442c6d5f Mon Sep 17 00:00:00 2001 From: vyshnav Date: Sat, 14 Sep 2024 13:01:38 +0530 Subject: [PATCH 1/8] Add new dependencies for Radix UI and lodash.debounce --- package-lock.json | 453 ++++++++++++++++++++++++++++++++++++++++++++++ package.json | 4 + 2 files changed, 457 insertions(+) diff --git a/package-lock.json b/package-lock.json index 7494261..a2f2528 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,15 +12,19 @@ "@next-auth/prisma-adapter": "^1.0.7", "@prisma/adapter-libsql": "^5.19.1", "@prisma/client": "^5.19.1", + "@radix-ui/react-avatar": "^1.1.0", "@radix-ui/react-icons": "^1.3.0", "@radix-ui/react-label": "^2.1.0", + "@radix-ui/react-popover": "^1.1.1", "@radix-ui/react-slot": "^1.1.0", "@radix-ui/react-tabs": "^1.1.0", "@tanstack/react-query": "^5.56.2", + "@types/lodash.debounce": "^4.0.9", "axios": "^1.7.7", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", "jest": "^29.7.0", + "lodash.debounce": "^4.0.8", "lucide-react": "^0.441.0", "next": "14.2.6", "next-auth": "^4.24.7", @@ -743,6 +747,40 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@floating-ui/core": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.7.tgz", + "integrity": "sha512-yDzVT/Lm101nQ5TCVeK65LtdN7Tj4Qpr9RTXJ2vPFLqtLxwOrpoxAHAJI8J3yYWUc40J0BDBheaitK5SJmno2g==", + "dependencies": { + "@floating-ui/utils": "^0.2.7" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.6.10", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.10.tgz", + "integrity": "sha512-fskgCFv8J8OamCmyun8MfjB1Olfn+uZKjOKZ0vhYF3gRmEUXcGOjxWL8bBr7i4kIuPZ2KD2S3EUIOxnjC8kl2A==", + "dependencies": { + "@floating-ui/core": "^1.6.0", + "@floating-ui/utils": "^0.2.7" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.1.tgz", + "integrity": "sha512-4h84MJt3CHrtG18mGsXuLCHMrug49d7DFkU0RMIyshRveBeyV2hmV/pDaF2Uxtu8kgq5r46llp5E5FQiR0K2Yg==", + "dependencies": { + "@floating-ui/dom": "^1.0.0" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.7.tgz", + "integrity": "sha512-X8R8Oj771YRl/w+c1HqAC1szL8zWQRwFvgDwT129k9ACdBoud/+/rX9V0qiMl6LWUdP9voC2nDVZYPMQQsb6eA==" + }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.14", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", @@ -1754,6 +1792,53 @@ "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.0.tgz", "integrity": "sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA==" }, + "node_modules/@radix-ui/react-arrow": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.0.tgz", + "integrity": "sha512-FmlW1rCg7hBpEBwFbjHwCW6AmWLQM6g/v0Sn8XbP9NvmSZ2San1FpQeyPtufzOMSIx7Y4dzjlHoifhp+7NkZhw==", + "dependencies": { + "@radix-ui/react-primitive": "2.0.0" + }, + "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 + } + } + }, + "node_modules/@radix-ui/react-avatar": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-avatar/-/react-avatar-1.1.0.tgz", + "integrity": "sha512-Q/PbuSMk/vyAd/UoIShVGZ7StHHeRFYU7wXmi5GV+8cLXflZAEpHL/F697H1klrzxKXNtZ97vWiC0q3RKUH8UA==", + "dependencies": { + "@radix-ui/react-context": "1.1.0", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "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 + } + } + }, "node_modules/@radix-ui/react-collection": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.0.tgz", @@ -1821,6 +1906,70 @@ } } }, + "node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.0.tgz", + "integrity": "sha512-/UovfmmXGptwGcBQawLzvn2jOfM0t4z3/uKffoBlj724+n3FvBbZ7M0aaBOmkp6pqFYpO4yx8tSVJjx3Fl2jig==", + "dependencies": { + "@radix-ui/primitive": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-escape-keydown": "1.1.0" + }, + "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 + } + } + }, + "node_modules/@radix-ui/react-focus-guards": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.0.tgz", + "integrity": "sha512-w6XZNUPVv6xCpZUqb/yN9DL6auvpGX3C/ee6Hdi16v2UUy25HV2Q5bcflsiDyT/g5RwbPQ/GIT1vLkeRb+ITBw==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-focus-scope": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.0.tgz", + "integrity": "sha512-200UD8zylvEyL8Bx+z76RJnASR2gRMuxlgFCPAe/Q/679a/r0eK3MBVYMb7vZODZcffZBdob1EGnky78xmVvcA==", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-callback-ref": "1.1.0" + }, + "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 + } + } + }, "node_modules/@radix-ui/react-icons": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-icons/-/react-icons-1.3.0.tgz", @@ -1868,6 +2017,96 @@ } } }, + "node_modules/@radix-ui/react-popover": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.1.tgz", + "integrity": "sha512-3y1A3isulwnWhvTTwmIreiB8CF4L+qRjZnK1wYLO7pplddzXKby/GnZ2M7OZY3qgnl6p9AodUIHRYGXNah8Y7g==", + "dependencies": { + "@radix-ui/primitive": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.0", + "@radix-ui/react-dismissable-layer": "1.1.0", + "@radix-ui/react-focus-guards": "1.1.0", + "@radix-ui/react-focus-scope": "1.1.0", + "@radix-ui/react-id": "1.1.0", + "@radix-ui/react-popper": "1.2.0", + "@radix-ui/react-portal": "1.1.1", + "@radix-ui/react-presence": "1.1.0", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-slot": "1.1.0", + "@radix-ui/react-use-controllable-state": "1.1.0", + "aria-hidden": "^1.1.1", + "react-remove-scroll": "2.5.7" + }, + "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 + } + } + }, + "node_modules/@radix-ui/react-popper": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.0.tgz", + "integrity": "sha512-ZnRMshKF43aBxVWPWvbj21+7TQCvhuULWJ4gNIKYpRlQt5xGRhLx66tMp8pya2UkGHTSlhpXwmjqltDYHhw7Vg==", + "dependencies": { + "@floating-ui/react-dom": "^2.0.0", + "@radix-ui/react-arrow": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.0", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-layout-effect": "1.1.0", + "@radix-ui/react-use-rect": "1.1.0", + "@radix-ui/react-use-size": "1.1.0", + "@radix-ui/rect": "1.1.0" + }, + "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 + } + } + }, + "node_modules/@radix-ui/react-portal": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.1.tgz", + "integrity": "sha512-A3UtLk85UtqhzFqtoC8Q0KvR2GbXF3mtPgACSazajqq6A41mEQgo53iPzY4i6BwDxlIFqWIhiQ2G729n+2aw/g==", + "dependencies": { + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "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 + } + } + }, "node_modules/@radix-ui/react-presence": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.0.tgz", @@ -2020,6 +2259,23 @@ } } }, + "node_modules/@radix-ui/react-use-escape-keydown": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.0.tgz", + "integrity": "sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw==", + "dependencies": { + "@radix-ui/react-use-callback-ref": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-use-layout-effect": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz", @@ -2034,6 +2290,45 @@ } } }, + "node_modules/@radix-ui/react-use-rect": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.0.tgz", + "integrity": "sha512-0Fmkebhr6PiseyZlYAOtLS+nb7jLmpqTrJyv61Pe68MKYW6OWdRE2kI70TaYY27u7H0lajqM3hSMMLFq18Z7nQ==", + "dependencies": { + "@radix-ui/rect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-size": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.0.tgz", + "integrity": "sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw==", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/rect": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.0.tgz", + "integrity": "sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg==" + }, "node_modules/@rushstack/eslint-patch": { "version": "1.10.4", "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.10.4.tgz", @@ -2182,6 +2477,19 @@ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", "dev": true }, + "node_modules/@types/lodash": { + "version": "4.17.7", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.7.tgz", + "integrity": "sha512-8wTvZawATi/lsmNu10/j2hk1KEP0IvjubqPE3cu1Xz7xfXXt5oCq3SNUz4fMIP4XGF9Ky+Ue2tBA3hcS7LSBlA==" + }, + "node_modules/@types/lodash.debounce": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/lodash.debounce/-/lodash.debounce-4.0.9.tgz", + "integrity": "sha512-Ma5JcgTREwpLRwMM+XwBR7DaWe96nC38uCBDFKZWbNKD+osjVzdpnUSwBcqCptrp16sSOLBAUb50Car5I0TCsQ==", + "dependencies": { + "@types/lodash": "*" + } + }, "node_modules/@types/node": { "version": "20.16.1", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.1.tgz", @@ -2509,6 +2817,17 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", "dev": true }, + "node_modules/aria-hidden": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.4.tgz", + "integrity": "sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/aria-query": { "version": "5.1.3", "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", @@ -3507,6 +3826,11 @@ "node": ">=8" } }, + "node_modules/detect-node-es": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", + "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==" + }, "node_modules/didyoumean": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", @@ -4579,6 +4903,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/get-nonce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz", + "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==", + "engines": { + "node": ">=6" + } + }, "node_modules/get-package-type": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", @@ -4932,6 +5264,14 @@ "node": ">= 0.4" } }, + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, "node_modules/is-arguments": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", @@ -6559,6 +6899,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -7689,6 +8034,73 @@ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "dev": true }, + "node_modules/react-remove-scroll": { + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.5.7.tgz", + "integrity": "sha512-FnrTWO4L7/Bhhf3CYBNArEG/yROV0tKmTv7/3h9QCFvH6sndeFf1wPqOcbFVu5VAulS5dV1wGT3GZZ/1GawqiA==", + "dependencies": { + "react-remove-scroll-bar": "^2.3.4", + "react-style-singleton": "^2.2.1", + "tslib": "^2.1.0", + "use-callback-ref": "^1.3.0", + "use-sidecar": "^1.1.2" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-remove-scroll-bar": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.6.tgz", + "integrity": "sha512-DtSYaao4mBmX+HDo5YWYdBWQwYIQQshUV/dVxFxK+KM26Wjwp1gZ6rv6OC3oujI6Bfu6Xyg3TwK533AQutsn/g==", + "dependencies": { + "react-style-singleton": "^2.2.1", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-style-singleton": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.1.tgz", + "integrity": "sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==", + "dependencies": { + "get-nonce": "^1.0.0", + "invariant": "^2.2.4", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", @@ -8761,6 +9173,47 @@ "punycode": "^2.1.0" } }, + "node_modules/use-callback-ref": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.2.tgz", + "integrity": "sha512-elOQwe6Q8gqZgDA8mrh44qRTQqpIHDcZ3hXTLjBe1i4ph8XpNJnO+aQf3NaG+lriLopI4HMx9VjQLfPQ6vhnoA==", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-sidecar": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.2.tgz", + "integrity": "sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw==", + "dependencies": { + "detect-node-es": "^1.1.0", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "^16.9.0 || ^17.0.0 || ^18.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", diff --git a/package.json b/package.json index ffb55c2..4fff8ef 100644 --- a/package.json +++ b/package.json @@ -15,15 +15,19 @@ "@next-auth/prisma-adapter": "^1.0.7", "@prisma/adapter-libsql": "^5.19.1", "@prisma/client": "^5.19.1", + "@radix-ui/react-avatar": "^1.1.0", "@radix-ui/react-icons": "^1.3.0", "@radix-ui/react-label": "^2.1.0", + "@radix-ui/react-popover": "^1.1.1", "@radix-ui/react-slot": "^1.1.0", "@radix-ui/react-tabs": "^1.1.0", "@tanstack/react-query": "^5.56.2", + "@types/lodash.debounce": "^4.0.9", "axios": "^1.7.7", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", "jest": "^29.7.0", + "lodash.debounce": "^4.0.8", "lucide-react": "^0.441.0", "next": "14.2.6", "next-auth": "^4.24.7", From d811fc3480c585f31d572596d573b5aeb1647222 Mon Sep 17 00:00:00 2001 From: vyshnav Date: Sat, 14 Sep 2024 13:01:45 +0530 Subject: [PATCH 2/8] Add change-role.ts for updating user roles --- src/app/actions/change-role.ts | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 src/app/actions/change-role.ts diff --git a/src/app/actions/change-role.ts b/src/app/actions/change-role.ts new file mode 100644 index 0000000..e3495df --- /dev/null +++ b/src/app/actions/change-role.ts @@ -0,0 +1,25 @@ +"use server"; + +import prisma from "@/server/db"; +import { revalidatePath } from "next/cache"; + +async function updateUserRole(id: string, role: string) { + try { + const updatedUser = await prisma.user.update({ + where: { id }, + data: { role }, + }); + revalidatePath("/admin/users"); + return updatedUser; + } catch (error) { + console.error("Error updating user role:", error); + return null; + } +} +export const makeAdmin = async (userId: string) => { + return await updateUserRole(userId, "ADMIN"); +}; + +export const makeParticipant = async (userId: string) => { + return await updateUserRole(userId, "PARTICIPANT"); +}; From f3fd4d1a6b3b5f6cee4e4b69602042dbdc41d0c7 Mon Sep 17 00:00:00 2001 From: vyshnav Date: Sat, 14 Sep 2024 13:01:51 +0530 Subject: [PATCH 3/8] Add Users page component with initial user data --- src/app/admin/users/page.tsx | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 src/app/admin/users/page.tsx diff --git a/src/app/admin/users/page.tsx b/src/app/admin/users/page.tsx new file mode 100644 index 0000000..eeb6bb9 --- /dev/null +++ b/src/app/admin/users/page.tsx @@ -0,0 +1,33 @@ +import UsersList from "@/components/Admin/user-list"; +import prisma from "@/server/db"; + +export default async function Users() { + let initialUserData = await prisma.user.findMany({ + select: { + id: true, + name: true, + email: true, + role: true, + image: true, + }, + take: 10, + }); + if (initialUserData === null) { + initialUserData = [ + { + id: "1", + name: "Test name", + email: "testEmail@gmail.com", + role: "PARTICIPANT", + image: "https://i.pravatar.cc/300?img=1", + }, + ]; + } + return ( + <> +
+ +
+ + ); +} From afab7bbb3419b2e462837107e4aaa5c82c70de9b Mon Sep 17 00:00:00 2001 From: vyshnav Date: Sat, 14 Sep 2024 13:01:59 +0530 Subject: [PATCH 4/8] Add Users page component with initial user data --- src/app/api/users/route.ts | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/app/api/users/route.ts diff --git a/src/app/api/users/route.ts b/src/app/api/users/route.ts new file mode 100644 index 0000000..2449bcd --- /dev/null +++ b/src/app/api/users/route.ts @@ -0,0 +1,20 @@ +import prisma from "@/server/db"; + +import { NextResponse } from "next/server"; +export async function GET(req: Request) { + const { searchParams } = new URL(req.url); + const page = parseInt(searchParams.get("page") || "1"); + const search = searchParams.get("search") || ""; + const limit = 10; + + const users = await prisma.user.findMany({ + skip: (page - 1) * limit, + take: limit, + where: { + name: { + contains: search, + }, + }, + }); + return NextResponse.json({ users }); +} From 1a1a73ec4c30c98d1065960042f76635d07e59c1 Mon Sep 17 00:00:00 2001 From: vyshnav Date: Sat, 14 Sep 2024 13:02:06 +0530 Subject: [PATCH 5/8] Add change-role component for updating user roles --- src/components/Admin/change-role.tsx | 34 ++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 src/components/Admin/change-role.tsx diff --git a/src/components/Admin/change-role.tsx b/src/components/Admin/change-role.tsx new file mode 100644 index 0000000..a5c8bf1 --- /dev/null +++ b/src/components/Admin/change-role.tsx @@ -0,0 +1,34 @@ +"use client"; +import { makeAdmin, makeParticipant } from "@/app/actions/change-role"; +import { Button } from "@/components/ui/button"; + +export default function ChangeRole({ userId, userRole }: { userId: string; userRole: string }) { + async function handleMakeAdmin() { + await makeAdmin(userId); + } + + async function handleMakeParticipant() { + await makeParticipant(userId); + } + + return ( +
+ + +
+ ); +} From 01488924401448e14f2124382fd282ee5a400677 Mon Sep 17 00:00:00 2001 From: vyshnav Date: Sat, 14 Sep 2024 13:02:11 +0530 Subject: [PATCH 6/8] Add UsersList component for displaying and managing user roles --- src/components/Admin/user-list.tsx | 165 +++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 src/components/Admin/user-list.tsx diff --git a/src/components/Admin/user-list.tsx b/src/components/Admin/user-list.tsx new file mode 100644 index 0000000..9174dfc --- /dev/null +++ b/src/components/Admin/user-list.tsx @@ -0,0 +1,165 @@ +/* eslint-disable react-hooks/exhaustive-deps */ +"use client"; + +import { useState, useEffect, useRef, useCallback } from "react"; +import axios from "axios"; +import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "../ui/card"; +import { Avatar, AvatarFallback, AvatarImage } from "../ui/avatar"; +import { Popover, PopoverContent, PopoverTrigger } from "../ui/popover"; +import { Button } from "../ui/button"; +import { ChevronDownIcon, SearchIcon } from "lucide-react"; +import { Input } from "../ui/input"; +import debounce from "lodash.debounce"; +import ChangeRole from "./change-role"; + +export interface User { + id: string; + name: string | null; + email: string | null; + role: string; + image: string | null; +} + +interface UsersListProps { + initialUsers: User[]; + initialPage: number; +} +export const dynamic = "force-dynamic"; +const UsersList: React.FC = ({ initialUsers, initialPage }) => { + const [userList, setUserList] = useState(initialUsers); + const [currentPage, setCurrentPage] = useState(initialPage); + const [loading, setLoading] = useState(false); + const [hasMore, setHasMore] = useState(true); + const [searchQuery, setSearchQuery] = useState(""); // Search query state + const loader = useRef(null); + + const fetchUsers = async (page: number, query: string) => { + if (loading) return; + setLoading(true); + try { + const response = await axios.get(`/api/users?page=${page}&search=${encodeURIComponent(query)}`); + if (response.data.users.length > 0) { + setUserList((prevUsers) => [...prevUsers, ...response.data.users]); + setCurrentPage(page); + } else { + setHasMore(false); + } + } catch (error) { + console.error("Error fetching users:", error); + } + setLoading(false); + }; + const loadMoreUsers = useCallback(() => { + if (hasMore) { + fetchUsers(currentPage + 1, searchQuery); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [currentPage, hasMore, searchQuery]); + + const debouncedFetchUsers = useCallback( + debounce(async (query: string) => { + setCurrentPage(1); // Reset page number + setHasMore(true); // Reset hasMore + try { + const response = await axios.get(`/api/users?page=1&search=${encodeURIComponent(query)}`); + setUserList(response.data.users); + } catch (error) { + console.error("Error fetching users:", error); + } + }, 500), + [] + ); + const handleSearchChange = (e: React.ChangeEvent) => { + const query = e.target.value; + setSearchQuery(query); + debouncedFetchUsers(query); // Use debounced fetch function + }; + + // Observe scroll and load more users when scrolled to the bottom + useEffect(() => { + if (loader.current) { + const observer = new IntersectionObserver( + (entries) => { + if (entries[0].isIntersecting && hasMore) { + loadMoreUsers(); + } + }, + { threshold: 1.0 } + ); + observer.observe(loader.current); + return () => observer.disconnect(); + } + }, [loader.current, hasMore, loadMoreUsers]); + + return ( + <> +
+
+ +
+
+ + +
+
+ + Users + Manage user roles and permissions. + + +
+ {userList.map((user) => ( +
+
+ + + + {user.name ? user.name[0] : "N/A"} + + +
+

+ {user.name || "Unknown"} +

+

+ {user.email || "No email"} +

+
+
+ + + + + + + + +
+ ))} +
+ {hasMore && ( +
+ {loading ? "Loading..." : "Load more"} +
+ )} +
+
+
+
+ + ); +}; + +export default UsersList; From 8389ced19be734a21d80daf2f2e9ff0b109ca278 Mon Sep 17 00:00:00 2001 From: vyshnav Date: Sat, 14 Sep 2024 13:02:15 +0530 Subject: [PATCH 7/8] Add Avatar component for displaying user avatars --- src/components/ui/avatar.tsx | 50 ++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 src/components/ui/avatar.tsx diff --git a/src/components/ui/avatar.tsx b/src/components/ui/avatar.tsx new file mode 100644 index 0000000..51e507b --- /dev/null +++ b/src/components/ui/avatar.tsx @@ -0,0 +1,50 @@ +"use client" + +import * as React from "react" +import * as AvatarPrimitive from "@radix-ui/react-avatar" + +import { cn } from "@/lib/utils" + +const Avatar = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +Avatar.displayName = AvatarPrimitive.Root.displayName + +const AvatarImage = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AvatarImage.displayName = AvatarPrimitive.Image.displayName + +const AvatarFallback = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName + +export { Avatar, AvatarImage, AvatarFallback } From 6f9e984314e499af13e3e0af24e875b1805e2576 Mon Sep 17 00:00:00 2001 From: vyshnav Date: Sat, 14 Sep 2024 13:02:24 +0530 Subject: [PATCH 8/8] Add Popover component for displaying popovers in the UI --- src/components/ui/popover.tsx | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 src/components/ui/popover.tsx diff --git a/src/components/ui/popover.tsx b/src/components/ui/popover.tsx new file mode 100644 index 0000000..29c7bd2 --- /dev/null +++ b/src/components/ui/popover.tsx @@ -0,0 +1,33 @@ +"use client" + +import * as React from "react" +import * as PopoverPrimitive from "@radix-ui/react-popover" + +import { cn } from "@/lib/utils" + +const Popover = PopoverPrimitive.Root + +const PopoverTrigger = PopoverPrimitive.Trigger + +const PopoverAnchor = PopoverPrimitive.Anchor + +const PopoverContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, align = "center", sideOffset = 4, ...props }, ref) => ( + + + +)) +PopoverContent.displayName = PopoverPrimitive.Content.displayName + +export { Popover, PopoverTrigger, PopoverContent, PopoverAnchor }