Skip to content

Commit

Permalink
fix: split components into three
Browse files Browse the repository at this point in the history
  • Loading branch information
Olha committed Mar 5, 2025
1 parent bac3534 commit 5d8e84e
Show file tree
Hide file tree
Showing 9 changed files with 435 additions and 92 deletions.
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
import {useAnalyticsContext} from '@atb/analytics';
import {
Amex,
MasterCard,
Vipps,
Visa,
} from '@atb/assets/svg/color/icons/ticketing';
import {useBottomSheetContext} from '@atb/components/bottom-sheet';
import {Button} from '@atb/components/button';
import {MessageInfoBox} from '@atb/components/message-info-box';
Expand Down Expand Up @@ -52,6 +46,9 @@ import {closeInAppBrowseriOS} from '@atb/in-app-browser';
import {openInAppBrowser} from '@atb/in-app-browser/in-app-browser';
import {APP_SCHEME} from '@env';
import {useAuthContext} from '@atb/auth';
import {GenericSectionItem, Section} from '@atb/components/sections';
import {formatNumberToString} from '@atb/utils/numbers';
import {PaymentSelectionCard} from './components/PaymentCard';

type Props = RootStackScreenProps<'Root_PurchaseConfirmationScreen'>;

Expand All @@ -61,7 +58,7 @@ export const Root_PurchaseConfirmationScreen: React.FC<Props> = ({
}) => {
const styles = useStyles();
const {theme} = useThemeContext();
const {t} = useTranslation();
const {t, language} = useTranslation();
const {userId} = useAuthContext();

const interactiveColor = theme.color.interactive[0];
Expand Down Expand Up @@ -108,6 +105,7 @@ export const Root_PurchaseConfirmationScreen: React.FC<Props> = ({
offer_id,
}),
);
const totalPriceString = formatNumberToString(totalPrice, language);

