Skip to content

Commit

Permalink
Merge pull request #1729 from kleros/feat/email-updateable-at-info
Browse files Browse the repository at this point in the history
feat(web): email-updateable-at-info
  • Loading branch information
alcercu authored Oct 29, 2024
2 parents 01673c3 + 3869072 commit 6e71e9d
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ import { ISettings } from "../../../../index";

import EmailVerificationInfo from "./EmailVerificationInfo";
import FormContact from "./FormContact";
import { isUndefined } from "src/utils";
import InfoCard from "components/InfoCard";
import { timeLeftUntil } from "utils/date";

const FormContainer = styled.form`
width: 100%;
Expand All @@ -33,7 +36,13 @@ const ButtonContainer = styled.div`
const FormContactContainer = styled.div`
display: flex;
flex-direction: column;
`;

const StyledInfoCard = styled(InfoCard)`
width: fit-content;
font-size: 14px;
margin-bottom: 8px;
word-wrap: break-word;
`;

const FormContactDetails: React.FC<ISettings> = ({ toggleIsSettingsOpen }) => {
Expand All @@ -44,6 +53,10 @@ const FormContactDetails: React.FC<ISettings> = ({ toggleIsSettingsOpen }) => {

const isEditingEmail = user?.email !== emailInput;

const isEmailUpdateable = user?.email
? !isUndefined(user?.emailUpdateableAt) && new Date(user.emailUpdateableAt).getTime() < new Date().getTime()
: true;

useEffect(() => {
if (!user || !userExists) return;

Expand All @@ -53,11 +66,12 @@ const FormContactDetails: React.FC<ISettings> = ({ toggleIsSettingsOpen }) => {
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
if (!address) {
throw new Error("Missing address");
return;
}

// if user exists then update email
if (userExists) {
if (!isEmailUpdateable) return;
const data = {
newEmail: emailInput,
};
Expand Down Expand Up @@ -108,11 +122,15 @@ const FormContactDetails: React.FC<ISettings> = ({ toggleIsSettingsOpen }) => {
isEditing={isEditingEmail}
/>
</FormContactContainer>

{!isEmailUpdateable ? (
<StyledInfoCard msg={`You can update email again ${timeLeftUntil(user?.emailUpdateableAt!)}`} />
) : null}
<ButtonContainer>
<Button
text="Save"
disabled={!isEditingEmail || !emailIsValid || isAddingUser || isFetchingUser || isUpdatingUser}
disabled={
!isEditingEmail || !emailIsValid || isAddingUser || isFetchingUser || isUpdatingUser || !isEmailUpdateable
}
/>
</ButtonContainer>
<EmailVerificationInfo toggleIsSettingsOpen={toggleIsSettingsOpen} />
Expand Down
2 changes: 1 addition & 1 deletion web/src/layout/Header/navbar/Menu/Settings/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ const StyledTabs = styled(Tabs)`
padding: 0 ${responsiveSize(8, 32, 300)};
width: 86vw;
max-width: 660px;
align-self: center;
${landscapeStyle(
() => css`
width: ${responsiveSize(300, 424, 300)};
Expand Down
12 changes: 5 additions & 7 deletions web/src/utils/atlas/fetchUser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,21 @@ import { toast } from "react-toastify";

import { OPTIONS } from "utils/wrapWithToast";

type GetUserResponse = {
user: {
email: string;
isEmailVerified: string;
};
};

export type User = {
email: string;
isEmailVerified: string;
emailUpdateableAt: string | null;
};

type GetUserResponse = {
user: User;
};
const query = gql`
query GetUser {
user {
email
isEmailVerified
emailUpdateableAt
}
}
`;
Expand Down
37 changes: 37 additions & 0 deletions web/src/utils/date.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,40 @@ export function formatDate(unixTimestamp: number, withTime = false): string {
: { month: "long", day: "2-digit", year: "numeric" };
return date.toLocaleDateString("en-US", options);
}

/**
* Calculates the time left until a specified date and formats it.
*
* @param {string} isoString - An ISO 8601 formatted date string (e.g., "2024-10-29T09:52:08.580Z").
* @returns {string} A human-readable string indicating the time left until the specified date.
* @example
* console.log(timeLeftUntil("2024-10-29T09:52:08.580Z"));
* // Outputs: "in x secs", "in x mins", "in x hrs", or "after October 29, 2024"
*/
export function timeLeftUntil(isoString: string): string {
const targetDate = new Date(isoString);
const now = new Date();
const timeDifference = targetDate.getTime() - now.getTime();

if (timeDifference <= 0) {
return "The date has already passed.";
}

const secondsLeft = Math.floor(timeDifference / 1000);
const minutesLeft = Math.floor(secondsLeft / 60);
const hoursLeft = Math.floor(minutesLeft / 60);
const daysLeft = Math.floor(hoursLeft / 24);

if (secondsLeft < 60) {
return `in ${secondsLeft} sec${secondsLeft > 1 ? "s" : ""}`;
} else if (minutesLeft < 60) {
return `in ${minutesLeft} min${minutesLeft > 1 ? "s" : ""}`;
} else if (hoursLeft < 24) {
return `in ${hoursLeft} hr${hoursLeft > 1 ? "s" : ""}`;
} else if (daysLeft < 2) {
return `in ${daysLeft} day${daysLeft > 1 ? "s" : ""}`;
} else {
const options: Intl.DateTimeFormatOptions = { year: "numeric", month: "long", day: "numeric" };
return `after ${targetDate.toLocaleDateString("en-US", options)}`;
}
}

0 comments on commit 6e71e9d

Please sign in to comment.