(Breaking change) Switch between set password and change password on the settings page. (#15582)

Here is what the PR does:

- Surface password state in validatePasswordResetToken, returning
hasPassword so the client can tell whether a user is setting or changing
their password.
- Consume that flag throughout the front end (mock data, stories,
GraphQL types) and update the Reset/Set Password modal to swap the
heading/button label and success toast accordingly.
- After a successful password set/reset, immediately update the
logged-in user’s hasPassword flag so the Settings screen reflects the
new state without a reload.

Modal has two states now - reset password modal uses change password
state since it made intuitive sense.

<p align="center">
<img width="404" height="397" alt="image"
src="https://github.com/user-attachments/assets/c54cc581-1248-4395-833d-0202758e1947"
/>
</p>

<p align="center">
<img width="403" height="393" alt="image"
src="https://github.com/user-attachments/assets/d8a39a95-27e6-4037-86f2-1f74176002ba"
/>
</p>

---------

Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
This commit is contained in:
Abdullah.
2025-11-05 15:29:37 +05:00
committed by GitHub
parent cc7343a8f2
commit 0fcfcec426
80 changed files with 756 additions and 358 deletions
@@ -5,6 +5,7 @@ export const VALIDATE_PASSWORD_RESET_TOKEN = gql`
validatePasswordResetToken(passwordResetToken: $token) {
id
email
hasPassword
}
}
`;
@@ -12,6 +12,7 @@ export type CurrentUser = Pick<
| 'userVars'
| 'firstName'
| 'lastName'
| 'hasPassword'
>;
export const currentUserState = createState<CurrentUser | null>({
@@ -35,6 +35,7 @@ const mockCurrentUser = {
userVars: {},
firstName: 'fake-first-name',
lastName: 'fake-last-name',
hasPassword: true,
};
const mockBilling: Billing = {
@@ -1,24 +0,0 @@
import { useLingui } from '@lingui/react/macro';
import { useHandleResetPassword } from '@/auth/sign-in-up/hooks/useHandleResetPassword';
import { Button } from 'twenty-ui/input';
import { H2Title } from 'twenty-ui/display';
export const ChangePassword = () => {
const { t } = useLingui();
const { handleResetPassword } = useHandleResetPassword();
return (
<>
<H2Title
title={t`Change Password`}
description={t`Receive an email containing password update link`}
/>
<Button
onClick={handleResetPassword()}
variant="secondary"
title={t`Change Password`}
/>
</>
);
};
@@ -0,0 +1,30 @@
import { useHandleResetPassword } from '@/auth/sign-in-up/hooks/useHandleResetPassword';
import { currentUserState } from '@/auth/states/currentUserState';
import { useLingui } from '@lingui/react/macro';
import { useRecoilValue } from 'recoil';
import { H2Title } from 'twenty-ui/display';
import { Button } from 'twenty-ui/input';
export const SetOrChangePassword = () => {
const { t } = useLingui();
const currentUser = useRecoilValue(currentUserState);
const { handleResetPassword } = useHandleResetPassword();
const hasPassword = currentUser?.hasPassword ?? false;
const heading = hasPassword ? t`Change Password` : t`Set Password`;
const description = hasPassword
? t`Receive an email containing password update link`
: t`Receive an email containing password set link`;
return (
<>
<H2Title title={heading} description={description} />
<Button
onClick={handleResetPassword()}
variant="secondary"
title={heading}
/>
</>
);
};
@@ -18,6 +18,7 @@ export const USER_QUERY_FRAGMENT = gql`
firstName
lastName
email
hasPassword
canAccessFullAdminPanel
canImpersonate
supportUserHash