From f41364c95c8627bec3b1b49214f9939f3fca5f3c Mon Sep 17 00:00:00 2001 From: Or Date: Sun, 3 Sep 2023 16:34:47 +0300 Subject: [PATCH 01/18] If price is undefined - return 0 --- .../client/Locomotion/src/context/newRideContext/utils.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/client/Locomotion/src/context/newRideContext/utils.ts b/examples/client/Locomotion/src/context/newRideContext/utils.ts index 8f486cc23..11f46158c 100644 --- a/examples/client/Locomotion/src/context/newRideContext/utils.ts +++ b/examples/client/Locomotion/src/context/newRideContext/utils.ts @@ -165,11 +165,12 @@ export const formatStopPointsForEstimations = (requestStopPoints: any[]) => requ lng: sp.lng, })); -export const getFormattedPrice = (priceCurrency: string | undefined, priceAmount: number) => { +export const getFormattedPrice = (priceCurrency: string | undefined, + priceAmount: number | undefined) => { if (!priceCurrency) { return i18n.t('rideDetails.noCharge'); } - return new Intl.NumberFormat('en-US', { style: 'currency', currency: priceCurrency }).format(priceAmount); + return new Intl.NumberFormat('en-US', { style: 'currency', currency: priceCurrency }).format(priceAmount || 0); }; From 5f2f034922a2d22e2a0b0056a2eed585179dfab7 Mon Sep 17 00:00:00 2001 From: Or Date: Wed, 6 Sep 2023 18:26:25 +0300 Subject: [PATCH 02/18] Show promo code banner when there is a coupon --- .../src/Components/BottomSheet/index.tsx | 14 ++++--- examples/client/Locomotion/src/I18n/en.json | 1 + .../src/context/bottomSheetContext/index.js | 6 +++ .../RideOptions/ServiceOptions/index.js | 38 +++++++++++++++---- 4 files changed, 45 insertions(+), 14 deletions(-) diff --git a/examples/client/Locomotion/src/Components/BottomSheet/index.tsx b/examples/client/Locomotion/src/Components/BottomSheet/index.tsx index c84492103..2c1068f12 100644 --- a/examples/client/Locomotion/src/Components/BottomSheet/index.tsx +++ b/examples/client/Locomotion/src/Components/BottomSheet/index.tsx @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/ban-ts-comment */ // @ts-nocheck import React, { - useCallback, useContext, forwardRef, useEffect, + useCallback, useContext, forwardRef, } from 'react'; import BottomSheet, { BottomSheetFooter, @@ -9,13 +9,13 @@ import BottomSheet, { } from '@gorhom/bottom-sheet'; import styled from 'styled-components'; import { Text, View } from 'react-native'; -import { UserContext } from '../../context/user'; +import { Trans } from 'react-i18next'; // eslint-disable-next-line import/no-unresolved import SafeView from '../SafeView'; import { BottomSheetContext } from '../../context/bottomSheetContext'; -const BottomSheetTopInfo = styled(View)` -background-color: #989898; +const BottomSheetTopInfo = styled(View)<{backgroundColor: string}>` +background-color: ${props => (props.backgroundColor ? props.backgroundColor : '#989898')}; /* position: absolute; height: 38px; top: -38px; */ @@ -50,6 +50,8 @@ const BottomSheetComponent = forwardRef(({ snapPoints, footerComponent, topBarText, + backgroundColor, + topBarTextTags, } = useContext(BottomSheetContext); const onAnimate = useCallback((from: any, to: any) => { if (!closeable && from !== -1) { @@ -78,9 +80,9 @@ const BottomSheetComponent = forwardRef(({ const getTopBar = () => ( <> {!!topBarText && ( - + - {topBarText} + )} diff --git a/examples/client/Locomotion/src/I18n/en.json b/examples/client/Locomotion/src/I18n/en.json index 3028d579d..34250c795 100644 --- a/examples/client/Locomotion/src/I18n/en.json +++ b/examples/client/Locomotion/src/I18n/en.json @@ -54,6 +54,7 @@ "noCharge": "No charge", "estimatedFare": "Estimated fare", "estimatedFareMessage": "Some of the fares are estimated and may vary based on ride and other conditions", + "couponDiscountMessage": "<0>Promo code applied!<\/0> {{couponDiscount}} will be discounted at the end of the ride", "type": { "pickup": "Pickup", "dropoff": "Drop off", diff --git a/examples/client/Locomotion/src/context/bottomSheetContext/index.js b/examples/client/Locomotion/src/context/bottomSheetContext/index.js index 250c3f554..64bee532d 100644 --- a/examples/client/Locomotion/src/context/bottomSheetContext/index.js +++ b/examples/client/Locomotion/src/context/bottomSheetContext/index.js @@ -33,6 +33,8 @@ const BottomSheetProvider = ({ children }) => { const [snapPointsState, setSnapPointsState] = useState(SNAP_POINT_STATES[BS_PAGES.LOADING]); const [footerComponent, setFooterComponent] = useState(null); const [topBarText, setTopBarText] = useState(''); + const [backgroundColor, setBackgroundColor] = useState(null); + const [topBarTextTags, setTopBarTextTags] = useState([]); const snapPoints = useMemo(() => snapPointsState, [snapPointsState]); return ( @@ -48,6 +50,10 @@ const BottomSheetProvider = ({ children }) => { setTopBarText, genericErrorDetails, setGenericErrorDetails, + backgroundColor, + setBackgroundColor, + topBarTextTags, + setTopBarTextTags, }} > {children} diff --git a/examples/client/Locomotion/src/pages/ActiveRide/RideDrawer/RideOptions/ServiceOptions/index.js b/examples/client/Locomotion/src/pages/ActiveRide/RideDrawer/RideOptions/ServiceOptions/index.js index 81da07ed5..d24f50f80 100644 --- a/examples/client/Locomotion/src/pages/ActiveRide/RideDrawer/RideOptions/ServiceOptions/index.js +++ b/examples/client/Locomotion/src/pages/ActiveRide/RideDrawer/RideOptions/ServiceOptions/index.js @@ -1,6 +1,9 @@ -import React, { useContext, useEffect } from 'react'; +import React, { useContext, useEffect, useState } from 'react'; import SkeletonContent from 'react-native-skeleton-content-nonexpo'; +import { Text } from 'react-native'; +import { getFormattedPrice } from '../../../../../context/newRideContext/utils'; import { RidePageContext } from '../../../../../context/newRideContext'; +import { UserContext } from '../../../../../context/user'; import ServiceCard from './ServiceCard'; import { ServiceOptionsContainer } from './styles'; import { serviceCardSkeleton } from './ServiceCard/skeleton'; @@ -9,19 +12,38 @@ import i18n from '../../../../../I18n'; const ServiceOptions = () => { const { serviceEstimations, stopRequestInterval } = useContext(RidePageContext); + const { getCoupon } = useContext(UserContext); const isDebuggingEnabled = (typeof atob !== 'undefined'); - const { - setTopBarText, - } = useContext(BottomSheetContext); - useEffect(() => () => stopRequestInterval(), []); + const { setTopBarText, setBackgroundColor, setTopBarTextTags } = useContext(BottomSheetContext); + const [coupon, setCoupon] = useState(null); + + const fetchCoupon = async () => { + const result = await getCoupon(); + setCoupon(result); + }; + + useEffect(() => { + fetchCoupon(); + return () => stopRequestInterval(); + }, []); useEffect(() => { - if ((serviceEstimations || []).some(estimation => estimation.isPriceEstimated)) { + if (coupon) { + const couponDiscount = coupon.percent_off ? `${coupon.percent_off}%` + : getFormattedPrice(coupon.currency, coupon.amount_off); + setTopBarText(i18n.t('rideDetails.couponDiscountMessage', { couponDiscount })); + setBackgroundColor('#25B861'); + setTopBarTextTags([]); + } else if ((serviceEstimations || []).some(estimation => estimation.isPriceEstimated)) { setTopBarText(i18n.t('rideDetails.estimatedFareMessage')); } - return () => setTopBarText(''); - }, [serviceEstimations]); + return () => { + setTopBarText(''); + setBackgroundColor(null); + setTopBarTextTags([]); + }; + }, [serviceEstimations, coupon]); return ( From e6e23d866835c77b733a5015b7e6a2d0c108c94b Mon Sep 17 00:00:00 2001 From: Or Date: Thu, 7 Sep 2023 13:29:30 +0300 Subject: [PATCH 03/18] Get coupon from context + get coupon text from utils --- .../src/context/newRideContext/utils.ts | 7 +++++++ .../Locomotion/src/context/user/index.tsx | 7 +++++++ .../RideButtons/PaymentButton/index.tsx | 21 +++++-------------- .../RideOptions/ServiceOptions/index.js | 21 +++++-------------- 4 files changed, 24 insertions(+), 32 deletions(-) diff --git a/examples/client/Locomotion/src/context/newRideContext/utils.ts b/examples/client/Locomotion/src/context/newRideContext/utils.ts index 11f46158c..e7056deb2 100644 --- a/examples/client/Locomotion/src/context/newRideContext/utils.ts +++ b/examples/client/Locomotion/src/context/newRideContext/utils.ts @@ -173,6 +173,13 @@ export const getFormattedPrice = (priceCurrency: string | undefined, return new Intl.NumberFormat('en-US', { style: 'currency', currency: priceCurrency }).format(priceAmount || 0); }; +export const getCouponText = (coupon: any) => { + if (!coupon || coupon.status === 'error') { + return ''; + } + return coupon.percent_off ? `${coupon.percent_off}%` : getFormattedPrice(coupon.currency, coupon.amount_off); +}; + export const getCurrencySymbol = (priceCurrency?: string) => { if (!priceCurrency) { diff --git a/examples/client/Locomotion/src/context/user/index.tsx b/examples/client/Locomotion/src/context/user/index.tsx index b05335044..8e4e9505e 100644 --- a/examples/client/Locomotion/src/context/user/index.tsx +++ b/examples/client/Locomotion/src/context/user/index.tsx @@ -47,8 +47,10 @@ interface UserContextInterface { updatePushToken: () => Promise, deleteUser: () => Promise, updateUser: (values: any) => Promise, + coupon: any | null, getCoupon: () => Promise, createCoupon: (values: any) => Promise, + setCoupon: (coupon: any | null) => void, onLogin: (phoneNumber: string, channel: string) => Promise } @@ -69,7 +71,9 @@ export const UserContext = createContext({ updatePushToken: async () => false, deleteUser: async () => true, updateUser: async (values: any) => undefined, + coupon: null, getCoupon: async () => undefined, + setCoupon: (coupon: any | null) => null, createCoupon: async (values: any) => undefined, onLogin: async (phoneNumber: string, channel: string) => undefined, }); @@ -78,6 +82,7 @@ const UserContextProvider = ({ children }: { children: any }) => { const usePayments = PaymentsContext.useContainer(); const [locationGranted, setLocationGranted] = useState(); const [user, setUser] = useState(null); + const [coupon, setCoupon] = useState(null); const getUserFromServer = () => getUserDetails(); @@ -252,7 +257,9 @@ const UserContextProvider = ({ children }: { children: any }) => { updatePushToken, deleteUser, updateUser, + coupon, getCoupon, + setCoupon: c => setCoupon(c), createCoupon, onLogin, }} diff --git a/examples/client/Locomotion/src/pages/ActiveRide/RideDrawer/RideOptions/RideButtons/PaymentButton/index.tsx b/examples/client/Locomotion/src/pages/ActiveRide/RideDrawer/RideOptions/RideButtons/PaymentButton/index.tsx index c5f4916c3..d89363e35 100644 --- a/examples/client/Locomotion/src/pages/ActiveRide/RideDrawer/RideOptions/RideButtons/PaymentButton/index.tsx +++ b/examples/client/Locomotion/src/pages/ActiveRide/RideDrawer/RideOptions/RideButtons/PaymentButton/index.tsx @@ -6,7 +6,7 @@ import { PaymentIcon } from 'react-native-payment-icons'; import styled, { ThemeContext } from 'styled-components'; import { useFocusEffect } from '@react-navigation/native'; import SkeletonContent from 'react-native-skeleton-content-nonexpo'; -import { getFormattedPrice } from '../../../../../../context/newRideContext/utils'; +import { getCouponText } from '../../../../../../context/newRideContext/utils'; import { MAIN_ROUTES } from '../../../../../routes'; import SvgIcon from '../../../../../../Components/SvgIcon'; import { FONT_SIZES, FONT_WEIGHTS, GREEN_COLOR } from '../../../../../../context/theme'; @@ -88,24 +88,12 @@ const PaymentButton = ({ invalid, }: PaymentButtonProps) => { const { primaryColor } = useContext(ThemeContext); - const [coupon, setCoupon] = useState(null); - const { getCoupon } = useContext(UserContext); + const { getCoupon, coupon, setCoupon } = useContext(UserContext); const isDebuggingEnabled = (typeof atob !== 'undefined'); const noCoupon = coupon && coupon.status === 'error'; - const loadPromoText = () => { - if (coupon && !noCoupon) { - let amount; - if (coupon.amount_off) { - amount = getFormattedPrice(coupon.currency, coupon.amount_off); - } else if (coupon.percent_off) { - amount = `${coupon.percent_off}%`; - } - - return i18n.t('home.promoCode.amountOff', { amount }); - } - return i18n.t('bottomSheetContent.ride.promoText'); - }; + const loadPromoText = () => (coupon && !noCoupon ? i18n.t('home.promoCode.amountOff', { amount: getCouponText(coupon) }) + : i18n.t('bottomSheetContent.ride.promoText')); const loadPromoButton = () => { if (id === PAYMENT_METHODS.CASH) { @@ -147,6 +135,7 @@ const PaymentButton = ({ ); } + return (null); }; const checkCoupon = async () => { diff --git a/examples/client/Locomotion/src/pages/ActiveRide/RideDrawer/RideOptions/ServiceOptions/index.js b/examples/client/Locomotion/src/pages/ActiveRide/RideDrawer/RideOptions/ServiceOptions/index.js index d24f50f80..a3ad57377 100644 --- a/examples/client/Locomotion/src/pages/ActiveRide/RideDrawer/RideOptions/ServiceOptions/index.js +++ b/examples/client/Locomotion/src/pages/ActiveRide/RideDrawer/RideOptions/ServiceOptions/index.js @@ -1,7 +1,7 @@ import React, { useContext, useEffect, useState } from 'react'; import SkeletonContent from 'react-native-skeleton-content-nonexpo'; import { Text } from 'react-native'; -import { getFormattedPrice } from '../../../../../context/newRideContext/utils'; +import { getCouponText, getFormattedPrice } from '../../../../../context/newRideContext/utils'; import { RidePageContext } from '../../../../../context/newRideContext'; import { UserContext } from '../../../../../context/user'; import ServiceCard from './ServiceCard'; @@ -12,26 +12,15 @@ import i18n from '../../../../../I18n'; const ServiceOptions = () => { const { serviceEstimations, stopRequestInterval } = useContext(RidePageContext); - const { getCoupon } = useContext(UserContext); + const { coupon } = useContext(UserContext); const isDebuggingEnabled = (typeof atob !== 'undefined'); const { setTopBarText, setBackgroundColor, setTopBarTextTags } = useContext(BottomSheetContext); - const [coupon, setCoupon] = useState(null); - const fetchCoupon = async () => { - const result = await getCoupon(); - setCoupon(result); - }; + useEffect(() => () => stopRequestInterval(), []); useEffect(() => { - fetchCoupon(); - return () => stopRequestInterval(); - }, []); - - useEffect(() => { - if (coupon) { - const couponDiscount = coupon.percent_off ? `${coupon.percent_off}%` - : getFormattedPrice(coupon.currency, coupon.amount_off); - setTopBarText(i18n.t('rideDetails.couponDiscountMessage', { couponDiscount })); + if (coupon && coupon.status !== 'error') { + setTopBarText(i18n.t('rideDetails.couponDiscountMessage', { couponDiscount: getCouponText(coupon) })); setBackgroundColor('#25B861'); setTopBarTextTags([]); } else if ((serviceEstimations || []).some(estimation => estimation.isPriceEstimated)) { From 7c16ac4a131f34d872e6d70452904119fe7cf2ae Mon Sep 17 00:00:00 2001 From: Or Date: Thu, 7 Sep 2023 14:05:45 +0300 Subject: [PATCH 04/18] Background color to const --- .../RideDrawer/RideOptions/ServiceOptions/index.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/examples/client/Locomotion/src/pages/ActiveRide/RideDrawer/RideOptions/ServiceOptions/index.js b/examples/client/Locomotion/src/pages/ActiveRide/RideDrawer/RideOptions/ServiceOptions/index.js index a3ad57377..7ddf0874c 100644 --- a/examples/client/Locomotion/src/pages/ActiveRide/RideDrawer/RideOptions/ServiceOptions/index.js +++ b/examples/client/Locomotion/src/pages/ActiveRide/RideDrawer/RideOptions/ServiceOptions/index.js @@ -1,7 +1,7 @@ -import React, { useContext, useEffect, useState } from 'react'; +import React, { useContext, useEffect } from 'react'; import SkeletonContent from 'react-native-skeleton-content-nonexpo'; import { Text } from 'react-native'; -import { getCouponText, getFormattedPrice } from '../../../../../context/newRideContext/utils'; +import { getCouponText } from '../../../../../context/newRideContext/utils'; import { RidePageContext } from '../../../../../context/newRideContext'; import { UserContext } from '../../../../../context/user'; import ServiceCard from './ServiceCard'; @@ -10,6 +10,8 @@ import { serviceCardSkeleton } from './ServiceCard/skeleton'; import { BottomSheetContext } from '../../../../../context/bottomSheetContext'; import i18n from '../../../../../I18n'; +const SUCCESS_COLOR = '#25B861'; + const ServiceOptions = () => { const { serviceEstimations, stopRequestInterval } = useContext(RidePageContext); const { coupon } = useContext(UserContext); @@ -21,7 +23,7 @@ const ServiceOptions = () => { useEffect(() => { if (coupon && coupon.status !== 'error') { setTopBarText(i18n.t('rideDetails.couponDiscountMessage', { couponDiscount: getCouponText(coupon) })); - setBackgroundColor('#25B861'); + setBackgroundColor(SUCCESS_COLOR); setTopBarTextTags([]); } else if ((serviceEstimations || []).some(estimation => estimation.isPriceEstimated)) { setTopBarText(i18n.t('rideDetails.estimatedFareMessage')); From b2fc61c5b1bf3dad36482a2038588114a7c46e5f Mon Sep 17 00:00:00 2001 From: Or Date: Thu, 7 Sep 2023 16:34:57 +0300 Subject: [PATCH 05/18] Split to functions --- .../RideOptions/ServiceOptions/index.js | 28 ++++++++++++++----- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/examples/client/Locomotion/src/pages/ActiveRide/RideDrawer/RideOptions/ServiceOptions/index.js b/examples/client/Locomotion/src/pages/ActiveRide/RideDrawer/RideOptions/ServiceOptions/index.js index 7ddf0874c..40672f2b2 100644 --- a/examples/client/Locomotion/src/pages/ActiveRide/RideDrawer/RideOptions/ServiceOptions/index.js +++ b/examples/client/Locomotion/src/pages/ActiveRide/RideDrawer/RideOptions/ServiceOptions/index.js @@ -20,19 +20,33 @@ const ServiceOptions = () => { useEffect(() => () => stopRequestInterval(), []); + const clearTopBar = () => { + setTopBarText(''); + setBackgroundColor(null); + setTopBarTextTags([]); + }; + + const setCouponTopBar = () => { + setTopBarText(i18n.t('rideDetails.couponDiscountMessage', { couponDiscount: getCouponText(coupon) })); + setBackgroundColor(SUCCESS_COLOR); + setTopBarTextTags([]); + }; + + const setEstimateFareTopBar = () => { + setTopBarText(i18n.t('rideDetails.estimatedFareMessage')); + setBackgroundColor(null); + setTopBarTextTags([]); + }; + useEffect(() => { if (coupon && coupon.status !== 'error') { - setTopBarText(i18n.t('rideDetails.couponDiscountMessage', { couponDiscount: getCouponText(coupon) })); - setBackgroundColor(SUCCESS_COLOR); - setTopBarTextTags([]); + setCouponTopBar(); } else if ((serviceEstimations || []).some(estimation => estimation.isPriceEstimated)) { - setTopBarText(i18n.t('rideDetails.estimatedFareMessage')); + setEstimateFareTopBar(); } return () => { - setTopBarText(''); - setBackgroundColor(null); - setTopBarTextTags([]); + clearTopBar(); }; }, [serviceEstimations, coupon]); From bc9b6ba1026d2e32145f36d7d299a1a0cf031587 Mon Sep 17 00:00:00 2001 From: Or Date: Thu, 7 Sep 2023 16:35:12 +0300 Subject: [PATCH 06/18] cr --- examples/client/Locomotion/src/Components/BottomSheet/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/client/Locomotion/src/Components/BottomSheet/index.tsx b/examples/client/Locomotion/src/Components/BottomSheet/index.tsx index 2c1068f12..4eb1b180b 100644 --- a/examples/client/Locomotion/src/Components/BottomSheet/index.tsx +++ b/examples/client/Locomotion/src/Components/BottomSheet/index.tsx @@ -15,7 +15,7 @@ import SafeView from '../SafeView'; import { BottomSheetContext } from '../../context/bottomSheetContext'; const BottomSheetTopInfo = styled(View)<{backgroundColor: string}>` -background-color: ${props => (props.backgroundColor ? props.backgroundColor : '#989898')}; +background-color: ${props => props.backgroundColor || '#989898'}; /* position: absolute; height: 38px; top: -38px; */ From 6a04ee1e3772ceb8c3775781df707e6ee7ec5671 Mon Sep 17 00:00:00 2001 From: Or Date: Sun, 10 Sep 2023 14:19:30 +0300 Subject: [PATCH 07/18] Group top bar properties to one object --- .../src/Components/BottomSheet/index.tsx | 10 ++++---- .../src/context/bottomSheetContext/index.js | 19 ++++++++------- .../RideOptions/ServiceOptions/index.js | 24 ++++++++++--------- .../RideDrawer/RideOptions/index.tsx | 1 - .../Locomotion/src/pages/ActiveRide/index.js | 4 ++-- 5 files changed, 29 insertions(+), 29 deletions(-) diff --git a/examples/client/Locomotion/src/Components/BottomSheet/index.tsx b/examples/client/Locomotion/src/Components/BottomSheet/index.tsx index 4eb1b180b..529e0649c 100644 --- a/examples/client/Locomotion/src/Components/BottomSheet/index.tsx +++ b/examples/client/Locomotion/src/Components/BottomSheet/index.tsx @@ -49,9 +49,7 @@ const BottomSheetComponent = forwardRef(({ setIsExpanded, snapPoints, footerComponent, - topBarText, - backgroundColor, - topBarTextTags, + topBarProps, } = useContext(BottomSheetContext); const onAnimate = useCallback((from: any, to: any) => { if (!closeable && from !== -1) { @@ -79,10 +77,10 @@ const BottomSheetComponent = forwardRef(({ const getTopBar = () => ( <> - {!!topBarText && ( - + {!!topBarProps.text && ( + - + )} diff --git a/examples/client/Locomotion/src/context/bottomSheetContext/index.js b/examples/client/Locomotion/src/context/bottomSheetContext/index.js index 64bee532d..beb25443e 100644 --- a/examples/client/Locomotion/src/context/bottomSheetContext/index.js +++ b/examples/client/Locomotion/src/context/bottomSheetContext/index.js @@ -27,14 +27,19 @@ export const SNAP_POINT_STATES = { [BS_PAGES.NO_AVAILABLE_SERVICES]: [STATIC_SNAP_POINTS], [BS_PAGES.PICKUP_NOT_IN_TERRITORY]: [STATIC_SNAP_POINTS], }; + +export const INITIAL_TOP_BAR_PROPS = { + text: '', + backgroundColor: null, + htmlTags: [], +}; + const BottomSheetProvider = ({ children }) => { const [isExpanded, setIsExpanded] = useState(false); const [genericErrorDetails, setGenericErrorDetails] = useState({}); const [snapPointsState, setSnapPointsState] = useState(SNAP_POINT_STATES[BS_PAGES.LOADING]); const [footerComponent, setFooterComponent] = useState(null); - const [topBarText, setTopBarText] = useState(''); - const [backgroundColor, setBackgroundColor] = useState(null); - const [topBarTextTags, setTopBarTextTags] = useState([]); + const [topBarProps, setTopBarProps] = useState(INITIAL_TOP_BAR_PROPS); const snapPoints = useMemo(() => snapPointsState, [snapPointsState]); return ( @@ -46,14 +51,10 @@ const BottomSheetProvider = ({ children }) => { setSnapPointsState, setFooterComponent, footerComponent, - topBarText, - setTopBarText, genericErrorDetails, setGenericErrorDetails, - backgroundColor, - setBackgroundColor, - topBarTextTags, - setTopBarTextTags, + topBarProps, + setTopBarProps, }} > {children} diff --git a/examples/client/Locomotion/src/pages/ActiveRide/RideDrawer/RideOptions/ServiceOptions/index.js b/examples/client/Locomotion/src/pages/ActiveRide/RideDrawer/RideOptions/ServiceOptions/index.js index 40672f2b2..77bc73bd7 100644 --- a/examples/client/Locomotion/src/pages/ActiveRide/RideDrawer/RideOptions/ServiceOptions/index.js +++ b/examples/client/Locomotion/src/pages/ActiveRide/RideDrawer/RideOptions/ServiceOptions/index.js @@ -7,7 +7,7 @@ import { UserContext } from '../../../../../context/user'; import ServiceCard from './ServiceCard'; import { ServiceOptionsContainer } from './styles'; import { serviceCardSkeleton } from './ServiceCard/skeleton'; -import { BottomSheetContext } from '../../../../../context/bottomSheetContext'; +import { BottomSheetContext, INITIAL_TOP_BAR_PROPS } from '../../../../../context/bottomSheetContext'; import i18n from '../../../../../I18n'; const SUCCESS_COLOR = '#25B861'; @@ -16,26 +16,28 @@ const ServiceOptions = () => { const { serviceEstimations, stopRequestInterval } = useContext(RidePageContext); const { coupon } = useContext(UserContext); const isDebuggingEnabled = (typeof atob !== 'undefined'); - const { setTopBarText, setBackgroundColor, setTopBarTextTags } = useContext(BottomSheetContext); + const { setTopBarProps } = useContext(BottomSheetContext); useEffect(() => () => stopRequestInterval(), []); const clearTopBar = () => { - setTopBarText(''); - setBackgroundColor(null); - setTopBarTextTags([]); + setTopBarProps(INITIAL_TOP_BAR_PROPS); }; const setCouponTopBar = () => { - setTopBarText(i18n.t('rideDetails.couponDiscountMessage', { couponDiscount: getCouponText(coupon) })); - setBackgroundColor(SUCCESS_COLOR); - setTopBarTextTags([]); + setTopBarProps({ + text: i18n.t('rideDetails.couponDiscountMessage', { couponDiscount: getCouponText(coupon) }), + backgroundColor: SUCCESS_COLOR, + htmlTags: [], + }); }; const setEstimateFareTopBar = () => { - setTopBarText(i18n.t('rideDetails.estimatedFareMessage')); - setBackgroundColor(null); - setTopBarTextTags([]); + setTopBarProps({ + text: i18n.t('rideDetails.estimatedFareMessage'), + backgroundColor: null, + htmlTags: [], + }); }; useEffect(() => { diff --git a/examples/client/Locomotion/src/pages/ActiveRide/RideDrawer/RideOptions/index.tsx b/examples/client/Locomotion/src/pages/ActiveRide/RideDrawer/RideOptions/index.tsx index 3d41b1ec9..6d51f12e9 100644 --- a/examples/client/Locomotion/src/pages/ActiveRide/RideDrawer/RideOptions/index.tsx +++ b/examples/client/Locomotion/src/pages/ActiveRide/RideDrawer/RideOptions/index.tsx @@ -34,7 +34,6 @@ const RideOptions = () => { const { setFooterComponent, - setTopBarText, } = useContext(BottomSheetContext); const { diff --git a/examples/client/Locomotion/src/pages/ActiveRide/index.js b/examples/client/Locomotion/src/pages/ActiveRide/index.js index 03fce2ca6..1dc6c8091 100644 --- a/examples/client/Locomotion/src/pages/ActiveRide/index.js +++ b/examples/client/Locomotion/src/pages/ActiveRide/index.js @@ -119,7 +119,7 @@ const RidePage = ({ mapSettings, navigation }) => { reverseLocationGeocode, } = useContext(RidePageContext); const { - setIsExpanded, snapPoints, isExpanded, topBarText, + setIsExpanded, snapPoints, isExpanded, topBarProps, } = useContext(BottomSheetContext); const { clientHasValidPaymentMethods, @@ -555,7 +555,7 @@ const RidePage = ({ mapSettings, navigation }) => { )} From 4a77981a9f0035657beac7379d6083091fa5396a Mon Sep 17 00:00:00 2001 From: Omer Gery <68545675+OmerGery@users.noreply.github.com> Date: Thu, 21 Sep 2023 13:02:38 +0300 Subject: [PATCH 08/18] fix logout from app (#780) * fix restart app on logout * add comment --- examples/client/Locomotion/src/services/network.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/examples/client/Locomotion/src/services/network.js b/examples/client/Locomotion/src/services/network.js index b41bdd98d..54d621dfc 100644 --- a/examples/client/Locomotion/src/services/network.js +++ b/examples/client/Locomotion/src/services/network.js @@ -80,8 +80,11 @@ class Network { this.axios.defaults.headers.common['x-loco-op-id'] = operationId; return this.axios[method](...args).catch((e) => { crashlytics().log(`HTTP Request Error ${e.message}`); - if ((e.response && e.response.status === 401) - || (e.response && e.response.status === 403)) { + const errorCode = e.response && e.response.status; + const isBadAuth = errorCode === 401 || errorCode === 403; + + // the purpose is to logout the user only if he is logged in, but has a bad token + if (isBadAuth && accessToken) { console.log('Got unauthorized response move to logout flow'); Auth.logout(); return null; From 728abf6112c2595bfa58d235d4f968d5ab26521f Mon Sep 17 00:00:00 2001 From: Or Date: Wed, 27 Sep 2023 15:32:51 +0300 Subject: [PATCH 09/18] Reset coupon on unmount --- .../RideDrawer/RideOptions/RideButtons/PaymentButton/index.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/client/Locomotion/src/pages/ActiveRide/RideDrawer/RideOptions/RideButtons/PaymentButton/index.tsx b/examples/client/Locomotion/src/pages/ActiveRide/RideDrawer/RideOptions/RideButtons/PaymentButton/index.tsx index d89363e35..ac33375e2 100644 --- a/examples/client/Locomotion/src/pages/ActiveRide/RideDrawer/RideOptions/RideButtons/PaymentButton/index.tsx +++ b/examples/client/Locomotion/src/pages/ActiveRide/RideDrawer/RideOptions/RideButtons/PaymentButton/index.tsx @@ -150,6 +150,7 @@ const PaymentButton = ({ useFocusEffect( useCallback(() => { checkCoupon(); + return () => setCoupon(null); }, []), ); const IconColor = invalid ? '#F83743' : primaryColor; From a862c6515489305836928176a1142f794b1a78f8 Mon Sep 17 00:00:00 2001 From: avivbarniv Date: Thu, 28 Sep 2023 17:33:03 +0300 Subject: [PATCH 10/18] add enforceProfilePicture setting --- .../client/Locomotion/src/context/onboarding/index.tsx | 7 +++++++ examples/client/Locomotion/src/context/settings/keys.ts | 1 + 2 files changed, 8 insertions(+) diff --git a/examples/client/Locomotion/src/context/onboarding/index.tsx b/examples/client/Locomotion/src/context/onboarding/index.tsx index 8d8c27469..59023989f 100644 --- a/examples/client/Locomotion/src/context/onboarding/index.tsx +++ b/examples/client/Locomotion/src/context/onboarding/index.tsx @@ -120,6 +120,13 @@ const OnboardingContextProvider = ({ children }: { children: any }) => { await getSettingByKey( SETTINGS_KEYS.CARD_PAGE_SETTINGS, ); + const enforceProfilePicture = await getSettingByKey( + SETTINGS_KEYS.ENFORCE_PROFILE_PICTURE, + ); + setRequiredOnboarding({ + ...requiredOnboarding, + [MAIN_ROUTES.AVATAR]: enforceProfilePicture, + }); const screenKey: string | undefined = Object.keys(keyToScreen).find(key => !user[key]); let unfinishedScreen = screenKey ? keyToScreen[screenKey] : keyToScreen.welcome; if (unfinishedScreen === MAIN_ROUTES.CARD) { diff --git a/examples/client/Locomotion/src/context/settings/keys.ts b/examples/client/Locomotion/src/context/settings/keys.ts index bf33358d7..4f2d0c70b 100644 --- a/examples/client/Locomotion/src/context/settings/keys.ts +++ b/examples/client/Locomotion/src/context/settings/keys.ts @@ -2,6 +2,7 @@ export default { SERVICE_ESTIMATIONS_INTERVAL_IN_SECONDS: 'riderApp.preRide.estimationsInterval', POST_RIDE_TIP_SETTINGS: 'riderApp.postRide.showTipPresetsAsPercentageThreshold', CARD_PAGE_SETTINGS: 'riderApp.onboarding.cardPageSettings', + ENFORCE_PROFILE_PICTURE: 'riderApp.enforceProfilePicture', MIN_APP_VERSION: 'riderApp.minAppVersion', CONTACT_US_URL: 'riderApp.contactUsUrl', TERMS_OF_USE_URL: 'riderApp.termsOfUseUrl', From f5e616b8c2827035ca694dd6b2f024f6a6f9a0f4 Mon Sep 17 00:00:00 2001 From: hilat-autofleet Date: Mon, 9 Oct 2023 11:05:26 +0300 Subject: [PATCH 11/18] add default max days --- .../Locomotion/src/Components/BsPages/index.tsx | 11 ++++++++++- .../Locomotion/src/context/newRideContext/utils.ts | 3 ++- .../client/Locomotion/src/context/settings/keys.ts | 1 + .../RideDrawer/RideOptions/RideButtons/index.tsx | 9 ++++++++- 4 files changed, 21 insertions(+), 3 deletions(-) diff --git a/examples/client/Locomotion/src/Components/BsPages/index.tsx b/examples/client/Locomotion/src/Components/BsPages/index.tsx index 2470aed19..c7a8e5c7f 100644 --- a/examples/client/Locomotion/src/Components/BsPages/index.tsx +++ b/examples/client/Locomotion/src/Components/BsPages/index.tsx @@ -293,14 +293,23 @@ export const ConfirmPickupTime = (props: any) => { const beforeTime = (windowSize && moment(unconfirmedPickupTime).add(windowSize, 'minutes').format('h:mm A')) || i18n.t('general.noTimeWindow'); const startDate = moment(unconfirmedPickupTime).add(unconfirmedPickupTime ? 0 : (minMinutesBeforeFutureRide || 0) + 1, 'minutes').toDate(); const [tempSelectedDate, setTempSelectedDate] = useState(startDate); + const [maxDaysFutureRide, setMaxDaysFutureRide] = useState(); const checkMinutesBeforeFutureRideSetting = async () => { const minutes = await getSettingByKey(SETTINGS_KEYS.MIN_MINUTES_BEFORE_FUTURE_RIDE); setMinMinutesBeforeFutureRide(minutes); }; + + const checkFutureBookingDays = async () => { + const maxDaysFromSettings = await getSettingByKey(SETTINGS_KEYS.MAX_DAYS_FOR_FUTURE_RIDE); + setMaxDaysFutureRide(maxDaysFromSettings); + }; + useEffect(() => { checkMinutesBeforeFutureRideSetting(); + checkFutureBookingDays(); }, []); + useEffect(() => { setTempSelectedDate(startDate); }, [minMinutesBeforeFutureRide]); @@ -359,7 +368,7 @@ export const ConfirmPickupTime = (props: any) => { textColor="black" isVisible={isDatePickerOpen} date={tempSelectedDate} - maximumDate={getFutureRideMaxDate()} + maximumDate={getFutureRideMaxDate(maxDaysFutureRide)} minimumDate={getFutureRideMinDate((minMinutesBeforeFutureRide || 0))} mode="datetime" title={renderDatePickerTitle()} diff --git a/examples/client/Locomotion/src/context/newRideContext/utils.ts b/examples/client/Locomotion/src/context/newRideContext/utils.ts index 8f486cc23..503ccd68a 100644 --- a/examples/client/Locomotion/src/context/newRideContext/utils.ts +++ b/examples/client/Locomotion/src/context/newRideContext/utils.ts @@ -24,9 +24,10 @@ export const FEEDBACK_TYPES = { }; export const RIDER_APP_SOURCE = 'RIDER_APP'; +export const DEFAULT_FUTURE_MAX_RIDE_DAYS = 7; export const getFutureRideMinDate = (minutesBefore: number) => moment().add(minutesBefore, 'minutes').toDate(); -export const getFutureRideMaxDate = () => moment().add(7, 'days').toDate(); +export const getFutureRideMaxDate = (daysAfter: number|undefined) => moment().add(daysAfter || DEFAULT_FUTURE_MAX_RIDE_DAYS, 'days').toDate(); export const TAG_OPTIONS = { FASTEST: i18n.t('services.tags.fastest'), diff --git a/examples/client/Locomotion/src/context/settings/keys.ts b/examples/client/Locomotion/src/context/settings/keys.ts index bf33358d7..081e0bcde 100644 --- a/examples/client/Locomotion/src/context/settings/keys.ts +++ b/examples/client/Locomotion/src/context/settings/keys.ts @@ -15,4 +15,5 @@ export default { MEASURE_SYSTEM: 'riderApp.measureSystem', MULTI_SP: 'riderApp.showMultiStopPoint', DISABLE_CAPTCHA_UI: 'riderApp.disableCaptchaUi', + MAX_DAYS_FOR_FUTURE_RIDE: 'riderApp.daysForFutureRideBooking', }; diff --git a/examples/client/Locomotion/src/pages/ActiveRide/RideDrawer/RideOptions/RideButtons/index.tsx b/examples/client/Locomotion/src/pages/ActiveRide/RideDrawer/RideOptions/RideButtons/index.tsx index 0e411aa3f..d05495a2f 100644 --- a/examples/client/Locomotion/src/pages/ActiveRide/RideDrawer/RideOptions/RideButtons/index.tsx +++ b/examples/client/Locomotion/src/pages/ActiveRide/RideDrawer/RideOptions/RideButtons/index.tsx @@ -83,6 +83,7 @@ const RideButtons = ({ const [passengersCounterError, setPassengersCounterError] = useState(false); const firstDate = () => moment(ride?.scheduledTo || undefined).add(ride?.scheduledTo ? 0 : (minMinutesBeforeFutureRide || 0) + 1, 'minutes').toDate(); const [tempSelectedDate, setTempSelectedDate] = useState(firstDate()); + const [maxDaysFutureRide, setMaxDaysFutureRide] = useState(); const paymentMethodNotAllowedOnService = chosenService && ride?.paymentMethodId && !chosenService.allowedPaymentMethods.includes(getPaymentMethod(ride.paymentMethodId)); @@ -102,9 +103,15 @@ const RideButtons = ({ setTempSelectedDate(firstDate()); }, [minMinutesBeforeFutureRide]); + const checkFutureBookingDays = async () => { + const maxDaysFromSettings = await getSettingByKey(SETTINGS_KEYS.MAX_DAYS_FOR_FUTURE_RIDE); + setMaxDaysFutureRide(maxDaysFromSettings); + }; + useEffect(() => { checkFutureRidesSetting(); checkMinutesBeforeFutureRideSetting(); + checkFutureBookingDays(); }, []); const [animatedOpacity] = useState(new Animated.Value(0)); @@ -174,7 +181,7 @@ const RideButtons = ({ textColor="black" isVisible={isDatePickerOpen} date={tempSelectedDate} - maximumDate={getFutureRideMaxDate()} + maximumDate={getFutureRideMaxDate(maxDaysFutureRide)} minimumDate={getFutureRideMinDate((minMinutesBeforeFutureRide || 0))} mode="datetime" title={renderDatePickerTitle()} From 101acbcedef527ab618872dbce7766b59a747acf Mon Sep 17 00:00:00 2001 From: Omer Gery <68545675+OmerGery@users.noreply.github.com> Date: Sun, 15 Oct 2023 18:19:47 +0300 Subject: [PATCH 12/18] Support offline method (#785) * start support offline method * wip * wip * wip * fixes * Update index.tsx * wip * Update index.js * change setting name * Update index.tsx * better showOffline * Update index.js * Update index.tsx * Update index.tsx * extract type text func * Update cardDetailUtils.ts * Revert "Update cardDetailUtils.ts" This reverts commit d16d76607fe4df638110fa22ece86687fcca2f86. * fix fall back offline payment text * remove promo code for offline payment * add background to offline svg * Update offline.svg * padding fixes * svg * add defaultPaymentMethodNotAllowedText for offline * remove unused --- .../src/Components/CardRow/index.tsx | 34 +++++++++--- .../src/Components/RideCard/index.tsx | 11 ++-- examples/client/Locomotion/src/I18n/en.json | 3 +- .../client/Locomotion/src/assets/offline.svg | 4 ++ .../Locomotion/src/context/payments/index.js | 14 ++++- .../Locomotion/src/context/settings/keys.ts | 1 + .../client/Locomotion/src/lib/ride/utils.ts | 4 +- .../RideButtons/PaymentButton/index.tsx | 15 +++--- .../RideOptions/RideButtons/index.tsx | 50 +++++++++++++----- .../RideOptions/RideButtons/styled.tsx | 2 +- .../RideDrawer/RideOptions/index.tsx | 7 ++- .../Locomotion/src/pages/Payments/consts.ts | 8 +++ .../pages/Payments/offlinePaymentMethod.ts | 22 ++++++++ .../src/popups/ChoosePaymentMethod/index.tsx | 52 ++++++++++++------- 14 files changed, 168 insertions(+), 59 deletions(-) create mode 100644 examples/client/Locomotion/src/assets/offline.svg create mode 100644 examples/client/Locomotion/src/pages/Payments/offlinePaymentMethod.ts diff --git a/examples/client/Locomotion/src/Components/CardRow/index.tsx b/examples/client/Locomotion/src/Components/CardRow/index.tsx index caf4e0b76..864fe9ac0 100644 --- a/examples/client/Locomotion/src/Components/CardRow/index.tsx +++ b/examples/client/Locomotion/src/Components/CardRow/index.tsx @@ -5,17 +5,16 @@ import { View, Text } from 'react-native'; import moment from 'moment'; import styled, { ThemeContext } from 'styled-components'; import { PaymentIcon } from 'react-native-payment-icons'; -import { PaymentMethodInterface } from 'context/payments/interface'; +import { paymentMethodToIconMap } from '../../pages/Payments/consts'; import Button from '../Button'; import { capitalizeFirstLetter, getLastFourForamttedShort } from '../../pages/Payments/cardDetailUtils'; import i18n from '../../I18n'; import SvgIcon from '../SvgIcon'; import selected from '../../assets/selected-v.svg'; import { Start, StartCapital } from '../../lib/text-direction'; -import cashIcon from '../../assets/cash.svg'; import chevronIcon from '../../assets/chevron.svg'; import { isCashPaymentMethod } from '../../lib/ride/utils'; - +import paymentContext from '../../context/payments'; type ContainerProps = { children: React.ReactNode, @@ -91,9 +90,15 @@ const style = { [StartCapital()]: 28, }; + const CardRow = (paymentMethod: any) => { const { primaryColor } = useContext(ThemeContext); + const { offlinePaymentText, loadOfflinePaymentText } = paymentContext.useContainer(); const [isCardExpired, setIsCardExpired] = useState(false); + + useEffect(() => { + loadOfflinePaymentText(); + }, []); useEffect(() => { let isExpired = false; setTimeout(() => { @@ -102,6 +107,23 @@ const CardRow = (paymentMethod: any) => { }, 100); }, [paymentMethod]); const testID = paymentMethod.addNew ? `${paymentMethod.testIdPrefix || ''}AddPaymentMethod` : (`${paymentMethod.testIdPrefix || ''}ChoosePaymentMethod`); + + const getPaymentMethodIcon = () => { + const { brand, id, lastFour } = paymentMethod; + const isCard = lastFour; + if (isCard) { + return ; + } + return ( + + ); + }; + return ( <>