Implemented search into each category instead of its own screen

This commit is contained in:
Yohan Simard 2019-11-15 18:08:47 +01:00
parent edfb32667c
commit d614e8a1ed
4 changed files with 49 additions and 145 deletions

View file

@ -5,7 +5,6 @@ import {createMaterialBottomTabNavigatorWithInitialRoute} from './MainTabNavigat
import SettingsScreen from '../screens/SettingsScreen'; import SettingsScreen from '../screens/SettingsScreen';
import AboutScreen from '../screens/About/AboutScreen'; import AboutScreen from '../screens/About/AboutScreen';
import ProximoListScreen from '../screens/Proximo/ProximoListScreen'; import ProximoListScreen from '../screens/Proximo/ProximoListScreen';
import ProximoSearchScreen from "../screens/Proximo/ProximoSearchScreen";
import AboutDependenciesScreen from '../screens/About/AboutDependenciesScreen'; import AboutDependenciesScreen from '../screens/About/AboutDependenciesScreen';
import ProxiwashAboutScreen from '../screens/Proxiwash/ProxiwashAboutScreen'; import ProxiwashAboutScreen from '../screens/Proxiwash/ProxiwashAboutScreen';
import ProximoAboutScreen from '../screens/Proximo/ProximoAboutScreen'; import ProximoAboutScreen from '../screens/Proximo/ProximoAboutScreen';
@ -27,7 +26,6 @@ function createAppContainerWithInitialRoute(initialRoute: string) {
Main: createMaterialBottomTabNavigatorWithInitialRoute(initialRoute), Main: createMaterialBottomTabNavigatorWithInitialRoute(initialRoute),
// Drawer: MainDrawerNavigator, // Drawer: MainDrawerNavigator,
ProximoListScreen: {screen: ProximoListScreen}, ProximoListScreen: {screen: ProximoListScreen},
ProximoSearchScreen: {screen: ProximoSearchScreen},
SettingsScreen: {screen: SettingsScreen}, SettingsScreen: {screen: SettingsScreen},
AboutScreen: {screen: AboutScreen}, AboutScreen: {screen: AboutScreen},
AboutDependenciesScreen: {screen: AboutDependenciesScreen}, AboutDependenciesScreen: {screen: AboutDependenciesScreen},
@ -44,7 +42,7 @@ function createAppContainerWithInitialRoute(initialRoute: string) {
initialRouteName: "Main", initialRouteName: "Main",
mode: 'card', mode: 'card',
headerMode: "none", headerMode: "none",
// transitionConfig: () => fromRight(), transitionConfig: () => fromRight(),
}) })
); );
} }

View file

