/*
* 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 .
*/
// @flow
import * as React from 'react';
import {Image, Platform, ScrollView, View} from 'react-native';
import i18n from 'i18n-js';
import {
RadioButton,
Searchbar,
Subheading,
Text,
Title,
withTheme,
} from 'react-native-paper';
import {StackNavigationProp} from '@react-navigation/stack';
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 {CustomThemeType} from '../../../managers/ThemeManager';
import CollapsibleFlatList from '../../../components/Collapsible/CollapsibleFlatList';
import type {ProximoArticleType} from './ProximoMainScreen';
function sortPrice(a: ProximoArticleType, b: ProximoArticleType): number {
return parseInt(a.price, 10) - parseInt(b.price, 10);
}
function sortPriceReverse(
a: ProximoArticleType,
b: ProximoArticleType,
): number {
return parseInt(b.price, 10) - parseInt(a.price, 10);
}
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;
type PropsType = {
navigation: StackNavigationProp,
route: {
params: {
data: {data: Array},
shouldFocusSearchBar: boolean,
},
},
theme: CustomThemeType,
};
type StateType = {
currentSortMode: number,
modalCurrentDisplayItem: React.Node,
currentSearchString: string,
};
/**
* Class defining Proximo article list of a certain category.
*/
class ProximoListScreen extends React.Component {
modalRef: Modalize | null;
listData: Array;
shouldFocusSearchBar: boolean;
constructor(props: PropsType) {
super(props);
this.listData = props.route.params.data.data.sort(sortName);
this.shouldFocusSearchBar = props.route.params.shouldFocusSearchBar;
this.state = {
currentSearchString: '',
currentSortMode: 3,
modalCurrentDisplayItem: null,
};
}
/**
* Creates the header content
*/
componentDidMount() {
const {navigation} = this.props;
navigation.setOptions({
headerRight: this.getSortMenuButton,
headerTitle: this.getSearchBar,
headerBackTitleVisible: false,
headerTitleContainerStyle:
Platform.OS === 'ios'
? {marginHorizontal: 0, width: '70%'}
: {marginHorizontal: 0, right: 50, left: 50},
});
}
/**
* Callback used when clicking on the sort menu button.
* It will open the modal to show a sort selection
*/
onSortMenuPress = () => {
this.setState({
modalCurrentDisplayItem: this.getModalSortMenu(),
});
if (this.modalRef) {
this.modalRef.open();
}
};
/**
* Callback used when the search changes
*
* @param str The new search string
*/
onSearchStringChange = (str: string) => {
this.setState({currentSearchString: str});
};
/**
* 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
*/
onListItemPress(item: ProximoArticleType) {
this.setState({
modalCurrentDisplayItem: this.getModalItemContent(item),
});
if (this.modalRef) {
this.modalRef.open();
}
}
/**
* Sets the current sort mode.
*
* @param mode The number representing the mode
*/
setSortMode(mode: string) {
const {currentSortMode} = this.state;
const currentMode = parseInt(mode, 10);
this.setState({
currentSortMode: currentMode,
});
switch (currentMode) {
case 1:
this.listData.sort(sortPrice);
break;
case 2:
this.listData.sort(sortPriceReverse);
break;
case 3:
this.listData.sort(sortName);
break;
case 4:
this.listData.sort(sortNameReverse);
break;
default:
this.listData.sort(sortName);
break;
}
if (this.modalRef && currentMode !== currentSortMode) this.modalRef.close();
}
/**
* Gets a color depending on the quantity available
*
* @param availableStock The quantity available
* @return
*/
getStockColor(availableStock: number): string {
const {theme} = this.props;
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 {*}
*/
getSortMenuButton = (): React.Node => {
return (
);
};
/**
* Gets the header search bar
*
* @return {*}
*/
getSearchBar = (): React.Node => {
return (
);
};
/**
* Gets the modal content depending on the given article
*
* @param item The article to display
* @return {*}
*/
getModalItemContent(item: ProximoArticleType): React.Node {
return (
{item.name}
{`${item.quantity} ${i18n.t('screens.proximo.inStock')}`}
{item.price}€
{item.description}
);
}
/**
* Gets the modal content to display a sort menu
*
* @return {*}
*/
getModalSortMenu(): React.Node {
const {currentSortMode} = this.state;
return (
{i18n.t('screens.proximo.sortOrder')}
{
this.setSortMode(value);
}}
value={currentSortMode}>
);
}
/**
* Gets a render item for the given article
*
* @param item The article to render
* @return {*}
*/
getRenderItem = ({item}: {item: ProximoArticleType}): React.Node => {
const {currentSearchString} = this.state;
if (stringMatchQuery(item.name, currentSearchString)) {
const onPress = () => {
this.onListItemPress(item);
};
const color = this.getStockColor(parseInt(item.quantity, 10));
return (
);
}
return null;
};
/**
* Extracts a key for the given article
*
* @param item The article to extract the key from
* @return {string} The extracted key
*/
keyExtractor = (item: ProximoArticleType): string => item.name + item.code;
/**
* Callback used when receiving the modal ref
*
* @param ref
*/
onModalRef = (ref: Modalize) => {
this.modalRef = ref;
};
itemLayout = (
data: ProximoArticleType,
index: number,
): {length: number, offset: number, index: number} => ({
length: LIST_ITEM_HEIGHT,
offset: LIST_ITEM_HEIGHT * index,
index,
});
render(): React.Node {
const {state} = this;
return (
{state.modalCurrentDisplayItem}
);
}
}
export default withTheme(ProximoListScreen);