Skip to content

Commit

Permalink
chore: [IOPAE-1067] Add skeleton in ServiceDetailsScreen (#5678)
Browse files Browse the repository at this point in the history
This pr depends on #5677

## Short description
This PR adds the skeleton for the loading state in
`ServiceDetailsScreen`.

<details open><summary>Details</summary>
<p>

| service details  |
| - |
| <video
src="https://github.com/pagopa/io-app/assets/29163287/befbec7c-57cb-42c7-9067-de424e8d49e7"
width="300"/> |

</p>
</details> 

## List of changes proposed in this pull request
- updated ServiceDetailsScreen in order to display the skeleton

## How to test
Using `io-dev-api-server`, navigate to the services tab and tap a
service. Check that the screen is displayed correctly.
  • Loading branch information
adelloste authored Apr 12, 2024
1 parent 31c063c commit c0b2871
Show file tree
Hide file tree
Showing 5 changed files with 178 additions and 38 deletions.
74 changes: 64 additions & 10 deletions ts/components/ui/Markdown/LoadingSkeleton.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from "react";
import { View } from "react-native";
import Placeholder from "rn-placeholder";
import { VSpacer } from "@pagopa/io-app-design-system";
import { IOColors, VSpacer } from "@pagopa/io-app-design-system";
import I18n from "../../../i18n";

type LoadingSkeletonProps = {
Expand All @@ -19,23 +19,77 @@ export const LoadingSkeleton = ({ testID }: LoadingSkeletonProps) => (
importantForAccessibility="no-hide-descendants"
accessibilityElementsHidden={true}
>
<Placeholder.Box width={"98%"} animate={"fade"} height={21} radius={4} />
<Placeholder.Box
width={"98%"}
animate={"fade"}
color={IOColors["grey-100"]}
height={21}
radius={4}
/>
<VSpacer size={8} />
<Placeholder.Box width={"86%"} animate={"fade"} height={21} radius={4} />
<Placeholder.Box
width={"86%"}
animate={"fade"}
color={IOColors["grey-100"]}
height={21}
radius={4}
/>
<VSpacer size={8} />
<Placeholder.Box width={"92%"} animate={"fade"} height={21} radius={4} />
<Placeholder.Box
width={"92%"}
animate={"fade"}
color={IOColors["grey-100"]}
height={21}
radius={4}
/>
<VSpacer size={8} />
<Placeholder.Box width={"80%"} animate={"fade"} height={21} radius={4} />
<Placeholder.Box
width={"80%"}
animate={"fade"}
color={IOColors["grey-100"]}
height={21}
radius={4}
/>
<VSpacer size={8} />
<Placeholder.Box width={"90%"} animate={"fade"} height={21} radius={4} />
<Placeholder.Box
width={"90%"}
animate={"fade"}
color={IOColors["grey-100"]}
height={21}
radius={4}
/>
<VSpacer size={8} />
<Placeholder.Box width={"96%"} animate={"fade"} height={21} radius={4} />
<Placeholder.Box
width={"96%"}
animate={"fade"}
color={IOColors["grey-100"]}
height={21}
radius={4}
/>
<VSpacer size={8} />
<Placeholder.Box width={"84%"} animate={"fade"} height={21} radius={4} />
<Placeholder.Box
width={"84%"}
animate={"fade"}
color={IOColors["grey-100"]}
height={21}
radius={4}
/>
<VSpacer size={8} />
<Placeholder.Box width={"88%"} animate={"fade"} height={21} radius={4} />
<Placeholder.Box
width={"88%"}
animate={"fade"}
color={IOColors["grey-100"]}
height={21}
radius={4}
/>
<VSpacer size={8} />
<Placeholder.Box width={"94%"} animate={"fade"} height={21} radius={4} />
<Placeholder.Box
width={"94%"}
animate={"fade"}
color={IOColors["grey-100"]}
height={21}
radius={4}
/>
</View>
</View>
);
9 changes: 8 additions & 1 deletion ts/features/services/components/CardWithMarkdownContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { memo } from "react";
import { StyleSheet, View } from "react-native";
import { IOColors } from "@pagopa/io-app-design-system";
import { Markdown } from "../../../components/ui/Markdown/Markdown";
import { LoadingSkeleton } from "../../../components/ui/Markdown/LoadingSkeleton";

const styles = StyleSheet.create({
card: {
Expand Down Expand Up @@ -31,4 +32,10 @@ const CardWithMarkdownContent = memo(
)
);

export { CardWithMarkdownContent };
const CardWithMarkdownContentSkeleton = () => (
<View style={styles.card}>
<LoadingSkeleton />
</View>
);

export { CardWithMarkdownContent, CardWithMarkdownContentSkeleton };
45 changes: 44 additions & 1 deletion ts/features/services/components/ServiceDetailsHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,14 @@ import { ImageURISource, StyleSheet, View } from "react-native";
import {
Avatar,
H3,
IOColors,
IOSpacingScale,
IOStyles,
LabelSmall
IOVisualCostants,
LabelSmall,
VSpacer
} from "@pagopa/io-app-design-system";
import Placeholder from "rn-placeholder";

const ITEM_PADDING_VERTICAL: IOSpacingScale = 6;
const AVATAR_MARGIN_RIGHT: IOSpacingScale = 16;
Expand Down Expand Up @@ -46,3 +50,42 @@ export const ServiceDetailsHeader = ({
</View>
</View>
);

export const ServiceDetailsHeaderSkeleton = () => (
<View style={styles.container} accessible={true}>
<View style={styles.itemAvatar}>
<Placeholder.Box
width={IOVisualCostants.avatarSizeMedium}
height={IOVisualCostants.avatarSizeMedium}
animate="fade"
radius={IOVisualCostants.avatarRadiusSizeMedium}
color={IOColors["grey-200"]}
/>
</View>
<View style={IOStyles.flex}>
<Placeholder.Box
animate="fade"
color={IOColors["grey-200"]}
height={16}
width={"100%"}
radius={8}
/>
<VSpacer size={8} />
<Placeholder.Box
animate="fade"
color={IOColors["grey-200"]}
height={16}
width={"80%"}
radius={8}
/>
<VSpacer size={8} />
<Placeholder.Box
animate="fade"
color={IOColors["grey-200"]}
height={8}
width={"60%"}
radius={8}
/>
</View>
</View>
);
54 changes: 31 additions & 23 deletions ts/features/services/navigation/navigator.tsx
Original file line number Diff line number Diff line change
@@ -1,36 +1,44 @@
import React from "react";
import { createStackNavigator } from "@react-navigation/stack";
import { myPortalEnabled } from "../../../config";
import LegacyServiceDetailsScreen from "../../../screens/services/LegacyServiceDetailsScreen";
import ServicesWebviewScreen from "../../../screens/services/ServicesWebviewScreen";
import { useIOSelector } from "../../../store/hooks";
import { isDesignSystemEnabledSelector } from "../../../store/reducers/persistedPreferences";
import { isGestureEnabled } from "../../../utils/navigation";
import { isNewServicesEnabled, myPortalEnabled } from "../../../config";
import { ServiceDetailsScreen } from "../screens/ServiceDetailsScreen";
import ServicesWebviewScreen from "../../../screens/services/ServicesWebviewScreen";
import LegacyServiceDetailsScreen from "../../../screens/services/LegacyServiceDetailsScreen";
import { ServicesParamsList } from "./params";
import { SERVICES_ROUTES } from "./routes";

const Stack = createStackNavigator<ServicesParamsList>();

const ServicesNavigator = () => (
<Stack.Navigator
initialRouteName={SERVICES_ROUTES.SERVICE_DETAIL}
screenOptions={{ gestureEnabled: isGestureEnabled, headerShown: false }}
>
<Stack.Screen
name={SERVICES_ROUTES.SERVICE_DETAIL}
component={
isNewServicesEnabled ? ServiceDetailsScreen : LegacyServiceDetailsScreen
}
options={{
headerShown: isNewServicesEnabled
}}
/>
{myPortalEnabled && (
const ServicesNavigator = () => {
const isDesignSystemEnabled = useIOSelector(isDesignSystemEnabledSelector);

return (
<Stack.Navigator
initialRouteName={SERVICES_ROUTES.SERVICE_DETAIL}
screenOptions={{ gestureEnabled: isGestureEnabled, headerShown: false }}
>
<Stack.Screen
name={SERVICES_ROUTES.SERVICE_WEBVIEW}
component={ServicesWebviewScreen}
name={SERVICES_ROUTES.SERVICE_DETAIL}
component={
isDesignSystemEnabled
? ServiceDetailsScreen
: LegacyServiceDetailsScreen
}
options={{
headerShown: isDesignSystemEnabled
}}
/>
)}
</Stack.Navigator>
);
{myPortalEnabled && (
<Stack.Screen
name={SERVICES_ROUTES.SERVICE_WEBVIEW}
component={ServicesWebviewScreen}
/>
)}
</Stack.Navigator>
);
};

export default ServicesNavigator;
34 changes: 31 additions & 3 deletions ts/features/services/screens/ServiceDetailsScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,15 @@ import { IOStackNavigationRouteProps } from "../../../navigation/params/AppParam
import { loadServiceDetail } from "../../../store/actions/services";
import { useIODispatch, useIOSelector } from "../../../store/hooks";
import { logosForService } from "../../../utils/services";
import { CardWithMarkdownContent } from "../components/CardWithMarkdownContent";
import {
CardWithMarkdownContent,
CardWithMarkdownContentSkeleton
} from "../components/CardWithMarkdownContent";
import { ServiceDetailsFailure } from "../components/ServiceDetailsFailure";
import { ServiceDetailsHeader } from "../components/ServiceDetailsHeader";
import {
ServiceDetailsHeader,
ServiceDetailsHeaderSkeleton
} from "../components/ServiceDetailsHeader";
import { ServiceDetailsMetadata } from "../components/ServiceDetailsMetadata";
import { ServiceDetailsPreferences } from "../components/ServiceDetailsPreferences";
import {
Expand Down Expand Up @@ -116,7 +122,29 @@ export const ServiceDetailsScreen = ({ route }: ServiceDetailsScreenProps) => {
}

if (isFirstRender || isLoadingService) {
// TODO: add a loading screen
return (
<ServiceDetailsScreenComponent>
<View
style={[
styles.headerContainer,
{
paddingTop: windowHeight + headerHeight,
marginTop: -windowHeight
}
]}
>
<ContentWrapper>
<ServiceDetailsHeaderSkeleton />
<VSpacer size={16} />
</ContentWrapper>
</View>
<ContentWrapper>
<View style={styles.cardContainer}>
<CardWithMarkdownContentSkeleton />
</View>
</ContentWrapper>
</ServiceDetailsScreenComponent>
);
}

const handlePressCta = (cta: CTA) => handleCtaAction(cta, linkTo, serviceId);
Expand Down

0 comments on commit c0b2871

Please sign in to comment.