diff --git a/apps/frontend/src/assets/business-handshake.svg b/apps/frontend/src/assets/business-handshake.svg new file mode 100644 index 000000000..e554b8c96 --- /dev/null +++ b/apps/frontend/src/assets/business-handshake.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/frontend/src/assets/coins/COP.png b/apps/frontend/src/assets/coins/COP.png new file mode 100644 index 000000000..f6826a475 Binary files /dev/null and b/apps/frontend/src/assets/coins/COP.png differ diff --git a/apps/frontend/src/assets/coins/EU.png b/apps/frontend/src/assets/coins/EU.png new file mode 100644 index 000000000..1636f1313 Binary files /dev/null and b/apps/frontend/src/assets/coins/EU.png differ diff --git a/apps/frontend/src/assets/coins/EUR.svg b/apps/frontend/src/assets/coins/EUR.svg deleted file mode 100644 index 9275f9dfa..000000000 --- a/apps/frontend/src/assets/coins/EUR.svg +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/apps/frontend/src/assets/coins/EURC.png b/apps/frontend/src/assets/coins/EURC.png deleted file mode 100644 index e0881a4f7..000000000 Binary files a/apps/frontend/src/assets/coins/EURC.png and /dev/null differ diff --git a/apps/frontend/src/assets/coins/MX.png b/apps/frontend/src/assets/coins/MX.png new file mode 100644 index 000000000..93760c1f1 Binary files /dev/null and b/apps/frontend/src/assets/coins/MX.png differ diff --git a/apps/frontend/src/assets/coins/USD.png b/apps/frontend/src/assets/coins/USD.png new file mode 100644 index 000000000..d24e4cf5f Binary files /dev/null and b/apps/frontend/src/assets/coins/USD.png differ diff --git a/apps/frontend/src/assets/coins/placeholder.svg b/apps/frontend/src/assets/coins/placeholder.svg index d90614e7c..e278354f2 100644 --- a/apps/frontend/src/assets/coins/placeholder.svg +++ b/apps/frontend/src/assets/coins/placeholder.svg @@ -1,5 +1,3 @@ - - - - + + diff --git a/apps/frontend/src/components/Alfredpay/AlfredpayKycFlow.tsx b/apps/frontend/src/components/Alfredpay/AlfredpayKycFlow.tsx index 077ee0488..8404bc788 100644 --- a/apps/frontend/src/components/Alfredpay/AlfredpayKycFlow.tsx +++ b/apps/frontend/src/components/Alfredpay/AlfredpayKycFlow.tsx @@ -1,28 +1,27 @@ -import { Trans, useTranslation } from "react-i18next"; +import { useCallback } from "react"; import { useAlfredpayKycActor, useAlfredpayKycSelector } from "../../contexts/rampState"; -import { cn } from "../../helpers/cn"; -import { Spinner } from "../Spinner"; +import { CustomerDefinitionScreen } from "./CustomerDefinitionScreen"; +import { DoneScreen } from "./DoneScreen"; +import { FailureKycScreen } from "./FailureKycScreen"; +import { FailureScreen } from "./FailureScreen"; +import { FillingScreen } from "./FillingScreen"; +import { LinkReadyScreen } from "./LinkReadyScreen"; +import { LoadingScreen } from "./LoadingScreen"; +import { OpeningLinkScreen } from "./OpeningLinkScreen"; +import { PollingScreen } from "./PollingScreen"; export const AlfredpayKycFlow = () => { - const { t } = useTranslation(); const actor = useAlfredpayKycActor(); const state = useAlfredpayKycSelector(); - const openLink = () => { - actor?.send({ type: "OPEN_LINK" }); - }; - - const completedFilling = () => { - actor?.send({ type: "COMPLETED_FILLING" }); - }; - - const toggleBusiness = () => { - actor?.send({ type: "TOGGLE_BUSINESS" }); - }; - - const userAccept = () => { - actor?.send({ type: "USER_ACCEPT" }); - }; + const openLink = useCallback(() => actor?.send({ type: "OPEN_LINK" }), [actor]); + const completedFilling = useCallback(() => actor?.send({ type: "COMPLETED_FILLING" }), [actor]); + const toggleBusiness = useCallback(() => actor?.send({ type: "TOGGLE_BUSINESS" }), [actor]); + const userAccept = useCallback(() => actor?.send({ type: "USER_ACCEPT" }), [actor]); + const userRetry = useCallback(() => actor?.send({ type: "USER_RETRY" }), [actor]); + const userCancel = useCallback(() => actor?.send({ type: "USER_CANCEL" }), [actor]); + const retryProcess = useCallback(() => actor?.send({ type: "RETRY_PROCESS" }), [actor]); + const cancelProcess = useCallback(() => actor?.send({ type: "CANCEL_PROCESS" }), [actor]); if (!actor || !state) return null; @@ -35,133 +34,53 @@ export const AlfredpayKycFlow = () => { stateValue === "GettingKycLink" || stateValue === "Retrying" ) { - return ( -
- -

{t("components.alfredpayKycFlow.loading")}

-
- ); + return ; } if (stateValue === "PollingStatus") { - return ( -
- -

{t("components.alfredpayKycFlow.verifyingStatus", { kycOrKyb })}

-

{t("components.alfredpayKycFlow.verifyingStatusDescription")}

-
- ); + return ; } if (stateValue === "LinkReady") { - return ( -
-

{t("components.alfredpayKycFlow.completeProcess", { kycOrKyb })}

- -
- ); + return ; } if (stateValue === "OpeningLink") { - return ( -
- -

{t("components.alfredpayKycFlow.openingLink")}

-
- ); + return ; } if (stateValue === "FillingKyc" || stateValue === "FinishingFilling") { - const isSubmitting = stateValue === "FinishingFilling"; - return ( -
-

{t("components.alfredpayKycFlow.completeInNewWindow", { kycOrKyb })}

- -
+ ); } if (stateValue === "Done") { - return ( -
-

{t("components.alfredpayKycFlow.completed", { kycOrKyb })}

-

{t("components.alfredpayKycFlow.accountVerified")}

- {/* Will not be rendered as the sub-state machine will stop and go to main kyc one */} -
- ); + return ; } if (stateValue === "FailureKyc") { return ( -
-

{t("components.alfredpayKycFlow.failed", { kycOrKyb })}

-

{context.error?.message || "An unknown error occurred."}

-
- - -
-
+ ); } if (stateValue === "Failure") { - return ( -
-

{t("components.alfredpayKycFlow.systemError")}

-

{context.error?.message || "An unknown error occurred."}

-
- - -
-
- ); + return ; } if (stateValue === "CostumerDefinition") { return ( -
-

{t("components.alfredpayKycFlow.continueWithPartner", { kycOrKyb })}

- -

- {context.business ? ( - - }} - i18nKey="components.alfredpayKycFlow.registerAsIndividual" - /> - ) : ( - - }} - i18nKey="components.alfredpayKycFlow.registerAsBusiness" - /> - )} -

