From 969cb00b04a5f594c538fa75ea664465aa919f4f Mon Sep 17 00:00:00 2001 From: Nafiu Taiwo Date: Thu, 25 Jul 2024 23:21:25 +0100 Subject: [PATCH 1/2] feat: password settings page --- .../_components/layout/navbar/index.tsx | 2 +- .../account/_component.tsx/password.tsx | 52 +++++++++ .../settings/account/page.tsx | 8 +- .../notification-settings-saved/index.tsx | 50 +++++++++ .../modals/password-successful/index.tsx | 50 +++++++++ .../common/password-check/index.tsx | 104 ++++++++++++++++++ .../common/password-input/index.tsx | 57 ++++++++++ 7 files changed, 321 insertions(+), 2 deletions(-) create mode 100644 src/app/dashboard/(user-dashboard)/settings/account/_component.tsx/password.tsx create mode 100644 src/components/common/modals/notification-settings-saved/index.tsx create mode 100644 src/components/common/modals/password-successful/index.tsx create mode 100644 src/components/common/password-check/index.tsx create mode 100644 src/components/common/password-input/index.tsx diff --git a/src/app/dashboard/(user-dashboard)/_components/layout/navbar/index.tsx b/src/app/dashboard/(user-dashboard)/_components/layout/navbar/index.tsx index c6c5d6c9c..935806e9c 100644 --- a/src/app/dashboard/(user-dashboard)/_components/layout/navbar/index.tsx +++ b/src/app/dashboard/(user-dashboard)/_components/layout/navbar/index.tsx @@ -56,7 +56,7 @@ const UserNavbar = () => { -
+
{navlinks.map((item, index) => ( { + const [open, setOpen] = useState(false); + return ( +
+
+

+ Password Settings +

+

+ Update password for enhanced account security +

+
+
+
+ + + +
+
+ Cancel + Update Password +
+
+ +
+ ); +}; + +export default Password; diff --git a/src/app/dashboard/(user-dashboard)/settings/account/page.tsx b/src/app/dashboard/(user-dashboard)/settings/account/page.tsx index db4d38750..3932937fa 100644 --- a/src/app/dashboard/(user-dashboard)/settings/account/page.tsx +++ b/src/app/dashboard/(user-dashboard)/settings/account/page.tsx @@ -1,5 +1,11 @@ +import PasswordSettings from "./_component.tsx/password"; + const page = () => { - return
page
; + return ( +
+ +
+ ); }; export default page; diff --git a/src/components/common/modals/notification-settings-saved/index.tsx b/src/components/common/modals/notification-settings-saved/index.tsx new file mode 100644 index 000000000..b46652e1b --- /dev/null +++ b/src/components/common/modals/notification-settings-saved/index.tsx @@ -0,0 +1,50 @@ +"use client"; + +import React from "react"; + +import CustomButton from "~/components/common/common-button/common-button"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogOverlay, + DialogTitle, +} from "~/components/ui/dialog"; + +interface ModalProperties { + show: boolean; + onClose: () => void; +} + +const NotificationSettingSavedModal: React.FC = ({ + show, + onClose, +}) => { + return ( + + + event.stopPropagation()} + > + + Notification Updated! + + + Notification preferences updated successfully. Remember, you can + always adjust these settings later. + +
+
+ Done +
+
+
+
+ ); +}; + +export default NotificationSettingSavedModal; diff --git a/src/components/common/modals/password-successful/index.tsx b/src/components/common/modals/password-successful/index.tsx new file mode 100644 index 000000000..450486634 --- /dev/null +++ b/src/components/common/modals/password-successful/index.tsx @@ -0,0 +1,50 @@ +"use client"; + +import React, { Dispatch, SetStateAction } from "react"; + +import CustomButton from "~/components/common/common-button/common-button"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogOverlay, + DialogTitle, +} from "~/components/ui/dialog"; + +interface ModalProperties { + show: boolean; + onClose: Dispatch>; +} + +const PasswordSuccessfulModal: React.FC = ({ + show, + onClose, +}) => { + return ( + + + event.stopPropagation()} + > + + Password Successfully Updated! + + + Your password has been successfully updated! You can now log in with + your new password. + +
+
onClose(!show)}> + Continue +
+
+
+
+ ); +}; + +export default PasswordSuccessfulModal; diff --git a/src/components/common/password-check/index.tsx b/src/components/common/password-check/index.tsx new file mode 100644 index 000000000..27c1489d8 --- /dev/null +++ b/src/components/common/password-check/index.tsx @@ -0,0 +1,104 @@ +"use client"; + +import { CircleCheck } from "lucide-react"; +import React, { useEffect, useState } from "react"; + +interface PasswordCheckProperties { + minLength: number; + password: string; + onStrengthChange: (strength: PasswordCheck) => void; +} + +interface PasswordCheck { + minLengthCheck: boolean; + containsUppercase: boolean; + containNumber: boolean; +} + +const handlerContainsNumber = (value: string) => { + const regex = /\d/; + return regex.test(value); +}; + +const handleContainsUpperCase = (value: string) => { + const regex = /[A-Z]/; + return regex.test(value); +}; + +const PasswordCheck: React.FC = ({ + password, + minLength, + onStrengthChange, +}) => { + const [checkPassword, setCheckPassword] = useState({ + minLengthCheck: false, + containsUppercase: false, + containNumber: false, + }); + + useEffect(() => { + const handleCheckPassword = (password: string) => { + const containsUpperCase = handleContainsUpperCase(password); + const containsNumber = handlerContainsNumber(password); + const minLengthCheck = password.length >= minLength; + + const newStrength: PasswordCheck = { + minLengthCheck, + containsUppercase: containsUpperCase, + containNumber: containsNumber, + }; + + setCheckPassword(newStrength); + onStrengthChange(newStrength); + }; + handleCheckPassword(password); + }, [password, minLength, onStrengthChange]); + + return ( +
+
+
+
+
+
+
+

Weak password. Must contain:

+
+ +

At least 1 uppercase

+
+
+ +

At least 1 number

+
+
+ +

At least {minLength} characters

+
+
+
+ ); +}; + +export default PasswordCheck; diff --git a/src/components/common/password-input/index.tsx b/src/components/common/password-input/index.tsx new file mode 100644 index 000000000..5f87dee32 --- /dev/null +++ b/src/components/common/password-input/index.tsx @@ -0,0 +1,57 @@ +"use client"; + +import { EyeIcon, EyeOff } from "lucide-react"; +import { useState } from "react"; + +import { Input } from "~/components/ui/input"; + +interface PasswordToggleProperties { + password: string; + onPasswordChange: (password: string) => void; + name: string; + placeholder: string; + id: string; +} + +const PasswordInput: React.FC = ({ + password, + onPasswordChange, + name, + id, + placeholder, +}) => { + const [isPasswordHidden, setPasswordHidden] = useState(true); + + const handleChange = (event: React.ChangeEvent) => { + onPasswordChange(event.target.value); + }; + + return ( +
+
+ + + +
+
+ ); +}; + +export { PasswordInput }; From ff6ea2f1b98091db913a5d78e843f76d058b56ab Mon Sep 17 00:00:00 2001 From: Nafiu Taiwo Date: Thu, 25 Jul 2024 23:44:22 +0100 Subject: [PATCH 2/2] feat: password settings page --- .../settings/account/_component.tsx/password.tsx | 10 +++++++--- .../common/modals/password-successful/index.tsx | 6 +++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/app/dashboard/(user-dashboard)/settings/account/_component.tsx/password.tsx b/src/app/dashboard/(user-dashboard)/settings/account/_component.tsx/password.tsx index e01becb3d..e72a0c5ad 100644 --- a/src/app/dashboard/(user-dashboard)/settings/account/_component.tsx/password.tsx +++ b/src/app/dashboard/(user-dashboard)/settings/account/_component.tsx/password.tsx @@ -40,11 +40,15 @@ const Password = () => { />
- Cancel - Update Password + setOpen(false)}> + Cancel + + setOpen(true)}> + Update Password +
- + setOpen(!open)} show={open} /> ); }; diff --git a/src/components/common/modals/password-successful/index.tsx b/src/components/common/modals/password-successful/index.tsx index 450486634..6b7446fa3 100644 --- a/src/components/common/modals/password-successful/index.tsx +++ b/src/components/common/modals/password-successful/index.tsx @@ -1,6 +1,6 @@ "use client"; -import React, { Dispatch, SetStateAction } from "react"; +import React from "react"; import CustomButton from "~/components/common/common-button/common-button"; import { @@ -13,7 +13,7 @@ import { interface ModalProperties { show: boolean; - onClose: Dispatch>; + onClose: () => void; } const PasswordSuccessfulModal: React.FC = ({ @@ -38,7 +38,7 @@ const PasswordSuccessfulModal: React.FC = ({ your new password.
-
onClose(!show)}> +
Continue