Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[TS migration] Migrate 'BlockingViews' component to TypeScript #32253

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,75 +1,75 @@
import PropTypes from 'prop-types';
import React from 'react';
import {View} from 'react-native';
import {ImageSourcePropType, View} from 'react-native';
import {SvgProps} from 'react-native-svg';
import AutoEmailLink from '@components/AutoEmailLink';
import Icon from '@components/Icon';
import sourcePropTypes from '@components/Image/sourcePropTypes';
import Text from '@components/Text';
import TextLink from '@components/TextLink';
import useLocalize from '@hooks/useLocalize';
import useThemeStyles from '@hooks/useThemeStyles';
import Navigation from '@libs/Navigation/Navigation';
import variables from '@styles/variables';
import {TranslationPaths} from '@src/languages/types';

const propTypes = {
type BlockingViewProps = {
/** Expensicon for the page */
icon: sourcePropTypes.isRequired,
icon: React.FC<SvgProps> | ImageSourcePropType;

/** Color for the icon (should be from theme) */
iconColor: PropTypes.string,
iconColor?: string;

/** Title message below the icon */
title: PropTypes.string.isRequired,
title: string;

/** Subtitle message below the title */
subtitle: PropTypes.string,
subtitle?: string;

/** Link message below the subtitle */
linkKey: PropTypes.string,
linkKey?: TranslationPaths;

/** Whether we should show a link to navigate elsewhere */
shouldShowLink: PropTypes.bool,
shouldShowLink?: boolean;

/** The custom icon width */
iconWidth: PropTypes.number,
iconWidth?: number;

/** The custom icon height */
iconHeight: PropTypes.number,
iconHeight?: number;

/** Function to call when pressing the navigation link */
onLinkPress: PropTypes.func,
onLinkPress?: () => void;

/** Whether we should embed the link with subtitle */
shouldEmbedLinkWithSubtitle: PropTypes.bool,
shouldEmbedLinkWithSubtitle?: boolean;
};

const defaultProps = {
iconColor: null,
subtitle: '',
shouldShowLink: false,
linkKey: 'notFound.goBackHome',
iconWidth: variables.iconSizeSuperLarge,
iconHeight: variables.iconSizeSuperLarge,
onLinkPress: () => Navigation.dismissModal(),
shouldEmbedLinkWithSubtitle: false,
};

function BlockingView(props) {
function BlockingView({
icon,
iconColor,
title,
subtitle = '',
linkKey = 'notFound.goBackHome',
shouldShowLink = false,
iconWidth = variables.iconSizeSuperLarge,
iconHeight = variables.iconSizeSuperLarge,
onLinkPress = () => Navigation.dismissModal(),
shouldEmbedLinkWithSubtitle = false,
}: BlockingViewProps) {
const styles = useThemeStyles();
const {translate} = useLocalize();
function renderContent() {
return (
<>
<AutoEmailLink
style={[styles.textAlignCenter]}
text={props.subtitle}
text={subtitle}
/>
{props.shouldShowLink ? (
{shouldShowLink ? (
<TextLink
onPress={props.onLinkPress}
onPress={onLinkPress}
style={[styles.link, styles.mt2]}
>
{translate(props.linkKey)}
{translate(linkKey)}
</TextLink>
) : null}
</>
Expand All @@ -79,14 +79,14 @@ function BlockingView(props) {
return (
<View style={[styles.flex1, styles.alignItemsCenter, styles.justifyContentCenter, styles.ph10]}>
<Icon
src={props.icon}
fill={props.iconColor}
width={props.iconWidth}
height={props.iconHeight}
src={icon}
fill={iconColor}
width={iconWidth}
height={iconHeight}
/>
<Text style={[styles.notFoundTextHeader]}>{props.title}</Text>
<Text style={[styles.notFoundTextHeader]}>{title}</Text>

{props.shouldEmbedLinkWithSubtitle ? (
{shouldEmbedLinkWithSubtitle ? (
<Text style={[styles.textAlignCenter]}>{renderContent()}</Text>
) : (
<View style={[styles.alignItemsCenter, styles.justifyContentCenter]}>{renderContent()}</View>
Expand All @@ -95,8 +95,6 @@ function BlockingView(props) {
);
}

BlockingView.propTypes = propTypes;
BlockingView.defaultProps = defaultProps;
BlockingView.displayName = 'BlockingView';

export default BlockingView;
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import PropTypes from 'prop-types';
import React from 'react';
import {View} from 'react-native';
import HeaderWithBackButton from '@components/HeaderWithBackButton';
Expand All @@ -7,54 +6,54 @@ import useLocalize from '@hooks/useLocalize';
import useThemeStyles from '@hooks/useThemeStyles';
import Navigation from '@libs/Navigation/Navigation';
import variables from '@styles/variables';
import {TranslationPaths} from '@src/languages/types';
import ROUTES from '@src/ROUTES';
import BlockingView from './BlockingView';

const propTypes = {
type FullPageNotFoundViewProps = {
/** Child elements */
children: PropTypes.node,
children?: React.ReactNode;

/** If true, child components are replaced with a blocking "not found" view */
shouldShow: PropTypes.bool,
shouldShow?: boolean;

/** The key in the translations file to use for the title */
titleKey: PropTypes.string,
titleKey?: TranslationPaths;

/** The key in the translations file to use for the subtitle */
subtitleKey: PropTypes.string,
subtitleKey?: TranslationPaths;

/** Whether we should show a link to navigate elsewhere */
shouldShowLink: PropTypes.bool,
shouldShowLink?: boolean;

/** Whether we should show the back button on the header */
shouldShowBackButton: PropTypes.bool,
shouldShowBackButton?: boolean;

/** The key in the translations file to use for the go back link */
linkKey: PropTypes.string,
linkKey?: TranslationPaths;

/** Method to trigger when pressing the back button of the header */
onBackButtonPress: PropTypes.func,
onBackButtonPress: () => void;

/** Function to call when pressing the navigation link */
onLinkPress: PropTypes.func,
};

const defaultProps = {
children: null,
shouldShow: false,
titleKey: 'notFound.notHere',
subtitleKey: 'notFound.pageNotFound',
linkKey: 'notFound.goBackHome',
onBackButtonPress: () => Navigation.goBack(ROUTES.HOME),
shouldShowLink: true,
shouldShowBackButton: true,
onLinkPress: () => Navigation.dismissModal(),
onLinkPress: () => void;
};

// eslint-disable-next-line rulesdir/no-negated-variables
function FullPageNotFoundView({children, shouldShow, titleKey, subtitleKey, linkKey, onBackButtonPress, shouldShowLink, shouldShowBackButton, onLinkPress}) {
cdOut marked this conversation as resolved.
Show resolved Hide resolved
function FullPageNotFoundView({
children = null,
shouldShow = false,
titleKey = 'notFound.notHere',
subtitleKey = 'notFound.pageNotFound',
linkKey = 'notFound.goBackHome',
onBackButtonPress = () => Navigation.goBack(ROUTES.HOME),
shouldShowLink = true,
shouldShowBackButton = true,
onLinkPress = () => Navigation.dismissModal(),
}: FullPageNotFoundViewProps) {
const styles = useThemeStyles();
const {translate} = useLocalize();

if (shouldShow) {
return (
cdOut marked this conversation as resolved.
Show resolved Hide resolved
<>
Expand All @@ -81,8 +80,6 @@ function FullPageNotFoundView({children, shouldShow, titleKey, subtitleKey, link
return children;
}

FullPageNotFoundView.propTypes = propTypes;
FullPageNotFoundView.defaultProps = defaultProps;
FullPageNotFoundView.displayName = 'FullPageNotFoundView';

export default FullPageNotFoundView;
42 changes: 0 additions & 42 deletions src/components/BlockingViews/FullPageOfflineBlockingView.js

This file was deleted.

31 changes: 31 additions & 0 deletions src/components/BlockingViews/FullPageOfflineBlockingView.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React from 'react';
import * as Expensicons from '@components/Icon/Expensicons';
import useLocalize from '@hooks/useLocalize';
import useNetwork from '@hooks/useNetwork';
import useTheme from '@hooks/useTheme';
import ChildrenProps from '@src/types/utils/ChildrenProps';
import BlockingView from './BlockingView';

function FullPageOfflineBlockingView({children}: ChildrenProps) {
const {translate} = useLocalize();
const {isOffline} = useNetwork();

const theme = useTheme();

if (isOffline) {
return (
<BlockingView
icon={Expensicons.OfflineCloud}
iconColor={theme.offline}
title={translate('common.youAppearToBeOffline')}
subtitle={translate('common.thisFeatureRequiresInternet')}
/>
);
}

return children;
}

FullPageOfflineBlockingView.displayName = 'FullPageOfflineBlockingView';

export default FullPageOfflineBlockingView;
Loading