Skip to content

Commit

Permalink
refactor: clean the code PE-5161
Browse files Browse the repository at this point in the history
  • Loading branch information
fedellen committed Dec 7, 2023
1 parent 9f3af3b commit f54b86d
Show file tree
Hide file tree
Showing 7 changed files with 107 additions and 81 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: Deploy to GitHub Pages
on:
push:
branches:
- PE-5161_gift_app_init
- prod

jobs:
deploy:
Expand Down
4 changes: 4 additions & 0 deletions src/GiftForm.css
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@
background-color: var(--dark-gray);
}

/*
If the input is not focused, and the placeholder is not shown, and the input is invalid,
then change the border color to red to indicate invalid email address.
*/
#recipient-email:not(:focus):not(:placeholder-shown):invalid {
border-color: var(--ardrive-red);
}
Expand Down
108 changes: 28 additions & 80 deletions src/GiftForm.tsx
Original file line number Diff line number Diff line change
@@ -1,104 +1,55 @@
import { TurboFactory, USD, TopUpRawResponse } from "@ardrive/turbo-sdk";
import { useState, useEffect, useRef } from "react";
import { useState, useRef } from "react";
import {
defaultUSDAmount,
paymentServiceUrl,
termsOfServiceUrl,
wincPerCredit,
} from "./constants";
import useDebounce from "./hooks/useDebounce";
import "./GiftForm.css";
import { getTopUpQuote } from "./utils/getTopUpQuote";
import { useWincForOneGiB } from "./hooks/useWincForOneGiB";
import { useCreditsForFiat } from "./hooks/useCreditsForFiat";

interface GiftFormProps {
errorCallback: (message: string) => void;
}

async function getTopUpQuote(
usdAmount: number,
recipientEmail: string,
): Promise<TopUpRawResponse> {
// TODO: support emails on turbo sdk
// turbo.createCheckoutSession({amount: USD(usdAmount / 100), email: recipientEmail,owner}})
const response = await fetch(
`${paymentServiceUrl}/v1/top-up/checkout-session/${recipientEmail}/usd/${
usdAmount * 100
}?destinationAddressType=email`,
);
const data = await response.json();
console.log("data", data);

return data;
}
const maxUSDAmount = 10000;
const minUSDAmount = 5;

