From 7dbdfca4a404a247d3c8b0fbb99022c8fa9c49ef Mon Sep 17 00:00:00 2001 From: codegod3333 Date: Sat, 28 Dec 2024 11:43:40 +0300 Subject: [PATCH 1/4] =?UTF-8?q?=E2=9C=A8=20Add=20Contact=20component=20wit?= =?UTF-8?q?h=20form=20handling,=20toast=20notifications,=20and=20=E2=98=81?= =?UTF-8?q?=EF=B8=8F=20Google=20Login=20integration=20in=20the=20login=20f?= =?UTF-8?q?orm?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/package-lock.json | 129 ++++++++++++++++------- frontend/package.json | 2 + frontend/pages/auth/login.jsx | 174 ++++++++++++++++++------------- frontend/pages/contact/index.jsx | 159 ++++++++++++++++++++++++++++ 4 files changed, 350 insertions(+), 114 deletions(-) create mode 100644 frontend/pages/contact/index.jsx diff --git a/frontend/package-lock.json b/frontend/package-lock.json index b4e1fea..2ba3ccf 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -13,11 +13,13 @@ "js-cookie": "^3.0.1", "next": "14.0.0", "nprogress": "^0.2.0", - "react": "17.0.2", - "react-dom": "17.0.2", + "react": "^18.2.0", + "react-dom": "18.2.0", "react-hook-form": "^7.17.5", + "react-icons": "^5.4.0", "react-redux": "^7.2.5", "react-toast-notifications": "^2.5.1", + "react-toastify": "^11.0.2", "underscore": "^1.13.1" }, "devDependencies": { @@ -1220,6 +1222,15 @@ "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/color": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/color/-/color-4.0.1.tgz", @@ -1486,6 +1497,7 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", + "license": "MIT", "dependencies": { "@babel/runtime": "^7.8.7", "csstype": "^3.0.2" @@ -3957,28 +3969,28 @@ } }, "node_modules/react": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", - "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==", + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "license": "MIT", "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" + "loose-envify": "^1.1.0" }, "engines": { "node": ">=0.10.0" } }, "node_modules/react-dom": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz", - "integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==", + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", + "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "license": "MIT", "dependencies": { "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "scheduler": "^0.20.2" + "scheduler": "^0.23.0" }, "peerDependencies": { - "react": "17.0.2" + "react": "^18.2.0" } }, "node_modules/react-hook-form": { @@ -3993,6 +4005,15 @@ "react": "^16.8.0 || ^17" } }, + "node_modules/react-icons": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.4.0.tgz", + "integrity": "sha512-7eltJxgVt7X64oHh6wSWNwwbKTCtMfK35hcjvJS0yxEAhPM8oUKdS3+kqaW1vicIltw+kR2unHaa12S9pPALoQ==", + "license": "MIT", + "peerDependencies": { + "react": "*" + } + }, "node_modules/react-redux": { "version": "7.2.5", "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.5.tgz", @@ -4035,10 +4056,24 @@ "react-dom": "^16.8.0 || ^17.0.0" } }, + "node_modules/react-toastify": { + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-11.0.2.tgz", + "integrity": "sha512-GjHuGaiXMvbls3ywqv8XdWONwrcO4DXCJIY1zVLkHU73gEElKvTTXNI5Vom3s/k/M8hnkrfsqgBSX3OwmlonbA==", + "license": "MIT", + "dependencies": { + "clsx": "^2.1.1" + }, + "peerDependencies": { + "react": "^18 || ^19", + "react-dom": "^18 || ^19" + } + }, "node_modules/react-transition-group": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.2.tgz", - "integrity": "sha512-/RNYfRAMlZwDSr6z4zNKV6xu53/e2BuaBbGhbyYIXTrmgu/bGHzmqOs7mJSJBHy9Ud+ApHx3QjrkKSp1pxvlFg==", + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", + "license": "BSD-3-Clause", "dependencies": { "@babel/runtime": "^7.5.5", "dom-helpers": "^5.0.1", @@ -4313,12 +4348,12 @@ } }, "node_modules/scheduler": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", - "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "license": "MIT", "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" + "loose-envify": "^1.1.0" } }, "node_modules/semver": { @@ -5959,6 +5994,11 @@ "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==" }, + "clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==" + }, "color": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/color/-/color-4.0.1.tgz", @@ -8007,22 +8047,20 @@ "dev": true }, "react": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", - "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==", + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" + "loose-envify": "^1.1.0" } }, "react-dom": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz", - "integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==", + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", + "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", "requires": { "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "scheduler": "^0.20.2" + "scheduler": "^0.23.0" } }, "react-hook-form": { @@ -8031,6 +8069,12 @@ "integrity": "sha512-4bPtPGkpVhZlgtTbtMGi0RFphKHgxCj5u3AsGz3SBdleELlG1pDf9zRQOtfGlOGkZlc7u78RzD0xu9kOw7PYdQ==", "requires": {} }, + "react-icons": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.4.0.tgz", + "integrity": "sha512-7eltJxgVt7X64oHh6wSWNwwbKTCtMfK35hcjvJS0yxEAhPM8oUKdS3+kqaW1vicIltw+kR2unHaa12S9pPALoQ==", + "requires": {} + }, "react-redux": { "version": "7.2.5", "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.5.tgz", @@ -8060,10 +8104,18 @@ "react-transition-group": "^4.4.1" } }, + "react-toastify": { + "version": "11.0.2", + "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-11.0.2.tgz", + "integrity": "sha512-GjHuGaiXMvbls3ywqv8XdWONwrcO4DXCJIY1zVLkHU73gEElKvTTXNI5Vom3s/k/M8hnkrfsqgBSX3OwmlonbA==", + "requires": { + "clsx": "^2.1.1" + } + }, "react-transition-group": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.2.tgz", - "integrity": "sha512-/RNYfRAMlZwDSr6z4zNKV6xu53/e2BuaBbGhbyYIXTrmgu/bGHzmqOs7mJSJBHy9Ud+ApHx3QjrkKSp1pxvlFg==", + "version": "4.4.5", + "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", + "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", "requires": { "@babel/runtime": "^7.5.5", "dom-helpers": "^5.0.1", @@ -8268,12 +8320,11 @@ } }, "scheduler": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", - "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1" + "loose-envify": "^1.1.0" } }, "semver": { diff --git a/frontend/package.json b/frontend/package.json index 5940388..a672b24 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -17,8 +17,10 @@ "react": "^18.2.0", "react-dom": "18.2.0", "react-hook-form": "^7.17.5", + "react-icons": "^5.4.0", "react-redux": "^7.2.5", "react-toast-notifications": "^2.5.1", + "react-toastify": "^11.0.2", "underscore": "^1.13.1" }, "devDependencies": { diff --git a/frontend/pages/auth/login.jsx b/frontend/pages/auth/login.jsx index 691da0c..a281f8f 100644 --- a/frontend/pages/auth/login.jsx +++ b/frontend/pages/auth/login.jsx @@ -1,4 +1,4 @@ -import Link from "next/link" +import Link from "next/link"; import { useRouter } from 'next/router'; import React from "react"; import { useForm } from "react-hook-form"; @@ -7,86 +7,110 @@ import { useToasts } from 'react-toast-notifications'; import { callLoginAPI } from 'services/auth.service'; import { saveToken } from 'store/modules/auth'; import { removeToken, setToken } from 'Utils/token'; - +import { FcGoogle } from "react-icons/fc"; // Import React icons const Login = () => { - const router = useRouter() - const { addToast } = useToasts() - const dispatch = useDispatch() - const { register, handleSubmit, formState: { errors } } = useForm(); + const router = useRouter(); + const { addToast } = useToasts(); + const dispatch = useDispatch(); + const { register, handleSubmit, formState: { errors } } = useForm(); - const onSubmit = async (input) => { - const { status, data } = await callLoginAPI(input); - if (status === 401 || status === 400) { - removeToken(null) - addToast(data.detail, { appearance: 'error', autoDismiss: true }) - } else { - setToken(data.access) - dispatch(saveToken(data.access)) - addToast("Login Success!", { appearance: 'success', autoDismiss: true }) - router.push('/') - } - }; + const onSubmit = async (input) => { + const { status, data } = await callLoginAPI(input); + if (status === 401 || status === 400) { + removeToken(null); + addToast(data.detail, { appearance: 'error', autoDismiss: true }); + } else { + setToken(data.access); + dispatch(saveToken(data.access)); + addToast("Login Success!", { appearance: 'success', autoDismiss: true }); + router.push('/'); + } + }; - return ( -
-
-
+ return ( +
+
+
+
+
+

Welcome Back!

+ Login here to explore more! +
+
+
+ + + {errors.username && {errors.username.message}}
-
-
-
-

Welcome Back !

- Login here to explore more! -
-
- {/* {error && ( - {error} - )} */} - - -
- - - {errors.username && {errors.username.message}} -
-
- - - {errors.password && {errors.password.message}} -
-
- - - - Are you aready registred user? - -
- -
-
+
+ + + {errors.password && {errors.password.message}} +
+
+ + + Are you already registered? +
+ +

+ By signing in, you agree to our{" "} + + Terms of Service + {" "} + and{" "} + + Privacy Policy + . +

+
+
- ); -} +
+
+ ); +}; -export default Login; \ No newline at end of file +export default Login; diff --git a/frontend/pages/contact/index.jsx b/frontend/pages/contact/index.jsx new file mode 100644 index 0000000..a1dcbf6 --- /dev/null +++ b/frontend/pages/contact/index.jsx @@ -0,0 +1,159 @@ +'use client'; + +import React, { useState } from "react"; +import { IoLocation } from "react-icons/io5"; +import { MdMarkEmailRead } from "react-icons/md"; +import { FaPhone } from "react-icons/fa"; +import { toast, ToastContainer } from "react-toastify"; +import "react-toastify/dist/ReactToastify.css"; + +const Contact = () => { + const [formData, setFormData] = useState({ + name: "", + email: "", + message: "", + }); + const [loading, setLoading] = useState(false); + + const handleChange = (e) => { + const { name, value } = e.target; + setFormData((prevData) => ({ ...prevData, [name]: value })); + }; + + const handleSubmit = async (e) => { + e.preventDefault(); + setLoading(true); + + try { + const response = await fetch("/api/contact", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify(formData), + }); + + if (response.ok) { + toast.success("Message sent successfully!"); + setFormData({ name: "", email: "", message: "" }); + } else { + toast.error("An error occurred, please try again."); + } + } catch (error) { + toast.error("An error occurred, please try again."); + console.error(error); + } finally { + setLoading(false); + } + }; + + return ( +
+

+ Get In Touch +

+ +
+ Contact Us + +
+

+ We're Here to Help +

+

+ Have questions about our products, need help with an order, or want to provide feedback? Our team is here to assist you. +

+
+ +

support@ecommerce.com

+
+
+ +

+123 456 7890

+
+
+ +

123 E-Commerce St, Shop City, EC 12345

+
+
+
+ +
+
+
+ + +
+
+ + +
+
+ +