Skip to content

Commit

Permalink
incrementers crypto (#3315)
Browse files Browse the repository at this point in the history
  • Loading branch information
ap-justin committed Sep 20, 2024
1 parent 7f4baf3 commit a8c77c5
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 15 deletions.
17 changes: 16 additions & 1 deletion src/components/donation/Steps/DonateMethods/Crypto/Form.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { DONATION_INCREMENTS } from "constants/common";
import TokenField from "../../../../TokenField";
import { useDonationState } from "../../Context";
import ContinueBtn from "../../common/ContinueBtn";
import Incrementers from "../../common/Incrementers";
import { ProgramSelector } from "../../common/ProgramSelector";
import type { CryptoFormStep } from "../../types";
import { nextFormState } from "../helpers";
Expand All @@ -10,7 +12,8 @@ import { useRhf } from "./useRhf";
export default function Form(props: CryptoFormStep) {
const { setState } = useDonationState();

const { handleSubmit, reset, program, token, errors } = useRhf(props);
const { handleSubmit, reset, program, token, errors, onIncrement } =
useRhf(props);

function submit(fv: DonateValues) {
setState((prev) => nextFormState(prev, { ...fv, method: "crypto" }));
Expand All @@ -37,6 +40,18 @@ export default function Form(props: CryptoFormStep) {
withMininum
/>

{token.value.id && token.value.rate && (
<Incrementers
onIncrement={onIncrement}
code={token.value.symbol}
rate={token.value.rate}
precision={token.value.precision}
increments={(
props.init.config?.increments || DONATION_INCREMENTS
).map((i) => i / token.value.rate ** 2)}
/>
)}

{(props.init.recipient.progDonationsAllowed ?? true) && (
<ProgramSelector
classes="my-2"
Expand Down
15 changes: 15 additions & 0 deletions src/components/donation/Steps/DonateMethods/Crypto/useRhf.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { yupResolver } from "@hookform/resolvers/yup";
import { centsDecimals, roundDown } from "helpers";
import { useController, useForm } from "react-hook-form";
import { schema, tokenShape } from "schemas/shape";
import { object } from "yup";
import type { OnIncrement } from "../../common/Incrementers";
import { DEFAULT_PROGRAM, initTokenOption } from "../../common/constants";
import type { CryptoFormStep } from "../../types";
import type { DonateValues as DV } from "./types";
Expand All @@ -17,6 +19,8 @@ export function useRhf(props: Props) {
reset,
setValue,
handleSubmit,
getValues,
trigger,
control,
formState: { errors },
} = useForm<DV>({
Expand All @@ -39,12 +43,23 @@ export function useRhf(props: Props) {
name: "token",
});

const onIncrement: OnIncrement = (inc) => {
const token = getValues("token");
const amnt = Number(token.amount);
if (Number.isNaN(amnt)) return trigger("token", { shouldFocus: true });
setValue("token", {
...token,
amount: roundDown(amnt + inc, centsDecimals(token.rate, token.precision)),
});
};

return {
program,
reset,
setValue,
handleSubmit,
token,
onIncrement,
errors: {
token: errors.token?.amount?.message || errors.token?.id?.message,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,9 +176,9 @@ describe("Stripe form test", () => {
await userEvent.clear(amountInput);
await userEvent.type(amountInput, "13");
await userEvent.click(incrementers[0]); // 50PHP * 40
expect(amountInput).toHaveDisplayValue("2013");
expect(amountInput).toHaveDisplayValue("2013.00");

await userEvent.click(incrementers[1]); // 50PHP * 100
expect(amountInput).toHaveDisplayValue("7013");
expect(amountInput).toHaveDisplayValue("7013.00");
});
});
4 changes: 3 additions & 1 deletion src/components/donation/Steps/DonateMethods/Stripe/useRhf.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { yupResolver } from "@hookform/resolvers/yup";
import { centsDecimals, roundDown } from "helpers";
import { useController, useForm } from "react-hook-form";
import { schema, stringNumber } from "schemas/shape";
import { requiredString } from "schemas/string";
Expand Down Expand Up @@ -61,9 +62,10 @@ export function useRhf(props: Omit<FormProps, "currencies">) {
});

const onIncrement: OnIncrement = (inc) => {
const currency = getValues("currency");
const amntNum = Number(getValues("amount"));
if (Number.isNaN(amntNum)) return trigger("amount", { shouldFocus: true });
setValue("amount", `${inc + amntNum}`);
setValue("amount", roundDown(amntNum + inc, centsDecimals(currency.rate)));
};

return {
Expand Down
29 changes: 18 additions & 11 deletions src/components/donation/Steps/common/Incrementers.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { DONATION_INCREMENTS } from "constants/common";
import { humanize, roundDownToNum } from "helpers";
import { centsDecimals, humanize } from "helpers";

export type OnIncrement = (increment: number) => void;

interface Props {
rate: number;
precision?: number;
code: string;
onIncrement: OnIncrement;
increments?: number[];
Expand All @@ -31,17 +32,22 @@ interface IIncrementer extends Props {
inc: number;
}

function Incrementer({ rate, inc, code, onIncrement }: IIncrementer) {
function Incrementer({
rate,
inc,
code,
onIncrement,
precision = 2,
}: IIncrementer) {
const value = rate * inc;
const roundedVal = roundDownToNum(value, 0);
return (
<button
data-testid="incrementer"
type="button"
className="text-sm font-medium border border-gray-l4 hover:border-gray-l3 rounded-full w-[7rem] h-10"
onClick={() => onIncrement(roundedVal)}
className="text-sm font-medium border border-gray-l4 hover:border-gray-l3 rounded-full p-3"
onClick={() => onIncrement(value)}
>
+{shortenHumanize(roundedVal)} {code.toUpperCase()}
+{shortenHumanize(value, rate, precision)} {code.toUpperCase()}
</button>
);
}
Expand All @@ -51,17 +57,18 @@ function Incrementer({ rate, inc, code, onIncrement }: IIncrementer) {
* containing enough precision to be of use to the end user. Numbers passed through
* should only have at most 5 digits in total (2 before the decimal, 3 digits after).
*/
function shortenHumanize(num: number): string {
function shortenHumanize(num: number, rate: number, precision = 2): string {
const decimals = centsDecimals(rate, precision);
if (num > 1e10) {
// numbers over 10 Billion
return `${humanize(num / 1e9, 3)}B`;
return `${humanize(num / 1e9, decimals)}B`;
} else if (num > 1e7) {
// numbers over 10 Million
return `${humanize(num / 1e6, 3)}M`;
return `${humanize(num / 1e6, decimals)}M`;
} else if (num > 1e4) {
// numbers over 10 Thousand
return `${humanize(num / 1e3, 3)}K`;
return `${humanize(num / 1e3, decimals)}K`;
}
// all other numbers under 10 Thousand
return `${num}`;
return humanize(num, decimals);
}

0 comments on commit a8c77c5

Please sign in to comment.