export function GiftForm({ errorCallback }: GiftFormProps) {
const [recipientEmail, setRecipientEmail] = useState<string>("");
const [termsAccepted, setTermsAccepted] = useState<boolean>(false);

const recipientEmailRef = useRef<HTMLInputElement>(null);

const [usdAmount, setUsdAmount] = useState<number>(defaultUSDAmount);
const debouncedUsdAmount = useDebounce(usdAmount, 500);
const [recipientEmail, setRecipientEmail] = useState<string>("");
const [isTermsAccepted, setTermsAccepted] = useState<boolean>(false);

const handleUSDChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const amount = Number(e.target.value);
if (amount > 10000) {
setUsdAmount(10000);
if (amount > maxUSDAmount) {
setUsdAmount(maxUSDAmount);
return;
}
if (amount < 5) {
setUsdAmount(5);
if (amount < minUSDAmount) {
setUsdAmount(minUSDAmount);
return;
}
setUsdAmount(Number(Number(e.target.value).toFixed(2)));
};

const [credits, setCredits] = useState<string | undefined>(undefined);

const usdWhenCreditsWereLastUpdatedRef = useRef<number | undefined>(
undefined,
const wincForOneGiB = useWincForOneGiB();
const debouncedUsdAmount = useDebounce(usdAmount, 500);
const [credits, usdWhenCreditsWereLastUpdatedRef] = useCreditsForFiat(
debouncedUsdAmount,
errorCallback,
);

const [wincForOneGiB, setWincForOneGiB] = useState<string | undefined>(
undefined,
);
useEffect(() => {
const turbo = TurboFactory.unauthenticated({
paymentServiceConfig: { url: paymentServiceUrl },
});
turbo.getFiatRates().then(({ winc }) => {
setWincForOneGiB(winc);
});
}, []);

// Get credits for USD amount when USD amount changes
useEffect(() => {
const getCreditsAndGiBForUSD = async (
usdAmount: number,
): Promise<string> => {
const turbo = TurboFactory.unauthenticated({
paymentServiceConfig: { url: paymentServiceUrl },
});
const { winc } = await turbo.getWincForFiat({
amount: USD(usdAmount),
promoCodes: [],
}); // todo: add promo codes support
return winc;
};
getCreditsAndGiBForUSD(debouncedUsdAmount)
.then((credits) => {
setCredits(credits);
})
.catch((err) => {
console.error(err);
errorCallback(`Error getting credits for USD amount: ${err.message}`);
});
usdWhenCreditsWereLastUpdatedRef.current = debouncedUsdAmount;
}, [debouncedUsdAmount, errorCallback]);
const recipientEmailRef = useRef<HTMLInputElement>(null);
const isEmailHtmlElementValid = recipientEmailRef.current?.checkValidity();

const canSubmitForm =
!!credits &&
!!recipientEmail &&
!!termsAccepted &&
recipientEmailRef.current?.checkValidity();
!!isTermsAccepted &&
isEmailHtmlElementValid;

const handleSubmit = (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
e.preventDefault();
Expand All @@ -108,9 +59,7 @@ export function GiftForm({ errorCallback }: GiftFormProps) {
}

getTopUpQuote(usdAmount, recipientEmail).then((topUpQuote) => {
const url = topUpQuote.paymentSession.url;

window.location.href = url;
window.location.href = topUpQuote.paymentSession.url;
});
};

Expand Down Expand Up @@ -171,15 +120,14 @@ export function GiftForm({ errorCallback }: GiftFormProps) {
<div id="conversions">
{"$".toLocaleUpperCase()}
<span className="conversion-amount">
{usdWhenCreditsWereLastUpdatedRef.current}
{usdWhenCreditsWereLastUpdatedRef}
</span>{" "}
{" "}
<span className="conversion-amount">
{(Number(credits) / 1_000_000_000_000).toFixed(4)}
</span>
<span className="conversion-amount">{credits.toFixed(4)}</span>
Credits ≈{" "}
<span className="conversion-amount">
{(Number(credits) / Number(wincForOneGiB)).toFixed(2)}
{(
Number(credits * wincPerCredit) / Number(wincForOneGiB)
).toFixed(2)}
</span>
GiB
</div>
Expand Down
4 changes: 4 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,7 @@ export const paymentServiceUrl =
: "http://localhost:3000";
export const termsOfServiceUrl = "https://ardrive.io/tos-and-privacy/";
export const defaultUSDAmount = 10.0;
export const turboConfig = {
paymentServiceConfig: { url: paymentServiceUrl },
};
export const wincPerCredit = 1_000_000_000_000;
32 changes: 32 additions & 0 deletions src/hooks/useCreditsForFiat.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { TurboFactory, USD } from "@ardrive/turbo-sdk";
import { useState, useRef, useEffect } from "react";
import { turboConfig, wincPerCredit } from "../constants";

export function useCreditsForFiat(
debouncedUsdAmount: number,
errorCallback: (message: string) => void,
): [number | undefined, number | undefined] {
const [winc, setWinc] = useState<string | undefined>(undefined);
const usdWhenCreditsWereLastUpdatedRef = useRef<number | undefined>(
undefined,
);

// Get credits for USD amount when USD amount has stopped debouncing
useEffect(() => {
TurboFactory.unauthenticated(turboConfig)
.getWincForFiat({ amount: USD(debouncedUsdAmount), promoCodes: [] })
.then(({ winc }) => {
usdWhenCreditsWereLastUpdatedRef.current = debouncedUsdAmount;
setWinc(winc);
})
.catch((err) => {
console.error(err);
errorCallback(`Error getting credits for USD amount: ${err.message}`);
});
}, [debouncedUsdAmount, errorCallback]);

return [
winc ? +winc / wincPerCredit : undefined,
usdWhenCreditsWereLastUpdatedRef.current,
];
}
20 changes: 20 additions & 0 deletions src/hooks/useWincForOneGiB.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { TurboFactory } from "@ardrive/turbo-sdk";
import { useState, useEffect } from "react";
import { turboConfig } from "../constants";

export function useWincForOneGiB() {
const [wincForOneGiB, setWincForOneGiB] = useState<string | undefined>(
undefined,
);

// On first render, get winc for 1 GiB for conversions
useEffect(() => {
TurboFactory.unauthenticated(turboConfig)
.getFiatRates()
.then(({ winc }) => {
setWincForOneGiB(winc);
});
}, []);

return wincForOneGiB;
}
18 changes: 18 additions & 0 deletions src/utils/getTopUpQuote.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { TopUpRawResponse } from "@ardrive/turbo-sdk";
import { paymentServiceUrl } from "../constants";

export async function getTopUpQuote(
usdAmount: number,
recipientEmail: string,
): Promise<TopUpRawResponse> {
// TODO: support emails on turbo sdk
// return turboFactory.unauthenticated(turboConfig).createCheckoutSession({ amount: USD(usdAmount / 100), email: recipientEmail })
const response = await fetch(
`${paymentServiceUrl}/v1/top-up/checkout-session/${recipientEmail}/usd/${
usdAmount * 100
}?destinationAddressType=email`,
);
const data = await response.json();

return data;
}

0 comments on commit f54b86d

Please sign in to comment.