Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 32 additions & 1 deletion sdk/src/bff-marshal.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import { BffBusiness } from "./backend-types/business";
import { BffChannel, BffChannelUiGroup } from "./backend-types/channel";
import { BffSucceededChannel } from "./backend-types/common";
import { BffCustomer } from "./backend-types/customer";
import { BffDigitalWallets } from "./backend-types/digital-wallets";
import { BffSession } from "./backend-types/session";
import { internal } from "./internal";
import {
XenditBusiness,
XenditCustomer,
XenditDigitalWallet,
XenditPaymentChannel,
XenditPaymentChannelGroup,
XenditSession,
XenditSucceededChannel,
} from "./public-data-types";
import {
assert,
Expand All @@ -23,7 +27,7 @@ type XenditItem = NonNullable<XenditSession["items"]>[number];

export function bffSessionToPublic(bffSession: BffSession): XenditSession {
assertNotEquals(bffSession.session_type, "AUTHORIZATION");
assertEquals(bffSession.mode, "COMPONENTS");
assertNotEquals(bffSession.mode, "CARDS_SESSION_JS");

return removeUndefinedPropertiesFromObject<XenditSession>({
id: bffSession.payment_session_id,
Expand All @@ -38,6 +42,7 @@ export function bffSessionToPublic(bffSession: BffSession): XenditSession {
expiresAt: new Date(bffSession.expires_at),
locale: bffSession.locale,
status: bffSession.status,
updated: new Date(bffSession.updated),
successReturnUrl: bffSession.success_return_url,
cancelReturnUrl: bffSession.cancel_return_url,
captureMethod: bffSession.capture_method,
Expand Down Expand Up @@ -76,6 +81,20 @@ export function bffSessionToPublic(bffSession: BffSession): XenditSession {
});
}

export function bffBusinessToPublic(
bffBusiness: BffBusiness | null,
): XenditBusiness | null {
if (!bffBusiness) {
return null;
}
return {
name: bffBusiness.name ?? undefined,
countryOfOperation: bffBusiness.country_of_operation ?? undefined,
merchantProfilePictureUrl:
bffBusiness.merchant_profile_picture_url ?? undefined,
};
}

export function bffCustomerToPublic(
bffCustomer: BffCustomer | null,
): XenditCustomer | null {
Expand All @@ -96,6 +115,18 @@ export function bffCustomerToPublic(
};
}

export function bffSucceededChannelToPublic(
bffSucceededChannel: BffSucceededChannel | null,
): XenditSucceededChannel | null {
if (!bffSucceededChannel) {
return null;
}
return {
channelCode: bffSucceededChannel.channel_code,
logoUrl: bffSucceededChannel.logo_url,
};
}

type ChannelMarshalConfig = {
options: {
filter?: string | string[] | RegExp;
Expand Down
27 changes: 16 additions & 11 deletions sdk/src/components/action-barcode.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { ComponentChildren } from "preact";
import { useCallback, useMemo, useState } from "preact/hooks";
import { amountFormat } from "../amount-format";
import { Instructions as InstructionsType } from "../backend-types/instructions";
import { TFunction } from "../localization";
import { generateBarcodeSvg } from "./action-barcode-utils";
import { useActionCard } from "./action-card";
import { Button, ButtonLoadingSpinner, ButtonVariant } from "./core/button";
import { Instructions } from "./instructions";

type Props = {
amount: number;
Expand All @@ -14,7 +14,7 @@ type Props = {
barcodeContent: string;
merchantName: string;
paymentCode: string;
instructions: InstructionsType;
renderInstructions: () => ComponentChildren;
title: string;
t: TFunction;
};
Expand All @@ -27,12 +27,13 @@ export function ActionBarcode(props: Props) {
onAffirm,
barcodeContent,
merchantName,
instructions,
renderInstructions,
title,
t,
} = props;

const [showSpinner, setShowSpinner] = useState(false);
const inActionCard = useActionCard();

const onMadePaymentClicked = useCallback(() => {
setShowSpinner(true);
Expand Down Expand Up @@ -68,12 +69,16 @@ export function ActionBarcode(props: Props) {

return (
<div className="xendit-action-present-to-customer">
<img
src={channelLogo}
alt="Channel Logo"
className="xendit-action-barcode-channel-logo"
/>
<div className="xendit-action-title">{title}</div>
{!inActionCard ? (
<>
<img
src={channelLogo}
alt="Channel Logo"
className="xendit-action-barcode-channel-logo"
/>
<div className="xendit-action-title">{title}</div>
</>
) : null}
<div
data-testid="barcode"
className="xendit-action-barcode-barcode-container"
Expand Down Expand Up @@ -115,7 +120,7 @@ export function ActionBarcode(props: Props) {
{t("action.payment_confirmation_instructions")}
</div>
</div>
<Instructions instructions={instructions} />
{renderInstructions()}
</div>
);
}
63 changes: 63 additions & 0 deletions sdk/src/components/action-card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { ComponentChildren, createContext } from "preact";
import { useContext } from "preact/hooks";

export type ActionCardProps = {
children: ComponentChildren;
color: string;
title?: string;
channelBrandName: string;
channelBrandLogoUrl: string;
actionIconSrc?: string;
actionText: string;
removePadding?: boolean;
};

const ActionCardContext = createContext(false);

export function ActionCard(props: ActionCardProps) {
return (
<div className="xendit-action-card-wrapper">
<div className="xendit-action-channel-info">
<img
className="xendit-action-channel-logo"
src={props.channelBrandLogoUrl}
alt=""
/>
<div className="xendit-action-heading xendit-text-24 xendit-text-semibold">
{props.title || props.channelBrandName}
</div>
</div>
<div
className="xendit-action-card"
style={{ backgroundColor: props.color ?? "#000" }}
>
<div className="xendit-action-card-text">
{props.actionIconSrc ? (
<img
className="xendit-action-card-icon"
src={props.actionIconSrc}
alt=""
/>
) : null}
<span className="xendit-text-12 xendit-text-inverse xendit-text-semibold">
{props.actionText}
</span>
</div>
<div
className="xendit-action-card-inner-content"
style={{
padding: props.removePadding ? 0 : null,
}}
>
<ActionCardContext.Provider value={true}>
{props.children}
</ActionCardContext.Provider>
</div>
</div>
</div>
);
}

export function useActionCard() {
return useContext(ActionCardContext);
}
80 changes: 44 additions & 36 deletions sdk/src/components/action-qr-custom-art.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import Icon from "./icon";

export type QrArtComponentProps = {
channelName: string;
channelLogo: string;
channelLogo?: string;
amountText: string;
qr: ComponentChildren;
merchantName: string;
Expand Down Expand Up @@ -68,14 +68,16 @@ function QrArtQris(props: QrArtComponentProps) {
}}
>
{hardcodedGraphics.closeButton({})}
<img
src={channelLogo}
alt={t("image_alt.channel_logo", { channelName })}
style={{
height: "64px",
alignSelf: "center",
}}
/>
{channelLogo ? (
<img
src={channelLogo}
alt={t("image_alt.channel_logo", { channelName })}
style={{
height: "64px",
alignSelf: "center",
}}
/>
) : null}
<div
className="xendit-text-center xendit-text-16"
style={{
Expand Down Expand Up @@ -236,15 +238,17 @@ function QrArtPaynow(props: QrArtComponentProps) {
overflow: "hidden",
}}
>
<img
src={channelLogo}
alt={t("image_alt.channel_logo", { channelName })}
style={{
height: "56px",
alignSelf: "center",
marginBottom: "8px",
}}
/>
{channelLogo ? (
<img
src={channelLogo}
alt={t("image_alt.channel_logo", { channelName })}
style={{
height: "56px",
alignSelf: "center",
marginBottom: "8px",
}}
/>
) : null}
{hardcodedGraphics.closeButton({})}
<div
style={{
Expand Down Expand Up @@ -387,15 +391,17 @@ function QrArtPromptPay(props: QrArtComponentProps) {
padding: "0 16px",
}}
>
<img
src={channelLogo}
alt={t("image_alt.channel_logo", { channelName })}
style={{
height: "56px",
alignSelf: "center",
marginTop: "16px",
}}
/>
{channelLogo ? (
<img
src={channelLogo}
alt={t("image_alt.channel_logo", { channelName })}
style={{
height: "56px",
alignSelf: "center",
marginTop: "16px",
}}
/>
) : null}
<div style={{ padding: "16px 42px" }}>{props.qr}</div>
<div
className="xendit-text-center xendit-text-semibold"
Expand Down Expand Up @@ -432,15 +438,17 @@ export function QrArtQrPh(props: QrArtComponentProps) {
overflow: "hidden",
}}
>
<img
src={channelLogo}
alt={t("image_alt.channel_logo", { channelName })}
style={{
height: "48px",
alignSelf: "center",
marginBottom: "16px",
}}
/>
{channelLogo ? (
<img
src={channelLogo}
alt={t("image_alt.channel_logo", { channelName })}
style={{
height: "48px",
alignSelf: "center",
marginBottom: "16px",
}}
/>
) : null}
{hardcodedGraphics.closeButton({})}
<div
style={{
Expand Down
17 changes: 11 additions & 6 deletions sdk/src/components/action-qr.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
QrArtConfig,
timestampForFilename,
} from "./action-qr-utils";
import { useActionCard } from "./action-card";

type Props = {
amount: number;
Expand Down Expand Up @@ -115,6 +116,8 @@ export function ActionQr(props: Props) {
[amount, businessName, channelName, currency, qrString],
);

const inActionCard = useActionCard();

if (props.hideUi) {
return (
<div
Expand Down Expand Up @@ -175,7 +178,7 @@ export function ActionQr(props: Props) {
return (
<>
<QrArtComponent
channelLogo={channelLogo}
channelLogo={inActionCard ? undefined : channelLogo}
channelName={channelName}
merchantName={businessName}
amountText={amountText}
Expand All @@ -197,11 +200,13 @@ export function ActionQr(props: Props) {
} else {
return (
<div className="xendit-action-present-to-customer">
<img
src={channelLogo}
alt={t("image_alt.channel_logo", { channelName })}
className="xendit-action-qr-channel-logo"
/>
{inActionCard ? null : (
<img
src={channelLogo}
alt={t("image_alt.channel_logo", { channelName })}
className="xendit-action-qr-channel-logo"
/>
)}
<div className="xendit-action-qr-content">
<div className="xendit-text-16 xendit-text-center xendit-qr-merchant-info">
<div className="xendit-text-semibold">{businessName}</div>
Expand Down
Loading
Loading