/* * 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, { useLayoutEffect, useRef, useState } from 'react'; import { Image, Platform, ScrollView, StyleSheet, View } from 'react-native'; import i18n from 'i18n-js'; import { RadioButton, Searchbar, Subheading, Text, Title, useTheme, } from 'react-native-paper'; import { Modalize } from 'react-native-modalize'; import CustomModal from '../../../components/Overrides/CustomModal'; import { stringMatchQuery } from '../../../utils/Search'; import ProximoListItem from '../../../components/Lists/Proximo/ProximoListItem'; import MaterialHeaderButtons, { Item, } from '../../../components/Overrides/CustomHeaderButton'; import type { ProximoArticleType } from './ProximoMainScreen'; import GENERAL_STYLES from '../../../constants/Styles'; import { useNavigation } from '@react-navigation/core'; import Urls from '../../../constants/Urls'; import WebSectionList, { SectionListDataType, } from '../../../components/Screens/WebSectionList'; import { readData } from '../../../utils/WebData'; import { StackScreenProps } from '@react-navigation/stack'; import { MainRoutes, MainStackParamsList, } from '../../../navigation/MainNavigator'; import { useCachedProximoArticles } from '../../../context/cacheContext'; function sortPrice(a: ProximoArticleType, b: ProximoArticleType): number { return a.price - b.price; } function sortPriceReverse( a: ProximoArticleType, b: ProximoArticleType ): number { return b.price - a.price; } function sortName(a: ProximoArticleType, b: ProximoArticleType): number { if (a.name.toLowerCase() < b.name.toLowerCase()) { return -1; } if (a.name.toLowerCase() > b.name.toLowerCase()) { return 1; } return 0; } function sortNameReverse(a: ProximoArticleType, b: ProximoArticleType): number { if (a.name.toLowerCase() < b.name.toLowerCase()) { return 1; } if (a.name.toLowerCase() > b.name.toLowerCase()) { return -1; } return 0; } const LIST_ITEM_HEIGHT = 84; const styles = StyleSheet.create({ modalContainer: { flex: 1, padding: 20, }, modalTitleContainer: { flexDirection: 'row', width: '100%', marginTop: 10, }, modalTitle: { marginLeft: 'auto', }, modalContent: { width: '100%', height: 150, marginTop: 20, marginBottom: 20, }, image: { flex: 1, resizeMode: 'contain', }, sortTitle: { marginBottom: 10, }, }); export type ArticlesType = Array; type Props = StackScreenProps; function ProximoListScreen(props: Props) { const navigation = useNavigation(); const theme = useTheme(); const { articles, setArticles } = useCachedProximoArticles(); const modalRef = useRef(null); const [currentSearchString, setCurrentSearchString] = useState(''); const [currentSortMode, setCurrentSortMode] = useState(2); const [modalCurrentDisplayItem, setModalCurrentDisplayItem] = useState(); const sortModes = [sortPrice, sortPriceReverse, sortName, sortNameReverse]; useLayoutEffect(() => { navigation.setOptions({ headerRight: getSortMenuButton, headerTitle: getSearchBar, headerBackTitleVisible: false, headerTitleContainerStyle: Platform.OS === 'ios' ? { marginHorizontal: 0, width: '70%' } : { marginHorizontal: 0, right: 50, left: 50 }, }); // eslint-disable-next-line react-hooks/exhaustive-deps }, [navigation, currentSortMode]); /** * Callback used when clicking on the sort menu button. * It will open the modal to show a sort selection */ const onSortMenuPress = () => { setModalCurrentDisplayItem(getModalSortMenu()); if (modalRef.current) { modalRef.current.open(); } }; /** * Callback used when clicking an article in the list. * It opens the modal to show detailed information about the article * * @param item The article pressed */ const onListItemPress = (item: ProximoArticleType) => { setModalCurrentDisplayItem(getModalItemContent(item)); if (modalRef.current) { modalRef.current.open(); } }; /** * Sets the current sort mode. * * @param mode The number representing the mode */ const setSortMode = (mode: string) => { const currentMode = parseInt(mode, 10); setCurrentSortMode(currentMode); if (modalRef.current && currentMode !== currentSortMode) { modalRef.current.close(); } }; /** * Gets a color depending on the quantity available * * @param availableStock The quantity available * @return */ const getStockColor = (availableStock: number): string => { let color: string; if (availableStock > 3) { color = theme.colors.success; } else if (availableStock > 0) { color = theme.colors.warning; } else { color = theme.colors.danger; } return color; }; /** * Gets the sort menu header button * * @return {*} */ const getSortMenuButton = () => { return ( ); }; /** * Gets the header search bar * * @return {*} */ const getSearchBar = () => { return ( // @ts-ignore ); }; /** * Gets the modal content depending on the given article * * @param item The article to display * @return {*} */ const getModalItemContent = (item: ProximoArticleType) => { return ( {item.name} {`${item.quantity} ${i18n.t('screens.proximo.inStock')}`} {item.price.toFixed(2)}€ {item.description} ); }; /** * Gets the modal content to display a sort menu * * @return {*} */ const getModalSortMenu = () => { return ( {i18n.t('screens.proximo.sortOrder')} ); }; /** * Gets a render item for the given article * * @param item The article to render * @return {*} */ const getRenderItem = ({ item }: { item: ProximoArticleType }) => { if (stringMatchQuery(item.name, currentSearchString)) { const onPress = () => { onListItemPress(item); }; const color = getStockColor(item.quantity); return ( ); } return null; }; /** * Extracts a key for the given article * * @param item The article to extract the key from * @return {string} The extracted key */ const keyExtractor = (item: ProximoArticleType): string => item.name + item.code; const createDataset = ( data: ArticlesType | undefined ): SectionListDataType => { if (data) { return [ { title: '', data: data .filter( (d) => props.route.params.category === -1 || props.route.params.category === d.category_id ) .sort(sortModes[currentSortMode]), keyExtractor: keyExtractor, }, ]; } else { return []; } }; return ( {modalCurrentDisplayItem} readData(Urls.proximo.articles)} createDataset={createDataset} refreshOnFocus={true} renderItem={getRenderItem} extraData={currentSearchString + currentSortMode} itemHeight={LIST_ITEM_HEIGHT} cache={articles} onCacheUpdate={setArticles} /> ); } export default ProximoListScreen;