Skip to content

Commit

Permalink
feat: add loaderPopup component
Browse files Browse the repository at this point in the history
  • Loading branch information
hel-axelor committed Jan 22, 2024
1 parent 1e3184f commit 2dcb91c
Show file tree
Hide file tree
Showing 4 changed files with 127 additions and 4 deletions.
4 changes: 3 additions & 1 deletion packages/apps/stock/src/screens/loader/LoaderScreen.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
import React from 'react';
import {Button, View} from 'react-native';
import {Screen} from '@axelor/aos-mobile-ui';
import {useLoaderListner} from '@axelor/aos-mobile-core';
import {LoaderPopup, useLoaderListner} from '@axelor/aos-mobile-core';

// Screen for test Loader functionnalities
const LoaderScreen = () => {
Expand All @@ -55,12 +55,14 @@ const LoaderScreen = () => {
const {loading, listener} = useLoaderListner({
process,
onSuccess: handleCustomAction,
disabled: true,
});

return (
<Screen>
<View>
<Button title="check process" onPress={listener} disabled={loading} />
<LoaderPopup loading={loading} timeout={5000} />
</View>
</Screen>
);
Expand Down
118 changes: 118 additions & 0 deletions packages/core/src/components/templates/Loader/LoaderPopup.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
/*
* Axelor Business Solutions
*
* Copyright (C) 2024 Axelor (<http://axelor.com>).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

import React, {useCallback, useEffect, useState} from 'react';
import {
BlockInteractionScreen,
Button,
Card,
Label,
Text,
useConfig,
useThemeColor,
} from '@axelor/aos-mobile-ui';
import {ActivityIndicator, Dimensions, StyleSheet, View} from 'react-native';
import {useTranslator} from '../../../i18n';
import {useNavigation} from '@react-navigation/native';

interface LoaderPopupProps {
loading: boolean;
timeout: number;
onSuccess: () => void;
onError: () => void;
}

const LoaderPopup = ({loading, timeout = 100}: LoaderPopupProps) => {
const navigation = useNavigation();
const I18n = useTranslator();
const Colors = useThemeColor();
const {setActivityIndicator} = useConfig();

const [showPopup, setShowPopup] = useState<boolean>(false);

const handleGoBack = useCallback(() => {
navigation.goBack();
}, [navigation]);

useEffect(() => {
if (loading && !showPopup) {
setActivityIndicator(true);
}

const timerId = setTimeout(() => {
setActivityIndicator(false);
setShowPopup(true);
}, timeout);

return () => clearTimeout(timerId);
}, [timeout, loading, showPopup, setActivityIndicator]);

if (!loading || !showPopup) {
return null;
}

return (
<BlockInteractionScreen hideHeader={true}>
<Card style={styles.popupContainer}>
<Label
type="danger"
message={I18n.t('Base_Loading_DoNotCloseTheApp')}
iconName="exclamation-triangle-fill"
/>
<View style={styles.activityIndicatorContainer}>
<ActivityIndicator
size="large"
color={Colors.primaryColor.background}
/>
<Text style={styles.loadingLabel}>
{I18n.t('Base_Loader_LoadingInProgress')}
</Text>
</View>
<Button
iconName="check-lg"
title={I18n.t('Base_Loader_NotifyMeWantItIsReady')}
onPress={handleGoBack}
/>
</Card>
</BlockInteractionScreen>
);
};

const styles = StyleSheet.create({
popupContainer: {
position: 'absolute',
width: 350,
top: Dimensions.get('window').height * 0.2,
left: Dimensions.get('window').width * 0.06,
elevation: 24,
shadowOpacity: 12,
paddingVertical: 10,
},
activityIndicatorContainer: {
flex: 1,
flexDirection: 'row',
justifyContent: 'center',
alignItems: 'center',
marginHorizontal: 30,
},
loadingLabel: {
fontWeight: 'bold',
},
});

export default LoaderPopup;
1 change: 1 addition & 0 deletions packages/core/src/components/templates/Loader/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

export {default as LoaderPopup} from './LoaderPopup';
export {default as useLoaderListner} from './use-loader-listener';
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,14 @@ interface LoaderListenerProps {
process: () => Promise<any>;
onSuccess?: () => void;
onError?: () => void;
disabled?: boolean;
}

const useLoaderListner = ({
process,
onSuccess = () => console.log('Process successfully completed.'),
onError = () => console.warn('An error has occurred!'),
disabled = false,
}: LoaderListenerProps) => {
const I18n = useTranslator();

Expand All @@ -49,7 +51,7 @@ const useLoaderListner = ({
topOffset: 30,
text1: I18n.t('Base_Success'),
text2: response || I18n.t('Base_Loader_ProccessSuccessMessage'),
onPress: onSuccess,
onPress: !disabled ? onSuccess : () => {},
});
} catch (error) {
showToastMessage({
Expand All @@ -58,12 +60,12 @@ const useLoaderListner = ({
topOffset: 30,
text1: I18n.t('Base_Error'),
text2: error || I18n.t('Base_Loader_ProccessErrorMessage'),
onPress: onError,
onPress: !disabled ? onError : () => {},
});
} finally {
setLoading(false);
}
}, [process, onSuccess, onError, I18n]);
}, [process, disabled, onSuccess, onError, I18n]);

useEffect(() => {
if (start && !loading) {
Expand Down

0 comments on commit 2dcb91c

Please sign in to comment.