[WEB-1330] chore: show password toggle improvement (#4471)

* chore: show password toggle improvement

* fix: merge conflict
This commit is contained in:
Anmol Singh Bhatia 2024-05-17 15:51:34 +05:30 committed by GitHub
parent 8d860396bd
commit 38f5ecbdf2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 60 additions and 36 deletions

View File

@ -64,13 +64,19 @@ export const InstanceSetupForm: FC = (props) => {
const errorCode = searchParams.get("error_code") || undefined; const errorCode = searchParams.get("error_code") || undefined;
const errorMessage = searchParams.get("error_message") || undefined; const errorMessage = searchParams.get("error_message") || undefined;
// state // state
const [showPassword, setShowPassword] = useState(false); const [showPassword, setShowPassword] = useState({
password: false,
retypePassword: false,
});
const [csrfToken, setCsrfToken] = useState<string | undefined>(undefined); const [csrfToken, setCsrfToken] = useState<string | undefined>(undefined);
const [formData, setFormData] = useState<TFormData>(defaultFromData); const [formData, setFormData] = useState<TFormData>(defaultFromData);
const [isPasswordInputFocused, setIsPasswordInputFocused] = useState(false); const [isPasswordInputFocused, setIsPasswordInputFocused] = useState(false);
const [isSubmitting, setIsSubmitting] = useState(false); const [isSubmitting, setIsSubmitting] = useState(false);
const [isRetryPasswordInputFocused, setIsRetryPasswordInputFocused] = useState(false); const [isRetryPasswordInputFocused, setIsRetryPasswordInputFocused] = useState(false);
const handleShowPassword = (key: keyof typeof showPassword) =>
setShowPassword((prev) => ({ ...prev, [key]: !prev[key] }));
const handleFormChange = (key: keyof TFormData, value: string | boolean) => const handleFormChange = (key: keyof TFormData, value: string | boolean) =>
setFormData((prev) => ({ ...prev, [key]: value })); setFormData((prev) => ({ ...prev, [key]: value }));
@ -228,7 +234,7 @@ export const InstanceSetupForm: FC = (props) => {
className="w-full border border-onboarding-border-100 !bg-onboarding-background-200 placeholder:text-onboarding-text-400" className="w-full border border-onboarding-border-100 !bg-onboarding-background-200 placeholder:text-onboarding-text-400"
id="password" id="password"
name="password" name="password"
type={showPassword ? "text" : "password"} type={showPassword.password ? "text" : "password"}
inputSize="md" inputSize="md"
placeholder="New password..." placeholder="New password..."
value={formData.password} value={formData.password}
@ -237,12 +243,12 @@ export const InstanceSetupForm: FC = (props) => {
onFocus={() => setIsPasswordInputFocused(true)} onFocus={() => setIsPasswordInputFocused(true)}
onBlur={() => setIsPasswordInputFocused(false)} onBlur={() => setIsPasswordInputFocused(false)}
/> />
{showPassword ? ( {showPassword.password ? (
<button <button
type="button" type="button"
tabIndex={-1} tabIndex={-1}
className="absolute right-3 top-3.5 flex items-center justify-center text-custom-text-400" className="absolute right-3 top-3.5 flex items-center justify-center text-custom-text-400"
onClick={() => setShowPassword(false)} onClick={() => handleShowPassword("password")}
> >
<EyeOff className="h-4 w-4" /> <EyeOff className="h-4 w-4" />
</button> </button>
@ -251,7 +257,7 @@ export const InstanceSetupForm: FC = (props) => {
type="button" type="button"
tabIndex={-1} tabIndex={-1}
className="absolute right-3 top-3.5 flex items-center justify-center text-custom-text-400" className="absolute right-3 top-3.5 flex items-center justify-center text-custom-text-400"
onClick={() => setShowPassword(true)} onClick={() => handleShowPassword("password")}
> >
<Eye className="h-4 w-4" /> <Eye className="h-4 w-4" />
</button> </button>
@ -269,7 +275,7 @@ export const InstanceSetupForm: FC = (props) => {
</label> </label>
<div className="relative"> <div className="relative">
<Input <Input
type={showPassword ? "text" : "password"} type={showPassword.retypePassword ? "text" : "password"}
id="confirm_password" id="confirm_password"
name="confirm_password" name="confirm_password"
inputSize="md" inputSize="md"
@ -280,12 +286,12 @@ export const InstanceSetupForm: FC = (props) => {
onFocus={() => setIsRetryPasswordInputFocused(true)} onFocus={() => setIsRetryPasswordInputFocused(true)}
onBlur={() => setIsRetryPasswordInputFocused(false)} onBlur={() => setIsRetryPasswordInputFocused(false)}
/> />
{showPassword ? ( {showPassword.retypePassword ? (
<button <button
type="button" type="button"
tabIndex={-1} tabIndex={-1}
className="absolute right-3 top-3.5 flex items-center justify-center text-custom-text-400" className="absolute right-3 top-3.5 flex items-center justify-center text-custom-text-400"
onClick={() => setShowPassword(false)} onClick={() => handleShowPassword("retypePassword")}
> >
<EyeOff className="h-4 w-4" /> <EyeOff className="h-4 w-4" />
</button> </button>
@ -294,7 +300,7 @@ export const InstanceSetupForm: FC = (props) => {
type="button" type="button"
tabIndex={-1} tabIndex={-1}
className="absolute right-3 top-3.5 flex items-center justify-center text-custom-text-400" className="absolute right-3 top-3.5 flex items-center justify-center text-custom-text-400"
onClick={() => setShowPassword(true)} onClick={() => handleShowPassword("retypePassword")}
> >
<Eye className="h-4 w-4" /> <Eye className="h-4 w-4" />
</button> </button>

View File

@ -87,7 +87,10 @@ export const ProfileSetup: React.FC<Props> = observer((props) => {
const [isRemoving, setIsRemoving] = useState(false); const [isRemoving, setIsRemoving] = useState(false);
const [isImageUploadModalOpen, setIsImageUploadModalOpen] = useState(false); const [isImageUploadModalOpen, setIsImageUploadModalOpen] = useState(false);
const [isPasswordInputFocused, setIsPasswordInputFocused] = useState(false); const [isPasswordInputFocused, setIsPasswordInputFocused] = useState(false);
const [showPassword, setShowPassword] = useState(false); const [showPassword, setShowPassword] = useState({
password: false,
retypePassword: false,
});
// hooks // hooks
const { resolvedTheme } = useTheme(); const { resolvedTheme } = useTheme();
// store hooks // store hooks
@ -112,6 +115,9 @@ export const ProfileSetup: React.FC<Props> = observer((props) => {
mode: "onChange", mode: "onChange",
}); });
const handleShowPassword = (key: keyof typeof showPassword) =>
setShowPassword((prev) => ({ ...prev, [key]: !prev[key] }));
const handleSetPassword = async (password: string) => { const handleSetPassword = async (password: string) => {
const token = await authService.requestCSRFToken().then((data) => data?.csrf_token); const token = await authService.requestCSRFToken().then((data) => data?.csrf_token);
await authService.setPassword(token, { password }); await authService.setPassword(token, { password });
@ -415,7 +421,7 @@ export const ProfileSetup: React.FC<Props> = observer((props) => {
render={({ field: { value, onChange, ref } }) => ( render={({ field: { value, onChange, ref } }) => (
<div className="relative flex items-center rounded-md"> <div className="relative flex items-center rounded-md">
<Input <Input
type={showPassword ? "text" : "password"} type={showPassword.password ? "text" : "password"}
name="password" name="password"
value={value} value={value}
onChange={onChange} onChange={onChange}
@ -426,15 +432,15 @@ export const ProfileSetup: React.FC<Props> = observer((props) => {
onFocus={() => setIsPasswordInputFocused(true)} onFocus={() => setIsPasswordInputFocused(true)}
onBlur={() => setIsPasswordInputFocused(false)} onBlur={() => setIsPasswordInputFocused(false)}
/> />
{showPassword ? ( {showPassword.password ? (
<EyeOff <EyeOff
className="absolute right-3 h-4 w-4 stroke-custom-text-400 hover:cursor-pointer" className="absolute right-3 h-4 w-4 stroke-custom-text-400 hover:cursor-pointer"
onClick={() => setShowPassword(false)} onClick={() => handleShowPassword("password")}
/> />
) : ( ) : (
<Eye <Eye
className="absolute right-3 h-4 w-4 stroke-custom-text-400 hover:cursor-pointer" className="absolute right-3 h-4 w-4 stroke-custom-text-400 hover:cursor-pointer"
onClick={() => setShowPassword(true)} onClick={() => handleShowPassword("password")}
/> />
)} )}
</div> </div>
@ -458,7 +464,7 @@ export const ProfileSetup: React.FC<Props> = observer((props) => {
render={({ field: { value, onChange, ref } }) => ( render={({ field: { value, onChange, ref } }) => (
<div className="relative flex items-center rounded-md"> <div className="relative flex items-center rounded-md">
<Input <Input
type={showPassword ? "text" : "password"} type={showPassword.retypePassword ? "text" : "password"}
name="confirm_password" name="confirm_password"
value={value} value={value}
onChange={onChange} onChange={onChange}
@ -467,15 +473,15 @@ export const ProfileSetup: React.FC<Props> = observer((props) => {
placeholder="Confirm password..." placeholder="Confirm password..."
className="w-full border-onboarding-border-100 pr-12 placeholder:text-onboarding-text-400" className="w-full border-onboarding-border-100 pr-12 placeholder:text-onboarding-text-400"
/> />
{showPassword ? ( {showPassword.retypePassword ? (
<EyeOff <EyeOff
className="absolute right-3 h-4 w-4 stroke-custom-text-400 hover:cursor-pointer" className="absolute right-3 h-4 w-4 stroke-custom-text-400 hover:cursor-pointer"
onClick={() => setShowPassword(false)} onClick={() => handleShowPassword("retypePassword")}
/> />
) : ( ) : (
<Eye <Eye
className="absolute right-3 h-4 w-4 stroke-custom-text-400 hover:cursor-pointer" className="absolute right-3 h-4 w-4 stroke-custom-text-400 hover:cursor-pointer"
onClick={() => setShowPassword(true)} onClick={() => handleShowPassword("retypePassword")}
/> />
)} )}
</div> </div>

View File

@ -45,7 +45,10 @@ const ResetPasswordPage: NextPageWithLayout = () => {
const router = useRouter(); const router = useRouter();
const { uidb64, token, email } = router.query; const { uidb64, token, email } = router.query;
// states // states
const [showPassword, setShowPassword] = useState(false); const [showPassword, setShowPassword] = useState({
password: false,
retypePassword: false,
});
const [resetFormData, setResetFormData] = useState<TResetPasswordFormValues>({ const [resetFormData, setResetFormData] = useState<TResetPasswordFormValues>({
...defaultValues, ...defaultValues,
email: email ? email.toString() : "", email: email ? email.toString() : "",
@ -57,6 +60,9 @@ const ResetPasswordPage: NextPageWithLayout = () => {
// hooks // hooks
const { resolvedTheme } = useTheme(); const { resolvedTheme } = useTheme();
const handleShowPassword = (key: keyof typeof showPassword) =>
setShowPassword((prev) => ({ ...prev, [key]: !prev[key] }));
const handleFormChange = (key: keyof TResetPasswordFormValues, value: string) => const handleFormChange = (key: keyof TResetPasswordFormValues, value: string) =>
setResetFormData((prev) => ({ ...prev, [key]: value })); setResetFormData((prev) => ({ ...prev, [key]: value }));
@ -129,7 +135,7 @@ const ResetPasswordPage: NextPageWithLayout = () => {
</label> </label>
<div className="relative flex items-center rounded-md bg-onboarding-background-200"> <div className="relative flex items-center rounded-md bg-onboarding-background-200">
<Input <Input
type={showPassword ? "text" : "password"} type={showPassword.password ? "text" : "password"}
name="password" name="password"
value={resetFormData.password} value={resetFormData.password}
onChange={(e) => handleFormChange("password", e.target.value)} onChange={(e) => handleFormChange("password", e.target.value)}
@ -141,15 +147,15 @@ const ResetPasswordPage: NextPageWithLayout = () => {
onBlur={() => setIsPasswordInputFocused(false)} onBlur={() => setIsPasswordInputFocused(false)}
autoFocus autoFocus
/> />
{showPassword ? ( {showPassword.password ? (
<EyeOff <EyeOff
className="absolute right-3 h-5 w-5 stroke-custom-text-400 hover:cursor-pointer" className="absolute right-3 h-5 w-5 stroke-custom-text-400 hover:cursor-pointer"
onClick={() => setShowPassword(false)} onClick={() => handleShowPassword("password")}
/> />
) : ( ) : (
<Eye <Eye
className="absolute right-3 h-5 w-5 stroke-custom-text-400 hover:cursor-pointer" className="absolute right-3 h-5 w-5 stroke-custom-text-400 hover:cursor-pointer"
onClick={() => setShowPassword(true)} onClick={() => handleShowPassword("password")}
/> />
)} )}
</div> </div>
@ -161,7 +167,7 @@ const ResetPasswordPage: NextPageWithLayout = () => {
</label> </label>
<div className="relative flex items-center rounded-md bg-onboarding-background-200"> <div className="relative flex items-center rounded-md bg-onboarding-background-200">
<Input <Input
type={showPassword ? "text" : "password"} type={showPassword.retypePassword ? "text" : "password"}
name="confirm_password" name="confirm_password"
value={resetFormData.confirm_password} value={resetFormData.confirm_password}
onChange={(e) => handleFormChange("confirm_password", e.target.value)} onChange={(e) => handleFormChange("confirm_password", e.target.value)}
@ -170,15 +176,15 @@ const ResetPasswordPage: NextPageWithLayout = () => {
onFocus={() => setIsRetryPasswordInputFocused(true)} onFocus={() => setIsRetryPasswordInputFocused(true)}
onBlur={() => setIsRetryPasswordInputFocused(false)} onBlur={() => setIsRetryPasswordInputFocused(false)}
/> />
{showPassword ? ( {showPassword.retypePassword ? (
<EyeOff <EyeOff
className="absolute right-3 h-5 w-5 stroke-custom-text-400 hover:cursor-pointer" className="absolute right-3 h-5 w-5 stroke-custom-text-400 hover:cursor-pointer"
onClick={() => setShowPassword(false)} onClick={() => handleShowPassword("retypePassword")}
/> />
) : ( ) : (
<Eye <Eye
className="absolute right-3 h-5 w-5 stroke-custom-text-400 hover:cursor-pointer" className="absolute right-3 h-5 w-5 stroke-custom-text-400 hover:cursor-pointer"
onClick={() => setShowPassword(true)} onClick={() => handleShowPassword("retypePassword")}
/> />
)} )}
</div> </div>

View File

@ -47,7 +47,10 @@ const SetPasswordPage: NextPageWithLayout = observer(() => {
const router = useRouter(); const router = useRouter();
const { email } = router.query; const { email } = router.query;
// states // states
const [showPassword, setShowPassword] = useState(false); const [showPassword, setShowPassword] = useState({
password: false,
retypePassword: false,
});
const [passwordFormData, setPasswordFormData] = useState<TResetPasswordFormValues>({ const [passwordFormData, setPasswordFormData] = useState<TResetPasswordFormValues>({
...defaultValues, ...defaultValues,
email: email ? email.toString() : "", email: email ? email.toString() : "",
@ -65,6 +68,9 @@ const SetPasswordPage: NextPageWithLayout = observer(() => {
authService.requestCSRFToken().then((data) => data?.csrf_token && setCsrfToken(data.csrf_token)); authService.requestCSRFToken().then((data) => data?.csrf_token && setCsrfToken(data.csrf_token));
}, [csrfToken]); }, [csrfToken]);
const handleShowPassword = (key: keyof typeof showPassword) =>
setShowPassword((prev) => ({ ...prev, [key]: !prev[key] }));
const handleFormChange = (key: keyof TResetPasswordFormValues, value: string) => const handleFormChange = (key: keyof TResetPasswordFormValues, value: string) =>
setPasswordFormData((prev) => ({ ...prev, [key]: value })); setPasswordFormData((prev) => ({ ...prev, [key]: value }));
@ -142,7 +148,7 @@ const SetPasswordPage: NextPageWithLayout = observer(() => {
</label> </label>
<div className="relative flex items-center rounded-md bg-onboarding-background-200"> <div className="relative flex items-center rounded-md bg-onboarding-background-200">
<Input <Input
type={showPassword ? "text" : "password"} type={showPassword.password ? "text" : "password"}
name="password" name="password"
value={passwordFormData.password} value={passwordFormData.password}
onChange={(e) => handleFormChange("password", e.target.value)} onChange={(e) => handleFormChange("password", e.target.value)}
@ -154,15 +160,15 @@ const SetPasswordPage: NextPageWithLayout = observer(() => {
onBlur={() => setIsPasswordInputFocused(false)} onBlur={() => setIsPasswordInputFocused(false)}
autoFocus autoFocus
/> />
{showPassword ? ( {showPassword.password ? (
<EyeOff <EyeOff
className="absolute right-3 h-5 w-5 stroke-custom-text-400 hover:cursor-pointer" className="absolute right-3 h-5 w-5 stroke-custom-text-400 hover:cursor-pointer"
onClick={() => setShowPassword(false)} onClick={() => handleShowPassword("password")}
/> />
) : ( ) : (
<Eye <Eye
className="absolute right-3 h-5 w-5 stroke-custom-text-400 hover:cursor-pointer" className="absolute right-3 h-5 w-5 stroke-custom-text-400 hover:cursor-pointer"
onClick={() => setShowPassword(true)} onClick={() => handleShowPassword("password")}
/> />
)} )}
</div> </div>
@ -174,7 +180,7 @@ const SetPasswordPage: NextPageWithLayout = observer(() => {
</label> </label>
<div className="relative flex items-center rounded-md bg-onboarding-background-200"> <div className="relative flex items-center rounded-md bg-onboarding-background-200">
<Input <Input
type={showPassword ? "text" : "password"} type={showPassword.retypePassword ? "text" : "password"}
name="confirm_password" name="confirm_password"
value={passwordFormData.confirm_password} value={passwordFormData.confirm_password}
onChange={(e) => handleFormChange("confirm_password", e.target.value)} onChange={(e) => handleFormChange("confirm_password", e.target.value)}
@ -183,15 +189,15 @@ const SetPasswordPage: NextPageWithLayout = observer(() => {
onFocus={() => setIsRetryPasswordInputFocused(true)} onFocus={() => setIsRetryPasswordInputFocused(true)}
onBlur={() => setIsRetryPasswordInputFocused(false)} onBlur={() => setIsRetryPasswordInputFocused(false)}
/> />
{showPassword ? ( {showPassword.retypePassword ? (
<EyeOff <EyeOff
className="absolute right-3 h-5 w-5 stroke-custom-text-400 hover:cursor-pointer" className="absolute right-3 h-5 w-5 stroke-custom-text-400 hover:cursor-pointer"
onClick={() => setShowPassword(false)} onClick={() => handleShowPassword("retypePassword")}
/> />
) : ( ) : (
<Eye <Eye
className="absolute right-3 h-5 w-5 stroke-custom-text-400 hover:cursor-pointer" className="absolute right-3 h-5 w-5 stroke-custom-text-400 hover:cursor-pointer"
onClick={() => setShowPassword(true)} onClick={() => handleShowPassword("retypePassword")}
/> />
)} )}
</div> </div>