diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index b3f86d4..653c2bb 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -42,7 +42,7 @@ function App() { } /> } /> - }> + }> }> } /> diff --git a/frontend/src/components/Auth/PasswordResetForm.tsx b/frontend/src/components/Auth/PasswordResetForm.tsx new file mode 100644 index 0000000..39c9d42 --- /dev/null +++ b/frontend/src/components/Auth/PasswordResetForm.tsx @@ -0,0 +1,122 @@ +import React, { useState } from "react"; +import Input from "../Layout/Input"; +import Button from "../Layout/Button"; +import { useAuth } from "../../context/AuthContext"; + +interface ResetPasswordData { + newPassword: string; + confirmNewPassword: string; +} + +interface ResetPasswordErrors { + newPasswordError?: string; + confirmNewPasswordError?: string; +} + +interface SubmitProps { + onSubmit: () => void; +} + +const PasswordResetForm: React.FC = ({ onSubmit }) => { + + const [errors, setErrors] = useState({}); + + const [resetData, setResetData] = useState({ + newPassword: "", + confirmNewPassword: "", + }); + + const confirmPasswordReset = () => { + alert('Password reset successfully!'); + // You can replace this with navigation or API success handling logic + }; + + const handlePasswordChange = (e: React.ChangeEvent) => { + const { name, value } = e.target; + setResetData((prev) => ({ + ...prev, + [name]: value, + })); + }; + + const validateResetForm = (): boolean => { + const newErrors: ResetPasswordErrors = {}; + + Object.keys(resetData).forEach((key) => { + if (!resetData[key as keyof ResetPasswordData]) { + newErrors[key as keyof ResetPasswordErrors] = "Confirm your password"; + } + }); + + if (resetData.newPassword !== resetData.confirmNewPassword) { + newErrors.confirmNewPasswordError = "Passwords do not match"; + } + + + setErrors(newErrors); + return Object.keys(newErrors).length === 0; + }; + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault(); + onSubmit(); + + if (validateResetForm()) { + try { + const response = await fetch("/user/reset_password//", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + credentials: "include", + body: JSON.stringify(resetData), + }); + + if (!response.ok) { + const data = await response.json(); + throw new Error(data.message || "An error has occurred while resetting"); + } + } catch (error: any) { + console.error("Password reset error:", error.message); + setErrors((prev) => ({ + ...prev, + general: error.message || "An unexpected error occurred.", + + })); + confirmPasswordReset(); + } + } +}; + + return ( + +
+ + + {errors.confirmNewPasswordError && ( +

{errors.confirmNewPasswordError}

+ )} + + + + +
+ + ); +}; + +export default PasswordResetForm \ No newline at end of file diff --git a/frontend/src/components/Checkout/CheckoutForm.tsx b/frontend/src/components/Checkout/CheckoutForm.tsx index 00e4a8c..d759d58 100644 --- a/frontend/src/components/Checkout/CheckoutForm.tsx +++ b/frontend/src/components/Checkout/CheckoutForm.tsx @@ -82,7 +82,7 @@ const CheckoutForm: React.FC = ({ onClose }) => { ✕
diff --git a/frontend/src/pages/ForgotPasswordPage.tsx b/frontend/src/pages/ForgotPasswordPage.tsx index 42474d5..f61348d 100644 --- a/frontend/src/pages/ForgotPasswordPage.tsx +++ b/frontend/src/pages/ForgotPasswordPage.tsx @@ -1,9 +1,15 @@ -import React from 'react' +import React from 'react'; +import PasswordResetForm from '../components/Auth/PasswordResetForm'; + +const ForgotPasswordPage: React.FC = () => { + const doNothing = (): void => {}; -const ForgotPasswordPage = () => { return ( -
ForgotPasswordPage
- ) -} +
+

Forgot Password

+ +
+ ); +}; -export default ForgotPasswordPage \ No newline at end of file +export default ForgotPasswordPage; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..b34b42b --- /dev/null +++ b/package-lock.json @@ -0,0 +1,28 @@ +{ + "name": "cs3305-team11", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "tailwind-scrollbar-hide": "^2.0.0" + } + }, + "node_modules/tailwind-scrollbar-hide": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/tailwind-scrollbar-hide/-/tailwind-scrollbar-hide-2.0.0.tgz", + "integrity": "sha512-lqiIutHliEiODwBRHy4G2+Tcayo2U7+3+4frBmoMETD72qtah+XhOk5XcPzC1nJvXhXUdfl2ajlMhUc2qC6CIg==", + "license": "MIT", + "peerDependencies": { + "tailwindcss": ">=3.0.0 || >= 4.0.0 || >= 4.0.0-beta.8 || >= 4.0.0-alpha.20" + } + }, + "node_modules/tailwindcss": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.0.3.tgz", + "integrity": "sha512-ImmZF0Lon5RrQpsEAKGxRvHwCvMgSC4XVlFRqmbzTEDb/3wvin9zfEZrMwgsa3yqBbPqahYcVI6lulM2S7IZAA==", + "license": "MIT", + "peer": true + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..ac42183 --- /dev/null +++ b/package.json @@ -0,0 +1,5 @@ +{ + "dependencies": { + "tailwind-scrollbar-hide": "^2.0.0" + } +}