mirror of
https://github.com/makeplane/plane
synced 2024-06-14 14:31:34 +00:00
[WEB-1324] chore: change password page improvement (#4462)
* chore: change password page improvement * chore: confirm password input improvement
This commit is contained in:
parent
061d52727e
commit
5ccb4f7d19
@ -69,6 +69,7 @@ export const InstanceSetupForm: FC = (props) => {
|
|||||||
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 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 }));
|
||||||
@ -276,6 +277,8 @@ export const InstanceSetupForm: FC = (props) => {
|
|||||||
onChange={(e) => handleFormChange("confirm_password", e.target.value)}
|
onChange={(e) => handleFormChange("confirm_password", e.target.value)}
|
||||||
placeholder="Confirm password"
|
placeholder="Confirm password"
|
||||||
className="w-full border border-onboarding-border-100 !bg-onboarding-background-200 pr-12 placeholder:text-onboarding-text-400"
|
className="w-full border border-onboarding-border-100 !bg-onboarding-background-200 pr-12 placeholder:text-onboarding-text-400"
|
||||||
|
onFocus={() => setIsRetryPasswordInputFocused(true)}
|
||||||
|
onBlur={() => setIsRetryPasswordInputFocused(false)}
|
||||||
/>
|
/>
|
||||||
{showPassword ? (
|
{showPassword ? (
|
||||||
<button
|
<button
|
||||||
@ -297,9 +300,9 @@ export const InstanceSetupForm: FC = (props) => {
|
|||||||
</button>
|
</button>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{!!formData.confirm_password && formData.password !== formData.confirm_password && (
|
{!!formData.confirm_password &&
|
||||||
<span className="text-sm text-red-500">Passwords don{"'"}t match</span>
|
formData.password !== formData.confirm_password &&
|
||||||
)}
|
!isRetryPasswordInputFocused && <span className="text-sm text-red-500">Passwords don{"'"}t match</span>}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="relative flex items-center pt-2 gap-2">
|
<div className="relative flex items-center pt-2 gap-2">
|
||||||
|
@ -44,6 +44,7 @@ export const PasswordForm: React.FC<Props> = (props) => {
|
|||||||
const [csrfToken, setCsrfToken] = useState<string | undefined>(undefined);
|
const [csrfToken, setCsrfToken] = useState<string | undefined>(undefined);
|
||||||
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);
|
||||||
// hooks
|
// hooks
|
||||||
const { data: instance, config: instanceConfig } = useInstance();
|
const { data: instance, config: instanceConfig } = useInstance();
|
||||||
// router
|
// router
|
||||||
@ -170,6 +171,8 @@ export const PasswordForm: React.FC<Props> = (props) => {
|
|||||||
onChange={(e) => handleFormChange("confirm_password", e.target.value)}
|
onChange={(e) => handleFormChange("confirm_password", e.target.value)}
|
||||||
placeholder="Confirm password"
|
placeholder="Confirm password"
|
||||||
className="h-[46px] w-full border border-onboarding-border-100 !bg-onboarding-background-200 pr-12 placeholder:text-onboarding-text-400"
|
className="h-[46px] w-full border border-onboarding-border-100 !bg-onboarding-background-200 pr-12 placeholder:text-onboarding-text-400"
|
||||||
|
onFocus={() => setIsRetryPasswordInputFocused(true)}
|
||||||
|
onBlur={() => setIsRetryPasswordInputFocused(false)}
|
||||||
/>
|
/>
|
||||||
{showPassword ? (
|
{showPassword ? (
|
||||||
<EyeOff
|
<EyeOff
|
||||||
@ -183,9 +186,9 @@ export const PasswordForm: React.FC<Props> = (props) => {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{!!passwordFormData.confirm_password && passwordFormData.password !== passwordFormData.confirm_password && (
|
{!!passwordFormData.confirm_password &&
|
||||||
<span className="text-sm text-red-500">Passwords don{"'"}t match</span>
|
passwordFormData.password !== passwordFormData.confirm_password &&
|
||||||
)}
|
!isRetryPasswordInputFocused && <span className="text-sm text-red-500">Passwords don{"'"}t match</span>}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div className="space-y-2.5">
|
<div className="space-y-2.5">
|
||||||
|
@ -53,6 +53,7 @@ export const AuthPasswordForm: React.FC<Props> = observer((props: Props) => {
|
|||||||
});
|
});
|
||||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||||
const [isPasswordInputFocused, setIsPasswordInputFocused] = useState(false);
|
const [isPasswordInputFocused, setIsPasswordInputFocused] = useState(false);
|
||||||
|
const [isRetryPasswordInputFocused, setIsRetryPasswordInputFocused] = useState(false);
|
||||||
|
|
||||||
const handleShowPassword = (key: keyof typeof showPassword) =>
|
const handleShowPassword = (key: keyof typeof showPassword) =>
|
||||||
setShowPassword((prev) => ({ ...prev, [key]: !prev[key] }));
|
setShowPassword((prev) => ({ ...prev, [key]: !prev[key] }));
|
||||||
@ -183,6 +184,8 @@ export const AuthPasswordForm: React.FC<Props> = observer((props: Props) => {
|
|||||||
onChange={(e) => handleFormChange("confirm_password", e.target.value)}
|
onChange={(e) => handleFormChange("confirm_password", e.target.value)}
|
||||||
placeholder="Confirm password"
|
placeholder="Confirm password"
|
||||||
className="disable-autofill-style h-[46px] w-full border border-onboarding-border-100 !bg-onboarding-background-200 pr-12 placeholder:text-onboarding-text-400"
|
className="disable-autofill-style h-[46px] w-full border border-onboarding-border-100 !bg-onboarding-background-200 pr-12 placeholder:text-onboarding-text-400"
|
||||||
|
onFocus={() => setIsRetryPasswordInputFocused(true)}
|
||||||
|
onBlur={() => setIsRetryPasswordInputFocused(false)}
|
||||||
/>
|
/>
|
||||||
{showPassword?.retypePassword ? (
|
{showPassword?.retypePassword ? (
|
||||||
<EyeOff
|
<EyeOff
|
||||||
@ -196,9 +199,9 @@ export const AuthPasswordForm: React.FC<Props> = observer((props: Props) => {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{!!passwordFormData.confirm_password && passwordFormData.password !== passwordFormData.confirm_password && (
|
{!!passwordFormData.confirm_password &&
|
||||||
<span className="text-sm text-red-500">Passwords don{"'"}t match</span>
|
passwordFormData.password !== passwordFormData.confirm_password &&
|
||||||
)}
|
!isRetryPasswordInputFocused && <span className="text-sm text-red-500">Passwords don{"'"}t match</span>}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
@ -52,6 +52,8 @@ const ResetPasswordPage: NextPageWithLayout = () => {
|
|||||||
});
|
});
|
||||||
const [csrfToken, setCsrfToken] = useState<string | undefined>(undefined);
|
const [csrfToken, setCsrfToken] = useState<string | undefined>(undefined);
|
||||||
const [isPasswordInputFocused, setIsPasswordInputFocused] = useState(false);
|
const [isPasswordInputFocused, setIsPasswordInputFocused] = useState(false);
|
||||||
|
const [isRetryPasswordInputFocused, setIsRetryPasswordInputFocused] = useState(false);
|
||||||
|
|
||||||
// hooks
|
// hooks
|
||||||
const { resolvedTheme } = useTheme();
|
const { resolvedTheme } = useTheme();
|
||||||
|
|
||||||
@ -165,6 +167,8 @@ const ResetPasswordPage: NextPageWithLayout = () => {
|
|||||||
onChange={(e) => handleFormChange("confirm_password", e.target.value)}
|
onChange={(e) => handleFormChange("confirm_password", e.target.value)}
|
||||||
placeholder="Confirm password"
|
placeholder="Confirm password"
|
||||||
className="h-[46px] w-full border border-onboarding-border-100 !bg-onboarding-background-200 pr-12 placeholder:text-onboarding-text-400"
|
className="h-[46px] w-full border border-onboarding-border-100 !bg-onboarding-background-200 pr-12 placeholder:text-onboarding-text-400"
|
||||||
|
onFocus={() => setIsRetryPasswordInputFocused(true)}
|
||||||
|
onBlur={() => setIsRetryPasswordInputFocused(false)}
|
||||||
/>
|
/>
|
||||||
{showPassword ? (
|
{showPassword ? (
|
||||||
<EyeOff
|
<EyeOff
|
||||||
@ -178,9 +182,11 @@ const ResetPasswordPage: NextPageWithLayout = () => {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{!!resetFormData.confirm_password && resetFormData.password !== resetFormData.confirm_password && (
|
{!!resetFormData.confirm_password &&
|
||||||
<span className="text-sm text-red-500">Passwords don{"'"}t match</span>
|
resetFormData.password !== resetFormData.confirm_password &&
|
||||||
)}
|
!isRetryPasswordInputFocused && (
|
||||||
|
<span className="text-sm text-red-500">Passwords don{"'"}t match</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<Button type="submit" variant="primary" className="w-full" size="lg" disabled={isButtonDisabled}>
|
<Button type="submit" variant="primary" className="w-full" size="lg" disabled={isButtonDisabled}>
|
||||||
Set password
|
Set password
|
||||||
|
@ -54,6 +54,7 @@ const SetPasswordPage: NextPageWithLayout = observer(() => {
|
|||||||
});
|
});
|
||||||
const [csrfToken, setCsrfToken] = useState<string | undefined>(undefined);
|
const [csrfToken, setCsrfToken] = useState<string | undefined>(undefined);
|
||||||
const [isPasswordInputFocused, setIsPasswordInputFocused] = useState(false);
|
const [isPasswordInputFocused, setIsPasswordInputFocused] = useState(false);
|
||||||
|
const [isRetryPasswordInputFocused, setIsRetryPasswordInputFocused] = useState(false);
|
||||||
// hooks
|
// hooks
|
||||||
const { resolvedTheme } = useTheme();
|
const { resolvedTheme } = useTheme();
|
||||||
// hooks
|
// hooks
|
||||||
@ -179,6 +180,8 @@ const SetPasswordPage: NextPageWithLayout = observer(() => {
|
|||||||
onChange={(e) => handleFormChange("confirm_password", e.target.value)}
|
onChange={(e) => handleFormChange("confirm_password", e.target.value)}
|
||||||
placeholder="Confirm password"
|
placeholder="Confirm password"
|
||||||
className="h-[46px] w-full border border-onboarding-border-100 !bg-onboarding-background-200 pr-12 placeholder:text-onboarding-text-400"
|
className="h-[46px] w-full border border-onboarding-border-100 !bg-onboarding-background-200 pr-12 placeholder:text-onboarding-text-400"
|
||||||
|
onFocus={() => setIsRetryPasswordInputFocused(true)}
|
||||||
|
onBlur={() => setIsRetryPasswordInputFocused(false)}
|
||||||
/>
|
/>
|
||||||
{showPassword ? (
|
{showPassword ? (
|
||||||
<EyeOff
|
<EyeOff
|
||||||
@ -193,7 +196,8 @@ const SetPasswordPage: NextPageWithLayout = observer(() => {
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{!!passwordFormData.confirm_password &&
|
{!!passwordFormData.confirm_password &&
|
||||||
passwordFormData.password !== passwordFormData.confirm_password && (
|
passwordFormData.password !== passwordFormData.confirm_password &&
|
||||||
|
!isRetryPasswordInputFocused && (
|
||||||
<span className="text-sm text-red-500">Passwords don{"'"}t match</span>
|
<span className="text-sm text-red-500">Passwords don{"'"}t match</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -44,6 +44,7 @@ const ChangePasswordPage: NextPageWithLayout = observer(() => {
|
|||||||
retypePassword: false,
|
retypePassword: false,
|
||||||
});
|
});
|
||||||
const [isPasswordInputFocused, setIsPasswordInputFocused] = useState(false);
|
const [isPasswordInputFocused, setIsPasswordInputFocused] = useState(false);
|
||||||
|
const [isRetryPasswordInputFocused, setIsRetryPasswordInputFocused] = useState(false);
|
||||||
|
|
||||||
// router
|
// router
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@ -150,7 +151,7 @@ const ChangePasswordPage: NextPageWithLayout = observer(() => {
|
|||||||
<input type="hidden" name="csrfmiddlewaretoken" value={csrfToken} />
|
<input type="hidden" name="csrfmiddlewaretoken" value={csrfToken} />
|
||||||
|
|
||||||
<h3 className="text-xl font-medium">Change password</h3>
|
<h3 className="text-xl font-medium">Change password</h3>
|
||||||
<div className="grid-col grid w-full grid-cols-1 items-center justify-between gap-10 xl:grid-cols-2 2xl:grid-cols-3">
|
<div className="flex flex-col gap-10 w-full max-w-96">
|
||||||
<div className="flex flex-col gap-1 ">
|
<div className="flex flex-col gap-1 ">
|
||||||
<h4 className="text-sm">Current password</h4>
|
<h4 className="text-sm">Current password</h4>
|
||||||
<div className="relative flex items-center rounded-md">
|
<div className="relative flex items-center rounded-md">
|
||||||
@ -244,6 +245,8 @@ const ChangePasswordPage: NextPageWithLayout = observer(() => {
|
|||||||
onChange={onChange}
|
onChange={onChange}
|
||||||
className="w-full"
|
className="w-full"
|
||||||
hasError={Boolean(errors.confirm_password)}
|
hasError={Boolean(errors.confirm_password)}
|
||||||
|
onFocus={() => setIsRetryPasswordInputFocused(true)}
|
||||||
|
onBlur={() => setIsRetryPasswordInputFocused(false)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
@ -259,7 +262,7 @@ const ChangePasswordPage: NextPageWithLayout = observer(() => {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{!!retypePassword && password !== retypePassword && (
|
{!!retypePassword && password !== retypePassword && !isRetryPasswordInputFocused && (
|
||||||
<span className="text-sm text-red-500">Passwords don{"'"}t match</span>
|
<span className="text-sm text-red-500">Passwords don{"'"}t match</span>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user