/* * Copyright (c) 2019 - 2020 Arnaud Vergnet. * * This file is part of Campus INSAT. * * Campus INSAT is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Campus INSAT 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Campus INSAT. If not, see . */ import React, { useState } from 'react'; import i18n from 'i18n-js'; import { Snackbar } from 'react-native-paper'; import { NativeScrollEvent, NativeSyntheticEvent, RefreshControl, SectionListData, SectionListRenderItemInfo, StyleSheet, View, } from 'react-native'; import * as Animatable from 'react-native-animatable'; import ErrorView from './ErrorView'; import BasicLoadingScreen from './BasicLoadingScreen'; import { TAB_BAR_HEIGHT } from '../Tabbar/CustomTabBar'; import { ERROR_TYPE } from '../../utils/WebData'; import CollapsibleSectionList from '../Collapsible/CollapsibleSectionList'; import GENERAL_STYLES from '../../constants/Styles'; import RequestScreen from './RequestScreen'; export type SectionListDataType = Array<{ title: string; icon?: string; data: Array; keyExtractor?: (data: ItemT) => string; }>; type Props = { request: () => Promise; refreshOnFocus: boolean; renderItem: (data: SectionListRenderItemInfo) => React.ReactNode; createDataset: ( data: RawData | undefined, isLoading: boolean ) => SectionListDataType; onScroll?: (event: NativeSyntheticEvent) => void; showError?: boolean; itemHeight?: number | null; autoRefreshTime?: number; updateData?: number | string; renderListHeaderComponent?: ( data?: RawData ) => React.ComponentType | React.ReactElement | null; renderSectionHeader?: ( data: { section: SectionListData }, isLoading: boolean ) => React.ReactElement | null; stickyHeader?: boolean; cache?: RawData; onCacheUpdate?: (newCache: RawData) => void; }; const styles = StyleSheet.create({ container: { minHeight: '100%', }, }); /** * Component used to render a SectionList with data fetched from the web * To force the component to update, change the value of updateData. */ function WebSectionList(props: Props) { const [snackbarVisible, setSnackbarVisible] = useState(false); const showSnackBar = () => setSnackbarVisible(true); const hideSnackBar = () => setSnackbarVisible(false); const getItemLayout = ( height: number, _data: Array> | null, index: number ): { length: number; offset: number; index: number } => { return { length: height, offset: height * index, index, }; }; const getRenderSectionHeader = ( data: { section: SectionListData }, loading: boolean ) => { const { renderSectionHeader } = props; if (renderSectionHeader) { return ( {renderSectionHeader(data, loading)} ); } return null; }; const getRenderItem = (data: SectionListRenderItemInfo) => { const { renderItem } = props; return ( {renderItem(data)} ); }; const onScroll = (event: NativeSyntheticEvent) => { if (props.onScroll) { props.onScroll(event); } }; const render = ( data: RawData | undefined, loading: boolean, refreshData: (newRequest?: () => Promise) => void ) => { const { itemHeight } = props; const dataset = props.createDataset(data, loading); if (!data && !loading) { showSnackBar(); } return ( ({ refreshControl: ( ), })} renderSectionHeader={(info) => getRenderSectionHeader(info, loading)} renderItem={getRenderItem} stickySectionHeadersEnabled={props.stickyHeader} style={styles.container} ListHeaderComponent={ props.renderListHeaderComponent != null ? props.renderListHeaderComponent(data) : null } ListEmptyComponent={ loading ? ( ) : ( ) } getItemLayout={ itemHeight ? (d, i) => getItemLayout(itemHeight, d, i) : undefined } onScroll={onScroll} hasTab={true} /> ); }; return ( request={props.request} render={render} showError={false} showLoading={false} autoRefreshTime={props.autoRefreshTime} refreshOnFocus={props.refreshOnFocus} cache={props.cache} onCacheUpdate={props.onCacheUpdate} /> {i18n.t('general.listUpdateFail')} ); } export default WebSectionList;