diff --git a/.env b/.env new file mode 100644 index 0000000..bde21b0 --- /dev/null +++ b/.env @@ -0,0 +1,9 @@ +REACT_APP_POST_URL=http://localhost:4000/api/posts +REACT_APP_POST_DELETE=http://localhost:4000/api/posts/ +REACT_APP_UPDATE_POST=http://localhost:4000/api/posts/ +REACT_APP_API_LOGIN=http://localhost:4000/api/auth/signin +REACT_APP_API_SIGNUP=http://localhost:4000/api/auth/signup +REACT_APP_POST_ID=http://localhost:4000/api/posts/ +REACT_APP_API_URL=https://api.example.com +REACT_APP_API_URL=https://api.example.com +REACT_APP_API_URL=https://api.example.com \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 96947db..dd5ac03 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "@fortawesome/free-brands-svg-icons": "^6.4.0", "@fortawesome/free-solid-svg-icons": "^6.4.0", "@fortawesome/react-fontawesome": "^0.2.0", + "@material-tailwind/react": "^2.0.6", "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", @@ -25,8 +26,9 @@ "react-dom": "^18.2.0", "react-hot-toast": "^2.4.0", "react-icons": "^4.8.0", - "react-router-dom": "^6.10.0", + "react-router-dom": "^6.14.2", "react-scripts": "5.0.1", + "tailwindcss-animated": "^1.0.1", "web-vitals": "^2.1.4", "yup": "^1.0.2" }, @@ -2324,6 +2326,21 @@ "postcss-selector-parser": "^6.0.10" } }, + "node_modules/@emotion/is-prop-valid": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz", + "integrity": "sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==", + "optional": true, + "dependencies": { + "@emotion/memoize": "0.7.4" + } + }, + "node_modules/@emotion/memoize": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz", + "integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==", + "optional": true + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", @@ -2376,6 +2393,45 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@floating-ui/core": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.3.1.tgz", + "integrity": "sha512-Bu+AMaXNjrpjh41znzHqaz3r2Nr8hHuHZT6V2LBKMhyMl0FgKA62PNYbqnfgmzOhoWZj70Zecisbo4H1rotP5g==" + }, + "node_modules/@floating-ui/dom": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.4.5.tgz", + "integrity": "sha512-96KnRWkRnuBSSFbj0sFGwwOUd8EkiecINVl0O9wiZlZ64EkpyAOG3Xc2vKKNJmru0Z7RqWNymA+6b8OZqjgyyw==", + "dependencies": { + "@floating-ui/core": "^1.3.1" + } + }, + "node_modules/@floating-ui/react": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.19.2.tgz", + "integrity": "sha512-JyNk4A0Ezirq8FlXECvRtQOX/iBe5Ize0W/pLkrZjfHW9GUV7Xnq6zm6fyZuQzaHHqEnVizmvlA96e1/CkZv+w==", + "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/@fortawesome/fontawesome-common-types": { "version": "6.4.0", "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-6.4.0.tgz", @@ -2433,6 +2489,14 @@ "react": ">=16.3" } }, + "node_modules/@heroicons/react": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/@heroicons/react/-/react-2.0.18.tgz", + "integrity": "sha512-7TyMjRrZZMBPa+/5Y8lN0iyvUU/01PeMGX2+RE7cQWpEUIcb4QotzUObFkJDejj/HUH4qjP/eQ0gzzKs2f+6Yw==", + "peerDependencies": { + "react": ">= 16" + } + }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz", @@ -3306,6 +3370,118 @@ "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==" }, + "node_modules/@material-tailwind/react": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@material-tailwind/react/-/react-2.0.6.tgz", + "integrity": "sha512-aT2BZd9AAlwuFiuA29FQbayK4RmPPHs5Q3RlB9cnTtpOHXz6v32i3YC90bh1fINpixFeKftJeO7YzeaukX5zsQ==", + "dependencies": { + "@floating-ui/react": "^0.19.0", + "@heroicons/react": "^2.0.13", + "classnames": "^2.3.2", + "deepmerge": "^4.2.2", + "framer-motion": "^6.5.1", + "material-ripple-effects": "^2.0.1", + "prop-types": "^15.8.1", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "tailwind-merge": "^1.8.1" + }, + "peerDependencies": { + "react": "^16 || ^17 || ^18", + "react-dom": "^16 || ^17 || ^18" + } + }, + "node_modules/@material-tailwind/react/node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@motionone/animation": { + "version": "10.15.1", + "resolved": "https://registry.npmjs.org/@motionone/animation/-/animation-10.15.1.tgz", + "integrity": "sha512-mZcJxLjHor+bhcPuIFErMDNyrdb2vJur8lSfMCsuCB4UyV8ILZLvK+t+pg56erv8ud9xQGK/1OGPt10agPrCyQ==", + "dependencies": { + "@motionone/easing": "^10.15.1", + "@motionone/types": "^10.15.1", + "@motionone/utils": "^10.15.1", + "tslib": "^2.3.1" + } + }, + "node_modules/@motionone/animation/node_modules/tslib": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", + "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==" + }, + "node_modules/@motionone/dom": { + "version": "10.12.0", + "resolved": "https://registry.npmjs.org/@motionone/dom/-/dom-10.12.0.tgz", + "integrity": "sha512-UdPTtLMAktHiqV0atOczNYyDd/d8Cf5fFsd1tua03PqTwwCe/6lwhLSQ8a7TbnQ5SN0gm44N1slBfj+ORIhrqw==", + "dependencies": { + "@motionone/animation": "^10.12.0", + "@motionone/generators": "^10.12.0", + "@motionone/types": "^10.12.0", + "@motionone/utils": "^10.12.0", + "hey-listen": "^1.0.8", + "tslib": "^2.3.1" + } + }, + "node_modules/@motionone/dom/node_modules/tslib": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", + "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==" + }, + "node_modules/@motionone/easing": { + "version": "10.15.1", + "resolved": "https://registry.npmjs.org/@motionone/easing/-/easing-10.15.1.tgz", + "integrity": "sha512-6hIHBSV+ZVehf9dcKZLT7p5PEKHGhDwky2k8RKkmOvUoYP3S+dXsKupyZpqx5apjd9f+php4vXk4LuS+ADsrWw==", + "dependencies": { + "@motionone/utils": "^10.15.1", + "tslib": "^2.3.1" + } + }, + "node_modules/@motionone/easing/node_modules/tslib": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", + "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==" + }, + "node_modules/@motionone/generators": { + "version": "10.15.1", + "resolved": "https://registry.npmjs.org/@motionone/generators/-/generators-10.15.1.tgz", + "integrity": "sha512-67HLsvHJbw6cIbLA/o+gsm7h+6D4Sn7AUrB/GPxvujse1cGZ38F5H7DzoH7PhX+sjvtDnt2IhFYF2Zp1QTMKWQ==", + "dependencies": { + "@motionone/types": "^10.15.1", + "@motionone/utils": "^10.15.1", + "tslib": "^2.3.1" + } + }, + "node_modules/@motionone/generators/node_modules/tslib": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", + "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==" + }, + "node_modules/@motionone/types": { + "version": "10.15.1", + "resolved": "https://registry.npmjs.org/@motionone/types/-/types-10.15.1.tgz", + "integrity": "sha512-iIUd/EgUsRZGrvW0jqdst8st7zKTzS9EsKkP+6c6n4MPZoQHwiHuVtTQLD6Kp0bsBLhNzKIBlHXponn/SDT4hA==" + }, + "node_modules/@motionone/utils": { + "version": "10.15.1", + "resolved": "https://registry.npmjs.org/@motionone/utils/-/utils-10.15.1.tgz", + "integrity": "sha512-p0YncgU+iklvYr/Dq4NobTRdAPv9PveRDUXabPEeOjBLSO/1FNB2phNTZxOxpi1/GZwYpAoECEa0Wam+nsmhSw==", + "dependencies": { + "@motionone/types": "^10.15.1", + "hey-listen": "^1.0.8", + "tslib": "^2.3.1" + } + }, + "node_modules/@motionone/utils/node_modules/tslib": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", + "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==" + }, "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": { "version": "5.1.1-v1", "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", @@ -3416,9 +3592,9 @@ } }, "node_modules/@remix-run/router": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.6.3.tgz", - "integrity": "sha512-EXJysQ7J3veRECd0kZFQwYYd5sJMcq2O/m60zu1W2l3oVQ9xtub8jTOtYRE0+M2iomyG/W3Ps7+vp2kna0C27Q==", + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.7.2.tgz", + "integrity": "sha512-7Lcn7IqGMV+vizMPoEl5F0XDshcdDYtMI6uJLQdQz5CfZAwy3vvGKYSUk789qndt5dEC4HfSjviSYlSoHGL2+A==", "engines": { "node": ">=14" } @@ -4936,6 +5112,22 @@ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, + "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/aria-hidden/node_modules/tslib": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", + "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==" + }, "node_modules/aria-query": { "version": "5.1.3", "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz", @@ -5771,6 +5963,11 @@ "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz", "integrity": "sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==" }, + "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/clean-css": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.2.tgz", @@ -8301,6 +8498,44 @@ "url": "https://www.patreon.com/infusion" } }, + "node_modules/framer-motion": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-6.5.1.tgz", + "integrity": "sha512-o1BGqqposwi7cgDrtg0dNONhkmPsUFDaLcKXigzuTFC5x58mE8iyTazxSudFzmT6MEyJKfjjU8ItoMe3W+3fiw==", + "dependencies": { + "@motionone/dom": "10.12.0", + "framesync": "6.0.1", + "hey-listen": "^1.0.8", + "popmotion": "11.0.3", + "style-value-types": "5.0.0", + "tslib": "^2.1.0" + }, + "optionalDependencies": { + "@emotion/is-prop-valid": "^0.8.2" + }, + "peerDependencies": { + "react": ">=16.8 || ^17.0.0 || ^18.0.0", + "react-dom": ">=16.8 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/framer-motion/node_modules/tslib": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", + "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==" + }, + "node_modules/framesync": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/framesync/-/framesync-6.0.1.tgz", + "integrity": "sha512-fUY88kXvGiIItgNC7wcTOl0SNRCVXMKSWW2Yzfmn7EKNc+MpCzcz9DhdHcdjbrtN3c6R4H5dTY2jiCpPdysEjA==", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/framesync/node_modules/tslib": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", + "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==" + }, "node_modules/fresh": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", @@ -8701,6 +8936,11 @@ "he": "bin/he" } }, + "node_modules/hey-listen": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/hey-listen/-/hey-listen-1.0.8.tgz", + "integrity": "sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==" + }, "node_modules/hoist-non-react-statics": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", @@ -11878,6 +12118,11 @@ "tmpl": "1.0.5" } }, + "node_modules/material-ripple-effects": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/material-ripple-effects/-/material-ripple-effects-2.0.1.tgz", + "integrity": "sha512-hHlUkZAuXbP94lu02VgrPidbZ3hBtgXBtjlwR8APNqOIgDZMV8MCIcsclL8FmGJQHvnORyvoQgC965vPsiyXLQ==" + }, "node_modules/mdn-data": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", @@ -12788,6 +13033,22 @@ "node": ">=4" } }, + "node_modules/popmotion": { + "version": "11.0.3", + "resolved": "https://registry.npmjs.org/popmotion/-/popmotion-11.0.3.tgz", + "integrity": "sha512-Y55FLdj3UxkR7Vl3s7Qr4e9m0onSnP8W7d/xQLsoJM40vs6UKHFdygs6SWryasTZYqugMjm3BepCF4CWXDiHgA==", + "dependencies": { + "framesync": "6.0.1", + "hey-listen": "^1.0.8", + "style-value-types": "5.0.0", + "tslib": "^2.1.0" + } + }, + "node_modules/popmotion/node_modules/tslib": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", + "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==" + }, "node_modules/postcss": { "version": "8.4.24", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.24.tgz", @@ -14364,11 +14625,11 @@ } }, "node_modules/react-router": { - "version": "6.12.1", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.12.1.tgz", - "integrity": "sha512-evd/GrKJOeOypD0JB9e1r7pQh2gWCsTbUfq059Wm1AFT/K2MNZuDo19lFtAgIhlBrp0MmpgpqtvZC7LPAs7vSw==", + "version": "6.14.2", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.14.2.tgz", + "integrity": "sha512-09Zss2dE2z+T1D03IheqAFtK4UzQyX8nFPWx6jkwdYzGLXd5ie06A6ezS2fO6zJfEb/SpG6UocN2O1hfD+2urQ==", "dependencies": { - "@remix-run/router": "1.6.3" + "@remix-run/router": "1.7.2" }, "engines": { "node": ">=14" @@ -14378,12 +14639,12 @@ } }, "node_modules/react-router-dom": { - "version": "6.12.1", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.12.1.tgz", - "integrity": "sha512-POIZN9UDKWwEDga054LvYr2KnK8V+0HR4Ny4Bwv8V7/FZCPxJgsCjYxXGxqxzHs7VBxMKZfgvtKhafuJkJSPGA==", + "version": "6.14.2", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.14.2.tgz", + "integrity": "sha512-5pWX0jdKR48XFZBuJqHosX3AAHjRAzygouMTyimnBPOLdY3WjzUSKhus2FVMihUFWzeLebDgr4r8UeQFAct7Bg==", "dependencies": { - "@remix-run/router": "1.6.3", - "react-router": "6.12.1" + "@remix-run/router": "1.7.2", + "react-router": "6.14.2" }, "engines": { "node": ">=14" @@ -15587,6 +15848,20 @@ "webpack": "^5.0.0" } }, + "node_modules/style-value-types": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/style-value-types/-/style-value-types-5.0.0.tgz", + "integrity": "sha512-08yq36Ikn4kx4YU6RD7jWEv27v4V+PUsOGa4n/as8Et3CuODMJQ00ENeAVXAeydX4Z2j1XHZF1K2sX4mGl18fA==", + "dependencies": { + "hey-listen": "^1.0.8", + "tslib": "^2.1.0" + } + }, + "node_modules/style-value-types/node_modules/tslib": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", + "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==" + }, "node_modules/stylehacks": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.1.tgz", @@ -15858,6 +16133,20 @@ "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==" }, + "node_modules/tabbable": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz", + "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==" + }, + "node_modules/tailwind-merge": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-1.14.0.tgz", + "integrity": "sha512-3mFKyCo/MBcgyOTlrY8T7odzZFx+w+qKSMAmdFzRvqBfLlSigU6TZnlFHK0lkMwj9Bj8OYU+9yW9lmGuS0QEnQ==", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/dcastil" + } + }, "node_modules/tailwindcss": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.3.2.tgz", @@ -15895,6 +16184,14 @@ "node": ">=14.0.0" } }, + "node_modules/tailwindcss-animated": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tailwindcss-animated/-/tailwindcss-animated-1.0.1.tgz", + "integrity": "sha512-u5wusj89ZwP8I+s8WZlaAd7aZTWBN/XEG6QgMKpkIKmAf3xP1A6WYf7oYIKmGaB10UAQaSqWopi/i1ozzZEs8Q==", + "peerDependencies": { + "tailwindcss": ">=3.1.0" + } + }, "node_modules/tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", diff --git a/package.json b/package.json index 1b69b34..334c917 100644 --- a/package.json +++ b/package.json @@ -7,6 +7,7 @@ "@fortawesome/free-brands-svg-icons": "^6.4.0", "@fortawesome/free-solid-svg-icons": "^6.4.0", "@fortawesome/react-fontawesome": "^0.2.0", + "@material-tailwind/react": "^2.0.6", "@testing-library/jest-dom": "^5.16.5", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", @@ -20,8 +21,9 @@ "react-dom": "^18.2.0", "react-hot-toast": "^2.4.0", "react-icons": "^4.8.0", - "react-router-dom": "^6.10.0", + "react-router-dom": "^6.14.2", "react-scripts": "5.0.1", + "tailwindcss-animated": "^1.0.1", "web-vitals": "^2.1.4", "yup": "^1.0.2" }, diff --git a/public/favicon.ico b/public/favicon.ico index a11777c..c5437c7 100644 Binary files a/public/favicon.ico and b/public/favicon.ico differ diff --git a/src/App.js b/src/App.js index 421cfd1..a604abb 100644 --- a/src/App.js +++ b/src/App.js @@ -7,27 +7,19 @@ import Login from "./components/Login/Login"; import RequiresAuth from "./components/RequiresAuth"; import { HomePageUser } from "./pages/HomePageUser"; import Navbar from "./components/Navbar/Navbar"; -import { useLocation } from "react-router-dom"; import ContactForm from "./pages/Contact"; -function App() { - const location = useLocation(); - const isLoginPage = location.pathname === "/login"; +import { Carousel } from "./components/Carousel/Carousel"; + +function App() { return ( - -
+
+ {/* Public routes */} - } /> + } /> } /> } /> } /> diff --git a/src/api/posts.js b/src/api/posts.js index 428e75b..1046063 100644 --- a/src/api/posts.js +++ b/src/api/posts.js @@ -1,7 +1,13 @@ import axios from "axios"; +const PostUrl = process.env.REACT_APP_POST_URL; +const UpdatePost = process.env.REACT_APP_UPDATE_POST; +const DeletePost = process.env.REACT_APP_POST_DELETE; +const PostId = process.env.REACT_APP_POST_ID; + + export const getPostsRequest = async () => - await axios.get("http://localhost:4000/api/posts", {}); + await axios.get(PostUrl, {}); export const createPostRequest = async (post, token) => { const form = new FormData(); @@ -10,28 +16,27 @@ export const createPostRequest = async (post, token) => { form.append(key, post[key]); } - return await axios.post("http://localhost:4000/api/posts", form, { + return await axios.post(PostUrl, form, { headers: { "Content-Type": "multipart/form-data", - // eslint-disable-next-line no-template-curly-in-string + Authorization: `Bearer ${token}`, }, }); }; export const deletePostRequest = async (id, token) => - await axios.delete("http://localhost:4000/api/posts/" + id, { + await axios.delete(DeletePost + id, { headers: { Authorization: `Bearer ${token}`, }, }); export const getPostRequest = async (id) => - await axios.get("http://localhost:4000/api/posts/" + id); - -export const updatePostRequest = async (id, newFields, token) => - await axios.put(`http://localhost:4000/api/posts/${id}`, newFields, { + await axios.get(PostId + id); + export const updatePostRequest = async (id, newFields, token) => + await axios.put(`${UpdatePost}/${id}`, newFields, { headers: { Authorization: `Bearer ${token}`, }, - }); + }); \ No newline at end of file diff --git a/src/components/Carousel/Carousel.jsx b/src/components/Carousel/Carousel.jsx new file mode 100644 index 0000000..9c7e90a --- /dev/null +++ b/src/components/Carousel/Carousel.jsx @@ -0,0 +1,74 @@ +import React, { useState } from "react"; +import { BsChevronCompactLeft, BsChevronCompactRight } from "react-icons/bs"; +import { RxDotFilled } from "react-icons/rx"; +import { useLocation } from "react-router-dom"; +export function Carousel() { + const slides = [ + { + url: "https://i2.wp.com/www.revistamercado.do/wp-content/uploads/2021/08/Mano-humana-y-robo%CC%81tica-tocan-un-cerebro-digital-1.jpg?w=1280&ssl=1", + }, + { + url: "https://i1.wp.com/www.revistamercado.do/wp-content/uploads/2021/08/Steve-Jobs-presenta-el-primer-iPhone-en-2007-1.jpg?w=1280&ssl=1", + }, + { + url: "https://i2.wp.com/www.revistamercado.do/wp-content/uploads/2021/08/Mujer-immersa-en-videojuego-con-realidad-virtual.jpg?w=1280&ssl=1", + }, + + { + url: "https://images.unsplash.com/photo-1512756290469-ec264b7fbf87?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2253&q=80", + }, + { + url: "https://i2.wp.com/www.revistamercado.do/wp-content/uploads/2021/08/Coche-auto%CC%81nomo-con-HUD-Head-Up-Display.-Vehi%CC%81culo-auto%CC%81nomo-en-las-calles-de-la-ciudad.png?w=1280&ssl=1", + }, + ]; + + const [currentIndex, setCurrentIndex] = useState(0); + + const prevSlide = () => { + const isFirstSlide = currentIndex === 0; + const newIndex = isFirstSlide ? slides.length - 1 : currentIndex - 1; + setCurrentIndex(newIndex); + }; + + const nextSlide = () => { + const isLastSlide = currentIndex === slides.length - 1; + const newIndex = isLastSlide ? 0 : currentIndex + 1; + setCurrentIndex(newIndex); + }; + + const goToSlide = (slideIndex) => { + setCurrentIndex(slideIndex); + }; + const location = useLocation(); + const isHomePage = location.pathname === "/"; + if (!isHomePage) { + return null; + } + return ( +
+
+ +
+ +
+ +
+ +
+
+ {slides.map((slide, slideIndex) => ( +
goToSlide(slideIndex)} + className="text-2xl cursor-pointer" + > + +
+ ))} +
+
+ ); +} diff --git a/src/components/Login/Login.jsx b/src/components/Login/Login.jsx index 9ba4e2d..eb47b3a 100644 --- a/src/components/Login/Login.jsx +++ b/src/components/Login/Login.jsx @@ -1,55 +1,26 @@ -import { useState } from "react"; -import useAuth from "../../hooks/useAuth"; -import axios from "axios"; -import { useLocation, useNavigate } from "react-router-dom"; -import backgroundImage from '../../Images/logoimg.jpg' -const Signin = () => { - const [data, setData] = useState({ - email: "", - password: "", - }); - const [error, setError] = useState(""); - - const { setAuth } = useAuth(); - const location = useLocation(); - const navigate = useNavigate(); - const from = location.state?.from?.pathname || "/"; - - +import backgroundImage from "../../Images/logoimg.jpg"; +import useLoginForm from "../../hooks/useLoginForm"; +import useAuthentication from "../../hooks/useAuthentication"; - const handleChange = ({ currentTarget: input }) => { - setData({ ...data, [input.name]: input.value }); - }; +const Signin = () => { + const { data, error, handleChange, setError } = useLoginForm(); + const { authenticate } = useAuthentication(); const handleSubmit = async (e) => { e.preventDefault(); - try { - const url = "http://localhost:4000/api/auth/signin"; - const { data: res } = await axios.post(url, data); - const roles = res?.roles; - const token = res?.token; - setAuth({ roles, token }); - - console.log(roles); - - navigate(from, { replace: true }); - } catch (error) { - if ( - error.response && - error.response.status >= 400 && - error.response.status <= 500 - ) { - setError(error.response.data.message); - } + const errorMessage = await authenticate(data); + if (errorMessage) { + setError(errorMessage); } }; + return (
+ >

TechTalk News

diff --git a/src/components/Navbar/Navbar.jsx b/src/components/Navbar/Navbar.jsx index a436255..0497621 100644 --- a/src/components/Navbar/Navbar.jsx +++ b/src/components/Navbar/Navbar.jsx @@ -1,72 +1,105 @@ -import React, { useState } from 'react'; -import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { faSignOutAlt } from '@fortawesome/free-solid-svg-icons'; -import { Link, useLocation } from 'react-router-dom'; +import React, { useState } from "react"; +import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { faSignOutAlt } from "@fortawesome/free-solid-svg-icons"; +import { Link, useLocation } from "react-router-dom"; import useAuth from "../../hooks/useAuth"; const Navbar = () => { const location = useLocation(); - const isLoginPage = location.pathname === '/login'; - const { setAuth, auth } = useAuth(); + const isLoginPage = location.pathname === "/login"; + const isHomePage = location.pathname === "/"; + const isFormPage = location.pathname === "/new"; + const isAdminPage = location.pathname === "/admin"; + const { setAuth, auth } = useAuth(); const handleLogout = () => { setAuth({ roles: null, token: null }); window.location = "/login"; }; - const [open, setOpen] = useState(true); + const [open, setOpen] = useState(false); const toggleMenu = () => { setOpen(!open); }; return ( -
+
-
+
- + TechTalk News -
-