@ -51,6 +51,7 @@ type State = {
sortPriceIcon: React.Node, sortPriceIcon: React.Node,
sortNameIcon: React.Node, sortNameIcon: React.Node,
modalCurrentDisplayItem: Object, modalCurrentDisplayItem: Object,
currentlyDisplayedData: Array<Object>,
}; };
/** /**
@ -59,19 +60,21 @@ type State = {
export default class ProximoListScreen extends React.Component<Props, State> { export default class ProximoListScreen extends React.Component<Props, State> {
modalRef: { current: null | Modalize }; modalRef: { current: null | Modalize };
originalData: Array<Object>;
constructor(props: any) { constructor(props: any) {
super(props); super(props);
this.modalRef = React.createRef(); this.modalRef = React.createRef();
this.originalData = this.props.navigation.getParam('data', []);
} }
state = { state = {
navData: this.props.navigation.getParam('data', []).sort(sortPrice), currentlyDisplayedData: this.props.navigation.getParam('data', []).sort(sortPrice),
currentSortMode: sortMode.price, currentSortMode: sortMode.price,
isSortReversed: false, isSortReversed: false,
sortPriceIcon: '', sortPriceIcon: '',
sortNameIcon: '', sortNameIcon: '',
modalCurrentDisplayItem: {} modalCurrentDisplayItem: {},
}; };
_menu: Menu; _menu: Menu;
@ -111,7 +114,7 @@ export default class ProximoListScreen extends React.Component<Props, State> {
currentSortMode: mode, currentSortMode: mode,
isSortReversed: isReverse isSortReversed: isReverse
}); });
let data = this.state.navData; let data = this.state.currentlyDisplayedData;
switch (mode) { switch (mode) {
case sortMode.price: case sortMode.price:
if (isReverse) { if (isReverse) {
@ -192,6 +195,35 @@ export default class ProximoListScreen extends React.Component<Props, State> {
} }
} }
sanitizeString(str: string) {
return str.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "");
}
/**
* Returns only the articles whose name contains str. Case and accents insensitive.
* @param str
* @returns {[]}
*/
filterData(str: string) {
let filteredData = [];
const testStr = this.sanitizeString(str);
const articles = this.originalData;
for (const article of articles) {
const name = this.sanitizeString(article.name);
if (name.includes(testStr)) {
filteredData.push(article)
}
}
return filteredData;
}
search(str: string) {
this.setState({
currentlyDisplayedData: this.filterData(str)
})
}
getModalContent() { getModalContent() {
return ( return (
<View style={{ <View style={{
@ -277,13 +309,13 @@ export default class ProximoListScreen extends React.Component<Props, State> {
hasBackButton={true} hasBackButton={true}
navigation={nav} navigation={nav}
hasSearchField={true} hasSearchField={true}
searchCallback={(text) => console.log(text)} searchCallback={(text) => this.search(text)}
rightButton={this.getSortMenu()}/> rightButton={this.getSortMenu()}/>
<Content> <Content>
<FlatList <FlatList
data={this.state.navData} data={this.state.currentlyDisplayedData}
extraData={this.state.navData} extraData={this.state.currentlyDisplayedData}
keyExtractor={(item) => item.name + item.code} keyExtractor={(item) => item.name + item.code}
style={{minHeight: 300, width: '100%'}} style={{minHeight: 300, width: '100%'}}
renderItem={({item}) => renderItem={({item}) =>

View file

@ -102,25 +102,13 @@ export default class ProximoMainScreen extends FetchedDataSectionList {
getRightButton() { getRightButton() {
return ( return (
<View <Touchable
style={{ style={{padding: 6}}
flexDirection: 'row' onPress={() => this.props.navigation.navigate('ProximoAboutScreen')}>
}}> <CustomMaterialIcon
<Touchable color={Platform.OS === 'ios' ? ThemeManager.getCurrentThemeVariables().brandPrimary : "#fff"}
style={{padding: 6}} icon="information"/>
onPress={() => this.props.navigation.navigate('ProximoSearchScreen', {data: this.state.fetchedData})}> </Touchable>
<CustomMaterialIcon
color={Platform.OS === 'ios' ? ThemeManager.getCurrentThemeVariables().brandPrimary : "#fff"}
icon="magnify"/>
</Touchable>
<Touchable
style={{padding: 6}}
onPress={() => this.props.navigation.navigate('ProximoAboutScreen')}>
<CustomMaterialIcon
color={Platform.OS === 'ios' ? ThemeManager.getCurrentThemeVariables().brandPrimary : "#fff"}
icon="information"/>
</Touchable>
</View>
); );
} }
@ -138,15 +126,16 @@ export default class ProximoMainScreen extends FetchedDataSectionList {
<CustomMaterialIcon <CustomMaterialIcon
icon={item.type.icon} icon={item.type.icon}
fontSize={30} fontSize={30}
color={ThemeManager.getCurrentThemeVariables().brandPrimary}
/> />
</Left> </Left>
<Body> <Body>
<Text> <Text>
{item.type.name} {item.type.name}
</Text> </Text>
<Badge><Text> <Text note>
{item.data.length} {item.data.length > 1 ? i18n.t('proximoScreen.articles') : i18n.t('proximoScreen.article')} {item.data.length} {item.data.length > 1 ? i18n.t('proximoScreen.articles') : i18n.t('proximoScreen.article')}
</Text></Badge> </Text>
</Body> </Body>
<Right> <Right>
<CustomMaterialIcon icon="chevron-right"/> <CustomMaterialIcon icon="chevron-right"/>

View file

@ -1,115 +0,0 @@
// @flow
import * as React from 'react';
import {Body, Container, Content, Left, ListItem, Right, Text, Thumbnail,} from 'native-base';
import {FlatList} from "react-native";
import i18n from "i18n-js";
import ThemeManager from "../../utils/ThemeManager";
import CustomHeader from "../../components/CustomHeader";
type Props = {
navigation: Object,
};
type State = {
filteredData: Array<Object>,
};
/**
* Class defining proximo's article list of a certain category.
*/
export default class ProximoSearchScreen extends React.Component<Props, State> {
state = {
filteredData: this.props.navigation.getParam('data', {articles: [{name: "Error"}]}).articles,
};
/**
* get color depending on quantity available
*
* @param availableStock
* @return
*/
getStockColor(availableStock: number) {
let color: string;
if (availableStock > 3)
color = ThemeManager.getCurrentThemeVariables().brandSuccess;
else if (availableStock > 0)
color = ThemeManager.getCurrentThemeVariables().brandWarning;
else
color = ThemeManager.getCurrentThemeVariables().brandDanger;
return color;
}
showItemDetails(item: Object) {
//TODO: implement onClick function (copy-paste from ProximoListScreen)
}
/**
* Returns only the articles whose name contains str. Case and accents insensitive.
* @param str
* @returns {[]}
*/
filterData(str: string) {
let filteredData = [];
const testStr: String = str.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "");
const articles: Object = this.props.navigation.getParam('data', {articles: [{name: "Error"}]}).articles;
for (const article: Object of articles) {
const name: String = String(article.name.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, ""));
if (name.includes(testStr)) {
filteredData.push(article)
}
}
return filteredData;
}
search(str: string) {
this.setState({
filteredData: this.filterData(str)
})
}
render() {
return (
<Container>
<CustomHeader
hasBackButton={true}
navigation={this.props.navigation}
hasSearchField={true}
searchCallback={(text) => this.search(text)}/>
<Content>
<FlatList
data={this.state.filteredData}
keyExtractor={(item) => item.name + item.code}
style={{minHeight: 300, width: '100%'}}
renderItem={({item}) =>
<ListItem
thumbnail
onPress={() => {this.showItemDetails(item);}} >
<Left>
<Thumbnail square source={{uri: item.image}}/>
</Left>
<Body>
<Text style={{marginLeft: 20}}>
{item.name}
</Text>
<Text note style={{
marginLeft: 20,
color: this.getStockColor(parseInt(item.quantity))
}}>
{item.quantity + ' ' + i18n.t('proximoScreen.inStock')}
</Text>
</Body>
<Right>
<Text style={{fontWeight: "bold"}}>
{item.price}
</Text>
</Right>
</ListItem>}
/>
</Content>
</Container>
);
}
}