Update Proximo screens to use TypeScript

This commit is contained in:
Arnaud Vergnet 2020-09-22 22:35:24 +02:00
parent 9f4dcda7d9
commit 2eb4a3e0c1
4 changed files with 168 additions and 148 deletions

View file

@ -1,83 +0,0 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
// @flow
import * as React from 'react';
import {Image, View} from 'react-native';
import i18n from 'i18n-js';
import {Card, Avatar, Paragraph, Text} from 'react-native-paper';
import CustomTabBar from '../../../components/Tabbar/CustomTabBar';
import CollapsibleScrollView from '../../../components/Collapsible/CollapsibleScrollView';
import type {CardTitleIconPropsType} from '../../../constants/PaperStyles';
const LOGO = 'https://etud.insa-toulouse.fr/~amicale_app/images/Proximo.png';
/**
* Class defining the proximo about screen.
*/
// eslint-disable-next-line react/prefer-stateless-function
export default class ProximoAboutScreen extends React.Component<null> {
render(): React.Node {
return (
<CollapsibleScrollView style={{padding: 5}}>
<View
style={{
width: '100%',
height: 100,
marginTop: 20,
marginBottom: 20,
justifyContent: 'center',
alignItems: 'center',
}}>
<Image
source={{uri: LOGO}}
style={{height: '100%', width: '100%', resizeMode: 'contain'}}
/>
</View>
<Text>{i18n.t('screens.proximo.description')}</Text>
<Card style={{margin: 5}}>
<Card.Title
title={i18n.t('screens.proximo.openingHours')}
left={(iconProps: CardTitleIconPropsType): React.Node => (
<Avatar.Icon size={iconProps.size} icon="clock-outline" />
)}
/>
<Card.Content>
<Paragraph>18h30 - 19h30</Paragraph>
</Card.Content>
</Card>
<Card
style={{margin: 5, marginBottom: CustomTabBar.TAB_BAR_HEIGHT + 20}}>
<Card.Title
title={i18n.t('screens.proximo.paymentMethods')}
left={(iconProps: CardTitleIconPropsType): React.Node => (
<Avatar.Icon size={iconProps.size} icon="cash" />
)}
/>
<Card.Content>
<Paragraph>
{i18n.t('screens.proximo.paymentMethodsDescription')}
</Paragraph>
</Card.Content>
</Card>
</CollapsibleScrollView>
);
}
}

View file

@ -0,0 +1,78 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
// @flow
import * as React from 'react';
import {Image, View} from 'react-native';
import i18n from 'i18n-js';
import {Card, Avatar, Paragraph, Text} from 'react-native-paper';
import CustomTabBar from '../../../components/Tabbar/CustomTabBar';
import CollapsibleScrollView from '../../../components/Collapsible/CollapsibleScrollView';
const LOGO = 'https://etud.insa-toulouse.fr/~amicale_app/images/Proximo.png';
/**
* Class defining the proximo about screen.
*/
export default function ProximoAboutScreen() {
return (
<CollapsibleScrollView style={{padding: 5}}>
<View
style={{
width: '100%',
height: 100,
marginTop: 20,
marginBottom: 20,
justifyContent: 'center',
alignItems: 'center',
}}>
<Image
source={{uri: LOGO}}
style={{height: '100%', width: '100%', resizeMode: 'contain'}}
/>
</View>
<Text>{i18n.t('screens.proximo.description')}</Text>
<Card style={{margin: 5}}>
<Card.Title
title={i18n.t('screens.proximo.openingHours')}
left={(iconProps) => (
<Avatar.Icon size={iconProps.size} icon="clock-outline" />
)}
/>
<Card.Content>
<Paragraph>18h30 - 19h30</Paragraph>
</Card.Content>
</Card>
<Card style={{margin: 5, marginBottom: CustomTabBar.TAB_BAR_HEIGHT + 20}}>
<Card.Title
title={i18n.t('screens.proximo.paymentMethods')}
left={(iconProps) => (
<Avatar.Icon size={iconProps.size} icon="cash" />
)}
/>
<Card.Content>
<Paragraph>
{i18n.t('screens.proximo.paymentMethodsDescription')}
</Paragraph>
</Card.Content>
</Card>
</CollapsibleScrollView>
);
}

View file