-
+ ); } diff --git a/apps/frontend/src/components/Alfredpay/CustomerDefinitionScreen.tsx b/apps/frontend/src/components/Alfredpay/CustomerDefinitionScreen.tsx new file mode 100644 index 000000000..9d4e16750 --- /dev/null +++ b/apps/frontend/src/components/Alfredpay/CustomerDefinitionScreen.tsx @@ -0,0 +1,56 @@ +import { memo } from "react"; +import { Trans, useTranslation } from "react-i18next"; +import businessHandshake from "../../assets/business-handshake.svg"; +import livenessCheck from "../../assets/liveness-check.svg"; +import { MenuButtons } from "../MenuButtons"; +import { StepFooter } from "../StepFooter"; + +interface CustomerDefinitionScreenProps { + kycOrKyb: string; + isBusiness: boolean; + onAccept: () => void; + onToggleBusiness: () => void; +} + +const toggleLinkClass = + "cursor-pointer border-0 bg-transparent p-0 font-[inherit] text-blue-600 underline touch-manipulation [@media(hover:hover)]:hover:text-blue-800"; + +export const CustomerDefinitionScreen = memo( + ({ kycOrKyb, isBusiness, onAccept, onToggleBusiness }: CustomerDefinitionScreenProps) => { + const { t } = useTranslation(); + + return ( +
+ + {isBusiness ? ( + Business Handshake + ) : ( + Liveness Check + )} + +

+ {t("components.alfredpayKycFlow.continueWithPartner", { kycOrKyb })} +

+ +

+ + }} + i18nKey={ + isBusiness ? "components.alfredpayKycFlow.registerAsIndividual" : "components.alfredpayKycFlow.registerAsBusiness" + } + /> +

+ + + + +
+ ); + } +); + +CustomerDefinitionScreen.displayName = "CustomerDefinitionScreen"; diff --git a/apps/frontend/src/components/Alfredpay/DoneScreen.tsx b/apps/frontend/src/components/Alfredpay/DoneScreen.tsx new file mode 100644 index 000000000..9dc067270 --- /dev/null +++ b/apps/frontend/src/components/Alfredpay/DoneScreen.tsx @@ -0,0 +1,20 @@ +import { memo } from "react"; +import { useTranslation } from "react-i18next"; + +interface DoneScreenProps { + kycOrKyb: string; +} + +export const DoneScreen = memo(({ kycOrKyb }: DoneScreenProps) => { + const { t } = useTranslation(); + + return ( +
+

{t("components.alfredpayKycFlow.completed", { kycOrKyb })}

+

{t("components.alfredpayKycFlow.accountVerified")}

+ {/* Will not be rendered as the sub-state machine will stop and go to main kyc one */} +
+ ); +}); + +DoneScreen.displayName = "DoneScreen"; diff --git a/apps/frontend/src/components/Alfredpay/FailureKycScreen.tsx b/apps/frontend/src/components/Alfredpay/FailureKycScreen.tsx new file mode 100644 index 000000000..d44722395 --- /dev/null +++ b/apps/frontend/src/components/Alfredpay/FailureKycScreen.tsx @@ -0,0 +1,30 @@ +import { memo } from "react"; +import { useTranslation } from "react-i18next"; + +interface FailureKycScreenProps { + kycOrKyb: string; + errorMessage: string | undefined; + onRetry: () => void; + onCancel: () => void; +} + +export const FailureKycScreen = memo(({ kycOrKyb, errorMessage, onRetry, onCancel }: FailureKycScreenProps) => { + const { t } = useTranslation(); + + return ( +
+

{t("components.alfredpayKycFlow.failed", { kycOrKyb })}

+

{errorMessage ?? "An unknown error occurred."}

+
+ + +
+
+ ); +}); + +FailureKycScreen.displayName = "FailureKycScreen"; diff --git a/apps/frontend/src/components/Alfredpay/FailureScreen.tsx b/apps/frontend/src/components/Alfredpay/FailureScreen.tsx new file mode 100644 index 000000000..b3cdb308f --- /dev/null +++ b/apps/frontend/src/components/Alfredpay/FailureScreen.tsx @@ -0,0 +1,28 @@ +import { memo } from "react"; +import { useTranslation } from "react-i18next"; + +interface FailureScreenProps { + errorMessage: string | undefined; + onRetry: () => void; + onCancel: () => void; +} + +export const FailureScreen = memo(({ errorMessage, onRetry, onCancel }: FailureScreenProps) => { + const { t } = useTranslation(); + + return ( +
+

{errorMessage ?? "An unknown error occurred."}

+
+ + +
+
+ ); +}); + +FailureScreen.displayName = "FailureScreen"; diff --git a/apps/frontend/src/components/Alfredpay/FillingScreen.tsx b/apps/frontend/src/components/Alfredpay/FillingScreen.tsx new file mode 100644 index 000000000..c78886777 --- /dev/null +++ b/apps/frontend/src/components/Alfredpay/FillingScreen.tsx @@ -0,0 +1,31 @@ +import { memo } from "react"; +import { useTranslation } from "react-i18next"; +import { Spinner } from "../Spinner"; + +interface FillingScreenProps { + kycOrKyb: string; + isSubmitting: boolean; + onCompletedFilling: () => void; +} + +export const FillingScreen = memo(({ kycOrKyb, isSubmitting, onCompletedFilling }: FillingScreenProps) => { + const { t } = useTranslation(); + + return ( +
+

{t("components.alfredpayKycFlow.completeInNewWindow", { kycOrKyb })}

+ +
+ ); +}); + +FillingScreen.displayName = "FillingScreen"; diff --git a/apps/frontend/src/components/Alfredpay/LinkReadyScreen.tsx b/apps/frontend/src/components/Alfredpay/LinkReadyScreen.tsx new file mode 100644 index 000000000..1f0e279d2 --- /dev/null +++ b/apps/frontend/src/components/Alfredpay/LinkReadyScreen.tsx @@ -0,0 +1,22 @@ +import { memo } from "react"; +import { useTranslation } from "react-i18next"; + +interface LinkReadyScreenProps { + kycOrKyb: string; + onOpenLink: () => void; +} + +export const LinkReadyScreen = memo(({ kycOrKyb, onOpenLink }: LinkReadyScreenProps) => { + const { t } = useTranslation(); + + return ( +
+

{t("components.alfredpayKycFlow.completeProcess", { kycOrKyb })}

+ +
+ ); +}); + +LinkReadyScreen.displayName = "LinkReadyScreen"; diff --git a/apps/frontend/src/components/Alfredpay/LoadingScreen.tsx b/apps/frontend/src/components/Alfredpay/LoadingScreen.tsx new file mode 100644 index 000000000..50286414a --- /dev/null +++ b/apps/frontend/src/components/Alfredpay/LoadingScreen.tsx @@ -0,0 +1,16 @@ +import { memo } from "react"; +import { useTranslation } from "react-i18next"; +import { Spinner } from "../Spinner"; + +export const LoadingScreen = memo(() => { + const { t } = useTranslation(); + + return ( +
+ +

{t("components.alfredpayKycFlow.loading")}

+
+ ); +}); + +LoadingScreen.displayName = "LoadingScreen"; diff --git a/apps/frontend/src/components/Alfredpay/OpeningLinkScreen.tsx b/apps/frontend/src/components/Alfredpay/OpeningLinkScreen.tsx new file mode 100644 index 000000000..4c7582ca1 --- /dev/null +++ b/apps/frontend/src/components/Alfredpay/OpeningLinkScreen.tsx @@ -0,0 +1,16 @@ +import { memo } from "react"; +import { useTranslation } from "react-i18next"; +import { Spinner } from "../Spinner"; + +export const OpeningLinkScreen = memo(() => { + const { t } = useTranslation(); + + return ( +
+ +

{t("components.alfredpayKycFlow.openingLink")}

+
+ ); +}); + +OpeningLinkScreen.displayName = "OpeningLinkScreen"; diff --git a/apps/frontend/src/components/Alfredpay/PollingScreen.tsx b/apps/frontend/src/components/Alfredpay/PollingScreen.tsx new file mode 100644 index 000000000..8d0b554d0 --- /dev/null +++ b/apps/frontend/src/components/Alfredpay/PollingScreen.tsx @@ -0,0 +1,21 @@ +import { memo } from "react"; +import { useTranslation } from "react-i18next"; +import { Spinner } from "../Spinner"; + +interface PollingScreenProps { + kycOrKyb: string; +} + +export const PollingScreen = memo(({ kycOrKyb }: PollingScreenProps) => { + const { t } = useTranslation(); + + return ( +
+ +

{t("components.alfredpayKycFlow.verifyingStatus", { kycOrKyb })}

+

{t("components.alfredpayKycFlow.verifyingStatusDescription")}

+
+ ); +}); + +PollingScreen.displayName = "PollingScreen"; diff --git a/apps/frontend/src/components/Avenia/AveniaKYBFlow/AveniaKYBVerifyStep.tsx b/apps/frontend/src/components/Avenia/AveniaKYBFlow/AveniaKYBVerifyStep.tsx index 4eaedbb91..cc4779498 100644 --- a/apps/frontend/src/components/Avenia/AveniaKYBFlow/AveniaKYBVerifyStep.tsx +++ b/apps/frontend/src/components/Avenia/AveniaKYBFlow/AveniaKYBVerifyStep.tsx @@ -28,7 +28,6 @@ export const AveniaKYBVerifyStep = ({ instructionsKey = "components.aveniaKYB.instructions", cancelButtonKey = "components.aveniaKYB.buttons.cancel" }: AveniaKYBVerifyStepProps) => { - const quote = useQuote(); const { t } = useTranslation(); return ( @@ -79,7 +78,7 @@ export const AveniaKYBVerifyStep = ({ - +
); }; diff --git a/apps/frontend/src/components/Avenia/AveniaKYCForm.tsx b/apps/frontend/src/components/Avenia/AveniaKYCForm.tsx index 2e23100c6..4d02236d7 100644 --- a/apps/frontend/src/components/Avenia/AveniaKYCForm.tsx +++ b/apps/frontend/src/components/Avenia/AveniaKYCForm.tsx @@ -2,7 +2,6 @@ import { isValidCnpj } from "@vortexfi/shared"; import { useTranslation } from "react-i18next"; import { useAveniaKycActor, useAveniaKycSelector } from "../../contexts/rampState"; import { useKYCForm } from "../../hooks/brla/useKYCForm"; -import { useQuote } from "../../stores/quote/useQuoteStore"; import { QuoteSummary } from "../QuoteSummary"; import { StepBackButton } from "../StepBackButton"; import { AveniaLivenessStep } from "../widget-steps/AveniaLivenessStep"; @@ -14,7 +13,6 @@ import { VerificationStatus } from "./VerificationStatus"; export const AveniaKYCForm = () => { const aveniaKycActor = useAveniaKycActor(); const aveniaState = useAveniaKycSelector(); - const quote = useQuote(); const { t } = useTranslation(); const { kycForm } = useKYCForm({ cpfApiError: null, initialData: aveniaState?.context.kycFormData }); @@ -154,7 +152,7 @@ export const AveniaKYCForm = () => { {content} - {quote && } + ); }; diff --git a/apps/frontend/src/components/Avenia/AveniaVerificationForm/index.tsx b/apps/frontend/src/components/Avenia/AveniaVerificationForm/index.tsx index 1df0d9896..00ebda4ff 100644 --- a/apps/frontend/src/components/Avenia/AveniaVerificationForm/index.tsx +++ b/apps/frontend/src/components/Avenia/AveniaVerificationForm/index.tsx @@ -77,7 +77,7 @@ export const AveniaVerificationForm = ({ form, fields, aveniaKycActor, isCompany )} - +