Skip to content

Commit

Permalink
feat: add payment error message (#1712)
Browse files Browse the repository at this point in the history
  • Loading branch information
rosvik authored Oct 27, 2021
1 parent 3da42fe commit ec7ff24
Show file tree
Hide file tree
Showing 8 changed files with 78 additions and 10 deletions.
15 changes: 9 additions & 6 deletions src/components/message-box/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@ import {useTranslation} from '@atb/translations';

type WithMessage = {
message: string;
retryFunction?: () => void;
onPress?: () => void;
onPressText?: string;
children?: never;
};
type WithChildren = {
message?: never;
retryFunction?: never;
onPress?: never;
onPressText?: string;
children: React.ReactNode;
};
export type MessageType = Statuses;
Expand All @@ -39,7 +41,8 @@ const MessageBox: React.FC<MessageBoxProps> = ({
children,
title,
withMargin = false,
retryFunction,
onPress,
onPressText = 'OK',
}) => {
const {theme} = useTheme();
const styles = useBoxStyle();
Expand All @@ -56,13 +59,13 @@ const MessageBox: React.FC<MessageBoxProps> = ({
<ThemeText style={{...styles.text, color: textColor}}>
{message}
</ThemeText>
{retryFunction && (
{onPress && (
<ThemeText
style={[styles.retryText, {color: textColor}]}
type="body__primary--underline"
onPress={retryFunction}
onPress={onPress}
>
{t(MessageBoxTexts.tryAgainButton)}
{onPressText}
</ThemeText>
)}
</>
Expand Down
2 changes: 1 addition & 1 deletion src/screens/Profile/DesignSystem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export default function DesignSystem() {
message="This is an error with retry link"
title="Title"
type="error"
retryFunction={presser}
onPress={presser}
/>
</Sections.GenericItem>
</Sections.Section>
Expand Down
4 changes: 3 additions & 1 deletion src/screens/Ticketing/Purchase/Confirmation/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {SelectPaymentMethod} from '../Payment';
import {CardPaymentMethod, PaymentMethod, SavedPaymentOption} from '../types';
import {useAuthState} from '@atb/auth';
import {usePreviousPaymentMethod} from '../saved-payment-utils';
import MessageBoxTexts from '@atb/translations/components/MessageBox';

export type RouteParams = {
preassignedFareProduct: PreassignedFareProduct;
Expand Down Expand Up @@ -222,7 +223,8 @@ const Confirmation: React.FC<ConfirmationProps> = ({
type="error"
title={t(PurchaseConfirmationTexts.errorMessageBox.title)}
message={t(PurchaseConfirmationTexts.errorMessageBox.message)}
retryFunction={refreshOffer}
onPress={refreshOffer}
onPressText={t(MessageBoxTexts.tryAgainButton)}
containerStyle={styles.errorMessage}
/>
)}
Expand Down
4 changes: 3 additions & 1 deletion src/screens/Ticketing/Purchase/Overview/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import FullScreenHeader from '@atb/components/screen-header/full-header';
import TravellersSheet from '@atb/screens/Ticketing/Purchase/Travellers/TravellersSheet';
import TravelDateSheet from '@atb/screens/Ticketing/Purchase/TravelDate/TravelDateSheet';
import {useTicketState} from '@atb/tickets';
import MessageBoxTexts from '@atb/translations/components/MessageBox';

export type OverviewProps = {
navigation: DismissableStackNavigationProp<
Expand Down Expand Up @@ -161,7 +162,8 @@ const PurchaseOverview: React.FC<OverviewProps> = ({
type="error"
title={t(PurchaseOverviewTexts.errorMessageBox.title)}
message={t(PurchaseOverviewTexts.errorMessageBox.message)}
retryFunction={refreshOffer}
onPress={refreshOffer}
onPressText={t(MessageBoxTexts.tryAgainButton)}
containerStyle={styles.errorMessage}
/>
)}
Expand Down
2 changes: 2 additions & 0 deletions src/screens/Ticketing/Tickets/Tabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ export const ActiveTickets: React.FC<Props> = () => {
isRefreshingTickets,
refreshTickets,
customerProfile,
didPaymentFail,
} = useTicketState();

const activeFareContracts = filterActiveOrCanBeUsedFareContracts(
Expand Down Expand Up @@ -178,6 +179,7 @@ export const ActiveTickets: React.FC<Props> = () => {
noTicketsLabel={t(TicketsTexts.activeTicketsTab.noTickets)}
now={now}
travelCard={customerProfile?.travelcard}
didPaymentFail={didPaymentFail}
/>
</View>
);
Expand Down
23 changes: 22 additions & 1 deletion src/screens/Ticketing/Tickets/TicketsScrollView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,12 @@ import ThemeText from '@atb/components/text';
import ErrorBoundary from '@atb/error-boundary';
import {RootStackParamList} from '@atb/navigation';
import {StyleSheet, useTheme} from '@atb/theme';
import {ActiveReservation, FareContract, TravelCard} from '@atb/tickets';
import {
ActiveReservation,
FareContract,
TravelCard,
useTicketState,
} from '@atb/tickets';
import {TicketsTexts, useTranslation} from '@atb/translations';
import {NavigationProp, useNavigation} from '@react-navigation/native';
import {isFuture} from 'date-fns';
Expand All @@ -14,6 +19,7 @@ import LinearGradient from 'react-native-linear-gradient';
import SimpleTicket from '../Ticket';
import TicketReservation from './TicketReservation';
import TravelCardInformation from './TravelCardInformation';
import MessageBox from '@atb/components/message-box';

type RootNavigationProp = NavigationProp<RootStackParamList>;

Expand All @@ -25,6 +31,7 @@ type Props = {
refreshTickets: () => void;
now: number;
travelCard?: TravelCard;
didPaymentFail?: boolean;
};

const TicketsScrollView: React.FC<Props> = ({
Expand All @@ -35,11 +42,13 @@ const TicketsScrollView: React.FC<Props> = ({
refreshTickets,
now,
travelCard,
didPaymentFail = false,
}) => {
const {theme} = useTheme();
const styles = useStyles();
const navigation = useNavigation<RootNavigationProp>();
const {t} = useTranslation();
const {resetPaymentStatus} = useTicketState();

const hasActiveTravelCard = !!travelCard;

Expand All @@ -59,6 +68,15 @@ const TicketsScrollView: React.FC<Props> = ({
travelCard={travelCard}
></TravelCardInformation>
)}
{didPaymentFail && (
<MessageBox
containerStyle={styles.messageBox}
type="error"
message={t(TicketsTexts.scrollView.paymentError)}
onPress={resetPaymentStatus}
onPressText={t(TicketsTexts.scrollView.paymentErrorButton)}
></MessageBox>
)}
{!fareContracts?.length && !reservations?.length && (
<ThemeText style={styles.noTicketsText}>{noTicketsLabel}</ThemeText>
)}
Expand Down Expand Up @@ -106,6 +124,9 @@ const useStyles = StyleSheet.createThemeHook((theme) => ({
gradient: {
backgroundColor: theme.colors.background_1.backgroundColor,
},
messageBox: {
marginBottom: theme.spacings.large,
},
}));

export default TicketsScrollView;
33 changes: 33 additions & 0 deletions src/tickets/TicketContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ type TicketReducerState = {
isRefreshingTickets: boolean;
errorRefreshingTickets: boolean;
customerProfile: CustomerProfile | undefined;
didPaymentFail: boolean;
};

type TicketReducerAction =
Expand All @@ -39,6 +40,10 @@ type TicketReducerAction =
| {
type: 'UPDATE_RESERVATIONS';
activeReservations: ActiveReservation[];
}
| {
type: 'UPDATE_PAYMENT_FAILED';
didPaymentFail: boolean;
};

type TicketReducer = (
Expand Down Expand Up @@ -105,13 +110,21 @@ const ticketReducer: TicketReducer = (
customerProfile: action.customerProfile,
};
}
case 'UPDATE_PAYMENT_FAILED': {
return {
...prevState,
didPaymentFail: action.didPaymentFail,
};
}
}
};

type TicketState = {
addReservation: (reservation: ActiveReservation) => void;
refreshTickets: () => void;
fareContracts: FareContract[];
didPaymentFail: boolean;
resetPaymentStatus: () => void;
findFareContractByOrderId: (id: string) => FareContract | undefined;
} & Pick<
TicketReducerState,
Expand All @@ -124,6 +137,7 @@ const initialReducerState: TicketReducerState = {
isRefreshingTickets: false,
errorRefreshingTickets: false,
customerProfile: undefined,
didPaymentFail: false,
};

const TicketContext = createContext<TicketState | undefined>(undefined);
Expand Down Expand Up @@ -238,6 +252,17 @@ const TicketContextProvider: React.FC = ({children}) => {
}),
);

if (
updatedReservations.some(
({paymentStatus}) => paymentStatus === 'REJECT',
)
) {
dispatch({
type: 'UPDATE_PAYMENT_FAILED',
didPaymentFail: true,
});
}

dispatch({
type: 'UPDATE_RESERVATIONS',
activeReservations: updatedReservations.filter(
Expand All @@ -248,6 +273,13 @@ const TicketContextProvider: React.FC = ({children}) => {
[activeReservations, getPaymentStatus],
);

const resetPaymentStatus = () => {
dispatch({
type: 'UPDATE_PAYMENT_FAILED',
didPaymentFail: false,
});
};

useInterval(
pollPaymentStatus,
500,
Expand All @@ -263,6 +295,7 @@ const TicketContextProvider: React.FC = ({children}) => {
activeReservations,
refreshTickets,
addReservation,
resetPaymentStatus,
findFareContractByOrderId: (orderId) =>
state.fareContracts.find((fc) => fc.orderId === orderId),
}}
Expand Down
5 changes: 5 additions & 0 deletions src/translations/screens/Tickets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,11 @@ const TicketsTexts = {
`Noe gikk feil når vi prøvde å laste inn billett med ordre-id ${orderId}`,
`Something went wrong when we tried to load ticket with order id ${orderId}`,
),
paymentError: _(
'Betalingen mislyktes. Sjekk om du har tilstrekkelige midler på konto eller prøv et annet betalingsmiddel.',
'Payment failed. Please check that you have sufficient funds on your account or try a different payment option.',
),
paymentErrorButton: _('Lukk', 'Close'),
},
travelCardInformation: {
reisebevis: _('Reisebevis', 'Travel token'),
Expand Down

0 comments on commit ec7ff24

Please sign in to comment.