const reserveMutation = useReserveOfferMutation({
offers,
Expand Down Expand Up @@ -191,28 +189,6 @@ export const Root_PurchaseConfirmationScreen: React.FC<Props> = ({
}
}

function getPaymentMethodTexts(method: PaymentMethod): string {
let str;
switch (method.paymentType) {
case PaymentType.Vipps:
str = t(PurchaseConfirmationTexts.payWithVipps.text);
break;
case PaymentType.Visa:
str = t(PurchaseConfirmationTexts.payWithVisa.text);
break;
case PaymentType.Mastercard:
str = t(PurchaseConfirmationTexts.payWithMasterCard.text);
break;
case PaymentType.Amex:
str = t(PurchaseConfirmationTexts.payWithAmex.text);
break;
}
if (method.recurringCard) {
str = str + ` (**** ${method.recurringCard.masked_pan})`;
}
return str;
}

async function selectPaymentMethod() {
openBottomSheet(() => {
return (
Expand Down Expand Up @@ -318,6 +294,16 @@ export const Root_PurchaseConfirmationScreen: React.FC<Props> = ({
type="error"
/>
)}
{paymentMethod && (
<Section>
<GenericSectionItem>
<PaymentSelectionCard
card={paymentMethod}
startAction={selectPaymentMethod}
/>
</GenericSectionItem>
</Section>
)}
{isSearchingOffer ? (
<ActivityIndicator
size="large"
Expand All @@ -330,12 +316,11 @@ export const Root_PurchaseConfirmationScreen: React.FC<Props> = ({
<View style={styles.flexColumn}>
<Button
expanded={true}
text={getPaymentMethodTexts(paymentMethod)}
text={t(
PurchaseConfirmationTexts.payTotal.text(totalPriceString),
)}
interactiveColor={interactiveColor}
disabled={!!offerError}
rightIcon={{
svg: getPaymentTypeSvg(paymentMethod.paymentType),
}}
onPress={() => {
analytics.logEvent(
'Ticketing',
Expand Down Expand Up @@ -401,19 +386,6 @@ export const Root_PurchaseConfirmationScreen: React.FC<Props> = ({
);
};

function getPaymentTypeSvg(paymentType: PaymentType) {
switch (paymentType) {
case PaymentType.Mastercard:
return MasterCard;
case PaymentType.Vipps:
return Vipps;
case PaymentType.Visa:
return Visa;
case PaymentType.Amex:
return Amex;
}
}

const useStyles = StyleSheet.createThemeHook((theme) => ({
container: {
flex: 1,
Expand All @@ -422,6 +394,7 @@ const useStyles = StyleSheet.createThemeHook((theme) => ({
flexColumn: {
flex: 1,
flexDirection: 'column',
marginVertical: theme.spacing.medium,
},
flexRowCenter: {
flex: 1,
Expand All @@ -441,4 +414,40 @@ const useStyles = StyleSheet.createThemeHook((theme) => ({
purchaseInformation: {
marginBottom: theme.spacing.medium,
},
content: {
padding: theme.spacing.medium,
rowGap: theme.spacing.medium,
},
card: {flex: 1, paddingVertical: theme.spacing.small},
cardTop: {
flex: 1,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
},
cardIcons: {
flex: 1,
flexDirection: 'row',
alignItems: 'center',
flexGrow: 1,
justifyContent: 'flex-end',
},
paymentMethod: {
display: 'flex',
flexDirection: 'column',
rowGap: theme.spacing.xSmall,
paddingLeft: theme.spacing.medium,
marginRight: 'auto',
},
maskedPan: {
color: theme.color.foreground.dynamic.secondary,
},

actionButton: {
marginLeft: theme.spacing.medium,
display: 'flex',
flexDirection: 'row',
columnGap: theme.spacing.small,
paddingHorizontal: theme.spacing.medium,
},
}));
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@ import {
Visa,
} from '@atb/assets/svg/color/icons/ticketing';
import {useFontScale} from '@atb/utils/use-font-scale';
import {Card} from '@atb/assets/svg/mono-icons/ticketing';

export type Brand = {
paymentType: PaymentType;
paymentType: PaymentType | undefined;
size?: number;
};

Expand All @@ -26,7 +27,7 @@ export const PaymentBrand: React.FC<Brand> = ({paymentType, size = 20}) => {
const Logo = ({
paymentType,
}: {
paymentType: PaymentType;
paymentType: PaymentType | undefined;
}): JSX.Element | null => {
switch (paymentType) {
case PaymentType.Visa:
Expand All @@ -38,6 +39,6 @@ const Logo = ({
case PaymentType.Amex:
return <Amex height="100%" width="100%" />;
default:
return null;
return <Card height="100%" width="100%" />;
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
import {PressableOpacity} from '@atb/components/pressable-opacity';
import {ThemeText} from '@atb/components/text';

import {StyleSheet, useThemeContext} from '@atb/theme';
import {humanizePaymentType, PaymentType} from '@atb/ticketing';
import {useTranslation} from '@atb/translations';
import React from 'react';

import {useFontScale} from '@atb/utils/use-font-scale';
import {PaymentBrand} from './PaymentBrand';
import PaymentMethodsTexts from '@atb/translations/screens/subscreens/PaymentMethods';
import {MessageInfoText} from '@atb/components/message-info-text';
import SelectPaymentMethodTexts from '@atb/translations/screens/subscreens/SelectPaymentMethodTexts';
import SvgEdit from '@atb/assets/svg/mono-icons/actions/Edit';
import {View} from 'react-native';
import {PaymentMethod} from '@atb/stacks-hierarchy/types';

export type Brand = {
paymentType: PaymentType | undefined;
size?: number;
};

export const PaymentSelectionCard = (props: {
card: PaymentMethod;
startAction: Function;
}) => {
const {card, startAction} = props;
const paymentName = humanizePaymentType(card.paymentType);
const style = useStyles();
const {theme} = useThemeContext();
const {t} = useTranslation();
const fontScale = useFontScale();
const multiplePaymentMethods = !(
card.recurringCard || card.paymentType === PaymentType.Vipps
);

return (
<View style={style.card}>
<View style={style.cardTop}>
<PaymentBrand
paymentType={multiplePaymentMethods ? undefined : card.paymentType}
/>
<View style={style.paymentMethod}>
<ThemeText>
{multiplePaymentMethods
? t(SelectPaymentMethodTexts.multiple_payment.title)
: paymentName}
</ThemeText>
{!multiplePaymentMethods &&
card.paymentType !== PaymentType.Vipps && (
<ThemeText
style={style.maskedPan}
accessibilityLabel={t(
PaymentMethodsTexts.a11y.cardInfo(
paymentName,
card.recurringCard?.masked_pan ?? '',
),
)}
>
**** {card.recurringCard?.masked_pan}
</ThemeText>
)}
</View>

<View style={style.cardIcons}>
<PressableOpacity
accessibilityLabel={t(
PaymentMethodsTexts.a11y.deleteCardIcon(
paymentName,
card.recurringCard?.masked_pan ?? '',
),
)}
style={style.actionButton}
onPress={() => {
startAction();
}}
>
<ThemeText>{t(PaymentMethodsTexts.editPaymentMethod)}</ThemeText>
<SvgEdit
height={21 * fontScale}
width={21 * fontScale}
fill={theme.color.foreground.dynamic.primary}
/>
</PressableOpacity>
</View>
</View>
{false && (
<>
{/* this is just a template for the future message implementation */}
<MessageInfoText
style={style.warningMessage}
message="Expiration messsage"
type="warning"
/>
</>
)}
</View>
);
};

const useStyles = StyleSheet.createThemeHook((theme) => ({
warningMessage: {
marginBottom: theme.spacing.medium,
},

card: {flex: 1, paddingVertical: theme.spacing.small},
cardTop: {
flex: 1,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-between',
},
cardIcons: {
flex: 1,
flexDirection: 'row',
alignItems: 'center',
flexGrow: 1,
justifyContent: 'flex-end',
},
paymentMethod: {
display: 'flex',
flexDirection: 'column',
rowGap: theme.spacing.xSmall,
paddingLeft: theme.spacing.medium,
marginRight: 'auto',
},
maskedPan: {
color: theme.color.foreground.dynamic.secondary,
},

actionButton: {
marginLeft: theme.spacing.medium,
display: 'flex',
flexDirection: 'row',
columnGap: theme.spacing.small,
paddingHorizontal: theme.spacing.medium,
},
}));
Loading

0 comments on commit 5d8e84e

Please sign in to comment.