diff --git a/LEARN.md b/LEARN.md
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/LEARN.md
@@ -0,0 +1 @@
+
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..713e7c7
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2023 Guillermo Zevallos
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
index a07adb2..6e8237f 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,73 @@
-# AI-image-generation
\ No newline at end of file
+
+# AI Image Generation (PixelAI)
+PixelAI is an application that uses artificial intelligence to generate images from text.
+
+## Features
+
+- Text-to-image generation
+- Share generated images in a gallery.
+- User management
+- Create images with predefined models.
+
+
+## Installation
+
+Install my project with npm
+
+```bash
+ npm install AI-image-generation
+ cd AI-image-generation
+```
+
+## Environment Variables
+
+To run this project, you will need to add the following environment variables to your .env file
+
+
+**Frontend:**
+```
+VITE_GOOGLE_CLIENT_ID
+VITE_SERVER
+```
+
+**Backend:**
+```
+PORT
+SD_API_Key
+MONGODB_CNN
+GOOGLE_CLIENT_ID
+GOOGLE_SECRET_ID
+FACEBOOK_APP_ID
+FACEBOOK_APP_SECRET
+CLOUDINARY_CLOUD_NAME
+CLOUDINARY_API_KEY
+CLOUDINARY_API_SECRET
+COOKIE_SECRET
+CLIENT_URL
+```
+## Demo
+
+[Live Demo](https://pixelai.vercel.app/) 😎
+
+
+## Screenshots
+
+
+
+
+## Tech Stack
+
+**Client:** React, Typescript, Redux, TailwindCSS
+
+**Server:** Node, Express, MongoDB
+
+
+## Feedback
+
+If you have any feedback, please reach out to us at guiller.zeva16@gmail.com
+
+
+## License
+
+[MIT](https://choosealicense.com/licenses/mit/)
+
diff --git a/client/.example.env b/client/.example.env
new file mode 100644
index 0000000..5f6feca
--- /dev/null
+++ b/client/.example.env
@@ -0,0 +1,2 @@
+VITE_GOOGLE_CLIENT_ID= google cloud
+VITE_SERVER= URL backend
\ No newline at end of file
diff --git a/client/package-lock.json b/client/package-lock.json
index c582541..714760a 100644
--- a/client/package-lock.json
+++ b/client/package-lock.json
@@ -8,13 +8,19 @@
"name": "client",
"version": "0.0.0",
"dependencies": {
+ "@headlessui/react": "^1.7.13",
"@reduxjs/toolkit": "^1.9.2",
"@types/file-saver": "^2.0.5",
"@types/react-redux": "^7.1.25",
+ "@vercel/analytics": "^1.0.0",
"file-saver": "^2.0.5",
+ "flowbite": "^1.6.4",
+ "flowbite-react": "^0.4.2",
"react": "^18.2.0",
+ "react-blurhash": "^0.3.0",
"react-dom": "^18.2.0",
"react-icons": "^4.7.1",
+ "react-masonry-css": "^1.0.16",
"react-multi-carousel": "^2.8.2",
"react-redux": "^8.0.5",
"react-router-dom": "^6.8.0",
@@ -750,6 +756,60 @@
"node": ">=12"
}
},
+ "node_modules/@floating-ui/core": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.2.5.tgz",
+ "integrity": "sha512-qrcbyfnRVziRlB6IYwjCopYhO7Vud750JlJyuljruIXcPxr22y8zdckcJGsuOdnQ639uVD1tTXddrcH3t3QYIQ=="
+ },
+ "node_modules/@floating-ui/dom": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.2.5.tgz",
+ "integrity": "sha512-+sAUfpQ3Frz+VCbPCqj+cZzvEESy3fjSeT/pDWkYCWOBXYNNKZfuVsHuv8/JO2zze8+Eb/Q7a6hZVgzS81fLbQ==",
+ "dependencies": {
+ "@floating-ui/core": "^1.2.4"
+ }
+ },
+ "node_modules/@floating-ui/react": {
+ "version": "0.20.1",
+ "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.20.1.tgz",
+ "integrity": "sha512-JHTHJ+/YsIxNFH8uJDFa5OyI6dSUZcle6wAFe0zRTjgWD+rkACfBBoJtx2itTtn7C4a7xAz4jgxdEQcMel194g==",
+ "dependencies": {
+ "@floating-ui/react-dom": "^1.3.0",
+ "aria-hidden": "^1.1.3",
+ "tabbable": "^6.0.1"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0",
+ "react-dom": ">=16.8.0"
+ }
+ },
+ "node_modules/@floating-ui/react-dom": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-1.3.0.tgz",
+ "integrity": "sha512-htwHm67Ji5E/pROEAr7f8IKFShuiCKHwUC/UY4vC3I5jiSvGFAYnSYiZO5MlGmads+QqvUkR9ANHEguGrDv72g==",
+ "dependencies": {
+ "@floating-ui/dom": "^1.2.1"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0",
+ "react-dom": ">=16.8.0"
+ }
+ },
+ "node_modules/@headlessui/react": {
+ "version": "1.7.13",
+ "resolved": "https://registry.npmjs.org/@headlessui/react/-/react-1.7.13.tgz",
+ "integrity": "sha512-9n+EQKRtD9266xIHXdY5MfiXPDfYwl7zBM7KOx2Ae3Gdgxy8QML1FkCMjq6AsOf0l6N9uvI4HcFtuFlenaldKg==",
+ "dependencies": {
+ "client-only": "^0.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "react": "^16 || ^17 || ^18",
+ "react-dom": "^16 || ^17 || ^18"
+ }
+ },
"node_modules/@jridgewell/gen-mapping": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz",
@@ -801,7 +861,6 @@
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
"integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
- "dev": true,
"dependencies": {
"@nodelib/fs.stat": "2.0.5",
"run-parallel": "^1.1.9"
@@ -814,7 +873,6 @@
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
"integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
- "dev": true,
"engines": {
"node": ">= 8"
}
@@ -823,7 +881,6 @@
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
"integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
- "dev": true,
"dependencies": {
"@nodelib/fs.scandir": "2.1.5",
"fastq": "^1.6.0"
@@ -832,6 +889,15 @@
"node": ">= 8"
}
},
+ "node_modules/@popperjs/core": {
+ "version": "2.11.7",
+ "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.7.tgz",
+ "integrity": "sha512-Cr4OjIkipTtcXKjAsm8agyleBuDHvxzeBoa1v543lbv1YaIwQjESsVcmjiWiPEbC1FIeHOG/Op9kdCmAmiS3Kw==",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/popperjs"
+ }
+ },
"node_modules/@reduxjs/toolkit": {
"version": "1.9.2",
"resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.2.tgz",
@@ -922,6 +988,14 @@
"resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz",
"integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA=="
},
+ "node_modules/@vercel/analytics": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@vercel/analytics/-/analytics-1.0.0.tgz",
+ "integrity": "sha512-RQmj7pv82JwGDHrnKeRc6TtSw2U7rWNubc2IH0ernTzWTj02yr9zvIYiYJeztsBzrJtWv7m8Nz6vxxb+cdEtJw==",
+ "peerDependencies": {
+ "react": "^16.8||^17||^18"
+ }
+ },
"node_modules/@vitejs/plugin-react": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-3.0.1.tgz",
@@ -945,7 +1019,6 @@
"version": "7.4.1",
"resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
"integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
- "dev": true,
"bin": {
"acorn": "bin/acorn"
},
@@ -957,7 +1030,6 @@
"version": "1.8.2",
"resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz",
"integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==",
- "dev": true,
"dependencies": {
"acorn": "^7.0.0",
"acorn-walk": "^7.0.0",
@@ -968,7 +1040,6 @@
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz",
"integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==",
- "dev": true,
"engines": {
"node": ">=0.4.0"
}
@@ -989,7 +1060,6 @@
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
- "dev": true,
"dependencies": {
"normalize-path": "^3.0.0",
"picomatch": "^2.0.4"
@@ -1001,8 +1071,18 @@
"node_modules/arg": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
- "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==",
- "dev": true
+ "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg=="
+ },
+ "node_modules/aria-hidden": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.3.tgz",
+ "integrity": "sha512-xcLxITLe2HYa1cnYnwCjkOO1PqUHQpozB8x9AR0OgWN2woOBi5kSDVxKfd0b7sb1hw5qFeJhXm9H1nu3xSfLeQ==",
+ "dependencies": {
+ "tslib": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
},
"node_modules/autoprefixer": {
"version": "10.4.13",
@@ -1041,16 +1121,20 @@
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
- "dev": true,
"engines": {
"node": ">=8"
}
},
+ "node_modules/blurhash": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/blurhash/-/blurhash-2.0.5.tgz",
+ "integrity": "sha512-cRygWd7kGBQO3VEhPiTgq4Wc43ctsM+o46urrmPOiuAe+07fzlSB9OJVdpgDL0jPqXUVQ9ht7aq7kxOeJHRK+w==",
+ "peer": true
+ },
"node_modules/braces": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
- "dev": true,
"dependencies": {
"fill-range": "^7.0.1"
},
@@ -1090,7 +1174,6 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
"integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==",
- "dev": true,
"engines": {
"node": ">= 6"
}
@@ -1129,7 +1212,6 @@
"version": "3.5.3",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz",
"integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==",
- "dev": true,
"funding": [
{
"type": "individual",
@@ -1156,7 +1238,6 @@
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
- "dev": true,
"dependencies": {
"is-glob": "^4.0.1"
},
@@ -1164,6 +1245,16 @@
"node": ">= 6"
}
},
+ "node_modules/classnames": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.3.2.tgz",
+ "integrity": "sha512-CSbhY4cFEJRe6/GQzIk5qXZ4Jeg5pcsP7b5peFSDpffpe1cqjASH/n9UTjBwOp6XpMSTwQ8Za2K5V02ueA7Tmw=="
+ },
+ "node_modules/client-only": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz",
+ "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="
+ },
"node_modules/color-convert": {
"version": "1.9.3",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
@@ -1189,7 +1280,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
"integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
- "dev": true,
"bin": {
"cssesc": "bin/cssesc"
},
@@ -1202,6 +1292,11 @@
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz",
"integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw=="
},
+ "node_modules/debounce": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz",
+ "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug=="
+ },
"node_modules/debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
@@ -1223,7 +1318,6 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/defined/-/defined-1.0.1.tgz",
"integrity": "sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q==",
- "dev": true,
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
@@ -1232,7 +1326,6 @@
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/detective/-/detective-5.2.1.tgz",
"integrity": "sha512-v9XE1zRnz1wRtgurGu0Bs8uHKFSTdteYZNbIPFVhUZ39L/S79ppMpdmVOZAnoz1jfEFodc48n6MX483Xo3t1yw==",
- "dev": true,
"dependencies": {
"acorn-node": "^1.8.2",
"defined": "^1.0.0",
@@ -1248,14 +1341,17 @@
"node_modules/didyoumean": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
- "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
- "dev": true
+ "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw=="
},
"node_modules/dlv": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
- "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==",
- "dev": true
+ "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA=="
+ },
+ "node_modules/easy-bem": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/easy-bem/-/easy-bem-1.1.1.tgz",
+ "integrity": "sha512-GJRqdiy2h+EXy6a8E6R+ubmqUM08BK0FWNq41k24fup6045biQ8NXxoXimiwegMQvFFV3t1emADdGNL1TlS61A=="
},
"node_modules/electron-to-chromium": {
"version": "1.4.284",
@@ -1322,7 +1418,6 @@
"version": "3.2.12",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz",
"integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==",
- "dev": true,
"dependencies": {
"@nodelib/fs.stat": "^2.0.2",
"@nodelib/fs.walk": "^1.2.3",
@@ -1338,7 +1433,6 @@
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
- "dev": true,
"dependencies": {
"is-glob": "^4.0.1"
},
@@ -1350,7 +1444,6 @@
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz",
"integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==",
- "dev": true,
"dependencies": {
"reusify": "^1.0.4"
}
@@ -1364,7 +1457,6 @@
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
- "dev": true,
"dependencies": {
"to-regex-range": "^5.0.1"
},
@@ -1372,6 +1464,32 @@
"node": ">=8"
}
},
+ "node_modules/flowbite": {
+ "version": "1.6.4",
+ "resolved": "https://registry.npmjs.org/flowbite/-/flowbite-1.6.4.tgz",
+ "integrity": "sha512-//kSaigwERCcE3udumadB3+xfOXeN/ZQzcub2qVCHuB7uscB4XIm3yP9R8zL0XsEOnYG2lnroq/dydQZbzvESw==",
+ "dependencies": {
+ "@popperjs/core": "^2.9.3",
+ "mini-svg-data-uri": "^1.4.3"
+ }
+ },
+ "node_modules/flowbite-react": {
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/flowbite-react/-/flowbite-react-0.4.2.tgz",
+ "integrity": "sha512-o4VsyYpJKfmiuHdfFA36o4slimdOyTKHmBIcqZNtd9eYCMrRDqEttUISIBPLDB9MArPZ13U1snAIKXHLp2Nr/A==",
+ "dependencies": {
+ "@floating-ui/react": "^0.20.1",
+ "classnames": "^2.3.2",
+ "react-icons": "^4.7.1",
+ "react-indiana-drag-scroll": "^2.2.0"
+ },
+ "peerDependencies": {
+ "flowbite": "^1",
+ "react": "^18",
+ "react-dom": "^18",
+ "tailwindcss": "^3"
+ }
+ },
"node_modules/fraction.js": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz",
@@ -1389,7 +1507,6 @@
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
- "dev": true,
"hasInstallScript": true,
"optional": true,
"os": [
@@ -1402,8 +1519,7 @@
"node_modules/function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
- "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
- "dev": true
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
},
"node_modules/gensync": {
"version": "1.0.0-beta.2",
@@ -1418,7 +1534,6 @@
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
"integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
- "dev": true,
"dependencies": {
"is-glob": "^4.0.3"
},
@@ -1439,7 +1554,6 @@
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
- "dev": true,
"dependencies": {
"function-bind": "^1.1.1"
},
@@ -1477,7 +1591,6 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
- "dev": true,
"dependencies": {
"binary-extensions": "^2.0.0"
},
@@ -1489,7 +1602,6 @@
"version": "2.11.0",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz",
"integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==",
- "dev": true,
"dependencies": {
"has": "^1.0.3"
},
@@ -1501,7 +1613,6 @@
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
- "dev": true,
"engines": {
"node": ">=0.10.0"
}
@@ -1510,7 +1621,6 @@
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
- "dev": true,
"dependencies": {
"is-extglob": "^2.1.1"
},
@@ -1522,7 +1632,6 @@
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
- "dev": true,
"engines": {
"node": ">=0.12.0"
}
@@ -1560,7 +1669,6 @@
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.6.tgz",
"integrity": "sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg==",
- "dev": true,
"engines": {
"node": ">=10"
}
@@ -1601,7 +1709,6 @@
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
"integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
- "dev": true,
"engines": {
"node": ">= 8"
}
@@ -1610,7 +1717,6 @@
"version": "4.0.5",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
"integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
- "dev": true,
"dependencies": {
"braces": "^3.0.2",
"picomatch": "^2.3.1"
@@ -1619,11 +1725,18 @@
"node": ">=8.6"
}
},
+ "node_modules/mini-svg-data-uri": {
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz",
+ "integrity": "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==",
+ "bin": {
+ "mini-svg-data-uri": "cli.js"
+ }
+ },
"node_modules/minimist": {
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz",
"integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==",
- "dev": true,
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
@@ -1638,7 +1751,6 @@
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz",
"integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==",
- "dev": true,
"bin": {
"nanoid": "bin/nanoid.cjs"
},
@@ -1656,7 +1768,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
- "dev": true,
"engines": {
"node": ">=0.10.0"
}
@@ -1674,7 +1785,6 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
"integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
- "dev": true,
"engines": {
"node": ">= 6"
}
@@ -1682,20 +1792,17 @@
"node_modules/path-parse": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
- "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
- "dev": true
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
},
"node_modules/picocolors": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
- "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==",
- "dev": true
+ "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
},
"node_modules/picomatch": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
- "dev": true,
"engines": {
"node": ">=8.6"
},
@@ -1707,7 +1814,6 @@
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
"integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
- "dev": true,
"engines": {
"node": ">=0.10.0"
}
@@ -1716,7 +1822,6 @@
"version": "8.4.21",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz",
"integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==",
- "dev": true,
"funding": [
{
"type": "opencollective",
@@ -1740,7 +1845,6 @@
"version": "14.1.0",
"resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-14.1.0.tgz",
"integrity": "sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw==",
- "dev": true,
"dependencies": {
"postcss-value-parser": "^4.0.0",
"read-cache": "^1.0.0",
@@ -1757,7 +1861,6 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.0.tgz",
"integrity": "sha512-77QESFBwgX4irogGVPgQ5s07vLvFqWr228qZY+w6lW599cRlK/HmnlivnnVUxkjHnCu4J16PDMHcH+e+2HbvTQ==",
- "dev": true,
"dependencies": {
"camelcase-css": "^2.0.1"
},
@@ -1776,7 +1879,6 @@
"version": "3.1.4",
"resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz",
"integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==",
- "dev": true,
"dependencies": {
"lilconfig": "^2.0.5",
"yaml": "^1.10.2"
@@ -1805,7 +1907,6 @@
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.0.0.tgz",
"integrity": "sha512-0DkamqrPcmkBDsLn+vQDIrtkSbNkv5AD/M322ySo9kqFkCIYklym2xEmWkwo+Y3/qZo34tzEPNUw4y7yMCdv5w==",
- "dev": true,
"dependencies": {
"postcss-selector-parser": "^6.0.10"
},
@@ -1824,7 +1925,6 @@
"version": "6.0.11",
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.11.tgz",
"integrity": "sha512-zbARubNdogI9j7WY4nQJBiNqQf3sLS3wCP4WfOidu+p28LofJqDH1tcXypGrcmMHhDk2t9wGhCsYe/+szLTy1g==",
- "dev": true,
"dependencies": {
"cssesc": "^3.0.0",
"util-deprecate": "^1.0.2"
@@ -1836,14 +1936,12 @@
"node_modules/postcss-value-parser": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
- "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
- "dev": true
+ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="
},
"node_modules/queue-microtask": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
"integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
- "dev": true,
"funding": [
{
"type": "github",
@@ -1863,7 +1961,6 @@
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz",
"integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==",
- "dev": true,
"engines": {
"node": ">=10"
},
@@ -1882,6 +1979,15 @@
"node": ">=0.10.0"
}
},
+ "node_modules/react-blurhash": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/react-blurhash/-/react-blurhash-0.3.0.tgz",
+ "integrity": "sha512-XlKr4Ns1iYFRnk6DkAblNbAwN/bTJvxTVoxMvmTcURdc5oLoXZwqAF9N3LZUh/HT+QFlq5n6IS6VsDGsviYAiQ==",
+ "peerDependencies": {
+ "blurhash": "^2.0.3",
+ "react": ">=15"
+ }
+ },
"node_modules/react-dom": {
"version": "18.2.0",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz",
@@ -1902,11 +2008,37 @@
"react": "*"
}
},
+ "node_modules/react-indiana-drag-scroll": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/react-indiana-drag-scroll/-/react-indiana-drag-scroll-2.2.0.tgz",
+ "integrity": "sha512-+W/3B2OQV0FrbdnsoIo4dww/xpH0MUQJz6ziQb7H+oBko3OCbXuzDFYnho6v6yhGrYDNWYPuFUewb89IONEl/A==",
+ "dependencies": {
+ "classnames": "^2.2.6",
+ "debounce": "^1.2.0",
+ "easy-bem": "^1.1.1"
+ },
+ "engines": {
+ "node": ">=8",
+ "npm": ">=5"
+ },
+ "peerDependencies": {
+ "react": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0",
+ "react-dom": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
"node_modules/react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
},
+ "node_modules/react-masonry-css": {
+ "version": "1.0.16",
+ "resolved": "https://registry.npmjs.org/react-masonry-css/-/react-masonry-css-1.0.16.tgz",
+ "integrity": "sha512-KSW0hR2VQmltt/qAa3eXOctQDyOu7+ZBevtKgpNDSzT7k5LA/0XntNa9z9HKCdz3QlxmJHglTZ18e4sX4V8zZQ==",
+ "peerDependencies": {
+ "react": ">=16.0.0"
+ }
+ },
"node_modules/react-multi-carousel": {
"version": "2.8.2",
"resolved": "https://registry.npmjs.org/react-multi-carousel/-/react-multi-carousel-2.8.2.tgz",
@@ -2001,7 +2133,6 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
"integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==",
- "dev": true,
"dependencies": {
"pify": "^2.3.0"
}
@@ -2010,7 +2141,6 @@
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
- "dev": true,
"dependencies": {
"picomatch": "^2.2.1"
},
@@ -2048,7 +2178,6 @@
"version": "1.22.1",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz",
"integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==",
- "dev": true,
"dependencies": {
"is-core-module": "^2.9.0",
"path-parse": "^1.0.7",
@@ -2065,7 +2194,6 @@
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
"integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
- "dev": true,
"engines": {
"iojs": ">=1.0.0",
"node": ">=0.10.0"
@@ -2091,7 +2219,6 @@
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
"integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
- "dev": true,
"funding": [
{
"type": "github",
@@ -2131,7 +2258,6 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
"integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
- "dev": true,
"engines": {
"node": ">=0.10.0"
}
@@ -2152,7 +2278,6 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
- "dev": true,
"engines": {
"node": ">= 0.4"
},
@@ -2169,11 +2294,15 @@
"url": "https://github.com/sponsors/limonte"
}
},
+ "node_modules/tabbable": {
+ "version": "6.1.1",
+ "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.1.1.tgz",
+ "integrity": "sha512-4kl5w+nCB44EVRdO0g/UGoOp3vlwgycUVtkk/7DPyeLZUCuNFFKCFG6/t/DgHLrUPHjrZg6s5tNm+56Q2B0xyg=="
+ },
"node_modules/tailwindcss": {
"version": "3.2.4",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.2.4.tgz",
"integrity": "sha512-AhwtHCKMtR71JgeYDaswmZXhPcW9iuI9Sp2LvZPo9upDZ7231ZJ7eA9RaURbhpXGVlrjX4cFNlB4ieTetEb7hQ==",
- "dev": true,
"dependencies": {
"arg": "^5.0.2",
"chokidar": "^3.5.3",
@@ -2213,8 +2342,7 @@
"node_modules/tailwindcss/node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
- "dev": true
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"node_modules/to-fast-properties": {
"version": "2.0.0",
@@ -2229,7 +2357,6 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
- "dev": true,
"dependencies": {
"is-number": "^7.0.0"
},
@@ -2237,6 +2364,11 @@
"node": ">=8.0"
}
},
+ "node_modules/tslib": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz",
+ "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg=="
+ },
"node_modules/typescript": {
"version": "4.9.5",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
@@ -2287,8 +2419,7 @@
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
- "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
- "dev": true
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
},
"node_modules/vite": {
"version": "4.0.4",
@@ -2343,7 +2474,6 @@
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
- "dev": true,
"engines": {
"node": ">=0.4"
}
@@ -2358,7 +2488,6 @@
"version": "1.10.2",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
"integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==",
- "dev": true,
"engines": {
"node": ">= 6"
}
diff --git a/client/package.json b/client/package.json
index 7a592ff..59259a6 100644
--- a/client/package.json
+++ b/client/package.json
@@ -9,13 +9,19 @@
"preview": "vite preview"
},
"dependencies": {
+ "@headlessui/react": "^1.7.13",
"@reduxjs/toolkit": "^1.9.2",
"@types/file-saver": "^2.0.5",
"@types/react-redux": "^7.1.25",
+ "@vercel/analytics": "^1.0.0",
"file-saver": "^2.0.5",
+ "flowbite": "^1.6.4",
+ "flowbite-react": "^0.4.2",
"react": "^18.2.0",
+ "react-blurhash": "^0.3.0",
"react-dom": "^18.2.0",
"react-icons": "^4.7.1",
+ "react-masonry-css": "^1.0.16",
"react-multi-carousel": "^2.8.2",
"react-redux": "^8.0.5",
"react-router-dom": "^6.8.0",
diff --git a/client/src/components/GeneratePage/Generator.tsx b/client/src/components/GeneratePage/Generator.tsx
deleted file mode 100644
index 6c20c38..0000000
--- a/client/src/components/GeneratePage/Generator.tsx
+++ /dev/null
@@ -1,123 +0,0 @@
-import { useGenerator } from "../../hooks/useGenerator";
-import { RxSymbol, RxPaperPlane } from "react-icons/rx";
-import CarouselModel from "../Homepage/CarouselModel";
-import Loader from "../Loader";
-
-const Generator = () => {
- const {
- loading,
- form,
- models,
- handleChange,
- handleSurpriseMe,
- handleRandomNegativePrompt,
- handleSubmit,
- createPost,
- handleModel,
- removerModel,
- } = useGenerator();
-
- return (
-
-
-
-
-
-
- {loading ? (
-
-
-
- ) : (
-
- )}
-
-
-
-
-
- Share post
-
-
-
-
-
-
- );
-};
-
-export default Generator;
diff --git a/client/src/components/GeneratePage/Hero.tsx b/client/src/components/GeneratePage/Hero.tsx
index 63cf173..4df12c4 100644
--- a/client/src/components/GeneratePage/Hero.tsx
+++ b/client/src/components/GeneratePage/Hero.tsx
@@ -1,15 +1,15 @@
const Hero = () => {
return (
-
-
- Generate your image
+
+
+ Create a bespoke image that's all your own.
-
+ {/*
Join the future of image creation with our{" "}
PixelAI app. Discover how easy it
is to generate stunning images with just a few clicks. Download it now
and experience the magic of artificial intelligence in your creations.
-
+
*/}
);
};
diff --git a/client/src/components/GeneratePage/History.tsx b/client/src/components/GeneratePage/History.tsx
new file mode 100644
index 0000000..3ab3884
--- /dev/null
+++ b/client/src/components/GeneratePage/History.tsx
@@ -0,0 +1,64 @@
+import { useState, useEffect, useCallback } from "react";
+import { History } from "../../types/user";
+import Swal from "sweetalert2";
+import Loader from "../Loader";
+import Gallery from "../Homepage/Gallery";
+import { useAppSelector } from "../../hooks/useRedux";
+
+export const HistoryGallery = () => {
+ const { credits } = useAppSelector(state => state.auth);
+ const [history, setHistory] = useState();
+ const [loading, setLoading] = useState(false);
+
+ const fetchPosts = useCallback(async () => {
+ try {
+ setLoading(true);
+ const response = await fetch(
+ `${import.meta.env.VITE_SERVER}/api/v1/user/history`,
+ {
+ credentials: "include",
+ }
+ );
+
+ if (response.ok) {
+ const result = await response.json();
+ setHistory(result);
+ }
+ } catch (error) {
+ Swal.fire({
+ title: "We had a problem loading history",
+ icon: "error",
+ focusConfirm: false,
+ confirmButtonText: "Ok",
+ });
+ } finally {
+ setLoading(false);
+ }
+ }, [credits]);
+
+ useEffect(() => {
+ fetchPosts();
+ }, [fetchPosts]);
+
+ return (
+
+ {loading ? (
+
+ ) : (
+ <>
+ {!!history?.length && (
+ <>
+
+ History
+
+
+ >
+ )}
+ >
+ )}
+
+ );
+};
diff --git a/client/src/components/GeneratePage/generator/DisplayPanel.tsx b/client/src/components/GeneratePage/generator/DisplayPanel.tsx
new file mode 100644
index 0000000..b1185ba
--- /dev/null
+++ b/client/src/components/GeneratePage/generator/DisplayPanel.tsx
@@ -0,0 +1,29 @@
+import { GeneratorContext } from "../../../context/generator";
+import { useContext } from "react";
+import Loader from "../../Loader";
+import { useAppSelector } from "../../../hooks/useRedux";
+
+export const DisplayPanel = () => {
+ const { image, height, prompt, width } = useAppSelector(
+ state => state.generator
+ );
+ const { loading } = useContext(GeneratorContext);
+
+ return (
+
+ {!image ? (
+
+ {loading && }
+
+ ) : (
+
+ )}
+
+ );
+};
diff --git a/client/src/components/GeneratePage/generator/Form.tsx b/client/src/components/GeneratePage/generator/Form.tsx
new file mode 100644
index 0000000..daac23f
--- /dev/null
+++ b/client/src/components/GeneratePage/generator/Form.tsx
@@ -0,0 +1,72 @@
+import { RxSymbol, RxPaperPlane, RxInfoCircled } from "react-icons/rx";
+import { Tooltip } from "flowbite-react";
+import { FaMagic } from "react-icons/fa";
+import { GeneratorContext } from "../../../context/generator";
+import { useContext } from "react";
+import { useAppSelector } from "../../../hooks/useRedux";
+
+export const Form = () => {
+ const { prompt, negative_prompt } = useAppSelector(state => state.generator);
+ const {
+ handleSubmit,
+ handleSurpriseMe,
+ handleRandomNegativePrompt,
+ handleChange,
+ loading,
+ } = useContext(GeneratorContext);
+
+ return (
+
+
+
+ Prompt
+
+
+
+
+ Surprise me
+
+
+
+
+
+
+ Negative Prompt
+
+ Random
+
+
+
+
+
+
+ );
+};
diff --git a/client/src/components/GeneratePage/generator/Generator.tsx b/client/src/components/GeneratePage/generator/Generator.tsx
new file mode 100644
index 0000000..033a0ff
--- /dev/null
+++ b/client/src/components/GeneratePage/generator/Generator.tsx
@@ -0,0 +1,26 @@
+import { GeneratorProvider } from "../../../context/generator";
+import { DisplayPanel } from "./DisplayPanel";
+import { SelectModel } from "./SelectModel";
+import { Settings } from "./Settings";
+
+
+export const Generator = () => {
+
+ return (
+
+
+
+ );
+};
diff --git a/client/src/components/GeneratePage/generator/SelectModel.tsx b/client/src/components/GeneratePage/generator/SelectModel.tsx
new file mode 100644
index 0000000..703d546
--- /dev/null
+++ b/client/src/components/GeneratePage/generator/SelectModel.tsx
@@ -0,0 +1,17 @@
+import { GeneratorContext } from "../../../context/generator";
+import CarouselModel from "../../Homepage/CarouselModel";
+import { useContext } from "react";
+
+export const SelectModel = () => {
+ const { models, handleModel, removerModel } = useContext(GeneratorContext);
+
+ return (
+
+ );
+};
diff --git a/client/src/components/GeneratePage/generator/Settings.tsx b/client/src/components/GeneratePage/generator/Settings.tsx
new file mode 100644
index 0000000..9fe2f10
--- /dev/null
+++ b/client/src/components/GeneratePage/generator/Settings.tsx
@@ -0,0 +1,77 @@
+import { GeneratorContext } from "../../../context/generator";
+import { useAppSelector } from "../../../hooks/useRedux";
+import { Form } from "./Form";
+import { useContext, useState } from 'react';
+import { RxPaperPlane } from "react-icons/rx";
+export const Settings = () => {
+ const { handleSubmit, loading, handleSize, createPost } =
+ useContext(GeneratorContext);
+ const { model, image } = useAppSelector(state => state.generator);
+ const [loadingPost, setLoadingPost] = useState(false);
+
+ return (
+ <>
+
+
+
+
+
+ Model:{" "}
+ {model ? model : "none"}
+
+
+
+
Size
+
+
handleSize("1/1")}>
+ 1/1
+
+
handleSize("16/9")}>
+ 16/9
+
+
handleSize("9/16")}>
+ 9/16
+
+
+
+
+
+
+ Generate 😜
+
+
+
+
+
+ {
+ setLoadingPost(true);
+ createPost()
+ }}
+ disabled={!image || loadingPost}
+ className=" mt-4 disabled:opacity-25 rounded-full gradient p-[2px] hover:text-white focus:outline-none focus:ring active:text-opacity-75">
+
+ Share post
+
+
+
+
+ >
+ );
+};
diff --git a/client/src/components/Homepage/Card.tsx b/client/src/components/Homepage/Card.tsx
index e233ead..c1d1449 100644
--- a/client/src/components/Homepage/Card.tsx
+++ b/client/src/components/Homepage/Card.tsx
@@ -1,25 +1,32 @@
import { Link } from "react-router-dom";
import { Post } from "../../types/post";
+import Image from "../Image";
+import { History } from "../../types/user";
type CardProps = {
post: Post;
- className?: string;
+ className?: string;
};
-const Card = ({ post, className }: CardProps) => {
+const Card = ({ post, className = "" }: CardProps) => {
+ // console.log(post);
return (
-
-
+
-
+
-
+
{
)}
-
+ {/*
{post.prompt}
-
+ */}
);
};
+export const HistoryCard = ({ history, className }: { history: History, className?:string }) => {
+ return (
+
+
+
+ );
+};
+
export default Card;
diff --git a/client/src/components/Homepage/CarouselModel.tsx b/client/src/components/Homepage/CarouselModel.tsx
index 307c82a..c00e7de 100644
--- a/client/src/components/Homepage/CarouselModel.tsx
+++ b/client/src/components/Homepage/CarouselModel.tsx
@@ -1,6 +1,4 @@
-import { useState, useEffect } from 'react';
import { Model } from "../../types/model";
-import { modelList } from "../../utils/models";
import Carousel from "react-multi-carousel";
import "react-multi-carousel/lib/styles.css";
@@ -28,9 +26,11 @@ type CarouselModelProps = {
handleModel: (model_id:string)=>void
removerModel:(model_id: string)=>void
models: Model[];
+ title?: string
+ className?:string;
}
-const CarouselModel = ({models,handleModel, removerModel}:CarouselModelProps) => {
+const CarouselModel = ({models,handleModel, removerModel, title, className}:CarouselModelProps) => {
const onActive = (model: any) =>{
if(model.active){
@@ -42,19 +42,21 @@ const CarouselModel = ({models,handleModel, removerModel}:CarouselModelProps) =>
}
return (
-
+
+
+ {title}
{models.map((model, index) => (
onActive(model)}
- className={`flex p-2 rounded-xl items-center gap-4 mr-4 hover:bg-neutral-900 transition hover:ease-out ${
+ className={`flex p-2 rounded-xl items-center gap-4 mr-4 select-none hover:bg-neutral-900 active:bg-black active:bg-opacity-70 transition hover:ease-out ${
model.active && "bg-hover"
}`}>
{model.name}
diff --git a/client/src/components/Homepage/Gallery.tsx b/client/src/components/Homepage/Gallery.tsx
index 218c87a..f596a5a 100644
--- a/client/src/components/Homepage/Gallery.tsx
+++ b/client/src/components/Homepage/Gallery.tsx
@@ -1,21 +1,59 @@
import { Post } from "../../types/post";
-import Card from "./Card";
+import { History } from "../../types/user";
+import Card, { HistoryCard } from "./Card";
+import Masonry from "react-masonry-css";
type GalleryProps = {
- posts: Post[];
+ posts: Post[] | History[];
+ type?: "history";
};
-const Gallery = ({ posts }: GalleryProps) => {
+
+const breakpointColumnsObj = {
+ default: 5,
+ 1100: 4,
+ 900: 4,
+ 700: 3,
+ 580: 2,
+};
+
+const GalleryLayout = ({ children }: { children: React.ReactNode }) => {
return (
-
-
- {posts.map((post, index) => (
-
+
+ {/* array of JSX items */}
+ {children}
+
+
+ );
+};
+
+const Gallery = ({ posts, type }: GalleryProps) => {
+ if (type) {
+ return (
+
+ {(posts as History[]).map((post, index) => (
+
))}
-
-
+
+ );
+ }
+
+ return (
+
+ {/* array of JSX items */}
+ {(posts as Post[]).map((post, index) => (
+
+ ))}
+
);
};
diff --git a/client/src/components/Image.tsx b/client/src/components/Image.tsx
new file mode 100644
index 0000000..963f863
--- /dev/null
+++ b/client/src/components/Image.tsx
@@ -0,0 +1,45 @@
+import { ImgHTMLAttributes, FC, useState, useEffect } from "react";
+import { Blurhash } from "react-blurhash";
+
+interface ImageProps extends ImgHTMLAttributes {
+ image_data?: {
+ encoded: string;
+ width: number;
+ height: number;
+ };
+}
+
+const Image: FC = props => {
+ const [imageLoaded, setImageLoaded] = useState(false);
+
+ useEffect(() => {
+ const image = new (window as any).Image();
+ image.onload = () => {
+ setImageLoaded(true);
+ };
+ image.src = props.src;
+ }, [props.src]);
+
+ return (
+ <>
+
+ {props.image_data && (
+
+ )}
+
+ setImageLoaded(true)}
+ />
+ >
+ );
+};
+
+export default Image;
diff --git a/client/src/components/Navbar.tsx b/client/src/components/Navbar.tsx
index d7a70aa..83747c4 100644
--- a/client/src/components/Navbar.tsx
+++ b/client/src/components/Navbar.tsx
@@ -2,16 +2,30 @@ import { Link } from "react-router-dom";
import { useAppSelector } from "../hooks/useRedux";
import { FcGoogle } from "react-icons/fc";
import UserNavbar from "./UserNavbar";
+import { FaFacebook } from "react-icons/fa";
+
+import { Menu, Transition } from "@headlessui/react";
+import { Fragment, useEffect, useRef, useState } from "react";
const Navbar = () => {
const { status } = useAppSelector(state => state.auth);
const handleOnClick = () => {
- window.open(`${import.meta.env.VITE_SERVER}/api/v1/auth/google/callback`, "_self");
+ window.open(
+ `${import.meta.env.VITE_SERVER}/api/v1/auth/google/callback`,
+ "_self"
+ );
+ };
+
+ const handleFacebookOnClick = () => {
+ window.open(
+ `${import.meta.env.VITE_SERVER}/api/v1/auth/facebook/callback`,
+ "_self"
+ );
};
return (
-
+
PixelAI
@@ -22,14 +36,55 @@ const Navbar = () => {
{status === "authenticated" ? (
) : status === "not-authenticated" ? (
-
-
- Sign in with google
-
-
-
+ <>
+
+
+
+ Access all features
+
+
+
+
+
+
+
+
+
+ Sign in with Google
+
+
+
+
+
+
+
+
+
+ Sign in with Facebook
+
+
+
+
+
+
+
+
+
+
+ >
) : (
<>>
)}
diff --git a/client/src/components/UserNavbar.tsx b/client/src/components/UserNavbar.tsx
index cb867aa..f3f4a25 100644
--- a/client/src/components/UserNavbar.tsx
+++ b/client/src/components/UserNavbar.tsx
@@ -1,9 +1,10 @@
import { TbNewSection } from "react-icons/tb";
import { Link } from "react-router-dom";
import { useAppSelector } from "../hooks/useRedux";
+import { Badge, Tooltip } from "flowbite-react";
const UserNavbar = () => {
- const { profilePic, username , slug} = useAppSelector(state => state.auth);
+ const { profilePic, username, slug, credits } = useAppSelector(state => state.auth);
return (
@@ -12,7 +13,7 @@ const UserNavbar = () => {
to="/generate">
Generate your image
-
+
@@ -20,6 +21,15 @@ const UserNavbar = () => {
aria-hidden="true"
className="block h-6 w-px rounded-full bg-gray-200">
+
+
+ {credits}
+
+
+
diff --git a/client/src/context/generator/GeneratorContext.tsx b/client/src/context/generator/GeneratorContext.tsx
new file mode 100644
index 0000000..010cdad
--- /dev/null
+++ b/client/src/context/generator/GeneratorContext.tsx
@@ -0,0 +1,18 @@
+import { createContext } from "react";
+import { Post } from "../../types/post";
+import { Model } from "../../types/model";
+
+interface ContextProps {
+ loading: boolean,
+ models: Model[],
+ handleChange: (event: React.ChangeEvent
) => void,
+ handleSurpriseMe: () => void,
+ handleRandomNegativePrompt: () => void,
+ handleSubmit: () => Promise,
+ createPost: () => Promise,
+ handleModel: (model_id: string) => void,
+ removerModel:(model_id: string) => void,
+ handleSize: (aspect: string) => void
+}
+
+export const GeneratorContext = createContext({} as ContextProps);
diff --git a/client/src/context/generator/GeneratorProvider.tsx b/client/src/context/generator/GeneratorProvider.tsx
new file mode 100644
index 0000000..4b0d356
--- /dev/null
+++ b/client/src/context/generator/GeneratorProvider.tsx
@@ -0,0 +1,40 @@
+import { FC } from 'react'
+import { GeneratorContext } from './GeneratorContext'
+import { useGenerator } from '../../hooks/useGenerator'
+
+type providerProps = {
+ children: JSX.Element | JSX.Element[]
+}
+
+export const GeneratorProvider: FC = ({children})=>{
+
+ const {
+ loading,
+ models,
+ handleChange,
+ handleSurpriseMe,
+ handleRandomNegativePrompt,
+ handleSubmit,
+ createPost,
+ handleModel,
+ removerModel,
+ handleSize
+ } = useGenerator();
+
+ return (
+
+ {children}
+
+ )
+}
\ No newline at end of file
diff --git a/client/src/context/generator/index.ts b/client/src/context/generator/index.ts
new file mode 100644
index 0000000..ca59e57
--- /dev/null
+++ b/client/src/context/generator/index.ts
@@ -0,0 +1,3 @@
+
+export * from './GeneratorContext'
+export * from './GeneratorProvider'
\ No newline at end of file
diff --git a/client/src/hooks/useGenerator.ts b/client/src/hooks/useGenerator.ts
index 0f777e1..5fea722 100644
--- a/client/src/hooks/useGenerator.ts
+++ b/client/src/hooks/useGenerator.ts
@@ -1,38 +1,43 @@
-import { useState } from "react";
+import { useState, useEffect } from 'react';
import { Model } from "../types/model";
-import { Post } from "../types/post";
import { modelList } from "../utils/models";
-import { useAppSelector } from './useRedux';
+import { useAppDispatch, useAppSelector } from './useRedux';
import { useNavigate } from 'react-router';
import Swal from "sweetalert2";
import { getRandomPrompt } from "../utils";
+import { onSetId, onSetImage, onSetModel, onSetNegativePrompt, onSetNegativePromptBtn, onSetPrompt, onSetSize } from "../store/generator/genratorSlice";
+import { refetchCredits } from '../store/auth/thunks';
export const useGenerator = () => {
const { _id } = useAppSelector(state => state.auth)
+ const { prompt, userid, model, negative_prompt, image, width, height } = useAppSelector(state => state.generator)
+
+ const dispatch = useAppDispatch();
+
const navigate = useNavigate();
const [models, setModels] = useState(modelList);
const [loading, setLoading] = useState(false);
- const [form, setForm] = useState({
- userid: _id,
- prompt: "",
- negative_prompt: "",
- image: "",
- model: "",
- });
+ useEffect(()=>{
+ dispatch(onSetId(_id))
+ },[])
+
const handleSurpriseMe = () => {
- const randomPrompt = getRandomPrompt(form.prompt);
- setForm({ ...form, prompt: randomPrompt });
+ const randomPrompt = getRandomPrompt(prompt);
+ dispatch(onSetPrompt(randomPrompt))
};
const handleRandomNegativePrompt = () => {
- const randomPrompt = getRandomPrompt(form.prompt, true);
-
- setForm((prev) => ({ ...form, negative_prompt: prev.negative_prompt.concat(" | "+randomPrompt) }));
+ const nevRandomPrompt = getRandomPrompt(prompt, true);
+ dispatch(onSetNegativePromptBtn(nevRandomPrompt))
};
+ const handleSize = (aspect: string)=>{
+ dispatch(onSetSize(aspect))
+ }
+
const handleModel = (model_id: string) => {
setModels(models.map(model => {
if (model.mode_id === model_id) {
@@ -43,10 +48,9 @@ export const useGenerator = () => {
return model;
}))
- setForm({
- ...form,
- model: model_id,
- });
+ console.log(model_id);
+
+ dispatch(onSetModel(model_id))
};
const removerModel = (model_id: string) => {
@@ -56,35 +60,36 @@ export const useGenerator = () => {
}
return model;
}));
- setForm({
- ...form,
- model: '',
- });
+
+ dispatch(onSetModel(''))
}
const handleChange = (event: React.ChangeEvent) => {
- setForm({
- ...form,
- [event.target.name]: event.target.value,
- });
+
+ if(event.target.name === 'prompt'){
+ dispatch(onSetPrompt(event.target.value))
+ }else{
+ dispatch(onSetNegativePrompt(event.target.value))
+ }
};
const createPost = async () => {
- if (form.prompt && form.prompt.length > 5) {
+ if (prompt && prompt.length > 5) {
try {
setLoading(true);
const response = await fetch(`${import.meta.env.VITE_SERVER}/api/v1/post/create`, {
method: "POST",
+ credentials: 'include',
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
- userid: form.userid,
- model: form.model,
- prompt: form.prompt,
- negative_prompt: form.negative_prompt,
- image: form.image,
+ userid,
+ model,
+ prompt: prompt,
+ negative_prompt,
+ image,
}),
});
const data = await response.json();
@@ -116,37 +121,38 @@ export const useGenerator = () => {
}
}
- const handleSubmit = async (event: React.FormEvent) => {
- event.preventDefault();
+ const handleSubmit = async () => {
+ if(image) dispatch(onSetImage(''))
- if (form.prompt && form.prompt.length > 5) {
+ if (prompt && prompt.length > 5) {
try {
setLoading(true);
//* FETCH
const response = await fetch(`${import.meta.env.VITE_SERVER}/api/v1/generate`, {
method: "POST",
+ credentials: 'include',
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
- prompt: form.prompt,
- negative_prompt: form.negative_prompt,
- model: form.model,
+ prompt,
+ negative_prompt,
+ model,
+ width,
+ height
}),
});
const data = await response.json();
- if (data.message || data.messege) {
- throw new Error('Out of service')
+ if (data.message) {
+ throw new Error(data.message)
}
- setForm({
- ...form,
- image: data.image,
- });
- } catch (error) {
+ dispatch(onSetImage(data.image))
+
+ } catch (error: any) {
Swal.fire({
- title: 'Out of service',
+ title: error.message || 'Out of service',
text: 'Try again later',
icon: 'error',
focusConfirm: false,
@@ -154,6 +160,7 @@ export const useGenerator = () => {
})
} finally {
setLoading(false);
+ dispatch(refetchCredits())
}
} else {
// alert("llenar el campo");
@@ -170,7 +177,7 @@ export const useGenerator = () => {
return {
loading,
- form,
+ // form,
models,
handleChange,
handleSurpriseMe,
@@ -178,7 +185,8 @@ export const useGenerator = () => {
handleSubmit,
createPost,
handleModel,
- removerModel
+ removerModel,
+ handleSize
};
};
diff --git a/client/src/index.css b/client/src/index.css
index 731a1c5..647fb3b 100644
--- a/client/src/index.css
+++ b/client/src/index.css
@@ -8,7 +8,7 @@
:root {
--dark: #464545;
- --thumb-bg: #57505065;
+ --thumb-bg: #86868665;
}
::-webkit-scrollbar {
width: 5px;
@@ -26,20 +26,69 @@
background: #252423;
}
+.my-masonry-grid {
+ display: -webkit-box; /* Not needed if autoprefixing */
+ display: -ms-flexbox; /* Not needed if autoprefixing */
+ display: flex;
+ margin-left: 0px; /* gutter size offset */
+ width: 100%;
+ margin: auto;
+}
+.my-masonry-grid_column {
+ padding-left: 7.5px;
+ padding-right: 7.5px;
+ background-clip: padding-box;
+}
+
+/* Style your items */
+.my-masonry-grid_column > div {
+ /* change div to reference your elements you put in */
+
+ margin-bottom: 15px;
+}
+
+@keyframes fadeIn {
+ 0% {
+ opacity: 0;
+ }
+ 100% {
+ opacity: 1;
+ }
+}
+
+@-webkit-keyframes fadeIn {
+ 0% {
+ opacity: 0;
+ }
+ 100% {
+ opacity: 1;
+ }
+}
+
+.fadeIn {
+ -webkit-animation-duration: 0.5s;
+ animation-duration: 0.5s;
+ -webkit-animation-fill-mode: both;
+ animation-fill-mode: both;
+
+ -webkit-animation-name: fadeIn;
+ animation-name: fadeIn;
+}
+
body {
background: #202020;
overflow-x: hidden;
- background-blend-mode: multiply;
+ background-blend-mode: multiply;
color: #f2f2f2;
}
-.background{
- background: #323232 ;
+.background {
+ background: #323232;
background-blend-mode: multiply;
}
-body::before{
- content: '';
+body::before {
+ content: "";
position: absolute;
z-index: -1;
top: -15rem;
@@ -47,7 +96,12 @@ body::before{
transform: translateX(-50%);
border-radius: 100%;
filter: blur(50px);
- background: linear-gradient(to right, rgb(251, 113, 133), rgb(217, 70, 239), rgb(99, 102, 241));
+ background: linear-gradient(
+ to right,
+ rgb(251, 113, 133),
+ rgb(217, 70, 239),
+ rgb(99, 102, 241)
+ );
width: 100vw;
height: 300px;
}
@@ -61,12 +115,50 @@ body::before{
border-radius: 5px;
}
+.bg-generator {
+ background-color: hwb(0 13% 87% / 0.377);
+ /* background: rgb(105,105,255); */
+ position: relative;
+ z-index: 0;
+ background-color: #202020;
+ background-image: url("data:image/svg+xml,%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%23333333' fill-opacity='0.5'%3E%3Cpath d='M36 34v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zm0-30V0h-2v4h-4v2h4v4h2V6h4V4h-4zM6 34v-4H4v4H0v2h4v4h2v-4h4v-2H6zM6 4V0H4v4H0v2h4v4h2V6h4V4H6z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
+}
+
+.bg-newimage {
+ background-color: #303030;
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='80' height='80' viewBox='0 0 80 80'%3E%3Cg fill='%23202020' fill-opacity='0.4'%3E%3Cpath fill-rule='evenodd' d='M11 0l5 20H6l5-20zm42 31a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM0 72h40v4H0v-4zm0-8h31v4H0v-4zm20-16h20v4H20v-4zM0 56h40v4H0v-4zm63-25a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm10 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM53 41a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm10 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm10 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-30 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-28-8a5 5 0 0 0-10 0h10zm10 0a5 5 0 0 1-10 0h10zM56 5a5 5 0 0 0-10 0h10zm10 0a5 5 0 0 1-10 0h10zm-3 46a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm10 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM21 0l5 20H16l5-20zm43 64v-4h-4v4h-4v4h4v4h4v-4h4v-4h-4zM36 13h4v4h-4v-4zm4 4h4v4h-4v-4zm-4 4h4v4h-4v-4zm8-8h4v4h-4v-4z'/%3E%3C/g%3E%3C/svg%3E");
+}
+
+.bg-generator::after {
+ position: absolute;
+ content: "";
+ top: 0;
+ right: 0;
+ width: 100%;
+ height: 100%;
+ z-index: -1;
+ background: rgb(32, 32, 32);
+ background: linear-gradient(
+ 0deg,
+ rgba(32, 32, 32, 0) 50%,
+ rgba(32, 32, 32, 1) 100%
+ );
+}
+
.gradient {
- @apply bg-gradient-to-r from-rose-400 via-fuchsia-500 to-indigo-500
+ @apply bg-gradient-to-r from-rose-400 via-fuchsia-500 to-indigo-500;
+}
+
+.gradient-shadow {
+ @apply bg-gradient-to-r from-rose-400 via-fuchsia-500 to-indigo-500 blur-sm;
}
.gradient-google {
- background: linear-gradient(-120deg, #0477BF, #49BF72, #F2DC6B, #F24B59);
+ background: linear-gradient(-120deg, #0477bf, #49bf72, #f2dc6b, #f24b59);
+}
+
+.gradient-facebook {
+ @apply bg-gradient-to-r from-blue-500 to-blue-600;
}
.text-gradient {
diff --git a/client/src/main.tsx b/client/src/main.tsx
index cfc7108..eda4d5a 100644
--- a/client/src/main.tsx
+++ b/client/src/main.tsx
@@ -1,14 +1,17 @@
-import React from 'react'
-import ReactDOM from 'react-dom/client'
-import { Provider } from 'react-redux'
-import App from './App'
-import './index.css'
-import { store } from './store/store'
+import React from "react";
+import ReactDOM from "react-dom/client";
+import { Provider } from "react-redux";
+import App from "./App";
+import "./index.css";
+import { store } from "./store/store";
+import { Analytics as VercelAnalytics } from "@vercel/analytics/react"
-ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
- //
+
+ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
+
-
+
- //
-)
+
+
+);
diff --git a/client/src/pages/GeneratePage.tsx b/client/src/pages/GeneratePage.tsx
index b3a4f55..03b29ad 100644
--- a/client/src/pages/GeneratePage.tsx
+++ b/client/src/pages/GeneratePage.tsx
@@ -1,11 +1,15 @@
-import Generator from "../components/GeneratePage/Generator";
import Hero from "../components/GeneratePage/Hero";
+import { HistoryGallery } from "../components/GeneratePage/History";
+import { Generator } from "../components/GeneratePage/generator/Generator";
+import { useAppSelector } from "../hooks/useRedux";
const GeneratePage = () => {
+ const { status } = useAppSelector(state => state.auth);
return (
-
+
+ {status === "authenticated" && }
);
};
diff --git a/client/src/pages/UserPage.tsx b/client/src/pages/UserPage.tsx
index 94112f6..44d0a71 100644
--- a/client/src/pages/UserPage.tsx
+++ b/client/src/pages/UserPage.tsx
@@ -4,12 +4,19 @@ import { Navigate } from "react-router";
import { User } from "../types/user";
import Gallery from "../components/Homepage/Gallery";
import Loader from "../components/Loader";
+import { FiLogOut } from "react-icons/fi";
+import { useAppSelector } from "../hooks/useRedux";
const UserPage = () => {
+ const { status, slug } = useAppSelector(state => state.auth);
const { username } = useParams();
const [user, setUser] = useState();
const [loading, setLoading] = useState(false);
+ const handleOnClick = () => {
+ window.open(`${import.meta.env.VITE_SERVER}/api/v1/auth/logout`, "_self");
+ };
+
const fetchUser = async () => {
setLoading(true);
@@ -20,7 +27,6 @@ const UserPage = () => {
if (response.ok) {
const result = await response.json();
- console.log(result.user);
setUser(result.user);
}
} catch (error) {
@@ -55,7 +61,7 @@ const UserPage = () => {
className="pt-16 bg-bgColor min-h-[100vh]"
style={{
backgroundImage:
- "url(https://cdna.artstation.com/p/assets/images/images/000/215/866/large/anton-fadeev-bloodmoon-ruins2-1-800-logo.jpg?1443930004)",
+ "url(https://res.cloudinary.com/dzx6dg1ws/image/upload/v1681429585/anton-fadeev-bloodmoon-ruins2-1-800-logo_ocriyh.jpg)",
}}>
@@ -68,10 +74,17 @@ const UserPage = () => {
/>
-
+
{user[0].username}
+ {status === "authenticated" && slug === username && (
+
+
+
+ )}
diff --git a/client/src/routes/AppRouter.tsx b/client/src/routes/AppRouter.tsx
index e7ddc53..9bd0257 100644
--- a/client/src/routes/AppRouter.tsx
+++ b/client/src/routes/AppRouter.tsx
@@ -1,4 +1,3 @@
-import React from "react";
import { Navigate, Route } from "react-router";
import { Routes } from "react-router-dom";
import GeneratePage from "../pages/GeneratePage";
@@ -26,7 +25,6 @@ const AppRouter = () => {
}/>
-
}/>
diff --git a/client/src/store/auth/authSlice.ts b/client/src/store/auth/authSlice.ts
index b884915..cf8a622 100644
--- a/client/src/store/auth/authSlice.ts
+++ b/client/src/store/auth/authSlice.ts
@@ -8,7 +8,8 @@ const initialState: User = {
slug: '',
email: '',
profilePic: '',
- posts: []
+ posts: [],
+ credits: 0,
}
const authSlice = createSlice({
@@ -22,6 +23,7 @@ const authSlice = createSlice({
state.slug = payload.slug
state.email = payload.email
state.profilePic = payload.profilePic
+ state.credits = payload.credits
},
logout: (state) => {
state.status = 'not-authenticated';
@@ -33,10 +35,13 @@ const authSlice = createSlice({
},
checkingCredentials: (state) => {
state.status = 'checking';
+ },
+ verifyCredits: (state, {payload}) => {
+ state.credits= payload.credits
}
}
});
-export const { login, logout, checkingCredentials } = authSlice.actions
+export const { login, logout, checkingCredentials, verifyCredits } = authSlice.actions
export default authSlice.reducer
\ No newline at end of file
diff --git a/client/src/store/auth/thunks.ts b/client/src/store/auth/thunks.ts
index 902afc8..0890b7b 100644
--- a/client/src/store/auth/thunks.ts
+++ b/client/src/store/auth/thunks.ts
@@ -1,7 +1,7 @@
import { AnyAction } from "@reduxjs/toolkit";
import { ThunkAction } from "redux-thunk";
import { RootState } from "../store";
-import { checkingCredentials, login, logout } from './authSlice';
+import { checkingCredentials, login, logout, verifyCredits } from './authSlice';
@@ -11,7 +11,6 @@ export const startLoginWithGoogle = (): ThunkAction => {
+export const refetchCredits = (): ThunkAction => {
return async (dispatch, getState) => {
-
-
+ try {
+ const response = await fetch(`${import.meta.env.VITE_SERVER}/api/v1/generate/credits`, { credentials: 'include' });
+ const data = await response.json();
+
+ dispatch(verifyCredits(data))
+ } catch (error) {
+ console.log('error loading credits');
+ }
}
}
\ No newline at end of file
diff --git a/client/src/store/generator/genratorSlice.ts b/client/src/store/generator/genratorSlice.ts
new file mode 100644
index 0000000..e43fc8b
--- /dev/null
+++ b/client/src/store/generator/genratorSlice.ts
@@ -0,0 +1,62 @@
+import { createSlice } from "@reduxjs/toolkit";
+import { Post } from "../../types/post";
+
+type GeneratorState = Omit
+
+const initialState: GeneratorState = {
+ userid: '',
+ prompt: "",
+ negative_prompt: "",
+ image: "",
+ model: "",
+ width: '512',
+ height: '512'
+};
+
+const gallerySlice = createSlice({
+ name: 'generator',
+ initialState,
+ reducers: {
+ onSetId: (state, { payload }) => {
+ state.userid = payload
+ },
+ onSetPrompt: (state, { payload }) => {
+ state.prompt = payload
+ },
+ onSetNegativePrompt: (state, { payload }) => {
+ state.negative_prompt = payload
+ },
+ onSetNegativePromptBtn: (state, { payload }) => {
+ state.negative_prompt = state.negative_prompt.concat(" | " + payload)
+ },
+ onSetModel: (state, { payload }) => {
+ state.model = payload
+ },
+ onSetImage: (state, { payload }) => {
+ state.image = payload
+ },
+ onSetSize: (state, { payload }) => {
+ switch (payload) {
+ case '1/1':
+ state.width = '512'
+ state.height = '512'
+ break;
+
+ case '16/9':
+ state.width = '960'
+ state.height = '512'
+ break;
+ case '9/16':
+ state.width = '288'
+ state.height = '512'
+ break;
+ default:
+ break;
+ }
+ },
+ },
+});
+
+export const { onSetId, onSetPrompt, onSetNegativePrompt, onSetNegativePromptBtn, onSetModel, onSetImage, onSetSize } = gallerySlice.actions;
+
+export default gallerySlice.reducer;
diff --git a/client/src/store/store.ts b/client/src/store/store.ts
index e6c945e..002f081 100644
--- a/client/src/store/store.ts
+++ b/client/src/store/store.ts
@@ -2,11 +2,13 @@ import { configureStore } from '@reduxjs/toolkit'
import authSliceReduce from './auth/authSlice';
import gallerySliceReduce from './gallery/gallerySlice';
+import generatorSliceReduce from './generator/genratorSlice';
export const store = configureStore({
reducer: {
auth: authSliceReduce,
- gallery: gallerySliceReduce
+ gallery: gallerySliceReduce,
+ generator: generatorSliceReduce
},
})
diff --git a/client/src/types/post.ts b/client/src/types/post.ts
index 8eb5f82..017645a 100644
--- a/client/src/types/post.ts
+++ b/client/src/types/post.ts
@@ -1,9 +1,16 @@
import { User } from './user';
-export interface Post{
+export interface Post {
userid: string,
prompt: string,
negative_prompt: string,
image: string,
+ width: string,
+ height: string,
model: string,
- user?:User
+ user?:User,
+ image_data?:{
+ encoded: string,
+ width: number,
+ height: number
+ }
}
\ No newline at end of file
diff --git a/client/src/types/user.ts b/client/src/types/user.ts
index 890df2e..2da80c9 100644
--- a/client/src/types/user.ts
+++ b/client/src/types/user.ts
@@ -7,5 +7,14 @@ export interface User {
slug: string,
email: string,
profilePic: string,
- posts: Post[]
-}
\ No newline at end of file
+ posts: Post[],
+ credits: number,
+}
+
+export type History = {
+ _id: string,
+ prompt: string,
+ negative_prompt: string,
+ image: string,
+ model: string,
+}
diff --git a/client/src/utils/models.ts b/client/src/utils/models.ts
index 74eccc1..5343676 100644
--- a/client/src/utils/models.ts
+++ b/client/src/utils/models.ts
@@ -1,132 +1,118 @@
import { Model } from "../types/model";
export const modelList: Model[] = [
-
+ {
+ name: 'majicMIX Fantasy',
+ mode_id: 'majicmixfantasy',
+ image_url: 'https://res.cloudinary.com/dzx6dg1ws/image/upload/v1687821322/PixelAI/2981986281684908770_soipeb.jpg',
+ active: false
+ },
+ {
+ name: 'Disney Pixal Cartoon Type',
+ mode_id: 'disney-pixal-cartoon',
+ image_url: 'https://res.cloudinary.com/dzx6dg1ws/image/upload/v1687821406/PixelAI/42705-1080836037-_masterpiece_best_quality_ultra-detailed_highly_detailed_CG_illustration_an_extremely_delicate_and_beauti_z6ujvf.jpg',
+ active: false
+ },
{
name: 'Dream Shaper',
mode_id: 'dream-shaper-8797',
- image_url: 'https://d1okzptojspljx.cloudfront.net/generations/9782515001675014614.png',
+ image_url: 'https://res.cloudinary.com/dzx6dg1ws/image/upload/v1687820345/PixelAI/5_m5hmxw.png',
active: false
},
{
name: 'Redshift Diffusion',
mode_id: 'redshift-diffusion',
- image_url: 'https://d1okzptojspljx.cloudfront.net/generations/12363803511669563372.png',
+ image_url: 'https://res.cloudinary.com/dzx6dg1ws/image/upload/v1687820433/PixelAI/9860833e-e8f7-404a-94dc-270b25df05c8-0_v3rxyp.png',
active: false
},
{
name: 'Arcane Diffusion',
mode_id: 'arcane-diffusion',
- image_url: 'https://d1okzptojspljx.cloudfront.net/generations/1493213501669561761.png',
+ image_url: 'https://res.cloudinary.com/dzx6dg1ws/image/upload/v1687820482/PixelAI/69438-3187489593-arcane_style___1girl_arm_tattoo_asymmetrical_bangs_bangs_blue_hair_braid_brown_shirt_cloud_tattoo_looking_at_viewer_lau_nrwaj7.jpg',
active: false
},
{
name: 'Stable Diffusion 2.1',
mode_id: 'stable-diffu-5089',
- image_url: 'https://d1okzptojspljx.cloudfront.net/generations/1829088371675101187.png',
- active: false
- },
- {
- name: 'Project Unreal Engine 5',
- mode_id: 'project-unreal-engin',
- image_url: 'https://d1okzptojspljx.cloudfront.net/generations/171433501675425853.png',
+ image_url: 'https://res.cloudinary.com/dzx6dg1ws/image/upload/v1687820631/PixelAI/1628938322191950983_imaixu.jpg',
active: false
},
{
name: 'Vintedois',
mode_id: 'vintedois-diffusion',
- image_url: 'https://stablediffusionapi.com/storage/generations/vintedois.png',
+ image_url: 'https://res.cloudinary.com/dzx6dg1ws/image/upload/v1687820692/PixelAI/vintedois_qvkvvw.png',
active: false
},
{
name: 'Deliberate',
mode_id: 'deliberate',
- image_url: 'https://d1okzptojspljx.cloudfront.net/generations/3577020801675158232.png',
+ image_url: 'https://res.cloudinary.com/dzx6dg1ws/image/upload/v1687820733/PixelAI/download_eqxzd5.jpg',
active: false
},
{
name: 'Elldreth Vivid Mix',
mode_id: 'elldreths-vi',
- image_url: 'https://d1okzptojspljx.cloudfront.net/generations/5642196911675175414.png',
+ image_url: 'https://res.cloudinary.com/dzx6dg1ws/image/upload/v1687820781/PixelAI/12373-3660953056-award_winning_waist_up_photo_of_a_rugged_fantasy_wizard_8K_wizard_hat_wearing_torn_wizard_robes_old_and_wrinkled_long_white_z4flgy.jpg',
active: false
},
{
name: 'Realistic Vision V1.3',
mode_id: 'realistic-vision-v13',
- image_url: 'https://d1okzptojspljx.cloudfront.net/generations/593190021675281138.png',
+ image_url: 'https://res.cloudinary.com/dzx6dg1ws/image/upload/v1687820851/PixelAI/download_xbpa4p.jpg',
active: false
},
{
name: 'OpenJourney V2',
mode_id: 'midjourney-v2',
- image_url: 'https://stablediffusionapi.com//storage/generations/out-0.png',
- active: false
- },
- {
- name: 'Babes',
- mode_id: 'babes',
- image_url: 'https://d1okzptojspljx.cloudfront.net/generations/479676201675092529.png',
+ image_url: 'https://res.cloudinary.com/dzx6dg1ws/image/upload/v1687820869/PixelAI/out-0_ww5vmc.png',
active: false
},
{
name: 'Anything V4',
mode_id: 'anything-v4',
- image_url: 'https://d1okzptojspljx.cloudfront.net/generations/14779611201675081298.png',
+ image_url: 'https://res.cloudinary.com/dzx6dg1ws/image/upload/v1687820897/PixelAI/Anything_v4_sucks_00004-2158472955-a_happy_furry_fandom_male_Khajiit_white_brown_male_tiger_big_nose_round_iris_wears_an_open_jacket_close_up_masculine_zs1azq.jpg',
active: false
},
- {
- name: 'redream',
- mode_id: 'redream',
- image_url: 'https://d1okzptojspljx.cloudfront.net/generations/21177596551674938226.png',
- active: false
- },
-
{
name: 'Low Poly World',
mode_id: 'lowpoly-diffusion',
- image_url: 'https://stablediffusionapi.com//storage/generations/lowpoly.png',
+ image_url: 'https://res.cloudinary.com/dzx6dg1ws/image/upload/v1687820942/PixelAI/prompthero-prompt-4194159f9d3_qbcwqv.png',
active: false
},
{
name: 'F222',
mode_id: 'f222-diffusion',
- image_url: 'https://d1okzptojspljx.cloudfront.net/generations/6729910051670825439.png',
+ image_url: 'https://res.cloudinary.com/dzx6dg1ws/image/upload/v1687820974/PixelAI/prompthero-prompt-af7e72451e1_a8rsdd.webp',
active: false
},
{
name: 'MidJourney PaperCut',
mode_id: 'midjourney-papercut',
- image_url: 'https://s3.amazonaws.com/moonup/production/uploads/1668139335005-633a520aecbd8b19357b4806.png',
- active: false
- },
- {
- name: 'SynthwavePunk',
- mode_id: 'synthwave-diffusion',
- image_url: 'https://s3.amazonaws.com/moonup/production/uploads/1670018139245-635eafb49f24f6db0a1eafd1.png',
+ image_url: 'https://res.cloudinary.com/dzx6dg1ws/image/upload/v1687820995/PixelAI/1668139335005-633a520aecbd8b19357b4806_iya7bj.png',
active: false
},
{
name: 'Robo Diffusion',
mode_id: 'robo-diffusion',
- image_url: 'https://d1okzptojspljx.cloudfront.net/generations/17449677621669563875.png',
+ image_url: 'https://res.cloudinary.com/dzx6dg1ws/image/upload/v1687821023/PixelAI/robo_example_byfqln.png',
active: false
},
{
name: 'GTA5 Artwork Diffusion',
mode_id: 'gta5-artwork-diffusi',
- image_url: 'https://d1okzptojspljx.cloudfront.net/generations/20313028851675529498.png',
+ image_url: 'https://res.cloudinary.com/dzx6dg1ws/image/upload/v1687821046/PixelAI/1670902497106-635eafb49f24f6db0a1eafd1_gbgti8.png',
active: false
},
{
name: 'MidJourney V4',
mode_id: 'midjourney',
- image_url: 'https://d1okzptojspljx.cloudfront.net/generations/14853540911669470514.png',
+ image_url: 'https://res.cloudinary.com/dzx6dg1ws/image/upload/v1687821069/PixelAI/8-midjourney-v4-v0-774tqcg0fz5a1_ngbk53.webp',
active: false
},
]
-export const getActiveFalse = ()=>{
- return modelList.map(model => ({...model, active:false}));
+export const getActiveFalse = () => {
+ return modelList.map(model => ({ ...model, active: false }));
}
\ No newline at end of file
diff --git a/client/tailwind.config.cjs b/client/tailwind.config.cjs
index 77b537f..fb2035b 100644
--- a/client/tailwind.config.cjs
+++ b/client/tailwind.config.cjs
@@ -1,20 +1,22 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
- content: ['./src/**/*.{ts,tsx}'],
+ content: ["./src/**/*.{ts,tsx}", "./node_modules/flowbite/**/*.js"],
+ plugins: [require("flowbite/plugin")],
+
theme: {
extend: {
screens: {
- xs: '480px',
+ xs: "480px",
},
colors: {
- 'bgColor': '#202020',
- "hover":"#333333"
+ bgColor: "#202020",
+ hover: "#333333",
},
fontFamily: {
- inter: ['Inter var', 'sans-serif'],
+ inter: ["Inter var", "sans-serif"],
},
},
},
plugins: [],
-};
\ No newline at end of file
+};
diff --git a/client/vercel.json b/client/vercel.json
new file mode 100644
index 0000000..998278c
--- /dev/null
+++ b/client/vercel.json
@@ -0,0 +1,8 @@
+{
+ "rewrites": [
+ {
+ "source": "/(.*)",
+ "destination": "/"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/pixelai.png b/pixelai.png
new file mode 100644
index 0000000..eb41e80
Binary files /dev/null and b/pixelai.png differ
diff --git a/server/.example.env b/server/.example.env
new file mode 100644
index 0000000..223d4bc
--- /dev/null
+++ b/server/.example.env
@@ -0,0 +1,12 @@
+PORT=8000
+SD_API_Key= stable diffusion api key
+MONGODB_CNN= mongo connection
+GOOGLE_CLIENT_ID= google cloud
+GOOGLE_SECRET_ID= google cloud
+FACEBOOK_APP_ID= Facebook login API
+FACEBOOK_APP_SECRET= Facebook login API
+CLOUDINARY_CLOUD_NAME=
+CLOUDINARY_API_KEY=
+CLOUDINARY_API_SECRET=
+COOKIE_SECRET= any text that serves as a key for the cookie
+CLIENT_URL= ULR frontend
\ No newline at end of file
diff --git a/server/controllers/auth.ts b/server/controllers/auth.ts
index 7ffd298..0e0b6ef 100644
--- a/server/controllers/auth.ts
+++ b/server/controllers/auth.ts
@@ -3,7 +3,7 @@ import { Request, Response } from "express";
export const loginSuccess = async (req: Request, res: Response) => {
- console.log(req.user);
+ // console.log(req.user);
if (req.user) {
diff --git a/server/controllers/generate.ts b/server/controllers/generate.ts
index 7360494..0782bdf 100644
--- a/server/controllers/generate.ts
+++ b/server/controllers/generate.ts
@@ -1,26 +1,30 @@
import { Request, Response } from "express"
import { fetchApi, fetchApiWithoutModel } from "../helpers/fetchAPi";
+import User from "../models/mongo/User";
export const generateImage = async (req: Request, res: Response) => {
- const { prompt, negative_prompt, model } = req.body;
+ const { prompt, negative_prompt, model, width, height } = req.body;
+
+ const userId = req.user['_id'];
+ const user = await User.findById(userId);
try {
let data;
if(model===''){
- data = await fetchApiWithoutModel(prompt, negative_prompt)
+ data = await fetchApiWithoutModel(prompt, negative_prompt, width, height)
}else{
- data = await fetchApi(prompt, negative_prompt, model)
+ data = await fetchApi(prompt, negative_prompt, model, width, height)
}
- console.log(data);
-
if( data.message === 'Server Error' || data.status === 'failed'){
return res.status(500).json({
'message': 'Try without selecting a model'
})
}
+ // REFACTOR---
+
if (data.status === 'processing') {
console.log('prrroocceessisingg');
@@ -36,6 +40,9 @@ export const generateImage = async (req: Request, res: Response) => {
})
data = await response.json();
+ user.credits -= 1;
+ user.history.push({prompt, negative_prompt, model, image: data.output[0]})
+ await user.save();
return res.status(200).json({
'image': data.output[0]
})
@@ -45,15 +52,31 @@ export const generateImage = async (req: Request, res: Response) => {
}else if(data.status === 'error'){
return res.status(500).json({
- 'message': 'Fuera de servicio'
+ 'message': 'Out of service'
})
}else{
+ user.credits -= 1;
+ user.history.push({prompt, negative_prompt, model, image: data.output[0]})
+ await user.save();
+
return res.status(200).json({
'image': data.output[0]
})
}
+ } catch (error) {
+ res.status(500).send('Something went wrong')
+ }
+}
+
+export const verifyCredits = async (req: Request, res: Response)=>{
+ const userId = req.user['_id'];
+ try {
+ const user = await User.findById(userId);
+ return res.status(200).json({
+ 'credits': user.credits
+ })
} catch (error) {
res.status(500).send('Something went wrong')
}
diff --git a/server/controllers/post.ts b/server/controllers/post.ts
index 0411bda..7114203 100644
--- a/server/controllers/post.ts
+++ b/server/controllers/post.ts
@@ -1,33 +1,51 @@
import { Request, Response } from "express"
import Post from "../models/mongo/Post";
import User from "../models/mongo/User";
+import cd from 'cloudinary'
+const cloudinary = cd.v2
+import dotenv from 'dotenv';
+import { blurhashFromURL } from "../helpers/blurhash-from-url";
+dotenv.config();
+
+cloudinary.config({
+ cloud_name: process.env.CLOUDINARY_CLOUD_NAME,
+ api_key: process.env.CLOUDINARY_API_KEY,
+ api_secret: process.env.CLOUDINARY_API_SECRET,
+});
export const getPosts = async (req: Request, res: Response) => {
const { limit = 10, since = 0, text = "", model = "" } = req.query;
- console.log(model);
let posts;
- if (model) {
- posts = await Post.find({ prompt: { $regex: text }, model: model })
- .sort({ $natural: -1 })
- .skip(Number(since))
- .limit(Number(limit))
- .populate('user')
- } else {
- posts = await Post.find({ prompt: { $regex: text } })
- .sort({ $natural: -1 })
- .skip(Number(since))
- .limit(Number(limit))
- .populate('user')
- }
-
+ try {
+ if (model) {
+ posts = await Post.find({ prompt: { $regex: text }, model: model })
+ .sort({ $natural: -1 })
+ .skip(Number(since))
+ .limit(Number(limit))
+ .populate('user', 'username slug profilePic')
+ } else {
+ posts = await Post.find({ prompt: { $regex: text } })
+ .sort({ $natural: -1 })
+ .skip(Number(since))
+ .limit(Number(limit))
+ .populate('user', 'username slug profilePic')
+ }
+
+ return res.json({
+ posts
+ })
+ } catch (error) {
+ console.log(error);
- res.json({
- posts
- })
+ return res.status(500).json({
+ msg: error,
+ error
+ })
+ }
}
export const createPost = async (req: Request, res: Response) => {
@@ -38,12 +56,18 @@ export const createPost = async (req: Request, res: Response) => {
try {
const user = await User.findById(userid);
+ const { secure_url } = await cloudinary.uploader.upload(image)
+
+ // blur load
+ const image_data = await blurhashFromURL(secure_url)
+
const postDB = new Post({
model,
prompt,
- image,
+ image: secure_url,
negative_prompt,
- user: user._id
+ user: user._id,
+ image_data
});
diff --git a/server/controllers/user.ts b/server/controllers/user.ts
index 2371250..2eb143f 100644
--- a/server/controllers/user.ts
+++ b/server/controllers/user.ts
@@ -3,13 +3,11 @@ import User from "../models/mongo/User";
export const getUser = async (req: Request, res: Response) => {
const { slug } = req.params;
-
-
+
try {
-
- const user = await User.find({slug}).populate('posts')
-
- res.json({
+ const user = await User.find({ slug }).select('-history').populate('posts')
+
+ return res.json({
user
})
@@ -17,5 +15,16 @@ export const getUser = async (req: Request, res: Response) => {
} catch (error) {
return res.status(401).json({ msg: 'User not found' });
}
+}
+
+export const getHistory = async (req: Request, res: Response) => {
+ const userId = req.user['_id'];
+
+ try {
+ const user = await User.findById(userId);
+ return res.status(200).json(user.history)
+ } catch (error) {
+ res.status(500).send('Something went wrong')
+ }
+}
-}
\ No newline at end of file
diff --git a/server/helpers/blurhash-from-url.ts b/server/helpers/blurhash-from-url.ts
new file mode 100644
index 0000000..68379ea
--- /dev/null
+++ b/server/helpers/blurhash-from-url.ts
@@ -0,0 +1,57 @@
+// import fetch from "node-fetch";
+import { encode, decode } from "blurhash";
+import sharp from 'sharp';
+import sizeOf from "image-size";
+
+export interface IOptions {
+ size?: number;
+}
+
+export interface IInput {
+ url: string;
+ options?: IOptions;
+}
+export interface IOutput {
+ encoded: string;
+ width: number;
+ height: number;
+}
+
+export const blurhashFromURL = async (url: string, options: IOptions = {}) => {
+ const { size = 4 } = options;
+
+ const response = await fetch(url);
+ const arrayBuffer = await response.arrayBuffer();
+ console.log(arrayBuffer);
+
+ const returnedBuffer = Buffer.from(arrayBuffer);
+
+ const { width, height, } = sizeOf(returnedBuffer);
+
+ const { info, data } = await sharp(returnedBuffer)
+ .resize(size, size, {
+ fit: "inside",
+ })
+ .ensureAlpha()
+ .raw()
+ .toBuffer({
+ resolveWithObject: true,
+ });
+
+
+ const encoded = encode(
+ new Uint8ClampedArray(data),
+ info.width,
+ info.height,
+ 4,
+ 4
+ );
+
+ const output: IOutput = {
+ encoded,
+ width,
+ height,
+ };
+
+ return JSON.parse(JSON.stringify(output));
+};
\ No newline at end of file
diff --git a/server/helpers/createSlug.ts b/server/helpers/createSlug.ts
index 5bde2d0..7f1571d 100644
--- a/server/helpers/createSlug.ts
+++ b/server/helpers/createSlug.ts
@@ -2,6 +2,9 @@ export const createSlug = (nombre) => {
let slug = nombre.trim().toLowerCase();
slug = slug.replace(/[^a-z0-9]+/g, "_");
-
+
+ const randomNumber = Math.floor(Math.random() * 10000);
+ slug += `-${randomNumber}`;
+
return slug;
}
\ No newline at end of file
diff --git a/server/helpers/fetchAPi.ts b/server/helpers/fetchAPi.ts
index d0c098d..777a8fd 100644
--- a/server/helpers/fetchAPi.ts
+++ b/server/helpers/fetchAPi.ts
@@ -1,20 +1,28 @@
-export const fetchApi = async (prompt: string, negative_prompt: string, model: string) => {
- const gen = {
- "key": process.env.SD_API_Key,
- "model_id": model,
- "prompt": prompt,
- "negative_prompt": negative_prompt,
- "width": "512",
- "height": "512",
- "samples": "1",
- "num_inference_steps": 60,
- "safety_checker": "not",
- "seed": 2029243644,
- "guidance_scale": 13,
- "webhook": null,
- "track_id": null
- }
-
+
+const options = (prompt: string, negative_prompt: string, width: string, height: string) => ({
+ "key": process.env.SD_API_Key,
+ "prompt": prompt,
+ "negative_prompt": negative_prompt + " nsfw, nude, tits, pussy, masturbating, cum, breasts, small_breasts",
+ "width": width,
+ "height": height,
+ "samples": "1",
+ "num_inference_steps": 60,
+ "seed": 2029243644,
+ "guidance_scale": 13,
+ "safety_checker": "yes",
+ "webhook": null,
+ "track_id": null
+})
+
+interface optionsWithModel extends ReturnType {
+ model_id?: string
+}
+
+export const fetchApi = async (prompt: string, negative_prompt: string, model: string, width: string, height: string) => {
+ const gen = options(prompt, negative_prompt, width, height) as optionsWithModel
+ gen.model_id = model
+
+
const response = await fetch('https://stablediffusionapi.com/api/v3/dreambooth', {
method: 'POST',
headers: {
@@ -26,22 +34,9 @@ export const fetchApi = async (prompt: string, negative_prompt: string, model: s
return await response.json();
}
-export const fetchApiWithoutModel = async (prompt: string, negative_prompt: string) => {
- const gen = {
- "key": process.env.SD_API_Key,
- "prompt": prompt,
- "negative_prompt": negative_prompt,
- "width": "512",
- "height": "512",
- "samples": "1",
- "num_inference_steps": 60,
- "seed": 2029243644,
- "guidance_scale": 13,
- "safety_checker": "not",
- "webhook": null,
- "track_id": null
- }
-
+export const fetchApiWithoutModel = async (prompt: string, negative_prompt: string, width: string, height: string) => {
+ const gen = options(prompt, negative_prompt, width, height)
+
const response = await fetch('https://stablediffusionapi.com/api/v3/text2img', {
method: 'POST',
headers: {
diff --git a/server/helpers/passport.ts b/server/helpers/passport.ts
index 8af44c9..498a923 100644
--- a/server/helpers/passport.ts
+++ b/server/helpers/passport.ts
@@ -1,4 +1,5 @@
import { Strategy as GoogleStrategy } from 'passport-google-oauth20'
+import {Strategy as FacebookStrategy} from 'passport-facebook'
import passport from 'passport'
import * as dotenv from 'dotenv';
import User from '../models/mongo/User';
@@ -35,6 +36,36 @@ passport.use(
)
)
+passport.use(
+ new FacebookStrategy(
+ {
+ clientID: `${process.env.FACEBOOK_APP_ID}`,
+ clientSecret: `${process.env.FACEBOOK_APP_SECRET}`,
+ callbackURL: `https://pixelai.azurewebsites.net/api/v1/auth/facebook/callback`,
+ profileFields: ['id', 'displayName', 'picture', 'emails']
+ },
+ async (_accessToken: string, _refreshToken: string, profile: any, done) => {
+ const user = await User.findById(profile.id);
+ // console.log(profile, 'passport');
+
+ if (user) {
+ return done(null, user);
+
+ } else {
+ const newuser = await User.create({
+ username: profile.displayName,
+ slug: createSlug(profile.displayName),
+ email: `${profile.id}-${profile.displayName}`,
+ profilePic: profile.photos[0].value,
+ _id: profile.id
+ })
+ return done(null, newuser);
+ }
+ }
+ )
+)
+
+
passport.serializeUser((user:any, done) => {
done(null, user.id)
})
diff --git a/server/middlewares/checkCredits.ts b/server/middlewares/checkCredits.ts
new file mode 100644
index 0000000..bad1e5a
--- /dev/null
+++ b/server/middlewares/checkCredits.ts
@@ -0,0 +1,24 @@
+import { Request, Response } from "express";
+import User from "../models/mongo/User";
+
+
+
+
+export const checkCredits = async (req: Request, res: Response, next) => {
+ const userId = req.user['_id'];
+ const user = await User.findById(userId);
+
+ if (!user) {
+ return res.status(404).json({ message: 'User not found' });
+ }
+
+ if (user.credits < 1) {
+ return res.status(400).json({ message: 'Insufficient credits' });
+ }
+
+ req.user = user;
+
+ next();
+ };
+
+
\ No newline at end of file
diff --git a/server/middlewares/isAuthenticated.ts b/server/middlewares/isAuthenticated.ts
new file mode 100644
index 0000000..d4d9cb7
--- /dev/null
+++ b/server/middlewares/isAuthenticated.ts
@@ -0,0 +1,17 @@
+import { Request, Response } from "express";
+
+declare global {
+ namespace Express {
+ interface User {
+ credits: number;
+ }
+ }
+ }
+
+export const isAuthenticated = (req: Request, res: Response, next) => {
+
+ if (req.isAuthenticated()) {
+ return next();
+ }
+ return res.status(401).json({ error: 'Unauthorized' });
+}
\ No newline at end of file
diff --git a/server/models/Server.ts b/server/models/Server.ts
index 31f0938..6172678 100644
--- a/server/models/Server.ts
+++ b/server/models/Server.ts
@@ -11,6 +11,11 @@ import helmet from "helmet";
import session from "express-session";
import '../helpers/passport'
import userRouter from "../routes/userRoute";
+import * as dotenv from 'dotenv';
+dotenv.config();
+
+let clientURL: string = process.env.CLIENT_URL
+
class Server {
private app: Application;
@@ -51,7 +56,7 @@ class Server {
name: 'MyCoolWebAppCookieName',
cookie: {
secure: true,
- httpOnly: false,
+ httpOnly: true,
sameSite: 'none'
}
}))
@@ -70,6 +75,9 @@ class Server {
this.app.use(`/api/v1${this.paths.post}`, postRouter)
this.app.use(`/api/v1${this.paths.auth}`, authRouter)
this.app.use(`/api/v1${this.paths.user}`, userRouter)
+ this.app.get('/', (req, res) => {
+ res.redirect(clientURL);
+ });
}
listen() {
diff --git a/server/models/mongo/Post.ts b/server/models/mongo/Post.ts
index e9e698a..ef19a51 100644
--- a/server/models/mongo/Post.ts
+++ b/server/models/mongo/Post.ts
@@ -6,6 +6,12 @@ const PostSchema = new Schema({
prompt: { type: String, required: [true, 'prompt is required'] },
negative_prompt: { type: String },
image: { type: String, required: [true, 'image url is required'] },
+ image_data:
+ {
+ encoded: { type: String },
+ width: {type: Number},
+ height: {type: Number}
+ },
user: {
type: String,
ref: 'User'
diff --git a/server/models/mongo/User.ts b/server/models/mongo/User.ts
index f5970de..e78a6af 100644
--- a/server/models/mongo/User.ts
+++ b/server/models/mongo/User.ts
@@ -24,7 +24,20 @@ const UserSchema = new Schema({
posts: [{
type: Schema.Types.ObjectId,
ref: 'Post'
+ }],
+ credits: {
+ type: Number,
+ required: true,
+ default: 10
+ },
+ history: [{
+ model: { type: String, },
+ prompt: { type: String, required: [true, 'prompt is required'] },
+ negative_prompt: { type: String },
+ image: { type: String, required: [true, 'image url is required'] },
}]
})
+
+
export default model('User', UserSchema)
diff --git a/server/package-lock.json b/server/package-lock.json
index 6498b88..0ca7722 100644
--- a/server/package-lock.json
+++ b/server/package-lock.json
@@ -7,20 +7,23 @@
"": {
"name": "server",
"version": "1.0.0",
- "license": "ISC",
"dependencies": {
"bcryptjs": "^2.4.3",
- "cloudinary": "^1.33.0",
+ "blurhash": "^2.0.5",
+ "cloudinary": "^1.35.0",
"cors": "^2.8.5",
"dotenv": "^16.0.3",
"express": "^4.18.2",
"express-session": "^1.17.3",
"express-validator": "^6.14.3",
"helmet": "^6.0.1",
+ "image-size": "^1.0.2",
"mongoose": "^6.9.0",
"morgan": "^1.10.0",
"passport": "^0.6.0",
- "passport-google-oauth20": "^2.0.0"
+ "passport-facebook": "^3.0.0",
+ "passport-google-oauth20": "^2.0.0",
+ "sharp": "^0.32.0"
},
"devDependencies": {
"@types/bcryptjs": "^2.4.2",
@@ -32,6 +35,7 @@
"@types/node": "^18.11.18",
"@types/passport": "^1.0.11",
"@types/passport-google-oauth20": "^2.0.11",
+ "@types/sharp": "^0.31.1",
"ts-node": "^10.9.1",
"typescript": "^4.9.5"
}
@@ -1328,6 +1332,15 @@
"@types/node": "*"
}
},
+ "node_modules/@types/sharp": {
+ "version": "0.31.1",
+ "resolved": "https://registry.npmjs.org/@types/sharp/-/sharp-0.31.1.tgz",
+ "integrity": "sha512-5nWwamN9ZFHXaYEincMSuza8nNfOof8nmO+mcI+Agx1uMUk4/pQnNIcix+9rLPXzKrm1pS34+6WRDbDV0Jn7ag==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
"node_modules/@types/webidl-conversions": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
@@ -1481,6 +1494,42 @@
"resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz",
"integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ=="
},
+ "node_modules/bl": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
+ "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
+ "dependencies": {
+ "buffer": "^5.5.0",
+ "inherits": "^2.0.4",
+ "readable-stream": "^3.4.0"
+ }
+ },
+ "node_modules/bl/node_modules/readable-stream": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/bl/node_modules/string_decoder": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+ "dependencies": {
+ "safe-buffer": "~5.2.0"
+ }
+ },
+ "node_modules/blurhash": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/blurhash/-/blurhash-2.0.5.tgz",
+ "integrity": "sha512-cRygWd7kGBQO3VEhPiTgq4Wc43ctsM+o46urrmPOiuAe+07fzlSB9OJVdpgDL0jPqXUVQ9ht7aq7kxOeJHRK+w=="
+ },
"node_modules/body-parser": {
"version": "1.20.1",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz",
@@ -1564,10 +1613,15 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/chownr": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
+ "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="
+ },
"node_modules/cloudinary": {
- "version": "1.33.0",
- "resolved": "https://registry.npmjs.org/cloudinary/-/cloudinary-1.33.0.tgz",
- "integrity": "sha512-pdqOgd2QAMCFWujdYw1yhZ+lHPTzc6YIfg4WIvbRyoojIbSd/YgnHT8OSnk/OM4Q1WPFD5FM9EEom+4ehG80IA==",
+ "version": "1.35.0",
+ "resolved": "https://registry.npmjs.org/cloudinary/-/cloudinary-1.35.0.tgz",
+ "integrity": "sha512-0aRLVOaVsoiqDCNkSzlPGR/oYOlE3AGrtwFTPx7xlZCPyKNzqeD9t9ENmPwzHn3yn/afAvy4h1sqb2yPyJOAow==",
"dependencies": {
"cloudinary-core": "^2.10.2",
"core-js": "^3.6.5",
@@ -1589,6 +1643,43 @@
"lodash": ">=4.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==",
+ "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",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+ },
+ "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==",
+ "dependencies": {
+ "color-name": "^1.0.0",
+ "simple-swizzle": "^0.2.2"
+ }
+ },
"node_modules/content-disposition": {
"version": "0.5.4",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
@@ -1622,9 +1713,9 @@
"integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
},
"node_modules/core-js": {
- "version": "3.27.2",
- "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.27.2.tgz",
- "integrity": "sha512-9ashVQskuh5AZEZ1JdQWp1GqSoC1e1G87MzRqg2gIfVAQ7Qn9K+uFj8EcniUFA4P2NLZfV+TOlX1SzoKfo+s7w==",
+ "version": "3.29.1",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.29.1.tgz",
+ "integrity": "sha512-+jwgnhg6cQxKYIIjGtAHq2nwUOolo9eoFZ4sHfUH09BLXBgxnH4gA0zEd+t+BO2cNB8idaBtZFcFTRjQJRJmAw==",
"hasInstallScript": true,
"funding": {
"type": "opencollective",
@@ -1672,6 +1763,28 @@
"ms": "2.0.0"
}
},
+ "node_modules/decompress-response": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
+ "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
+ "dependencies": {
+ "mimic-response": "^3.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/deep-extend": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
+ "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
"node_modules/deep-is": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
@@ -1710,6 +1823,14 @@
"npm": "1.2.8000 || >= 1.4.16"
}
},
+ "node_modules/detect-libc": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.1.tgz",
+ "integrity": "sha512-463v3ZeIrcWtdgIg6vI6XUncguvr2TnGl4SzDXinkt9mSLpBJKXT3mW6xT3VQdDN11+WVs29pgvivTc4Lp8v+w==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
"node_modules/diff": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
@@ -1740,6 +1861,14 @@
"node": ">= 0.8"
}
},
+ "node_modules/end-of-stream": {
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
+ "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
+ "dependencies": {
+ "once": "^1.4.0"
+ }
+ },
"node_modules/escape-html": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
@@ -1806,6 +1935,14 @@
"node": ">= 0.6"
}
},
+ "node_modules/expand-template": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
+ "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/express": {
"version": "4.18.2",
"resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz",
@@ -1949,6 +2086,11 @@
"node": ">= 0.6"
}
},
+ "node_modules/fs-constants": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
+ "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="
+ },
"node_modules/fs-extra": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
@@ -2034,10 +2176,15 @@
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"optional": true
},
+ "node_modules/github-from-package": {
+ "version": "0.0.0",
+ "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
+ "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw=="
+ },
"node_modules/graceful-fs": {
- "version": "4.2.10",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz",
- "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==",
+ "version": "4.2.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
"optional": true
},
"node_modules/has": {
@@ -2188,11 +2335,30 @@
}
]
},
+ "node_modules/image-size": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.0.2.tgz",
+ "integrity": "sha512-xfOoWjceHntRb3qFCrh5ZFORYH8XCdYpASltMhZ/Q0KZiOwjdE/Yl2QCiWdwD+lygV5bMCvauzgu5PxBX/Yerg==",
+ "dependencies": {
+ "queue": "6.0.2"
+ },
+ "bin": {
+ "image-size": "bin/image-size.js"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
+ "node_modules/ini": {
+ "version": "1.3.8",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
+ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
+ },
"node_modules/ip": {
"version": "1.1.8",
"resolved": "https://registry.npmjs.org/ip/-/ip-1.1.8.tgz",
@@ -2207,6 +2373,11 @@
"node": ">= 0.10"
}
},
+ "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=="
+ },
"node_modules/isarray": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
@@ -2320,6 +2491,30 @@
"node": ">= 0.6"
}
},
+ "node_modules/mimic-response": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
+ "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/minimist": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
+ "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/mkdirp-classic": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
+ "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A=="
+ },
"node_modules/mongodb": {
"version": "4.13.0",
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.13.0.tgz",
@@ -2443,6 +2638,11 @@
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
},
+ "node_modules/napi-build-utils": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz",
+ "integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg=="
+ },
"node_modules/negotiator": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
@@ -2460,6 +2660,22 @@
"node": ">= 0.4.0"
}
},
+ "node_modules/node-abi": {
+ "version": "3.35.0",
+ "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.35.0.tgz",
+ "integrity": "sha512-jAlSOFR1Bls963NmFwxeQkNTzqjUF0NThm8Le7eRIRGzFUVJuMOFZDLv5Y30W/Oaw+KEebEJLAigwO9gQHoEmw==",
+ "dependencies": {
+ "semver": "^7.3.5"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/node-addon-api": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.0.0.tgz",
+ "integrity": "sha512-GyHvgPvUXBvAkXa0YvYnhilSB1A+FRYMpIVggKzPZqdaZfevZOuzfWzyvgzOwRLHBeo/MMswmJFsrNF4Nw1pmA=="
+ },
"node_modules/oauth": {
"version": "0.9.15",
"resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz",
@@ -2500,6 +2716,14 @@
"node": ">= 0.8"
}
},
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
"node_modules/optionator": {
"version": "0.8.3",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz",
@@ -2599,6 +2823,17 @@
"url": "https://github.com/sponsors/jaredhanson"
}
},
+ "node_modules/passport-facebook": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/passport-facebook/-/passport-facebook-3.0.0.tgz",
+ "integrity": "sha512-K/qNzuFsFISYAyC1Nma4qgY/12V3RSLFdFVsPKXiKZt434wOvthFW1p7zKa1iQihQMRhaWorVE1o3Vi1o+ZgeQ==",
+ "dependencies": {
+ "passport-oauth2": "1.x.x"
+ },
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
"node_modules/passport-google-oauth20": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/passport-google-oauth20/-/passport-google-oauth20-2.0.0.tgz",
@@ -2647,6 +2882,31 @@
"resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz",
"integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg=="
},
+ "node_modules/prebuild-install": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz",
+ "integrity": "sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw==",
+ "dependencies": {
+ "detect-libc": "^2.0.0",
+ "expand-template": "^2.0.3",
+ "github-from-package": "0.0.0",
+ "minimist": "^1.2.3",
+ "mkdirp-classic": "^0.5.3",
+ "napi-build-utils": "^1.0.1",
+ "node-abi": "^3.3.0",
+ "pump": "^3.0.0",
+ "rc": "^1.2.7",
+ "simple-get": "^4.0.0",
+ "tar-fs": "^2.0.0",
+ "tunnel-agent": "^0.6.0"
+ },
+ "bin": {
+ "prebuild-install": "bin.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/prelude-ls": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
@@ -2716,6 +2976,15 @@
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
"optional": true
},
+ "node_modules/pump": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
+ "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+ "dependencies": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
"node_modules/punycode": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz",
@@ -2747,6 +3016,14 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/queue": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz",
+ "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==",
+ "dependencies": {
+ "inherits": "~2.0.3"
+ }
+ },
"node_modules/random-bytes": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz",
@@ -2777,6 +3054,20 @@
"node": ">= 0.8"
}
},
+ "node_modules/rc": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
+ "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
+ "dependencies": {
+ "deep-extend": "^0.6.0",
+ "ini": "~1.3.0",
+ "minimist": "^1.2.0",
+ "strip-json-comments": "~2.0.1"
+ },
+ "bin": {
+ "rc": "cli.js"
+ }
+ },
"node_modules/readable-stream": {
"version": "1.1.14",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
@@ -2825,6 +3116,36 @@
"node": ">=6"
}
},
+ "node_modules/semver": {
+ "version": "7.4.0",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.4.0.tgz",
+ "integrity": "sha512-RgOxM8Mw+7Zus0+zcLEUn8+JfoLpj/huFTItQy2hsM4khuC1HYRDp0cU482Ewn/Fcy6bCjufD8vAj7voC66KQw==",
+ "dependencies": {
+ "lru-cache": "^6.0.0"
+ },
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/semver/node_modules/lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/semver/node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
+ },
"node_modules/send": {
"version": "0.18.0",
"resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
@@ -2872,6 +3193,28 @@
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
"integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
},
+ "node_modules/sharp": {
+ "version": "0.32.0",
+ "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.32.0.tgz",
+ "integrity": "sha512-yLAypVcqj1toSAqRSwbs86nEzfyZVDYqjuUX8grhFpeij0DDNagKJXELS/auegDBRDg1XBtELdOGfo2X1cCpeA==",
+ "hasInstallScript": true,
+ "dependencies": {
+ "color": "^4.2.3",
+ "detect-libc": "^2.0.1",
+ "node-addon-api": "^6.0.0",
+ "prebuild-install": "^7.1.1",
+ "semver": "^7.3.8",
+ "simple-get": "^4.0.1",
+ "tar-fs": "^2.1.1",
+ "tunnel-agent": "^0.6.0"
+ },
+ "engines": {
+ "node": ">=14.15.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
"node_modules/side-channel": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
@@ -2890,6 +3233,57 @@
"resolved": "https://registry.npmjs.org/sift/-/sift-16.0.1.tgz",
"integrity": "sha512-Wv6BjQ5zbhW7VFefWusVP33T/EM0vYikCaQ2qR8yULbsilAT8/wQaXvuQ3ptGLpoKx+lihJE3y2UTgKDyyNHZQ=="
},
+ "node_modules/simple-concat": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
+ "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/simple-get": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz",
+ "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
+ "decompress-response": "^6.0.0",
+ "once": "^1.3.1",
+ "simple-concat": "^1.0.0"
+ }
+ },
+ "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==",
+ "dependencies": {
+ "is-arrayish": "^0.3.1"
+ }
+ },
"node_modules/smart-buffer": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
@@ -2986,12 +3380,67 @@
"integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==",
"optional": true
},
+ "node_modules/strip-json-comments": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
+ "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/strnum": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz",
"integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==",
"optional": true
},
+ "node_modules/tar-fs": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz",
+ "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==",
+ "dependencies": {
+ "chownr": "^1.1.1",
+ "mkdirp-classic": "^0.5.2",
+ "pump": "^3.0.0",
+ "tar-stream": "^2.1.4"
+ }
+ },
+ "node_modules/tar-stream": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
+ "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
+ "dependencies": {
+ "bl": "^4.0.3",
+ "end-of-stream": "^1.4.1",
+ "fs-constants": "^1.0.0",
+ "inherits": "^2.0.3",
+ "readable-stream": "^3.1.1"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/tar-stream/node_modules/readable-stream": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/tar-stream/node_modules/string_decoder": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+ "dependencies": {
+ "safe-buffer": "~5.2.0"
+ }
+ },
"node_modules/toidentifier": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
@@ -3060,6 +3509,17 @@
"integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==",
"optional": true
},
+ "node_modules/tunnel-agent": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
+ "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
+ "dependencies": {
+ "safe-buffer": "^5.0.1"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
"node_modules/type-check": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
@@ -3130,6 +3590,11 @@
"node": ">= 0.8"
}
},
+ "node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
+ },
"node_modules/utils-merge": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
@@ -3170,9 +3635,9 @@
}
},
"node_modules/vm2": {
- "version": "3.9.13",
- "resolved": "https://registry.npmjs.org/vm2/-/vm2-3.9.13.tgz",
- "integrity": "sha512-0rvxpB8P8Shm4wX2EKOiMp7H2zq+HUE/UwodY0pCZXs9IffIKZq6vUti5OgkVCTakKo9e/fgO4X1fkwfjWxE3Q==",
+ "version": "3.9.14",
+ "resolved": "https://registry.npmjs.org/vm2/-/vm2-3.9.14.tgz",
+ "integrity": "sha512-HgvPHYHeQy8+QhzlFryvSteA4uQLBCOub02mgqdR+0bN/akRZ48TGB1v0aCv7ksyc0HXx16AZtMHKS38alc6TA==",
"optional": true,
"dependencies": {
"acorn": "^8.7.0",
@@ -3214,6 +3679,11 @@
"node": ">=0.10.0"
}
},
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
+ },
"node_modules/xregexp": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz",
diff --git a/server/package.json b/server/package.json
index f0a3989..411881c 100644
--- a/server/package.json
+++ b/server/package.json
@@ -11,20 +11,23 @@
},
"keywords": [],
"author": "",
- "license": "ISC",
"dependencies": {
"bcryptjs": "^2.4.3",
- "cloudinary": "^1.33.0",
+ "blurhash": "^2.0.5",
+ "cloudinary": "^1.35.0",
"cors": "^2.8.5",
"dotenv": "^16.0.3",
"express": "^4.18.2",
"express-session": "^1.17.3",
"express-validator": "^6.14.3",
"helmet": "^6.0.1",
+ "image-size": "^1.0.2",
"mongoose": "^6.9.0",
"morgan": "^1.10.0",
"passport": "^0.6.0",
- "passport-google-oauth20": "^2.0.0"
+ "passport-facebook": "^3.0.0",
+ "passport-google-oauth20": "^2.0.0",
+ "sharp": "^0.32.0"
},
"devDependencies": {
"@types/bcryptjs": "^2.4.2",
@@ -36,6 +39,7 @@
"@types/node": "^18.11.18",
"@types/passport": "^1.0.11",
"@types/passport-google-oauth20": "^2.0.11",
+ "@types/sharp": "^0.31.1",
"ts-node": "^10.9.1",
"typescript": "^4.9.5"
}
diff --git a/server/routes/authRouter.ts b/server/routes/authRouter.ts
index 4061159..a473e04 100644
--- a/server/routes/authRouter.ts
+++ b/server/routes/authRouter.ts
@@ -10,7 +10,7 @@ let clientURL: string = process.env.CLIENT_URL
const authRouter = Router();
-authRouter.get('/login/success',loginSuccess)
+authRouter.get('/login/success', loginSuccess)
authRouter.get('/login/failed', loginFailed)
@@ -21,6 +21,13 @@ authRouter.get('/google/callback', passport.authenticate('google', {
failureRedirect: '/login/failed'
}))
+authRouter.get("/facebook", passport.authenticate('facebook', { scope: 'email' }));
+
+authRouter.get('/facebook/callback', passport.authenticate('facebook', {
+ successRedirect: clientURL,
+ failureRedirect: '/login/failed'
+}))
+
authRouter.get('/logout', logout)
export default authRouter;
\ No newline at end of file
diff --git a/server/routes/generateRouter.ts b/server/routes/generateRouter.ts
index 0613acd..205d003 100644
--- a/server/routes/generateRouter.ts
+++ b/server/routes/generateRouter.ts
@@ -1,13 +1,22 @@
import { Router } from "express";
import { check } from "express-validator";
-import { generateImage } from "../controllers/generate";
+import { generateImage, verifyCredits } from "../controllers/generate";
import { validate } from "../middlewares/validate";
+import { isAuthenticated } from "../middlewares/isAuthenticated";
+import { checkCredits } from "../middlewares/checkCredits";
const generateRouter = Router();
generateRouter.post('/',[
+ isAuthenticated,
+ checkCredits,
check('prompt',"Prompt is required").not().isEmpty(),
validate
], generateImage)
+generateRouter.get('/credits', [
+ isAuthenticated,
+ validate
+], verifyCredits)
+
export default generateRouter
\ No newline at end of file
diff --git a/server/routes/userRoute.ts b/server/routes/userRoute.ts
index 339bf21..932e30b 100644
--- a/server/routes/userRoute.ts
+++ b/server/routes/userRoute.ts
@@ -1,10 +1,15 @@
import { Router } from "express";
-import { getUser } from "../controllers/user";
+import { getHistory, getUser } from "../controllers/user";
+import { isAuthenticated } from "../middlewares/isAuthenticated";
+import { validate } from "../middlewares/validate";
const userRouter = Router();
-userRouter.get('/:slug', getUser)
-
+userRouter.get('/history',[
+ isAuthenticated,
+ validate
+],getHistory)
+userRouter.get('/:slug', getUser)
export default userRouter
\ No newline at end of file
diff --git "a/task/Task_2_AI_vs_Human\342\200\223Academic_Essay_Authenticity_Challenge.ipynb" "b/task/Task_2_AI_vs_Human\342\200\223Academic_Essay_Authenticity_Challenge.ipynb"
new file mode 100644
index 0000000..b284c13
--- /dev/null
+++ "b/task/Task_2_AI_vs_Human\342\200\223Academic_Essay_Authenticity_Challenge.ipynb"
@@ -0,0 +1,739 @@
+{
+ "nbformat": 4,
+ "nbformat_minor": 0,
+ "metadata": {
+ "colab": {
+ "provenance": [],
+ "mount_file_id": "1mYWOZdUA25h-MHks0Yy4f-UW-ge7Xyms",
+ "authorship_tag": "ABX9TyMna4pfYo5KLeNb1ANM0rZu",
+ "include_colab_link": true
+ },
+ "kernelspec": {
+ "name": "python3",
+ "display_name": "Python 3"
+ },
+ "language_info": {
+ "name": "python"
+ }
+ },
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {
+ "id": "view-in-github",
+ "colab_type": "text"
+ },
+ "source": [
+ " "
+ ]
+ },
+ {
+ "cell_type": "code",
+ "source": [
+ "pip install imbalanced-learn scikit-learn"
+ ],
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/"
+ },
+ "collapsed": true,
+ "id": "kgdQznP-OPXE",
+ "outputId": "75654bac-98c9-4354-ffb4-be9061ed61dd"
+ },
+ "execution_count": 12,
+ "outputs": [
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "Requirement already satisfied: imbalanced-learn in /usr/local/lib/python3.10/dist-packages (0.12.3)\n",
+ "Requirement already satisfied: scikit-learn in /usr/local/lib/python3.10/dist-packages (1.5.2)\n",
+ "Requirement already satisfied: numpy>=1.17.3 in /usr/local/lib/python3.10/dist-packages (from imbalanced-learn) (1.26.4)\n",
+ "Requirement already satisfied: scipy>=1.5.0 in /usr/local/lib/python3.10/dist-packages (from imbalanced-learn) (1.13.1)\n",
+ "Requirement already satisfied: joblib>=1.1.1 in /usr/local/lib/python3.10/dist-packages (from imbalanced-learn) (1.4.2)\n",
+ "Requirement already satisfied: threadpoolctl>=2.0.0 in /usr/local/lib/python3.10/dist-packages (from imbalanced-learn) (3.5.0)\n"
+ ]
+ }
+ ]
+ },
+ {
+ "cell_type": "code",
+ "source": [
+ "import pandas as pd\n",
+ "\n",
+ "from imblearn.over_sampling import SMOTE\n",
+ "from sklearn.model_selection import train_test_split\n",
+ "from sklearn.feature_extraction.text import TfidfVectorizer"
+ ],
+ "metadata": {
+ "id": "xiPdGyRK8ixp"
+ },
+ "execution_count": 2,
+ "outputs": []
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {
+ "id": "aM6UEL28AFUM",
+ "colab": {
+ "base_uri": "https://localhost:8080/",
+ "height": 423
+ },
+ "outputId": "632cd243-a00d-4cd9-a33a-b30c03265020"
+ },
+ "outputs": [
+ {
+ "output_type": "execute_result",
+ "data": {
+ "text/plain": [
+ " id \\\n",
+ "0 cc7727e8bfbc6e0051b71ceeeb928755def0f5e94b5168... \n",
+ "1 fa7e1bc99ea20c78df905eb3780cb835bed078b64fce6a... \n",
+ "2 d16ec17f6ffd059cf2eefe79ca2ccd9bdb78ea5ec2d6a0... \n",
+ "3 838f538cf1b0e03e51e423266844492af1a72874a224d4... \n",
+ "4 cd9fe478b001e04bcdc276f9675b90bc8c6332a7ea8abf... \n",
+ "... ... \n",
+ "2091 1cf89b43ddf6f54c41ce5ff8d584dd47fbe21fc9007048... \n",
+ "2092 90aeae7d7df06d9e45cff4494973ad4cc668aa92f395b7... \n",
+ "2093 a6ac8461fe6b71161372b63438d531af3168e3f4c5ce1c... \n",
+ "2094 a0bf652b04c7f6fdfea48ccabcc853aa21c832ce749257... \n",
+ "2095 21847eeb48b24217c3c17297c1d7ea3856d234e5c76ae2... \n",
+ "\n",
+ " essay label \n",
+ "0 I disagree with the statement that the develop... ai \n",
+ "1 I disagree with the statement that the primary... ai \n",
+ "2 International sports events require the most w... human \n",
+ "3 While some individuals may argue that working ... ai \n",
+ "4 I disagree with the statement that working rem... ai \n",
+ "... ... ... \n",
+ "2091 Capital punishment is always associated with i... human \n",
+ "2092 Sport play an essential role in shaping the pe... human \n",
+ "2093 It is true that artificial activities cause te... human \n",
+ "2094 Packing of goods has become a noticeable issue... human \n",
+ "2095 In my opinion, cultural traditions should be p... ai \n",
+ "\n",
+ "[2096 rows x 3 columns]"
+ ],
+ "text/html": [
+ "\n",
+ " \n",
+ "
\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " id \n",
+ " essay \n",
+ " label \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 \n",
+ " cc7727e8bfbc6e0051b71ceeeb928755def0f5e94b5168... \n",
+ " I disagree with the statement that the develop... \n",
+ " ai \n",
+ " \n",
+ " \n",
+ " 1 \n",
+ " fa7e1bc99ea20c78df905eb3780cb835bed078b64fce6a... \n",
+ " I disagree with the statement that the primary... \n",
+ " ai \n",
+ " \n",
+ " \n",
+ " 2 \n",
+ " d16ec17f6ffd059cf2eefe79ca2ccd9bdb78ea5ec2d6a0... \n",
+ " International sports events require the most w... \n",
+ " human \n",
+ " \n",
+ " \n",
+ " 3 \n",
+ " 838f538cf1b0e03e51e423266844492af1a72874a224d4... \n",
+ " While some individuals may argue that working ... \n",
+ " ai \n",
+ " \n",
+ " \n",
+ " 4 \n",
+ " cd9fe478b001e04bcdc276f9675b90bc8c6332a7ea8abf... \n",
+ " I disagree with the statement that working rem... \n",
+ " ai \n",
+ " \n",
+ " \n",
+ " ... \n",
+ " ... \n",
+ " ... \n",
+ " ... \n",
+ " \n",
+ " \n",
+ " 2091 \n",
+ " 1cf89b43ddf6f54c41ce5ff8d584dd47fbe21fc9007048... \n",
+ " Capital punishment is always associated with i... \n",
+ " human \n",
+ " \n",
+ " \n",
+ " 2092 \n",
+ " 90aeae7d7df06d9e45cff4494973ad4cc668aa92f395b7... \n",
+ " Sport play an essential role in shaping the pe... \n",
+ " human \n",
+ " \n",
+ " \n",
+ " 2093 \n",
+ " a6ac8461fe6b71161372b63438d531af3168e3f4c5ce1c... \n",
+ " It is true that artificial activities cause te... \n",
+ " human \n",
+ " \n",
+ " \n",
+ " 2094 \n",
+ " a0bf652b04c7f6fdfea48ccabcc853aa21c832ce749257... \n",
+ " Packing of goods has become a noticeable issue... \n",
+ " human \n",
+ " \n",
+ " \n",
+ " 2095 \n",
+ " 21847eeb48b24217c3c17297c1d7ea3856d234e5c76ae2... \n",
+ " In my opinion, cultural traditions should be p... \n",
+ " ai \n",
+ " \n",
+ " \n",
+ "
\n",
+ "
2096 rows × 3 columns
\n",
+ "
\n",
+ "
\n",
+ "
\n"
+ ],
+ "application/vnd.google.colaboratory.intrinsic+json": {
+ "type": "dataframe",
+ "variable_name": "df_train",
+ "summary": "{\n \"name\": \"df_train\",\n \"rows\": 2096,\n \"fields\": [\n {\n \"column\": \"id\",\n \"properties\": {\n \"dtype\": \"string\",\n \"num_unique_values\": 2096,\n \"samples\": [\n \"9c19b95cf96c181850a33ccc33f14443cbec84349e600fca635c984ba741771b\",\n \"30681070f65e86c11b9d74a8bcace8cd30f4b440f93e758fb53d081b44164190_model_3_15696\",\n \"8342da2435cd23908285fdc61f5706a3b8fe898fd4c2097b9517efbcf34388e6_model_3_15632\"\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"essay\",\n \"properties\": {\n \"dtype\": \"string\",\n \"num_unique_values\": 2096,\n \"samples\": [\n \"Young people today are under a lot of pressure, which seems to come from many directions. The problems they are experiencing happen not only at school, but also at home, and it seems that without adult guidance, our young generation will continue to struggle.Teenage years have never been simple, and many would agree that the amount of challenges has only increased with the passage of time. Bullying has been a problem for quite a while, and children and adolescents would have experienced it at school in the past, but then it would stop at home. At present, however, things have been made worse by social media penetrating the supposedly safe space of our teenagers. The unfortunate behaviour of their peers can now reach them even in their bedrooms, causing them constant distress.Another issue troubling many young people is the pressure to succeed by their families. Whether at school or at home, they often feel as if they are not smart enough, which creates overwhelm and despair. Understandably, their parents are pursuing a worthy goal of ensuring their children get a great start in life; however, many teens feel that they are failing their families when they don\\u2019t live up to their expectations. This often leads to dishonest and unethical behaviour, such as cheating on tests or plagiarising other students\\u2019 work. When uncovered, these incidents have a profound effect on young people\\u2019s future careers, not to mention their emotional well-being.It is hard to underestimate the importance of parental support to navigating life as a young person. From helping teens build a positive body image and self-esteem, to handling classmates\\u2019 difficult behaviour, to guidance where study is concerned, parents can make a world of difference. Talking to their sons and daughters about matters that worry them, listening and making non-judgmental suggestions are great ways to help. Getting a professional involved where necessary and engaging with teachers, councilors and coaches is another opportunity for parents to provide assistance. Last but not least, parents can make their children better and happier people by simply giving them unconditional love.To sum up, being a young person in the modern world isn\\u2019t easy. By banding together and paying careful attention to their teens, families can help them overcome any obstacles to becoming successful adults.\",\n \"While some may argue that the primary purpose of education is to prepare students for the workforce, I strongly disagree with this statement. Education is a multifaceted institution that serves various purposes, and its primary goal should not be limited to workforce preparation.\\n\\nFirstly, education plays a crucial role in shaping individuals' critical thinking and problem-solving skills. By exposing students to diverse subjects and ideas, education helps them develop analytical minds, enabling them to navigate complex situations and make informed decisions. These skills are essential not only in the workforce but also in personal and civic life. For instance, a well-educated individual can critically evaluate information, identify biases, and make sound judgments, which are vital for effective participation in democratic processes.\\n\\nSecondly, education fosters personal growth and development, allowing individuals to explore their interests and passions. By providing opportunities for students to engage in extracurricular activities, sports, and creative pursuits, education helps them discover their strengths and weaknesses, build confidence, and develop a sense of purpose. This, in turn, enables them to lead fulfilling lives, regardless of their career choices. For example, a student who excels in music or art may not necessarily pursue a career in these fields but can still benefit from the skills and values they acquired through their education.\\n\\nLastly, education has a profound impact on individuals' social and emotional well-being. By promoting empathy, tolerance, and understanding, education helps students develop positive relationships with others, build strong communities, and contribute to the greater good. This is evident in the many examples of educators and alumni who have made significant contributions to social justice, environmental sustainability, and humanitarian causes.\\n\\nIn conclusion, while education can certainly prepare students for the workforce, its primary purpose should be to empower individuals with the knowledge, skills, and values necessary to lead fulfilling lives, contribute to society, and make a positive impact on the world.\",\n \"I disagree with the statement that the development of artificial intelligence will create more jobs than it will eliminate. While it is true that AI has the potential to automate certain tasks, I believe that its impact on job creation will be limited.\\n\\nFirstly, AI will undoubtedly replace many jobs that are repetitive, routine, and can be easily automated. For instance, self-service kiosks are already replacing cashiers in many retail stores. Similarly, AI-powered chatbots are taking over customer service roles. These jobs will be eliminated, and many workers will struggle to adapt to the changing job market.\\n\\nMoreover, the development of AI will also lead to the creation of new jobs in fields such as AI development, deployment, and maintenance. However, these jobs will require highly specialized skills and education, which not everyone possesses. In addition, the number of new jobs created in these fields will likely be limited compared to the number of jobs eliminated.\\n\\nFurthermore, the benefits of AI, such as increased productivity and efficiency, will likely be concentrated among a small group of companies and individuals, rather than being evenly distributed across the workforce. This could exacerbate income inequality and create new social and economic challenges.\\n\\nIn conclusion, while AI has the potential to bring about significant benefits, I believe that its impact on job creation will be limited. The jobs that are eliminated will likely outweigh the new jobs created, and the benefits of AI will be concentrated among a small group of individuals. Therefore, I disagree with the statement that the development of artificial intelligence will create more jobs than it will eliminate.\"\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"label\",\n \"properties\": {\n \"dtype\": \"category\",\n \"num_unique_values\": 2,\n \"samples\": [\n \"human\",\n \"ai\"\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n }\n ]\n}"
+ }
+ },
+ "metadata": {},
+ "execution_count": 3
+ }
+ ],
+ "source": [
+ "df_train = pd.read_json('/content/drive/MyDrive/TESIS/dataset-task2/english-unzip/academic_essay_english_train.jsonl', lines=True)\n",
+ "df_test = pd.read_json('/content/drive/MyDrive/TESIS/dataset-task2/english-unzip/academic_essay_english_dev.jsonl', orient='records', lines=True)\n",
+ "df_no_labels = pd.read_json('/content/drive/MyDrive/TESIS/dataset-task2/english-unzip/academic_essay_english_dev_test_no_label.jsonl', orient='records', lines=True)\n",
+ "\n",
+ "# se muestra dos elementos\n",
+ "df_train\n",
+ "\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "source": [
+ "df_train['label'].value_counts()\n",
+ "\n",
+ "# Se encuentra desbalanceado"
+ ],
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/",
+ "height": 178
+ },
+ "id": "YLR-m09C9YaN",
+ "outputId": "b19bf774-eb0b-44be-8116-96df7e11660c"
+ },
+ "execution_count": null,
+ "outputs": [
+ {
+ "output_type": "execute_result",
+ "data": {
+ "text/plain": [
+ "label\n",
+ "ai 1467\n",
+ "human 629\n",
+ "Name: count, dtype: int64"
+ ],
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " count \n",
+ " \n",
+ " \n",
+ " label \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " ai \n",
+ " 1467 \n",
+ " \n",
+ " \n",
+ " human \n",
+ " 629 \n",
+ " \n",
+ " \n",
+ "
\n",
+ "
dtype: int64 "
+ ]
+ },
+ "metadata": {},
+ "execution_count": 4
+ }
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "source": [
+ "# Balancear por SMOTE"
+ ],
+ "metadata": {
+ "id": "UImkIgldOWKS"
+ }
+ },
+ {
+ "cell_type": "code",
+ "source": [
+ "from imblearn.over_sampling import SMOTE\n",
+ "from sklearn.model_selection import train_test_split\n",
+ "from sklearn.feature_extraction.text import TfidfVectorizer\n",
+ "\n",
+ "# Asignar X e Y\n",
+ "X_train = df_train['essay']\n",
+ "Y_train = df_train['label']\n",
+ "\n",
+ "# 1. Create a TF-IDF vectorizer\n",
+ "vectorizer = TfidfVectorizer()\n",
+ "\n",
+ "# 2. Fit the vectorizer to your training data and transform it\n",
+ "X_train_tfidf = vectorizer.fit_transform(X_train)\n",
+ "\n",
+ "# 3. Now apply SMOTE to the numerical representation\n",
+ "smote = SMOTE(random_state=42)\n",
+ "X_smote, y_smote = smote.fit_resample(X_train_tfidf, Y_train)\n",
+ "\n",
+ "# Print the shape of the original and resampled data\n",
+ "print(\"Original dataset shape:\", X_train_tfidf.shape, Y_train.shape)\n",
+ "print(\"Resampled dataset shape:\", X_smote.shape, y_smote.shape)\n",
+ "\n",
+ "# Print the value counts of the target variable before and after SMOTE\n",
+ "print(\"\\nOriginal target variable distribution:\")\n",
+ "print(Y_train.value_counts())\n",
+ "print(\"\\nResampled target variable distribution:\")\n",
+ "print(y_smote.value_counts())\n",
+ "\n",
+ "Y_train"
+ ],
+ "metadata": {
+ "colab": {
+ "base_uri": "https://localhost:8080/",
+ "height": 701
+ },
+ "id": "mPqV3x0GOYBC",
+ "outputId": "f3c7d9eb-8c93-4582-9867-31336a95d14d"
+ },
+ "execution_count": 39,
+ "outputs": [
+ {
+ "output_type": "stream",
+ "name": "stdout",
+ "text": [
+ "Original dataset shape: (2096, 12043) (2096,)\n",
+ "Resampled dataset shape: (2934, 12043) (2934,)\n",
+ "\n",
+ "Original target variable distribution:\n",
+ "label\n",
+ "ai 1467\n",
+ "human 629\n",
+ "Name: count, dtype: int64\n",
+ "\n",
+ "Resampled target variable distribution:\n",
+ "label\n",
+ "ai 1467\n",
+ "human 1467\n",
+ "Name: count, dtype: int64\n"
+ ]
+ },
+ {
+ "output_type": "execute_result",
+ "data": {
+ "text/plain": [
+ "0 ai\n",
+ "1 ai\n",
+ "2 human\n",
+ "3 ai\n",
+ "4 ai\n",
+ " ... \n",
+ "2091 human\n",
+ "2092 human\n",
+ "2093 human\n",
+ "2094 human\n",
+ "2095 ai\n",
+ "Name: label, Length: 2096, dtype: object"
+ ],
+ "text/html": [
+ "\n",
+ "\n",
+ "
\n",
+ " \n",
+ " \n",
+ " \n",
+ " label \n",
+ " \n",
+ " \n",
+ " \n",
+ " \n",
+ " 0 \n",
+ " ai \n",
+ " \n",
+ " \n",
+ " 1 \n",
+ " ai \n",
+ " \n",
+ " \n",
+ " 2 \n",
+ " human \n",
+ " \n",
+ " \n",
+ " 3 \n",
+ " ai \n",
+ " \n",
+ " \n",
+ " 4 \n",
+ " ai \n",
+ " \n",
+ " \n",
+ " ... \n",
+ " ... \n",
+ " \n",
+ " \n",
+ " 2091 \n",
+ " human \n",
+ " \n",
+ " \n",
+ " 2092 \n",
+ " human \n",
+ " \n",
+ " \n",
+ " 2093 \n",
+ " human \n",
+ " \n",
+ " \n",
+ " 2094 \n",
+ " human \n",
+ " \n",
+ " \n",
+ " 2095 \n",
+ " ai \n",
+ " \n",
+ " \n",
+ "
\n",
+ "
2096 rows × 1 columns
\n",
+ "
dtype: object "
+ ]
+ },
+ "metadata": {},
+ "execution_count": 39
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file