Skip to content

Commit

Permalink
chore: [PE-678] CGN partner detail change go to website from button t…
Browse files Browse the repository at this point in the history
…o list item (#6300)

## Short description
CGN partner detail change go to website from button to list item.


## List of changes proposed in this pull request
- remove bottom button
- update translation files
- add list item with same behavior as button had

## How to test
- login into the app
- go to cgn card brought wallet (add it if necessary)
- go to opportunities list
- trough categories list or partner list go to a partner detail screen
- check if the new design at the bottom of the screen


![image-20240917-152239](https://github.com/user-attachments/assets/7cfb8b6a-0a66-41b0-a7f9-3bc36f5ec2d3)
  • Loading branch information
freddi301 authored Oct 18, 2024
1 parent e0df6de commit 8fce513
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 140 deletions.
2 changes: 1 addition & 1 deletion locales/en/index.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2717,7 +2717,7 @@ bonus:
description: Description
contactInfo: Addresses
cta:
website: Go to partner's website
website: Visit the partner's website
categories:
counting: and other {{count}}
cultureAndEntertainment: Culture and entertainment
Expand Down
2 changes: 1 addition & 1 deletion locales/it/index.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2717,7 +2717,7 @@ bonus:
description: Descrizione
contactInfo: Contatti e informazioni
cta:
website: Vai al sito del partner
website: Visita il sito del partner
categories:
counting: e altre {{count}}
cultureAndEntertainment: Cultura e tempo libero
Expand Down
224 changes: 86 additions & 138 deletions ts/features/bonus/cgn/screens/merchants/CgnMerchantDetailScreen.tsx
Original file line number Diff line number Diff line change
@@ -1,27 +1,22 @@
import {
ContentWrapper,
GradientBottomActions,
Divider,
GradientScrollView,
H1,
IOSpacer,
IOSpacingScale,
IOToast,
IOVisualCostants,
ListItemAction,
ListItemHeader,
ListItemInfo,
VSpacer,
buttonSolidHeight
VSpacer
} from "@pagopa/io-app-design-system";
import Placeholder from "rn-placeholder";
import { Route, useRoute } from "@react-navigation/native";
import * as React from "react";
import { useCallback, useEffect, useMemo } from "react";
import Animated, {
Easing,
useAnimatedScrollHandler,
useAnimatedStyle,
useSharedValue,
withTiming
useSharedValue
} from "react-native-reanimated";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import {
Expand All @@ -31,7 +26,6 @@ import {
StyleSheet,
View
} from "react-native";
import { Address } from "../../../../../../definitions/cgn/merchants/Address";
import { Discount } from "../../../../../../definitions/cgn/merchants/Discount";
import { Merchant } from "../../../../../../definitions/cgn/merchants/Merchant";
import { isReady } from "../../../../../common/model/RemoteValue";
Expand All @@ -51,15 +45,10 @@ export type CgnMerchantDetailScreenNavigationParams = Readonly<{

const scrollTriggerOffsetValue: number = 88;

const gradientSafeArea: IOSpacingScale = 80;
const contentEndMargin: IOSpacingScale = 32;
const spaceBetweenActions: IOSpacer = 24;

const CgnMerchantDetailScreen = () => {
// ------- hooks
const safeAreaInsets = useSafeAreaInsets();

const gradientOpacity = useSharedValue(1);
const scrollTranslationY = useSharedValue(0);

const [titleHeight, setTitleHeight] = React.useState(0);
Expand All @@ -76,24 +65,14 @@ const CgnMerchantDetailScreen = () => {
dispatch(cgnSelectedMerchant.request(merchantID));
}, [merchantID, dispatch]);

const bottomMargin: number = React.useMemo(
const paddingBottom: number = React.useMemo(
() =>
safeAreaInsets.bottom === 0
? IOVisualCostants.appMarginDefault
: safeAreaInsets.bottom,
[safeAreaInsets]
);

const safeBottomAreaHeight: number = React.useMemo(
() => bottomMargin + buttonSolidHeight + contentEndMargin,
[bottomMargin]
);

const gradientAreaHeight: number = React.useMemo(
() => bottomMargin + buttonSolidHeight + gradientSafeArea,
[bottomMargin]
);

useEffect(loadMerchantDetail, [loadMerchantDetail]);

// ------- utils/logic
Expand All @@ -115,19 +94,10 @@ const CgnMerchantDetailScreen = () => {
}
};

const scrollHandler = useAnimatedScrollHandler(
({ contentOffset, layoutMeasurement, contentSize }) => {
// eslint-disable-next-line functional/immutable-data
scrollTranslationY.value = contentOffset.y;

const isEndReached =
Math.floor(layoutMeasurement.height + contentOffset.y) >=
Math.floor(contentSize.height);

// eslint-disable-next-line functional/immutable-data
gradientOpacity.value = isEndReached ? 0 : 1;
}
);
const scrollHandler = useAnimatedScrollHandler(({ contentOffset }) => {
// eslint-disable-next-line functional/immutable-data
scrollTranslationY.value = contentOffset.y;
});

const getTitleHeight = (event: LayoutChangeEvent) => {
const { height } = event.nativeEvent.layout;
Expand All @@ -148,89 +118,86 @@ const CgnMerchantDetailScreen = () => {
}
});

const footerCta = (url: string) => ({
label: I18n.t("bonus.cgn.merchantDetail.cta.website"),
onPress: () => handlePressMerchantWebsite(url)
});

const footerGradientOpacityTransition = useAnimatedStyle(() => ({
opacity: withTiming(gradientOpacity.value, {
duration: 200,
easing: Easing.ease
})
}));

const footerComponent = isReady(merchantDetail) &&
merchantDetail.value.websiteUrl && (
<GradientBottomActions
primaryActionProps={footerCta(merchantDetail.value.websiteUrl)}
transitionAnimStyle={footerGradientOpacityTransition}
dimensions={{
bottomMargin,
extraBottomMargin: 0,
gradientAreaHeight,
spaceBetweenActions,
safeBackgroundHeight: bottomMargin
const showAddresses =
isReady(merchantDetail) &&
merchantDetail.value.addresses !== undefined &&
merchantDetail.value.addresses.length > 0;

const showGotToWebsite =
isReady(merchantDetail) && merchantDetail.value.websiteUrl !== undefined;

if (isReady(merchantDetail)) {
return (
<Animated.ScrollView
style={{ flexGrow: 1 }}
onScroll={scrollHandler}
scrollEventThrottle={8}
scrollIndicatorInsets={{ right: 1 }}
snapToOffsets={[0]}
snapToEnd={false}
contentContainerStyle={{
flexGrow: 1,
paddingBottom
}}
/>
);

return (
<>
{isReady(merchantDetail) ? (
<>
<Animated.ScrollView
style={{ flexGrow: 1 }}
onScroll={scrollHandler}
scrollEventThrottle={8}
scrollIndicatorInsets={{ right: 1 }}
snapToOffsets={[0]}
snapToEnd={false}
contentContainerStyle={{
flexGrow: 1,
paddingBottom: safeBottomAreaHeight
}}
>
<ContentWrapper>
{merchantDetail.value.imageUrl !== undefined && (
<View onLayout={getTitleHeight}>
<Image
accessibilityIgnoresInvertColors
source={{ uri: merchantDetail.value.imageUrl }}
style={styles.merchantImage}
/>
<VSpacer size={24} />
</View>
)}
<H1>{merchantDetail.value.name}</H1>
<VSpacer size={24} />
<ListItemHeader
label={I18n.t("bonus.cgn.merchantDetail.title.deals")}
/>
{renderDiscountsList(merchantDetail.value.discounts)}
<VSpacer size={24} />
<ListItemInfo
numberOfLines={0}
label={I18n.t("bonus.cgn.merchantDetail.title.description")}
value={merchantDetail.value.description}
>
<ContentWrapper>
{merchantDetail.value.imageUrl !== undefined && (
<View onLayout={getTitleHeight}>
<Image
accessibilityIgnoresInvertColors
source={{ uri: merchantDetail.value.imageUrl }}
style={styles.merchantImage}
/>
<VSpacer size={24} />
{renderMerchantAddressesList(
merchantDetail.value.addresses,
merchantDetail.value.allNationalAddresses
)}
<VSpacer size={24} />
</ContentWrapper>
</Animated.ScrollView>
{footerComponent}
</>
) : (
<SafeAreaView style={IOStyles.flex}>
<CgnMerchantDetailScreenSkeleton />
</SafeAreaView>
)}
</>
);
</View>
)}
<H1>{merchantDetail.value.name}</H1>
<VSpacer size={24} />
<ListItemHeader
label={I18n.t("bonus.cgn.merchantDetail.title.deals")}
/>
{renderDiscountsList(merchantDetail.value.discounts)}
<VSpacer size={24} />
<ListItemInfo
numberOfLines={0}
label={I18n.t("bonus.cgn.merchantDetail.title.description")}
value={merchantDetail.value.description}
/>
<VSpacer size={24} />
{(showAddresses || showGotToWebsite) && (
<ListItemHeader
label={I18n.t("bonus.cgn.merchantDetail.title.contactInfo")}
/>
)}
{showGotToWebsite && (
<ListItemAction
variant="primary"
icon="website"
label={I18n.t("bonus.cgn.merchantDetail.cta.website")}
onPress={() =>
handlePressMerchantWebsite(merchantDetail.value.websiteUrl)
}
/>
)}
{showGotToWebsite && showAddresses && <Divider />}
{merchantDetail.value.addresses?.map((address, index) => (
<CgnAddressListItem
item={address}
key={index}
isAllNationalAddress={merchantDetail.value.allNationalAddresses}
/>
))}
<VSpacer size={24} />
</ContentWrapper>
</Animated.ScrollView>
);
} else {
return (
<SafeAreaView style={IOStyles.flex}>
<CgnMerchantDetailScreenSkeleton />
</SafeAreaView>
);
}
};

// ------------------------ render utils
Expand Down Expand Up @@ -258,25 +225,6 @@ const CgnMerchantDetailScreenSkeleton = () => (
</GradientScrollView>
);

const renderMerchantAddressesList = (
addresses: ReadonlyArray<Address> | undefined,
isAllNationalAddressMerchant: boolean
) =>
addresses !== undefined && addresses.length > 0 ? (
<>
<ListItemHeader
label={I18n.t("bonus.cgn.merchantDetail.title.contactInfo")}
/>
{addresses.map((address, index) => (
<CgnAddressListItem
item={address}
key={index}
isAllNationalAddress={isAllNationalAddressMerchant}
/>
))}
</>
) : null;

// ------------------------ styles - consts - export

const styles = StyleSheet.create({
Expand Down

0 comments on commit 8fce513

Please sign in to comment.