@ -17,8 +17,6 @@
* along with Campus INSAT. If not, see <https://www.gnu.org/licenses/>.
*/
// @flow
import * as React from 'react';
import {Image, Platform, ScrollView, View} from 'react-native';
import i18n from 'i18n-js';
@ -38,7 +36,6 @@ 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';
@ -54,34 +51,42 @@ function sortPriceReverse(
}
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;
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;
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,
navigation: StackNavigationProp<any>;
route: {
params: {
data: {data: Array<ProximoArticleType>},
shouldFocusSearchBar: boolean,
},
},
theme: CustomThemeType,
data: {data: Array<ProximoArticleType>};
shouldFocusSearchBar: boolean;
};
};
theme: ReactNativePaper.Theme;
};
type StateType = {
currentSortMode: number,
modalCurrentDisplayItem: React.Node,
currentSearchString: string,
currentSortMode: number;
modalCurrentDisplayItem: React.ReactNode;
currentSearchString: string;
};
/**
@ -96,6 +101,7 @@ class ProximoListScreen extends React.Component<PropsType, StateType> {
constructor(props: PropsType) {
super(props);
this.modalRef = null;
this.listData = props.route.params.data.data.sort(sortName);
this.shouldFocusSearchBar = props.route.params.shouldFocusSearchBar;
this.state = {
@ -186,7 +192,9 @@ class ProximoListScreen extends React.Component<PropsType, StateType> {
this.listData.sort(sortName);
break;
}
if (this.modalRef && currentMode !== currentSortMode) this.modalRef.close();
if (this.modalRef && currentMode !== currentSortMode) {
this.modalRef.close();
}
}
/**
@ -198,9 +206,13 @@ class ProximoListScreen extends React.Component<PropsType, StateType> {
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;
if (availableStock > 3) {
color = theme.colors.success;
} else if (availableStock > 0) {
color = theme.colors.warning;
} else {
color = theme.colors.danger;
}
return color;
}
@ -209,7 +221,7 @@ class ProximoListScreen extends React.Component<PropsType, StateType> {
*
* @return {*}
*/
getSortMenuButton = (): React.Node => {
getSortMenuButton = () => {
return (
<MaterialHeaderButtons>
<Item title="main" iconName="sort" onPress={this.onSortMenuPress} />
@ -222,8 +234,9 @@ class ProximoListScreen extends React.Component<PropsType, StateType> {
*
* @return {*}
*/
getSearchBar = (): React.Node => {
getSearchBar = () => {
return (
// @ts-ignore
<Searchbar
placeholder={i18n.t('screens.proximo.search')}
onChangeText={this.onSearchStringChange}
@ -237,7 +250,7 @@ class ProximoListScreen extends React.Component<PropsType, StateType> {
* @param item The article to display
* @return {*}
*/
getModalItemContent(item: ProximoArticleType): React.Node {
getModalItemContent(item: ProximoArticleType) {
return (
<View
style={{
@ -284,7 +297,7 @@ class ProximoListScreen extends React.Component<PropsType, StateType> {
*
* @return {*}
*/
getModalSortMenu(): React.Node {
getModalSortMenu() {
const {currentSortMode} = this.state;
return (
<View
@ -299,22 +312,22 @@ class ProximoListScreen extends React.Component<PropsType, StateType> {
onValueChange={(value: string) => {
this.setSortMode(value);
}}
value={currentSortMode}>
value={currentSortMode.toString()}>
<RadioButton.Item
label={i18n.t('screens.proximo.sortPrice')}
value={1}
value={'1'}
/>
<RadioButton.Item
label={i18n.t('screens.proximo.sortPriceReverse')}
value={2}
value={'2'}
/>
<RadioButton.Item
label={i18n.t('screens.proximo.sortName')}
value={3}
value={'3'}
/>
<RadioButton.Item
label={i18n.t('screens.proximo.sortNameReverse')}
value={4}
value={'4'}
/>
</RadioButton.Group>
</View>
@ -327,7 +340,7 @@ class ProximoListScreen extends React.Component<PropsType, StateType> {
* @param item The article to render
* @return {*}
*/
getRenderItem = ({item}: {item: ProximoArticleType}): React.Node => {
getRenderItem = ({item}: {item: ProximoArticleType}) => {
const {currentSearchString} = this.state;
if (stringMatchQuery(item.name, currentSearchString)) {
const onPress = () => {
@ -364,15 +377,15 @@ class ProximoListScreen extends React.Component<PropsType, StateType> {
};
itemLayout = (
data: ProximoArticleType,
data: Array<ProximoArticleType> | null | undefined,
index: number,
): {length: number, offset: number, index: number} => ({
): {length: number; offset: number; index: number} => ({
length: LIST_ITEM_HEIGHT,
offset: LIST_ITEM_HEIGHT * index,
index,
});
render(): React.Node {
render() {
const {state} = this;
return (
<View

View file

@ -27,43 +27,41 @@ import WebSectionList from '../../../components/Screens/WebSectionList';
import MaterialHeaderButtons, {
Item,
} from '../../../components/Overrides/CustomHeaderButton';
import type {CustomThemeType} from '../../../managers/ThemeManager';
import type {SectionListDataType} from '../../../components/Screens/WebSectionList';
import type {ListIconPropsType} from '../../../constants/PaperStyles';
const DATA_URL = 'https://etud.insa-toulouse.fr/~proximo/data/stock-v2.json';
const LIST_ITEM_HEIGHT = 84;
export type ProximoCategoryType = {
name: string,
icon: string,
id: string,
name: string;
icon: string;
id: string;
};
export type ProximoArticleType = {
name: string,
description: string,
quantity: string,
price: string,
code: string,
id: string,
type: Array<string>,
image: string,
name: string;
description: string;
quantity: string;
price: string;
code: string;
id: string;
type: Array<string>;
image: string;
};
export type ProximoMainListItemType = {
type: ProximoCategoryType,
data: Array<ProximoArticleType>,
type: ProximoCategoryType;
data: Array<ProximoArticleType>;
};
export type ProximoDataType = {
types: Array<ProximoCategoryType>,
articles: Array<ProximoArticleType>,
types: Array<ProximoCategoryType>;
articles: Array<ProximoArticleType>;
};
type PropsType = {
navigation: StackNavigationProp,
theme: CustomThemeType,
navigation: StackNavigationProp<any>;
theme: ReactNativePaper.Theme;
};
/**
@ -87,12 +85,20 @@ class ProximoMainScreen extends React.Component<PropsType> {
const str2 = b.type.name.toLowerCase();
// Make 'All' category with id -1 stick to the top
if (a.type.id === -1) return -1;
if (b.type.id === -1) return 1;
if (a.type.id === '-1') {
return -1;
}
if (b.type.id === '-1') {
return 1;
}
// Sort others by name ascending
if (str1 < str2) return -1;
if (str1 > str2) return 1;
if (str1 < str2) {
return -1;
}
if (str1 > str2) {
return 1;
}
return 0;
}
@ -105,16 +111,17 @@ class ProximoMainScreen extends React.Component<PropsType> {
*/
static getAvailableArticles(
articles: Array<ProximoArticleType> | null,
type: ?ProximoCategoryType,
type?: ProximoCategoryType,
): Array<ProximoArticleType> {
const availableArticles = [];
const availableArticles: Array<ProximoArticleType> = [];
if (articles != null) {
articles.forEach((article: ProximoArticleType) => {
if (
((type != null && article.type.includes(type.id)) || type == null) &&
parseInt(article.quantity, 10) > 0
)
) {
availableArticles.push(article);
}
});
}
return availableArticles;
@ -122,13 +129,18 @@ class ProximoMainScreen extends React.Component<PropsType> {
articles: Array<ProximoArticleType> | null;
constructor(props: PropsType) {
super(props);
this.articles = null;
}
/**
* Creates header button
*/
componentDidMount() {
const {navigation} = this.props;
navigation.setOptions({
headerRight: (): React.Node => this.getHeaderButtons(),
headerRight: () => this.getHeaderButtons(),
});
}
@ -168,7 +180,7 @@ class ProximoMainScreen extends React.Component<PropsType> {
* Gets the header buttons
* @return {*}
*/
getHeaderButtons(): React.Node {
getHeaderButtons() {
return (
<MaterialHeaderButtons>
<Item
@ -199,7 +211,7 @@ class ProximoMainScreen extends React.Component<PropsType> {
* @param item The category to render
* @return {*}
*/
getRenderItem = ({item}: {item: ProximoMainListItemType}): React.Node => {
getRenderItem = ({item}: {item: ProximoMainListItemType}) => {
const {navigation, theme} = this.props;
const dataToSend = {
shouldFocusSearchBar: false,
@ -219,14 +231,14 @@ class ProximoMainScreen extends React.Component<PropsType> {
title={item.type.name}
description={subtitle}
onPress={onPress}
left={(props: ListIconPropsType): React.Node => (
left={(props) => (
<List.Icon
style={props.style}
icon={item.type.icon}
color={theme.colors.primary}
/>
)}
right={(props: ListIconPropsType): React.Node => (
right={(props) => (
<List.Icon
color={props.color}
style={props.style}
@ -295,7 +307,7 @@ class ProximoMainScreen extends React.Component<PropsType> {
return finalData;
}
render(): React.Node {
render() {
const {navigation} = this.props;
return (
<WebSectionList