diff --git a/package-lock.json b/package-lock.json index e857530..d31bc9b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,7 +25,6 @@ "axios": "^1.7.2", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", - "formik": "^2.4.6", "ldrs": "^1.0.2", "lucide-react": "^0.408.0", "next": "14.2.5", @@ -38,9 +37,9 @@ "redux-thunk": "^3.1.0", "sass": "^1.77.8", "scss": "^0.2.4", + "sharp": "^0.33.4", "tailwind-merge": "^2.4.0", - "tailwindcss-animate": "^1.0.7", - "yup": "^1.4.0" + "tailwindcss-animate": "^1.0.7" }, "devDependencies": { "@types/node": "^20", @@ -261,6 +260,16 @@ "node": ">=6.9.0" } }, + "node_modules/@emnapi/runtime": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.2.0.tgz", + "integrity": "sha512-bV21/9LQmcQeCPEg3BDFtvwL6cwiTMksYNWQQ4KOxCZikEGalWtenoZ0wCiukJINlGCIi2KXx01g4FoH/LxpzQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@emotion/babel-plugin": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.12.0.tgz", @@ -445,6 +454,456 @@ "integrity": "sha512-sTcG+QZ6fdEUObICavU+aB3Mp8HY4n14wYHdxK4fXjPmv3PXZZeY5RaguJmGyeH/CJQhX3fqKUtS4qc1LoHwhQ==", "license": "MIT" }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.33.4", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.4.tgz", + "integrity": "sha512-p0suNqXufJs9t3RqLBO6vvrgr5OhgbWp76s5gTRvdmxmuv9E1rcaqGUsl3l4mKVmXPkTkTErXediAui4x+8PSA==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "glibc": ">=2.26", + "node": "^18.17.0 || ^20.3.0 || >=21.0.0", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.0.2" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.33.4", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.4.tgz", + "integrity": "sha512-0l7yRObwtTi82Z6ebVI2PnHT8EB2NxBgpK2MiKJZJ7cz32R4lxd001ecMhzzsZig3Yv9oclvqqdV93jo9hy+Dw==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "glibc": ">=2.26", + "node": "^18.17.0 || ^20.3.0 || >=21.0.0", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.0.2" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.2.tgz", + "integrity": "sha512-tcK/41Rq8IKlSaKRCCAuuY3lDJjQnYIW1UXU1kxcEKrfL8WR7N6+rzNoOxoQRJWTAECuKwgAHnPvqXGN8XfkHA==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "macos": ">=11", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.2.tgz", + "integrity": "sha512-Ofw+7oaWa0HiiMiKWqqaZbaYV3/UGL2wAPeLuJTx+9cXpCRdvQhCLG0IH8YGwM0yGWGLpsF4Su9vM1o6aer+Fw==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "macos": ">=10.13", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.2.tgz", + "integrity": "sha512-iLWCvrKgeFoglQxdEwzu1eQV04o8YeYGFXtfWU26Zr2wWT3q3MTzC+QTCO3ZQfWd3doKHT4Pm2kRmLbupT+sZw==", + "cpu": [ + "arm" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "glibc": ">=2.28", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.2.tgz", + "integrity": "sha512-x7kCt3N00ofFmmkkdshwj3vGPCnmiDh7Gwnd4nUwZln2YjqPxV1NlTyZOvoDWdKQVDL911487HOueBvrpflagw==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "glibc": ">=2.26", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.2.tgz", + "integrity": "sha512-cmhQ1J4qVhfmS6szYW7RT+gLJq9dH2i4maq+qyXayUSn9/3iY2ZeWpbAgSpSVbV2E1JUL2Gg7pwnYQ1h8rQIog==", + "cpu": [ + "s390x" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "glibc": ">=2.28", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.2.tgz", + "integrity": "sha512-E441q4Qdb+7yuyiADVi5J+44x8ctlrqn8XgkDTwr4qPJzWkaHwD489iZ4nGDgcuya4iMN3ULV6NwbhRZJ9Z7SQ==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "glibc": ">=2.26", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.2.tgz", + "integrity": "sha512-3CAkndNpYUrlDqkCM5qhksfE+qSIREVpyoeHIU6jd48SJZViAmznoQQLAv4hVXF7xyUB9zf+G++e2v1ABjCbEQ==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "musl": ">=1.2.2", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.2.tgz", + "integrity": "sha512-VI94Q6khIHqHWNOh6LLdm9s2Ry4zdjWJwH56WoiJU7NTeDwyApdZZ8c+SADC8OH98KWNQXnE01UdJ9CSfZvwZw==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "musl": ">=1.2.2", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.33.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.4.tgz", + "integrity": "sha512-RUgBD1c0+gCYZGCCe6mMdTiOFS0Zc/XrN0fYd6hISIKcDUbAW5NtSQW9g/powkrXYm6Vzwd6y+fqmExDuCdHNQ==", + "cpu": [ + "arm" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "glibc": ">=2.28", + "node": "^18.17.0 || ^20.3.0 || >=21.0.0", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.0.2" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.33.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.4.tgz", + "integrity": "sha512-2800clwVg1ZQtxwSoTlHvtm9ObgAax7V6MTAB/hDT945Tfyy3hVkmiHpeLPCKYqYR1Gcmv1uDZ3a4OFwkdBL7Q==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "glibc": ">=2.26", + "node": "^18.17.0 || ^20.3.0 || >=21.0.0", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.0.2" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.33.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.4.tgz", + "integrity": "sha512-h3RAL3siQoyzSoH36tUeS0PDmb5wINKGYzcLB5C6DIiAn2F3udeFAum+gj8IbA/82+8RGCTn7XW8WTFnqag4tQ==", + "cpu": [ + "s390x" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "glibc": ">=2.31", + "node": "^18.17.0 || ^20.3.0 || >=21.0.0", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.0.2" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.33.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.4.tgz", + "integrity": "sha512-GoR++s0XW9DGVi8SUGQ/U4AeIzLdNjHka6jidVwapQ/JebGVQIpi52OdyxCNVRE++n1FCLzjDovJNozif7w/Aw==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "glibc": ">=2.26", + "node": "^18.17.0 || ^20.3.0 || >=21.0.0", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.0.2" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.33.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.4.tgz", + "integrity": "sha512-nhr1yC3BlVrKDTl6cO12gTpXMl4ITBUZieehFvMntlCXFzH2bvKG76tBL2Y/OqhupZt81pR7R+Q5YhJxW0rGgQ==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "musl": ">=1.2.2", + "node": "^18.17.0 || ^20.3.0 || >=21.0.0", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.0.2" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.33.4", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.4.tgz", + "integrity": "sha512-uCPTku0zwqDmZEOi4ILyGdmW76tH7dm8kKlOIV1XC5cLyJ71ENAAqarOHQh0RLfpIpbV5KOpXzdU6XkJtS0daw==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "musl": ">=1.2.2", + "node": "^18.17.0 || ^20.3.0 || >=21.0.0", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.0.2" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.33.4", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.4.tgz", + "integrity": "sha512-Bmmauh4sXUsUqkleQahpdNXKvo+wa1V9KhT2pDA4VJGKwnKMJXiSTGphn0gnJrlooda0QxCtXc6RX1XAU6hMnQ==", + "cpu": [ + "wasm32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.1.1" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.33.4", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.4.tgz", + "integrity": "sha512-99SJ91XzUhYHbx7uhK3+9Lf7+LjwMGQZMDlO/E/YVJ7Nc3lyDFZPGhjwiYdctoH2BOzW9+TnfqcaMKt0jHLdqw==", + "cpu": [ + "ia32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.33.4", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.4.tgz", + "integrity": "sha512-3QLocdTRVIrFNye5YocZl+KKpYKP+fksi1QhmOArgx7GyhIbQp/WrJRu176jm8IxromS7RIkzMiMINVdBtC8Aw==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0", + "npm": ">=9.6.5", + "pnpm": ">=7.1.0", + "yarn": ">=3.2.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, "node_modules/@isaacs/cliui": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", @@ -1726,16 +2185,6 @@ "tslib": "^2.4.0" } }, - "node_modules/@types/hoist-non-react-statics": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.5.tgz", - "integrity": "sha512-SbcrWzkKBw2cdwRTwQAswfpB9g9LJWfjtUeW/jvNwbhC8cpmmNYVePa+ncbUe0rGTQ7G3Ff6mYUN2VMfLVr+Sg==", - "license": "MIT", - "dependencies": { - "@types/react": "*", - "hoist-non-react-statics": "^3.3.0" - } - }, "node_modules/@types/node": { "version": "20.14.10", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.10.tgz", @@ -2284,6 +2733,19 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/color": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1", + "color-string": "^1.9.0" + }, + "engines": { + "node": ">=12.5.0" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -2302,6 +2764,16 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "license": "MIT" }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "license": "MIT", + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -2421,15 +2893,6 @@ } } }, - "node_modules/deepmerge": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-2.2.1.tgz", - "integrity": "sha512-R9hc1Xa/NOBi9WRVUWg19rl1UB7Tt4kuPd+thNJgFZoxXsTz7ncaPaeIm+40oSGuP33DfMb4sZt1QIGiJzC4EA==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -2439,6 +2902,15 @@ "node": ">=0.4.0" } }, + "node_modules/detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "license": "Apache-2.0", + "engines": { + "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", @@ -2657,31 +3129,6 @@ "node": ">=12.20.0" } }, - "node_modules/formik": { - "version": "2.4.6", - "resolved": "https://registry.npmjs.org/formik/-/formik-2.4.6.tgz", - "integrity": "sha512-A+2EI7U7aG296q2TLGvNapDNTZp1khVt5Vk0Q/fyfSROss0V/V6+txt2aJnwEos44IxTCW/LYAi/zgWzlevj+g==", - "funding": [ - { - "type": "individual", - "url": "https://opencollective.com/formik" - } - ], - "license": "Apache-2.0", - "dependencies": { - "@types/hoist-non-react-statics": "^3.3.1", - "deepmerge": "^2.1.1", - "hoist-non-react-statics": "^3.3.0", - "lodash": "^4.17.21", - "lodash-es": "^4.17.21", - "react-fast-compare": "^2.0.1", - "tiny-warning": "^1.0.2", - "tslib": "^2.0.0" - }, - "peerDependencies": { - "react": ">=16.8.0" - } - }, "node_modules/fraction.js": { "version": "4.3.7", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", @@ -3030,18 +3477,6 @@ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "license": "MIT" }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "license": "MIT" - }, - "node_modules/lodash-es": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", - "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", - "license": "MIT" - }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -3666,12 +4101,6 @@ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "license": "MIT" }, - "node_modules/property-expr": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.6.tgz", - "integrity": "sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==", - "license": "MIT" - }, "node_modules/proxy-from-env": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", @@ -3723,12 +4152,6 @@ "react": "^18.3.1" } }, - "node_modules/react-fast-compare": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-2.0.4.tgz", - "integrity": "sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw==", - "license": "MIT" - }, "node_modules/react-icons": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.2.1.tgz", @@ -4024,12 +4447,64 @@ "node": ">= 0.2.0" } }, + "node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/server-only": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/server-only/-/server-only-0.0.1.tgz", "integrity": "sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA==", "license": "MIT" }, + "node_modules/sharp": { + "version": "0.33.4", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.4.tgz", + "integrity": "sha512-7i/dt5kGl7qR4gwPRD2biwD2/SvBn3O04J77XKFgL2OnZtQw+AG9wnuS/csmu80nPRHLYE9E41fyEiG8nhH6/Q==", + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "color": "^4.2.3", + "detect-libc": "^2.0.3", + "semver": "^7.6.0" + }, + "engines": { + "libvips": ">=8.15.2", + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.33.4", + "@img/sharp-darwin-x64": "0.33.4", + "@img/sharp-libvips-darwin-arm64": "1.0.2", + "@img/sharp-libvips-darwin-x64": "1.0.2", + "@img/sharp-libvips-linux-arm": "1.0.2", + "@img/sharp-libvips-linux-arm64": "1.0.2", + "@img/sharp-libvips-linux-s390x": "1.0.2", + "@img/sharp-libvips-linux-x64": "1.0.2", + "@img/sharp-libvips-linuxmusl-arm64": "1.0.2", + "@img/sharp-libvips-linuxmusl-x64": "1.0.2", + "@img/sharp-linux-arm": "0.33.4", + "@img/sharp-linux-arm64": "0.33.4", + "@img/sharp-linux-s390x": "0.33.4", + "@img/sharp-linux-x64": "0.33.4", + "@img/sharp-linuxmusl-arm64": "0.33.4", + "@img/sharp-linuxmusl-x64": "0.33.4", + "@img/sharp-wasm32": "0.33.4", + "@img/sharp-win32-ia32": "0.33.4", + "@img/sharp-win32-x64": "0.33.4" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -4063,6 +4538,21 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, + "node_modules/simple-swizzle/node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", + "license": "MIT" + }, "node_modules/source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -4373,18 +4863,6 @@ "node": ">=0.8" } }, - "node_modules/tiny-case": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tiny-case/-/tiny-case-1.0.3.tgz", - "integrity": "sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==", - "license": "MIT" - }, - "node_modules/tiny-warning": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", - "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==", - "license": "MIT" - }, "node_modules/to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", @@ -4406,12 +4884,6 @@ "node": ">=8.0" } }, - "node_modules/toposort": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", - "integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==", - "license": "MIT" - }, "node_modules/tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", @@ -4431,18 +4903,6 @@ "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", "license": "0BSD" }, - "node_modules/type-fest": { - "version": "2.19.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", - "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/typescript": { "version": "5.5.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz", @@ -4740,18 +5200,6 @@ "engines": { "node": ">= 14" } - }, - "node_modules/yup": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/yup/-/yup-1.4.0.tgz", - "integrity": "sha512-wPbgkJRCqIf+OHyiTBQoJiP5PFuAXaWiJK6AmYkzQAh5/c2K9hzSApBZG5wV9KoKSePF7sAxmNSvh/13YHkFDg==", - "license": "MIT", - "dependencies": { - "property-expr": "^2.0.5", - "tiny-case": "^1.0.3", - "toposort": "^2.0.2", - "type-fest": "^2.19.0" - } } } } diff --git a/package.json b/package.json index 1395dd8..5bb01f8 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "redux-thunk": "^3.1.0", "sass": "^1.77.8", "scss": "^0.2.4", + "sharp": "^0.33.4", "tailwind-merge": "^2.4.0", "tailwindcss-animate": "^1.0.7" }, diff --git a/src/app/api/v1/create/event/route.ts b/src/app/api/v1/create/event/route.ts index 60ebbe5..1c1e4ec 100644 --- a/src/app/api/v1/create/event/route.ts +++ b/src/app/api/v1/create/event/route.ts @@ -1,6 +1,21 @@ import { NextRequest, NextResponse } from "next/server"; import { createClient } from "@/utils/supabase/server"; import { Tables } from "@/types/supabase"; +import sharp from "sharp"; + +async function convertToAvif(inputFile: File): Promise { + const arrayBuffer = await inputFile.arrayBuffer(); + const buffer = Buffer.from(arrayBuffer); + + const avifBuffer = await sharp(buffer) + .avif() + .toBuffer(); + + const blob = new Blob([avifBuffer], { type: 'image/avif' }); + const avifFile = new File([blob], inputFile.name, { type: 'image/avif' }); + + return avifFile; +} function validateEvent(event: Tables<"events">): { valid: boolean; @@ -18,30 +33,51 @@ function validateEvent(event: Tables<"events">): { // Add more validations as needed return { valid: true }; } - export async function POST(request: NextRequest): Promise { try { const supabase = createClient(); const { data: { user }, error: userError, - } = await supabase.auth.getUser(); + } = await supabase.auth.getUser(); if (userError || !user) { return NextResponse.json( { success: false, message: "Unauthorized" }, { status: 401 } ); } - const isAdmin = await supabase.from("users").select("admin").eq("id", user.id); + + const isAdmin = await supabase + .from("users") + .select("admin") + .eq("id", user.id); if (isAdmin.error || !isAdmin.data || isAdmin.data.length === 0 || !isAdmin.data[0].admin) { return NextResponse.json( { success: false, message: "Unauthorized" }, { status: 401 } ); } - const body = await request.json(); - const { event }: { event: Tables<"events"> } = body; + + const formData = await request.formData(); + const event = Object.fromEntries(formData.entries()) as any; + + event.requirements = JSON.parse(event.requirements); event.creator = user.id; + + event.convenors = JSON.parse(event.convenors); + event.prizes = JSON.parse(event.prizes); + event.winners = JSON.parse(event.winners); + + const poster_file = formData.get("poster") as File; + let poster: File | null = null; + + if (poster_file) { + poster = await convertToAvif(poster_file); + } + + + delete event.poster; + const validation = validateEvent(event); if (!validation.valid) { return NextResponse.json( @@ -57,13 +93,29 @@ export async function POST(request: NextRequest): Promise { if (error) { throw new Error(error.message); } - if (!data || data.length === 0) { - throw new Error("Failed to create event"); + + const eventId = data[0]?.id; + if (!eventId) { + throw new Error("Failed to get event ID"); } + + if (poster_file && poster) { + + const { error: posterUploadError } = await supabase.storage + .from(process.env.BUCKET || "") + .upload(`/events/${eventId}/poster`, poster, { + upsert: true, + }); + + if (posterUploadError) { + throw new Error(posterUploadError.message); + } + } + return NextResponse.json({ success: true, message: "Event created successfully", - id: data[0].id, + id: eventId, }); } catch (error: any) { return NextResponse.json( diff --git a/src/app/api/v1/get/blog/route.ts b/src/app/api/v1/get/blog/route.ts index 09ad635..f1637fb 100644 --- a/src/app/api/v1/get/blog/route.ts +++ b/src/app/api/v1/get/blog/route.ts @@ -1,5 +1,6 @@ import { NextRequest, NextResponse } from "next/server"; import { createClient } from "@/utils/supabase/server"; +import { getPublicUrl } from "@/lib/utils"; export async function GET(request: NextRequest): Promise { try { @@ -26,12 +27,12 @@ export async function GET(request: NextRequest): Promise { ); } - const posterUrl = `${process.env.SUPABASE_STORAGE_URL}/web_data/images/${id}/poster`; - const blogFileUrl = `${process.env.SUPABASE_STORAGE_URL}/web_data/blogs/${id}/blog`; + const posterUrl = `${getPublicUrl(`/images/${id}/poster`)}`; + const blogFileUrl = `${getPublicUrl(`/blogs/${id}/blog`)}`; const { data: images, error: imagesError } = await supabase .storage - .from('web_data') + .from(process.env.BUCKET || "") .list(`images/${id}/`); if (imagesError) { @@ -41,7 +42,7 @@ export async function GET(request: NextRequest): Promise { ); } - const imageUrls = images.map(image => `${process.env.SUPABASE_STORAGE_URL}/web_data/blogs/${id}/images/${image.name}`); + const imageUrls = images.map(image => `${getPublicUrl(`/blogs/${id}/images/${image.name}`)}`); return NextResponse.json({ diff --git a/src/app/api/v1/get/blogs/route.ts b/src/app/api/v1/get/blogs/route.ts index 540bddd..60ee324 100644 --- a/src/app/api/v1/get/blogs/route.ts +++ b/src/app/api/v1/get/blogs/route.ts @@ -1,5 +1,6 @@ import { NextRequest, NextResponse } from "next/server"; import { createClient } from "@/utils/supabase/server"; +import { getPublicUrl } from "@/lib/utils"; export async function GET(request: NextRequest): Promise { try { @@ -32,19 +33,20 @@ export async function GET(request: NextRequest): Promise { const blogPromises = blogs.map(async (blog) => { - const posterUrl = `${process.env.SUPABASE_STORAGE_URL}/web_data/images/${blog.id}/poster`; - const blogFileUrl = `${process.env.SUPABASE_STORAGE_URL}/web_data/blogs/${blog.id}/blog`; + const posterUrl = `${getPublicUrl(`/images/${blog.id}/poster`)}`; + const blogFileUrl = `${getPublicUrl(`/blogs/${blog.id}/blog`)}`; const { data: images, error: imagesError } = await supabase .storage - .from('web_data') + .from(process.env.BUCKET || "") .list(`images/${blog.id}`); if (imagesError) { throw new Error(imagesError.message); } - const imageUrls = images.map(image => `${process.env.SUPABASE_STORAGE_URL}/web_data/images/${blog.id}/${image.name}`); + + const imageUrls = images.map(image => `${getPublicUrl(`/images/${blog.id}/${image.name}`)}`); return { ...blog, diff --git a/src/app/api/v1/submit/blog/route.ts b/src/app/api/v1/submit/blog/route.ts index 758d8e0..9db4dde 100644 --- a/src/app/api/v1/submit/blog/route.ts +++ b/src/app/api/v1/submit/blog/route.ts @@ -1,6 +1,22 @@ import { NextRequest, NextResponse } from "next/server"; import { createClient } from "@/utils/supabase/server"; import { Tables } from "@/types/supabase"; +import sharp from "sharp"; + + +async function convertToAvif(inputFile: File): Promise { + const arrayBuffer = await inputFile.arrayBuffer(); + const buffer = Buffer.from(arrayBuffer); + + const avifBuffer = await sharp(buffer) + .avif() + .toBuffer(); + + const blob = new Blob([avifBuffer], { type: 'image/avif' }); + const avifFile = new File([blob], inputFile.name, { type: 'image/avif' }); + + return avifFile; +} function validateRequestBody(body: { blogTable: Tables<"blogs">; @@ -36,8 +52,15 @@ export async function POST(request: NextRequest): Promise { const formData = await request.formData(); const blogData = JSON.parse(formData.get('blogData') as string); - const poster = formData.get('poster') as File; + const posterFile = formData.get('poster') as File; const blogFile = formData.get('blog') as File; + + let poster: File = posterFile; + + if (posterFile) { + poster = await convertToAvif(posterFile); + } + const images = formData.getAll('images') as File[]; const validation = validateRequestBody({ @@ -55,6 +78,16 @@ export async function POST(request: NextRequest): Promise { blogData.writer = user.id; + const { data: userData, error: userDataError} = await supabase.from("users").select("username").eq("id", user.id); + + if (userDataError || !userData || userData.length === 0) { + throw new Error(userDataError?.message || "Failed to get user data"); + } + + blogData.writer_name = user; + blogData.writer_username = userData[0].username; + console.log(blogData.writer_name); + const { data: blogs, error: blogsError } = await supabase .from("blogs") .insert([blogData]) @@ -67,19 +100,25 @@ export async function POST(request: NextRequest): Promise { const uploadPromises = [ supabase.storage - .from("web_data") - .upload(`blogs/${blogId}/blog`, blogFile), + .from(process.env.BUCKET || "") + .upload(`blogs/${blogId}/blog`, blogFile, { + upsert: true, + }), supabase.storage - .from("web_data") - .upload(`images/${blogId}/poster`, poster), + .from(process.env.BUCKET || "") + .upload(`images/${blogId}/poster`, poster, { + upsert: true, + }), ]; if (images.length > 0) { - images.forEach((image: File) => { + images.forEach(async (image: File) => { console.log("Uploading image", image); uploadPromises.push( supabase.storage - .from("web_data") - .upload(`images/${blogId}/${image.name}`, image) + .from(process.env.BUCKET || "") + .upload(`images/${blogId}/${image.name}`, await convertToAvif(image), { + upsert: true, + }) ); }); } diff --git a/src/app/blogs/page.jsx b/src/app/blogs/page.jsx index 86b3906..566644c 100644 --- a/src/app/blogs/page.jsx +++ b/src/app/blogs/page.jsx @@ -49,33 +49,6 @@ export default function Blogs() { } }; - - - // const blogsArray =[ - // { - // "id": 24, - // "title": "Seventh Blog", - // "intro": "This is the seventh blog", - // "writer": "b4e05b86-df08-49d8-a118-51c205216401", - // "created_at": "2024-07-26T07:33:28.697994+00:00", - // "posterUrl": "undefined/web_data/images/24/poster", - // "blogFileUrl": "undefined/web_data/blogs/24/blog", - // "images": [] - // }, - // { - // "id": 25, - // "title": "ReactJS Tic-Tac-Toe (💥Passed Job Interview 😂 ) (💥Passed Job Interview💥)", - // "intro": "From bugs to brilliance: the journey of a coder. From bugs to brilliance: the journey of a coder. From bugs to brilliance: the journey of a coder. From bugs to brilliance: the journey of a coder. From bugs to brilliance: the journey of a coder. From bugs to brilliance: the journey of a coder", - // "writer": "b4e05b86-df08-49d8-a118-51c205216401", - // "created_at": "2024-06-14T07:33:28.697994+00:00", - // "posterUrl": "undefined/web_data/images/24/poster", - // "blogFileUrl": "undefined/web_data/blogs/24/blog", - // "images": ["https://i.ibb.co/3RWZ6rF/image.png", - // "https://cdn.pixabay.com/photo/2024/05/16/20/20/digital-8766937_1280.png", - // "https://cdn.pixabay.com/photo/2024/05/20/13/28/ai-generated-8775234_1280.png" - // ] - // } - // ] const handleSearchInputChange = (event) => { setSearchInputValue(event.target.value); }; diff --git a/src/app/test_api/page.tsx b/src/app/test_api/page.tsx index 3a59582..eebb62c 100644 --- a/src/app/test_api/page.tsx +++ b/src/app/test_api/page.tsx @@ -12,27 +12,36 @@ export default function Page() { const [blogId, setBlogId] = useState("24"); const [events, setEvents] = useState([]); const [blogs, setBlogs] = useState([]); - const createEvent = async () => { + const createEvent = async () => { + if (!selectedPosterFile) { + console.error("Missing required event for blog submission"); + return; + } + + const formData = new FormData(); + formData.append("name", "CodeStrike v6.0"); + formData.append("description", "A competitive coding event"); + formData.append("date", "2024-07-30"); + formData.append("duration", "180"); + formData.append("mode", "true"); + formData.append("host_link", "https://www.example.com"); + formData.append("requirements", JSON.stringify(["Laptop", "Notebook"])); + formData.append("hosted_registration", "true"); + formData.append("register_until", "2024-09-28"); + formData.append("registration_link", "https://www.example.com"); + formData.append("poster", selectedPosterFile); + formData.append("venue_link", "https://maps.google.com/maps?width=100%25&height=600&hl=en&q=Indian%20Institute%20of%20Information%20Technology%20Vadodara+(IIIT%20Vadodara)&t=&z=14&ie=UTF8&iwloc=B&output=embed"); + formData.append("convenors", JSON.stringify(["devyash", "devyash", "devyash"])); + formData.append("prizes", JSON.stringify(["7Cr", "69L", "3.14L", {"fy special": "150 Rupiya"}])); + formData.append("winners", JSON.stringify(["devyash", "devyash", "devyash", {"fy special": "devyash"}])); + // current time + formData.append("time", new Date().toLocaleTimeString()); + const response = await fetch("/api/v1/create/event/", { method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - event: { - name: "CodeStrike v6.0", - description: "A competitive coding event", - date: "2024-07-30", - duration: 180, - mode: true, - host_link: "https://www.example.com", - requirements: ["Laptop", "Notebook"], - hosted_registration: true, - register_until: "2024-05-28", - registration_link: "https://www.example.com", - }, - }), + body: formData, }); + const data = await response.json(); console.log(data); }; diff --git a/src/lib/utils.ts b/src/lib/utils.ts index d084cca..9643c28 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -1,6 +1,11 @@ import { type ClassValue, clsx } from "clsx" +import sharp from "sharp" import { twMerge } from "tailwind-merge" export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)) } + +export const getPublicUrl = (path: string) => { + return `https://${process.env.PROJECT_ID}.supabase.co/storage/v1/object/public/${process.env.BUCKET}${path}` +} \ No newline at end of file diff --git a/src/types/supabase.ts b/src/types/supabase.ts index 84d5ff4..3ab8983 100644 Binary files a/src/types/supabase.ts and b/src/types/supabase.ts differ